Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

front end validation #83

Merged
merged 5 commits into from
Oct 30, 2022
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
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: '*'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this?

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