Skip to content

Commit

Permalink
Improve Signin and Signup Flow (#133)
Browse files Browse the repository at this point in the history
  • Loading branch information
zacharyblasczyk authored Oct 13, 2024
1 parent f918859 commit 06b5381
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 47 deletions.
2 changes: 1 addition & 1 deletion apps/webservice/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"match-sorter": "^6.3.4",
"murmurhash": "^2.0.1",
"next": "catalog:",
"next-auth": "5.0.0-beta.18",
"next-auth": "catalog:",
"next-themes": "^0.3.0",
"pretty-ms": "^9.0.0",
"randomcolor": "^0.6.2",
Expand Down
37 changes: 30 additions & 7 deletions apps/webservice/src/app/(auth)/login/LoginCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use client";

import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { IconBrandGoogle, IconLock } from "@tabler/icons-react";
import { signIn } from "next-auth/react";
import { z } from "zod";
import { useLocalStorage } from "react-use";

import { Button } from "@ctrlplane/ui/button";
import {
Expand All @@ -12,25 +14,44 @@ import {
FormItem,
FormLabel,
FormMessage,
FormRootError,
useForm,
} from "@ctrlplane/ui/form";
import { Input } from "@ctrlplane/ui/input";
import * as schema from "@ctrlplane/validators/auth";

export const LoginCard: React.FC<{
isGoogleEnabled: boolean;
isOidcEnabled: boolean;
}> = ({ isGoogleEnabled, isOidcEnabled }) => {
const router = useRouter();
const form = useForm({
schema: z.object({
email: z.string().email(),
password: z.string().min(8),
}),
schema: schema.signInSchema,
defaultValues: { email: "", password: "" },
});

const onSubmit = form.handleSubmit((data, event) => {
const [lastEnteredEmail, setLastEnteredEmail] = useLocalStorage(
"lastEnteredEmail",
"",
);

useEffect(() => {
if (lastEnteredEmail) form.setValue("email", lastEnteredEmail);
const subscription = form.watch(({ email }) =>
setLastEnteredEmail(email ?? ""),
);
return () => subscription.unsubscribe();
}, [form, lastEnteredEmail, setLastEnteredEmail]);

const onSubmit = form.handleSubmit(async (data, event) => {
event?.preventDefault();
signIn("credentials", { ...data, callbackUrl: "/" });
await signIn("credentials", { ...data })
.then(() => router.push("/"))
.catch(() => {
form.setError("root", {
message: "Sign in failed. Please try again.",
});
});
});

return (
Expand Down Expand Up @@ -69,6 +90,8 @@ export const LoginCard: React.FC<{
</FormItem>
)}
/>

<FormRootError />
<Button type="submit" className="w-full">
Login
</Button>
Expand Down
45 changes: 32 additions & 13 deletions apps/webservice/src/app/(auth)/sign-up/SignUpCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use client";

import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { signIn } from "next-auth/react";
import { z } from "zod";
import { useLocalStorage } from "react-use";

import { Button } from "@ctrlplane/ui/button";
import {
Expand All @@ -12,34 +13,52 @@ import {
FormItem,
FormLabel,
FormMessage,
FormRootError,
useForm,
} from "@ctrlplane/ui/form";
import { Input } from "@ctrlplane/ui/input";
import * as schema from "@ctrlplane/validators/auth";

import { api } from "~/trpc/react";

const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
password: z.string().min(8),
});

export const SignUpCard: React.FC = () => {
const router = useRouter();
const signUp = api.user.auth.signUp.useMutation();
const form = useForm({
schema,
schema: schema.signUpSchema,
defaultValues: {
name: "",
email: "",
password: "",
},
});

const onSubmit = form.handleSubmit(async (data) => {
await signUp.mutateAsync(data);
await signIn("credentials", data);
router.replace("/");
const [lastEnteredEmail, setLastEnteredEmail] = useLocalStorage(
"lastEnteredEmail",
"",
);

useEffect(() => {
if (lastEnteredEmail) form.setValue("email", lastEnteredEmail);

const subscription = form.watch(
(value, { name }) =>
name === "email" && setLastEnteredEmail(value.email ?? ""),
);
return () => subscription.unsubscribe();
}, [form, lastEnteredEmail, setLastEnteredEmail]);

const onSubmit = form.handleSubmit((data) => {
signUp
.mutateAsync(data)
.then(() => {
signIn("credentials", data).then(() => router.push("/"));
})
.catch(() => {
form.setError("root", {
message: "Sign up failed. Please try again.",
});
});
});

return (
Expand Down Expand Up @@ -92,7 +111,7 @@ export const SignUpCard: React.FC = () => {
</FormItem>
)}
/>

<FormRootError />
<Button
type="submit"
className="w-full"
Expand Down
2 changes: 1 addition & 1 deletion apps/webservice/src/app/(auth)/sign-up/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default async function LoginPage() {
<Button variant="ghost" className="text-muted-foreground">
Contact
</Button>
<Link href="/sign-up" passHref>
<Link href="/login" passHref>
<Button variant="outline">Login</Button>
</Link>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/webshell-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"express-rate-limit": "^7.3.0",
"helmet": "^7.1.0",
"ms": "^2.1.3",
"next-auth": "5.0.0-beta.18",
"next-auth": "catalog:",
"ws": "^8.17.0",
"zod": "catalog:"
},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"db:push": "pnpm -F db push",
"db:studio": "pnpm -F db studio",
"dev": "turbo dev --parallel --concurrency 30 --cache-workers 30 --filter=!./integrations/**/*",
"dev:docker": "docker compose -f docker-compose.dev.yaml up -d",
"format": "turbo format --continue -- --cache --cache-location node_modules/.cache/.prettiercache",
"format:fix": "turbo format --continue -- --write --cache --cache-location node_modules/.cache/.prettiercache",
"lint": "turbo lint --continue -- --cache --cache-location node_modules/.cache/.eslintcache",
Expand Down
2 changes: 1 addition & 1 deletion packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@t3-oss/env-nextjs": "catalog:",
"bcryptjs": "^2.4.3",
"next": "catalog:",
"next-auth": "5.0.0-beta.18",
"next-auth": "catalog:",
"react": "18.3.1",
"react-dom": "18.3.1",
"zod": "catalog:"
Expand Down
2 changes: 2 additions & 0 deletions packages/auth/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export const authConfig: NextAuthConfig = {
pages: { signIn: "/login" },
session: { strategy: "jwt" },

secret: env.AUTH_SECRET,

adapter: DrizzleAdapter(db, {
usersTable: schema.user,
accountsTable: schema.account,
Expand Down
7 changes: 4 additions & 3 deletions packages/auth/src/utils/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ const getUserByEmail = (email: string) =>

export const getUserByCredentials = async (email: string, password: string) => {
const user = await getUserByEmail(email);
if (user == null) return null;
if (user == null) return new Error("Invalid credentials");
const { passwordHash } = user;
if (passwordHash == null) return null;
return compareSync(password, passwordHash) ? user : null;
if (passwordHash == null) return new Error("Invalid credentials");
const isPasswordCorrect = compareSync(password, passwordHash);
return isPasswordCorrect ? user : new Error("Invalid credentials");
};
4 changes: 4 additions & 0 deletions packages/validators/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export const signInSchema = z.object({
.max(32, "Password must be less than 32 characters"),
});

export const signUpSchema = signInSchema.extend({
name: z.string().min(1, "Name is required"),
});

export enum Permission {
IamSetPolicy = "iam.setIamPolicy",

Expand Down
43 changes: 23 additions & 20 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ catalog:
"tsx": ^4.19.1
"lodash-es": ^4.17.21
"next": ^14.2.13
"next-auth": "5.0.0-beta.22"
"@next/eslint-plugin-next": ^14.2.6
"bullmq": ^5.15.0

Expand Down

0 comments on commit 06b5381

Please sign in to comment.