Skip to content
This repository has been archived by the owner on Dec 31, 2023. It is now read-only.

Vương: Change password page #59

Merged
merged 6 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.hardingadonis.miu.controller.web;

import io.hardingadonis.miu.model.*;
import io.hardingadonis.miu.services.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet(name = "ChangePasswordServlet", urlPatterns = {"/change-password"})
public class ChangePasswordServlet extends HttpServlet {

private static final String CHANGE_PASSWORD_SUCCESS_PARAM = "changePasswordSuccess";

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");

User user = (User) request.getSession().getAttribute("user");

if (user == null) {
response.sendRedirect("login");
return;
}

request.getRequestDispatcher("/view/web/change-password.jsp").forward(request, response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");

String hashedCurrentPassword = Hash.SHA256(request.getParameter("current-password"));
String hashedNewPassword = Hash.SHA256(request.getParameter("new-password"));

User user = (User) request.getSession().getAttribute("user");

if (!user.getHashedPassword().equals(hashedCurrentPassword)) {
request.setAttribute("error_msg", "Sai mật khẩu!");
} else if (hashedCurrentPassword.equals(hashedNewPassword)) {
request.setAttribute("error_msg", "Mật khẩu mới không được trùng với mật khẩu cũ!");
} else {
user.setHashedPassword(hashedNewPassword);
Singleton.userDAO.update(user);

request.getSession(false).invalidate();
response.sendRedirect("login?" + CHANGE_PASSWORD_SUCCESS_PARAM + "=true");

return;
}

this.doGet(request, response);
}
}
17 changes: 17 additions & 0 deletions src/main/webapp/assets/css/web/change-password.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.option {
transition: background-color 0.3s;
}

.option:hover {
background-color: #d1d8e0;
}

.option:active {
background-color: rgba(109, 121, 134, 0.9);
color: #ffffff;
}

.option-selected {
background-color: rgba(165, 175, 185, 0.9);
color: #ffffff;
}
63 changes: 63 additions & 0 deletions src/main/webapp/assets/js/web/changePasswordHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const form = document.getElementById('change-password-form');
const currentPasswordInput = document.getElementById('current-password');
const newPasswordInput = document.getElementById('new-password');
const confirmNewPasswordInput = document.getElementById('confirm-new-password');
const errorMessage = document.getElementById('error-message');

form.addEventListener('submit', function (event) {
event.preventDefault();

if (!isStrongPassword(newPasswordInput.value)) {
errorMessage.textContent = 'Mật khẩu mới phải có ít nhất 6 ký tự, trong đó có ít nhất 1 chữ số, 1 chữ cái viết hoa, 1 ký tự đặc biệt!';
newPasswordInput.focus();
return;
}

if (!isPasswordMatch(newPasswordInput.value, confirmNewPasswordInput.value)) {
errorMessage.textContent = 'Mật khẩu mới không khớp!';
confirmNewPasswordInput.focus();
return;
}

this.submit();
});

currentPasswordInput.addEventListener('input', function () {
removeSpaces(currentPasswordInput);
});

newPasswordInput.addEventListener('input', function () {
removeSpaces(newPasswordInput);
});

confirmNewPasswordInput.addEventListener('input', function () {
removeSpaces(confirmNewPasswordInput);
});

function removeSpaces(input) {
input.value = input.value.replace(/\s/g, '');
}

function isPasswordMatch(password, confirmPassword) {
return password === confirmPassword;
}

function isStrongPassword(password) {
if (password.length < 6) {
return false;
}

if (!/\d/.test(password)) {
return false;
}

if (!/[!@#$%^&*()_+{}\[\]:;<>,.?~\\/-]/.test(password)) {
return false;
}

if (!/[A-Z]/.test(password)) {
return false;
}

return true;
}
78 changes: 78 additions & 0 deletions src/main/webapp/view/web/change-password.jsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<%@ page contentType="text/html" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" />
<link rel="stylesheet" href="<%=request.getContextPath()%>/assets/css/web/common/common.css" />
<link rel="stylesheet" href="<%=request.getContextPath()%>/assets/css/web/change-password.css" />

<link rel="icon" type="image/x-icon" href="<%=request.getContextPath()%>/assets/images/favicon/favicon.png">

<title>Miu Shop | Đổi mật khẩu</title>
</head>

<body>
<%@include file="common/_header.jsp" %>

<section class="py-5 my-5">
<div class="container">
<div class="row">
<div class="col-lg-3 col-sm-12 text-center">
<img src="./${sessionScope.user.avatarPath}" alt="Avatar" class="img-thumbnail rounded">
<h3 class="my-4">${sessionScope.user.fullName}</h3>
<ul class="nav flex-column">
<li class="nav-item">
<a href="profile" class="nav-link text-muted option">Thông tin chung</a>
<a href="delivery-address" class="nav-link text-muted option">Địa chỉ giao hàng</a>
<a href="purchase-history" class="nav-link text-muted option">Lịch sử mua hàng</a>
<a href="change-password" class="nav-link text-muted option option-selected">Đổi mật khẩu</a>
</li>
</ul>
</div>

<div class="col-lg-9 col-sm-12">
<div class="container-fluid p-3 border border-dark">
<h6 class="m-3 text-center display-6">Thay đổi mật khẩu</h6>

<form id="change-password-form" action="change-password" method="post" class="px-5">
<div class="mb-3">
<label for="current-password" class="form-label">Mật khẩu hiện tại</label>
<input name="current-password" class="form-control" type="password" id="current-password" required>
</div>

<div class="mb-3">
<label for="new-password" class="form-label">Mật khẩu mới</label>
<input name="new-password" type="password" class="form-control" id="new-password" required>
</div>

<div class="mb-3">
<label for="confirm-new-password" class="form-label">Xác nhận mật khẩu mới</label>
<input name="confirm-new-password" class="form-control" type="password" id="confirm-new-password" required>
</div>

<div class="my-3 text-center">
<div id="error-message" class="text-danger my-3">${error_msg}</div>
<button type="submit" class="btn btn-outline-dark">Xác Nhận</button>
</div>
</form>
</div>
</div>
</div>
</div>
</section>

<%@include file="common/_footer.jsp" %>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="<%=request.getContextPath()%>/assets/js/web/common/commonHandler.js"></script>
<script src="<%=request.getContextPath()%>/assets/js/web/changePasswordHandler.js"></script>
</body>

</html>
14 changes: 14 additions & 0 deletions src/main/webapp/view/web/login.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@
</div>
</c:if>

<%-- Kiểm tra xem có URL parameter changePasswordSuccess hay không --%>
<c:if test="${param.changePasswordSuccess == 'true'}">
<style>
.main {
min-height: 75vh;
padding-bottom: 8.5vh;
}
</style>

<div class="alert alert-success mx-auto" role="alert" style="max-width: 500px;">
Bạn đã đổi mật khẩu thành công. Vui lòng đăng nhập để tiếp tục.
</div>
</c:if>

<div class="container main">
<div class="row">
<div class="col-md-6 side-image">
Expand Down