Skip to content

Commit

Permalink
Merge pull request #83 from CS3219-AY2223S1/US/validation
Browse files Browse the repository at this point in the history
front end validation
  • Loading branch information
tanyjnaaman authored Oct 30, 2022
2 parents 6546a5f + 1b6d8c0 commit b0b2824
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 10 deletions.
39 changes: 36 additions & 3 deletions frontend/src/components/AccountPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import {
} from "../api/UserServiceApi";
import { UserContext, UserContextType } from "../contexts/UserContext";
import useIsMobile from "../hooks/useIsMobile";
import { Snackbar} from "@mui/material";
import MuiAlert from "@mui/material/Alert";
import { Button } from "./Button";
import { TextField } from "./TextField";
import { validatePassword, validateUsername } from "../components/user/utils";

const SettingsCard = styled.form`
border-radius: 20px;
Expand Down Expand Up @@ -49,8 +52,7 @@ function AccountPage() {
// ================ State management ================
// UI states
const isMobile = useIsMobile();
const [isErrorSnackbarOpen, setIsErrorSnackbarOpen] =
useState<Boolean>(false);
const [isErrorSnackbarOpen, setIsErrorSnackbarOpen] = useState(false);
const [errorSnackBarContent, setErrorSnackbarContent] = useState<String>("");

// contexts
Expand All @@ -62,13 +64,19 @@ function AccountPage() {
// ================ Event handlers ==================
const handleChangeUsername = async (e: any) => {
e.preventDefault();

const usernameIsValid = validateUsername(username);
setIsUsernameError(!usernameIsValid);
if(!usernameIsValid){return;}

await apiCallUserChangeUsername(username, "")
.then((response) => {
if (response.status === 200) {
navigate("/");
} else {
const errorMessage: string =
"Something went wrong! Please try again later.";
response.data.message ??
"Something went wrong! Please try again later.";
setErrorSnackbarContent(errorMessage);
}
setIsErrorSnackbarOpen(true);
Expand All @@ -80,6 +88,11 @@ function AccountPage() {

const handleChangePassword = async (e: any) => {
e.preventDefault();

const passwordIsValid = validatePassword(password, password);
setIsPasswordError(!passwordIsValid);
if(!passwordIsValid){return;}

await apiCallUserChangePassword("", password)
.then((response) => {
if (response.status === 200) {
Expand Down Expand Up @@ -129,6 +142,25 @@ function AccountPage() {
<Button onClick={handleChangePassword}>Confirm New Password</Button>
);

/**
* This renders the error snackbar.
*/
const errorSnackbar = (
<Snackbar
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
open={isErrorSnackbarOpen}
autoHideDuration={5000}
onClose={() => setIsErrorSnackbarOpen(false)}
role="alert"
>
<MuiAlert elevation={6} variant="filled" severity="error">
{errorSnackBarContent}
</MuiAlert>
</Snackbar>
);



// ====== Render ======
return (
<SettingsCard>
Expand All @@ -139,6 +171,7 @@ function AccountPage() {
{changePassword_TextField}
<ButtonContainer>{changePassword_button}</ButtonContainer>
</form>
{errorSnackbar}
</SettingsCard>
);
}
Expand Down
1 change: 1 addition & 0 deletions user-service/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const ENV_IS_PROD = process.env.ENV == 'PROD'
*/
export const CORS_OPTIONS: cors.CorsOptions = {
credentials: true,
// origin: '*'
origin: 'http://localhost:3000' // TODO: currently we allow all origins
}

Expand Down
4 changes: 2 additions & 2 deletions user-service/src/controller/services/response-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ export function createInternalServerErrorResponse(
) {
return response
.status(statusCode ?? 500)
.json({ message: message ?? "Internal server error." });
.json({ data:{ message: message ?? "Internal server error." }});
}

export function createOkResponse(response: Response, data?: unknown) {
return response.status(200).json(data);
}

export function createBadRequestResponse(response: Response, message?: string) {
return response.status(400).json({ message: message ?? "Bad request." });
return response.status(400).json({ data:{ message: message ?? "Bad request." }});
}
13 changes: 9 additions & 4 deletions user-service/src/controller/services/user-services.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { randomUUID, sign } from "crypto";
import { randomUUID } from "crypto";
import {
DbPermissionDeniedException,
DbReadException,
DbWriteException,
UserDetailValidationException,
UsernameClashException,
UserNotFoundException,
UserServiceException,
} from "../../exceptions";
import { LoginDetails, SignUpDetails } from "../../interfaces/login-details";
Expand All @@ -17,7 +19,7 @@ export async function createUser(signupDetails: SignUpDetails) {
// 1. check if user exists
const username = signupDetails.username;
if (await userWithUsernameExists(username)) {
throw new DbWriteException("User already exists.");
throw new UsernameClashException("User already exists.");
}

// 2. if user does not exist, we create and save the uservalidate the change
Expand Down Expand Up @@ -63,6 +65,9 @@ export async function modifyUser(id: string, signupDetails: SignUpDetails) {
{ password: signupDetails.password }
);
} else {
if (await userWithUsernameExists(signupDetails.username)) {
throw new UsernameClashException("User already exists");
}
user1 = await UserModel.findOneAndUpdate(
{ id },
{ username: signupDetails.username }
Expand Down Expand Up @@ -130,7 +135,7 @@ export async function deleteUser(userId: string) {
try {
// 1. check if user exists
if (!(await userWithIdExists(userId))) {
throw new DbWriteException(
throw new UserNotFoundException(
"User does not exist, but we are trying to delete them."
);
}
Expand Down Expand Up @@ -229,4 +234,4 @@ export function validateSignupDetails(details: SignUpDetails) {
"Invalid username! Needs to be alphanumeric, no special characters, and between 1 and 20 characters."
);
}
}
}
26 changes: 26 additions & 0 deletions user-service/src/exceptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,32 @@ export class UserDetailValidationException extends UserServiceException {
}
}

/**
* Exception thrown when creating/renaming an account clashes with an existing account
*/
export class UsernameClashException extends UserServiceException {
constructor(message: string) {
super(message,409);

// Set the prototype explicitly.
Object.setPrototypeOf(this, DbWriteException.prototype);
}
}

/**
* Exception thrown when deleting an account that does not exist
*/
export class UserNotFoundException extends UserServiceException {
constructor(message: string) {
super(message,404);

// Set the prototype explicitly.
Object.setPrototypeOf(this, DbWriteException.prototype);
}
}



/**
* Exception thrown when there is an error writing to the database.
*/
Expand Down
2 changes: 1 addition & 1 deletion user-service/tests/test-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe("signup", () => {
const res = await agent
.post("/signup")
.send({ username: "user1", password: "testpw" });
expect(res.statusCode).toEqual(500);
expect(res.statusCode).toEqual(409);
});

// empty username
Expand Down

0 comments on commit b0b2824

Please sign in to comment.