Skip to content

Commit

Permalink
Better behavior regarding minimum length checks (#256)
Browse files Browse the repository at this point in the history
* Better client-side messages for field minimum lengths

* We should not setHasChanged(false) on error when editing

* Raise error if title length < 4

* editing: Raise error if desc length < 6

* have humanReadableError return strings verbatim

If typeof error === 'string', then obviously the string `error` is the
error we should be returning.

* Add backend checks to length of name and description
  • Loading branch information
chennisden authored Aug 6, 2024
1 parent 373b714 commit 8e5ac8c
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 23 deletions.
5 changes: 4 additions & 1 deletion frontend/src/components/listing/ListingDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ const ListingDescription = (props: Props) => {
setIsEditing(false);
return;
}
if (newDescription.length < 6) {
addErrorAlert("Description must be at least 6 characters long.");
return;
}
setSubmitting(true);
const { error } = await auth.client.PUT("/listings/edit/{id}", {
params: {
Expand All @@ -78,7 +82,6 @@ const ListingDescription = (props: Props) => {
});
if (error) {
addErrorAlert(error);
setHasChanged(false);
} else {
addAlert("Listing updated successfully", "success");
setIsEditing(false);
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/listing/ListingHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const ListingTitle = (props: Props) => {
setIsEditing(false);
return;
}
if (newTitle.length < 4) {
addErrorAlert("Title must be at least 4 characters long.");
return;
}
setSubmitting(true);
const { error } = await auth.client.PUT("/listings/edit/{id}", {
params: {
Expand All @@ -40,7 +44,6 @@ const ListingTitle = (props: Props) => {
});
if (error) {
addErrorAlert(error);
setHasChanged(false);
} else {
addAlert("Listing updated successfully", "success");
setIsEditing(false);
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/constants/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ export const BACKEND_URL =

// eslint-disable-next-line
export const humanReadableError = (error: any | undefined) => {
if (isAxiosError(error)) {
if (typeof error === "string") {
return error;
} else if (isAxiosError(error)) {
const axiosError = error as AxiosError;
const request = axiosError.request,
response = axiosError.response;
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/pages/Create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ const Create = () => {
>
{/* Name */}
<div>
<Input placeholder="Name" type="text" {...register("name")} />
<Input
placeholder="Name (at least 4 characters)"
type="text"
{...register("name")}
/>
{errors?.name && (
<ErrorMessage>{errors?.name?.message}</ErrorMessage>
)}
Expand All @@ -73,7 +77,7 @@ const Create = () => {
{/* Description Input */}
<div className="relative">
<TextArea
placeholder="Description"
placeholder="Description (at least 6 characters)"
rows={4}
{...register("description", {
setValueAs: (value) => {
Expand Down
34 changes: 18 additions & 16 deletions frontend/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ export const LoginSchema = z.object({
required_error: "Email is required",
invalid_type_error: "Email should be end at @gmail",
})
.min(1, { message: "Email Required" })
.min(1, { message: "Email is required." })
.email("Invalid Email"),
password: z
.string({
required_error: "Password is Required",
required_error: "Password is required.",
})
.min(4, { message: "Password Required" }),
.min(4, { message: "Password is required." }),
});

export type LoginType = z.infer<typeof LoginSchema>;
Expand All @@ -22,44 +22,46 @@ export const SignUpSchema = z
.object({
email: z
.string({
required_error: "Email is required",
required_error: "Email required.",
})
.min(1, { message: "Email Required" })
.email("Invalid Email"),
.min(1, { message: "Email required." })
.email("Invalid email."),
password: z
.string({
required_error: "Password is Required",
required_error: "Password required.",
})
.min(4, { message: "Password Required" })
.min(4, { message: "Password must be at least 4 characters long." })
.refine(
(password) => {
const result = zxcvbn(password);
return result.score >= 2;
},
{
message: "Password is too weak",
message: "Password is too weak.",
},
),
confirmPassword: z
.string({
required_error: "Confirm Password is Required",
required_error: "Must confirm password.",
})
.min(4, { message: "Confirm Password Required" }),
.min(8, {
message: "Must confirm password with length at least 8 characters.",
}),
})
.refine((data) => data.confirmPassword === data.password, {
message: "Password not matched",
message: "Passwords do not match.",
path: ["confirmPassword"],
});

export type SignupType = z.infer<typeof SignUpSchema>;

export const NewListingSchema = z.object({
name: z
.string({ required_error: "Name is required" })
.min(4, { message: "Name is required" }),
.string({ required_error: "Name is required." })
.min(4, { message: "Name must be at least 4 characters long." }),
description: z
.string({ required_error: "Description is required" })
.min(6, { message: "Description is required" }),
.string({ required_error: "Description is required." })
.min(6, { message: "Description must be at least 6 characters long." }),
});

export type NewListingType = z.infer<typeof NewListingSchema>;
Expand Down
14 changes: 12 additions & 2 deletions store/app/routers/listings.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,19 @@ async def edit_listing(
) -> bool:
listing_info = await crud.get_listing(id)
if listing_info is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Listing not found")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Listing not found.")
if listing_info.user_id != user.id:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You do not own this listing")
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You do not own this listing.")
if listing.name is not None and len(listing.name) < 4:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Listing name must be at least 4 characters long.",
)
if listing.description is not None and len(listing.description) < 6:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Listing description must be at least 6 characters long.",
)
await crud.edit_listing(
listing_id=id,
name=listing.name,
Expand Down

0 comments on commit 8e5ac8c

Please sign in to comment.