Skip to content

Commit

Permalink
implement password verification during signup
Browse files Browse the repository at this point in the history
  • Loading branch information
jthrilly committed Feb 26, 2025
1 parent 4d41ab7 commit 0074fdc
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function ConnectUploadThing() {
to visit UploadThing. Create an app and copy and paste your API key
below.
</Paragraph>
<Alert variant="info" className="mt-4">
<Alert variant="info">
<AlertTitle>Good to know:</AlertTitle>
<AlertDescription>
Your UploadThing account is unique to you, meaning that no one else
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { SignUpForm } from '~/app/(blobs)/(setup)/_components/SignUpForm';
import { Alert, AlertDescription, AlertTitle } from '~/components/ui/Alert';
import Heading from '~/components/ui/typography/Heading';
import Paragraph from '~/components/ui/typography/Paragraph';

Expand All @@ -13,6 +14,14 @@ function CreateAccount() {
administrator account can be created.
</Paragraph>
</div>
<Alert variant="warning">
<AlertTitle>Important</AlertTitle>
<AlertDescription>
It is not possible to recover the account details if they are lost.
Make sure to store the account details in a safe place, such as a
password manager.
</AlertDescription>
</Alert>
<SignUpForm />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function ConfigureStudy() {
the dashboard.
</Paragraph>
<ProtocolUploader
className="m-14 p-6"
className="m-10 p-8"
buttonVariant="outline"
buttonSize="lg"
hideCancelButton
Expand Down
6 changes: 3 additions & 3 deletions app/(blobs)/(setup)/_components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ function OnboardSteps({ steps }: { steps: string[] }) {
>
<div
className={cn(
'text-md flex h-10 w-10 items-center justify-center rounded-full border border-primary/[.06] font-bold',
'border-primary/[.06] flex h-10 w-10 items-center justify-center rounded-full border text-sm font-bold',
index < currentStep - 1 &&
'border-teal-400 bg-success text-white',
'bg-success border-teal-400 text-white',
index === currentStep - 1 &&
'border-primary bg-primary text-white',
)}
Expand All @@ -39,7 +39,7 @@ function OnboardSteps({ steps }: { steps: string[] }) {
)}
</div>
<div className="flex flex-col">
<Heading variant={'h4-all-caps'} className="m-0">
<Heading variant={'h4-all-caps'} className="m-0 text-xs">
{step}
</Heading>
</div>
Expand Down
25 changes: 23 additions & 2 deletions app/(blobs)/(setup)/_components/SignUpForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,20 @@ export const SignUpForm = () => {
const {
register,
handleSubmit,
watch,
trigger,
formState: { errors, isValid, isSubmitting },
} = useZodForm({
schema: createUserSchema,
mode: 'onTouched',
});

const onSubmit = async (data: unknown) => {
await signup(data);
};

const password = watch('password');

return (
<form
className="flex flex-col"
Expand All @@ -34,19 +39,35 @@ export const SignUpForm = () => {
placeholder="username..."
autoComplete="do-not-autofill"
error={errors.username?.message}
{...register('username')}
{...register('username', {})}
/>
</div>
<div className="mb-6 flex flex-wrap">
<Input
className="w-full"
label="Password"
hint="Your password must be at least 8 characters long, and contain at least one each of lowercase, uppercase, number and symbol characters."
type="password"
placeholder="******************"
autoComplete="do-not-autofill"
error={errors.password?.message}
{...register('password')}
{...register('password', {
onChange: () => trigger('password'),
})}
/>
{password && password.length > 0 && (
<Input
className="w-full"
label="Confirm password"
type="password"
placeholder="******************"
autoComplete="do-not-autofill"
error={errors.confirmPassword?.message}
{...register('confirmPassword', {
onChange: () => trigger('confirmPassword'),
})}
/>
)}
</div>
<div className="flex flex-wrap justify-end">
<Button disabled={isSubmitting || !isValid} type="submit">
Expand Down
4 changes: 3 additions & 1 deletion components/ui/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Heading from './typography/Heading';
import { paragraphVariants } from './typography/Paragraph';

const alertVariants = cva(
'relative w-full bg-card text-foreground rounded-lg border p-4 [&>svg~*]:pl-6 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',
'relative w-full bg-card text-foreground rounded-lg border p-4 [&>svg~*]:pl-6 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground gap-2 grid my-6',
{
variants: {
variant: {
Expand All @@ -17,6 +17,8 @@ const alertVariants = cva(
'bg-destructive/5 border-destructive text-destructive [&>svg]:text-destructive [--color-link:var(--color-destructive)]',
success:
'bg-success/5 border-success text-success [&>svg]:text-success [--color-link:var(--color-success)]',
warning:
'bg-warning/2 border-warning text-warning [--color-link:var(--color-warning)]',
},
},
defaultVariants: {
Expand Down
49 changes: 30 additions & 19 deletions schemas/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,36 @@ import { isStrongPassword } from 'validator';
import { z } from 'zod';
import { zfd } from 'zod-form-data';

export const createUserSchema = z.object({
username: z
.string()
.min(4, { message: 'Username must be at least 4 characters' })
.refine((s) => !s.includes(' '), 'Username cannot contain spaces'),
password: z.string().refine(
(password) =>
isStrongPassword(password, {
minLowercase: 1,
minUppercase: 1,
minNumbers: 1,
minSymbols: 1,
}),
{
message:
'Password must contain at least 1 lowercase, 1 uppercase, 1 number, and 1 symbol',
},
),
});
export const createUserSchema = z
.object({
username: z
.string()
.min(4, { message: 'Username must be at least 4 characters' })
.refine((s) => !s.includes(' '), 'Username cannot contain spaces'),
password: z.string().refine(
(password) =>
isStrongPassword(password, {
minLowercase: 1,
minUppercase: 1,
minNumbers: 1,
minSymbols: 1,
}),
{
message:
'Password must contain at least 1 lowercase, 1 uppercase, 1 number, and 1 symbol',
},
),
confirmPassword: z.string().min(1),
})
.superRefine((val, ctx) => {
if (val.password !== val.confirmPassword) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Passwords do not match',
path: ['confirmPassword'],
});
}
});

export const createUserFormDataSchema = zfd.formData(createUserSchema);

Expand Down
7 changes: 5 additions & 2 deletions styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@
--color-info: hsl(var(--info));
--color-info-foreground: hsl(var(--info-foreground));

--color-warning: hsl(var(--warning));
--color-warning-foreground: hsl(var(--warning-foreground));

--color-muted: hsl(var(--muted));
--color-muted-foreground: hsl(var(--muted-foreground));

Expand Down Expand Up @@ -322,8 +325,8 @@
calc(var(--kiwi-lightness) - var(--dark-mod));

--neon-carrot-hue: 32;
--neon-carrot-saturation: 90%;
--neon-carrot-lightness: 55%;
--neon-carrot-saturation: 92%;
--neon-carrot-lightness: 52%;
--neon-carrot: var(--neon-carrot-hue) var(--neon-carrot-saturation)
var(--neon-carrot-lightness);
--neon-carrot--dark: var(--neon-carrot-hue) var(--neon-carrot-saturation)
Expand Down

0 comments on commit 0074fdc

Please sign in to comment.