authverse 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/dist/index.cjs +827 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +799 -0
- package/dist/template/api/route.ts +4 -0
- package/dist/template/app-auth-uiDesign/forget/page.tsx +7 -0
- package/dist/template/app-auth-uiDesign/layout.tsx +9 -0
- package/dist/template/app-auth-uiDesign/login/page.tsx +7 -0
- package/dist/template/app-auth-uiDesign/reset-password/page.tsx +7 -0
- package/dist/template/app-auth-uiDesign/signup/page.tsx +7 -0
- package/dist/template/components/ForgetComponent.tsx +121 -0
- package/dist/template/components/GithubProviders.tsx +21 -0
- package/dist/template/components/GoogleProviders.tsx +21 -0
- package/dist/template/components/LoginComponent.tsx +145 -0
- package/dist/template/components/Logout.tsx +21 -0
- package/dist/template/components/ResetComponent.tsx +150 -0
- package/dist/template/components/SingUpComponent.tsx +173 -0
- package/dist/template/config/drizzle.config.ts +13 -0
- package/dist/template/config/prisma.config.ts +12 -0
- package/dist/template/db/drizzle.ts +6 -0
- package/dist/template/db/schema.ts +68 -0
- package/dist/template/email/reset-password.tsx +132 -0
- package/dist/template/lib/Mongodb/auth.ts +20 -0
- package/dist/template/lib/Mysql/auth.ts +27 -0
- package/dist/template/lib/Postgresql/auth.ts +20 -0
- package/dist/template/lib/auth-client.ts +5 -0
- package/dist/template/lib/auth-drizzle.ts +16 -0
- package/dist/template/prisma/mongodb/schema.prisma +70 -0
- package/dist/template/prisma/mysql/schema.prisma +68 -0
- package/dist/template/prisma/postgresql/schema.prisma +68 -0
- package/dist/template/proxy/proxy.ts +15 -0
- package/dist/template/server/user.ts +49 -0
- package/package.json +62 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
4
|
+
import { Controller, useForm } from "react-hook-form";
|
|
5
|
+
import { toast } from "sonner";
|
|
6
|
+
import * as z from "zod";
|
|
7
|
+
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
9
|
+
import {
|
|
10
|
+
Card,
|
|
11
|
+
CardContent,
|
|
12
|
+
CardDescription,
|
|
13
|
+
CardFooter,
|
|
14
|
+
CardHeader,
|
|
15
|
+
CardTitle,
|
|
16
|
+
} from "@/components/ui/card";
|
|
17
|
+
import {
|
|
18
|
+
Field,
|
|
19
|
+
FieldError,
|
|
20
|
+
FieldGroup,
|
|
21
|
+
FieldLabel,
|
|
22
|
+
} from "@/components/ui/field";
|
|
23
|
+
import { Input } from "@/components/ui/input";
|
|
24
|
+
import { authClient } from "@/lib/auth-client";
|
|
25
|
+
import Link from "next/link";
|
|
26
|
+
import { useRouter } from "next/navigation";
|
|
27
|
+
import { useState } from "react";
|
|
28
|
+
|
|
29
|
+
const formSchema = z.object({
|
|
30
|
+
email: z.string().email(),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const ForgetComponent = () => {
|
|
34
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
35
|
+
const router = useRouter();
|
|
36
|
+
|
|
37
|
+
const form = useForm<z.infer<typeof formSchema>>({
|
|
38
|
+
resolver: zodResolver(formSchema),
|
|
39
|
+
defaultValues: {
|
|
40
|
+
email: "",
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const onSubmit = async (value: z.infer<typeof formSchema>) => {
|
|
45
|
+
setIsLoading(true);
|
|
46
|
+
try {
|
|
47
|
+
const { data, error } = await authClient.requestPasswordReset({
|
|
48
|
+
email: value.email,
|
|
49
|
+
redirectTo: "/auth/reset-password",
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (error) {
|
|
53
|
+
setIsLoading(false);
|
|
54
|
+
toast.error(error.message);
|
|
55
|
+
}
|
|
56
|
+
if (data) {
|
|
57
|
+
setIsLoading(false);
|
|
58
|
+
toast.success("Password reset email sent. Please check your inbox.");
|
|
59
|
+
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
toast.error("Something went wrong. Please try again.");
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Card className="w-full sm:max-w-md shadow-md">
|
|
67
|
+
<CardHeader>
|
|
68
|
+
<CardTitle className="text-2xl leading-4">Forger Password</CardTitle>
|
|
69
|
+
<CardDescription>Please enter your email</CardDescription>
|
|
70
|
+
</CardHeader>
|
|
71
|
+
<CardContent>
|
|
72
|
+
<form id="form-login" onSubmit={form.handleSubmit(onSubmit)}>
|
|
73
|
+
<FieldGroup>
|
|
74
|
+
<Controller
|
|
75
|
+
name="email"
|
|
76
|
+
control={form.control}
|
|
77
|
+
render={({ field, fieldState }) => (
|
|
78
|
+
<Field data-invalid={fieldState.invalid}>
|
|
79
|
+
<FieldLabel htmlFor="form-login-email">Email</FieldLabel>
|
|
80
|
+
<Input
|
|
81
|
+
{...field}
|
|
82
|
+
id="form-login-email"
|
|
83
|
+
aria-invalid={fieldState.invalid}
|
|
84
|
+
placeholder="example@domain.com"
|
|
85
|
+
autoComplete="off"
|
|
86
|
+
disabled={isLoading}
|
|
87
|
+
/>
|
|
88
|
+
{fieldState.invalid && (
|
|
89
|
+
<FieldError errors={[fieldState.error]} />
|
|
90
|
+
)}
|
|
91
|
+
</Field>
|
|
92
|
+
)}
|
|
93
|
+
/>
|
|
94
|
+
</FieldGroup>
|
|
95
|
+
</form>
|
|
96
|
+
</CardContent>
|
|
97
|
+
<CardFooter>
|
|
98
|
+
<div className="w-full">
|
|
99
|
+
<Field orientation="horizontal">
|
|
100
|
+
<Button
|
|
101
|
+
type="submit"
|
|
102
|
+
form="form-login"
|
|
103
|
+
className="w-full"
|
|
104
|
+
disabled={isLoading}
|
|
105
|
+
>
|
|
106
|
+
{isLoading ? "Resetting..." : "Reset Password"}
|
|
107
|
+
</Button>
|
|
108
|
+
</Field>
|
|
109
|
+
<div className="w-full text-center pt-4 space-x-2">
|
|
110
|
+
<span>Already have an account?</span>
|
|
111
|
+
<Link href="/auth/login" className="underline">
|
|
112
|
+
Login
|
|
113
|
+
</Link>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</CardFooter>
|
|
117
|
+
</Card>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export default ForgetComponent;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { authClient } from "@/lib/auth-client";
|
|
4
|
+
import { Button } from "../ui/button";
|
|
5
|
+
import { FaGithub } from "react-icons/fa";
|
|
6
|
+
|
|
7
|
+
const GithubProviders = () => {
|
|
8
|
+
const signIn = async () => {
|
|
9
|
+
const data = await authClient.signIn.social({
|
|
10
|
+
provider: "github",
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
return (
|
|
14
|
+
<Button className="w-full text-base" variant="outline" onClick={signIn}>
|
|
15
|
+
<FaGithub />
|
|
16
|
+
Sign in with GitHub
|
|
17
|
+
</Button>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default GithubProviders;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { authClient } from "@/lib/auth-client";
|
|
4
|
+
import { Button } from "../ui/button";
|
|
5
|
+
import { FaGoogle } from "react-icons/fa";
|
|
6
|
+
|
|
7
|
+
const GoogleProviders = () => {
|
|
8
|
+
const signIn = async () => {
|
|
9
|
+
const data = await authClient.signIn.social({
|
|
10
|
+
provider: "google",
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
return (
|
|
14
|
+
<Button className="w-full text-base" variant="outline" onClick={signIn}>
|
|
15
|
+
<FaGoogle />
|
|
16
|
+
Sign in with Google
|
|
17
|
+
</Button>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default GoogleProviders;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Controller, useForm } from "react-hook-form";
|
|
4
|
+
import { toast } from "sonner";
|
|
5
|
+
import * as z from "zod";
|
|
6
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
7
|
+
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
9
|
+
import {
|
|
10
|
+
Card,
|
|
11
|
+
CardContent,
|
|
12
|
+
CardDescription,
|
|
13
|
+
CardFooter,
|
|
14
|
+
CardHeader,
|
|
15
|
+
CardTitle,
|
|
16
|
+
} from "@/components/ui/card";
|
|
17
|
+
import {
|
|
18
|
+
Field,
|
|
19
|
+
FieldError,
|
|
20
|
+
FieldGroup,
|
|
21
|
+
FieldLabel,
|
|
22
|
+
} from "@/components/ui/field";
|
|
23
|
+
import { Input } from "@/components/ui/input";
|
|
24
|
+
import Link from "next/link";
|
|
25
|
+
import { useState } from "react";
|
|
26
|
+
import { signIn } from "@/server/user";
|
|
27
|
+
import { useRouter } from "next/navigation";
|
|
28
|
+
|
|
29
|
+
const formSchema = z.object({
|
|
30
|
+
email: z.string().email(),
|
|
31
|
+
password: z.string().min(8, {
|
|
32
|
+
message: "Password must be at least 8 characters",
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const LoginComponent = () => {
|
|
37
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
38
|
+
const router = useRouter();
|
|
39
|
+
|
|
40
|
+
const form = useForm<z.infer<typeof formSchema>>({
|
|
41
|
+
resolver: zodResolver(formSchema),
|
|
42
|
+
defaultValues: {
|
|
43
|
+
email: "",
|
|
44
|
+
password: "",
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
|
49
|
+
setIsLoading(true);
|
|
50
|
+
try {
|
|
51
|
+
const { success, message } = await signIn(data.email, data.password);
|
|
52
|
+
|
|
53
|
+
if (success === true) {
|
|
54
|
+
router.push("/");
|
|
55
|
+
toast.success(message);
|
|
56
|
+
} else {
|
|
57
|
+
toast.error(message);
|
|
58
|
+
}
|
|
59
|
+
setIsLoading(false);
|
|
60
|
+
} catch (error: any) {
|
|
61
|
+
toast.error(error.message);
|
|
62
|
+
setIsLoading(false);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<Card className="w-full sm:max-w-md shadow-md">
|
|
68
|
+
<CardHeader>
|
|
69
|
+
<CardTitle className="text-2xl leading-4">Welcome Back</CardTitle>
|
|
70
|
+
<CardDescription>Please sign in to your account.</CardDescription>
|
|
71
|
+
</CardHeader>
|
|
72
|
+
<CardContent>
|
|
73
|
+
<form id="form-login" onSubmit={form.handleSubmit(onSubmit)}>
|
|
74
|
+
<FieldGroup>
|
|
75
|
+
<Controller
|
|
76
|
+
name="email"
|
|
77
|
+
control={form.control}
|
|
78
|
+
render={({ field, fieldState }) => (
|
|
79
|
+
<Field data-invalid={fieldState.invalid}>
|
|
80
|
+
<FieldLabel htmlFor="form-login-email">Email</FieldLabel>
|
|
81
|
+
<Input
|
|
82
|
+
{...field}
|
|
83
|
+
id="form-login-email"
|
|
84
|
+
aria-invalid={fieldState.invalid}
|
|
85
|
+
placeholder="example@domain.com"
|
|
86
|
+
autoComplete="off"
|
|
87
|
+
disabled={isLoading}
|
|
88
|
+
/>
|
|
89
|
+
{fieldState.invalid && (
|
|
90
|
+
<FieldError errors={[fieldState.error]} />
|
|
91
|
+
)}
|
|
92
|
+
</Field>
|
|
93
|
+
)}
|
|
94
|
+
/>
|
|
95
|
+
<Controller
|
|
96
|
+
name="password"
|
|
97
|
+
control={form.control}
|
|
98
|
+
render={({ field, fieldState }) => (
|
|
99
|
+
<Field data-invalid={fieldState.invalid}>
|
|
100
|
+
<FieldLabel htmlFor="form-login-password">
|
|
101
|
+
Password
|
|
102
|
+
</FieldLabel>
|
|
103
|
+
<Input
|
|
104
|
+
{...field}
|
|
105
|
+
id="form-login-password"
|
|
106
|
+
aria-invalid={fieldState.invalid}
|
|
107
|
+
placeholder="********"
|
|
108
|
+
autoComplete="off"
|
|
109
|
+
type="password"
|
|
110
|
+
disabled={isLoading}
|
|
111
|
+
/>
|
|
112
|
+
{fieldState.invalid && (
|
|
113
|
+
<FieldError errors={[fieldState.error]} />
|
|
114
|
+
)}
|
|
115
|
+
</Field>
|
|
116
|
+
)}
|
|
117
|
+
/>
|
|
118
|
+
</FieldGroup>
|
|
119
|
+
</form>
|
|
120
|
+
</CardContent>
|
|
121
|
+
<CardFooter>
|
|
122
|
+
<div className="w-full">
|
|
123
|
+
<Field orientation="horizontal">
|
|
124
|
+
<Button
|
|
125
|
+
type="submit"
|
|
126
|
+
form="form-login"
|
|
127
|
+
className="w-full"
|
|
128
|
+
disabled={isLoading}
|
|
129
|
+
>
|
|
130
|
+
{isLoading ? "Logining..." : "Login"}
|
|
131
|
+
</Button>
|
|
132
|
+
</Field>
|
|
133
|
+
<div className="w-full text-center pt-4 space-x-2">
|
|
134
|
+
<span>Don't have an account?</span>
|
|
135
|
+
<Link href="/auth/signup" className="underline">
|
|
136
|
+
Sing up
|
|
137
|
+
</Link>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</CardFooter>
|
|
141
|
+
</Card>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default LoginComponent;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Button } from "@/components/ui/button";
|
|
3
|
+
import { authClient } from "@/lib/auth-client";
|
|
4
|
+
import { LogOutIcon } from "lucide-react";
|
|
5
|
+
import { useRouter } from "next/navigation";
|
|
6
|
+
|
|
7
|
+
const Logout = () => {
|
|
8
|
+
const router = useRouter();
|
|
9
|
+
const handleLogout = async () => {
|
|
10
|
+
await authClient.signOut();
|
|
11
|
+
router.push("/auth/login");
|
|
12
|
+
};
|
|
13
|
+
return (
|
|
14
|
+
<Button variant="outline" onClick={handleLogout}>
|
|
15
|
+
<LogOutIcon className="mr-1 h-4 w-4" />
|
|
16
|
+
Logout
|
|
17
|
+
</Button>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default Logout;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
4
|
+
import { Controller, useForm } from "react-hook-form";
|
|
5
|
+
import { toast } from "sonner";
|
|
6
|
+
import * as z from "zod";
|
|
7
|
+
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
9
|
+
import {
|
|
10
|
+
Card,
|
|
11
|
+
CardContent,
|
|
12
|
+
CardDescription,
|
|
13
|
+
CardFooter,
|
|
14
|
+
CardHeader,
|
|
15
|
+
CardTitle,
|
|
16
|
+
} from "@/components/ui/card";
|
|
17
|
+
import {
|
|
18
|
+
Field,
|
|
19
|
+
FieldError,
|
|
20
|
+
FieldGroup,
|
|
21
|
+
FieldLabel,
|
|
22
|
+
} from "@/components/ui/field";
|
|
23
|
+
import { Input } from "@/components/ui/input";
|
|
24
|
+
import { authClient } from "@/lib/auth-client";
|
|
25
|
+
import { useRouter, useSearchParams } from "next/navigation";
|
|
26
|
+
import { useState } from "react";
|
|
27
|
+
|
|
28
|
+
const formSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
password: z.string().min(8, {
|
|
31
|
+
message: "Password must be at least 8 characters",
|
|
32
|
+
}),
|
|
33
|
+
confirmPassword: z.string(),
|
|
34
|
+
})
|
|
35
|
+
.refine((data) => data.password === data.confirmPassword, {
|
|
36
|
+
message: "Passwords do not match",
|
|
37
|
+
path: ["confirmPassword"],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const ResetComponent = () => {
|
|
41
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
42
|
+
const router = useRouter();
|
|
43
|
+
const searchParams = useSearchParams();
|
|
44
|
+
const token = searchParams.get("token") as string;
|
|
45
|
+
|
|
46
|
+
const form = useForm<z.infer<typeof formSchema>>({
|
|
47
|
+
resolver: zodResolver(formSchema),
|
|
48
|
+
defaultValues: {
|
|
49
|
+
password: "",
|
|
50
|
+
confirmPassword: "",
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const onSubmit = async (value: z.infer<typeof formSchema>) => {
|
|
55
|
+
setIsLoading(true);
|
|
56
|
+
try {
|
|
57
|
+
const { data, error } = await authClient.resetPassword({
|
|
58
|
+
newPassword: value.password,
|
|
59
|
+
token,
|
|
60
|
+
});
|
|
61
|
+
if (error) {
|
|
62
|
+
toast.error(error.message);
|
|
63
|
+
}
|
|
64
|
+
if (data) {
|
|
65
|
+
toast.success("Password has been reset successfully.");
|
|
66
|
+
router.push("/auth/login");
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
toast.error("Something went wrong. Please try again.");
|
|
70
|
+
setIsLoading(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<Card className="w-full sm:max-w-md shadow-md">
|
|
76
|
+
<CardHeader>
|
|
77
|
+
<CardTitle className="text-2xl leading-4">Reset Password</CardTitle>
|
|
78
|
+
<CardDescription>Please enter your new password</CardDescription>
|
|
79
|
+
</CardHeader>
|
|
80
|
+
<CardContent>
|
|
81
|
+
<form id="form-login" onSubmit={form.handleSubmit(onSubmit)}>
|
|
82
|
+
<FieldGroup>
|
|
83
|
+
<Controller
|
|
84
|
+
name="password"
|
|
85
|
+
control={form.control}
|
|
86
|
+
render={({ field, fieldState }) => (
|
|
87
|
+
<Field data-invalid={fieldState.invalid}>
|
|
88
|
+
<FieldLabel htmlFor="form-login-password">
|
|
89
|
+
Password
|
|
90
|
+
</FieldLabel>
|
|
91
|
+
<Input
|
|
92
|
+
{...field}
|
|
93
|
+
id="form-login-password"
|
|
94
|
+
aria-invalid={fieldState.invalid}
|
|
95
|
+
placeholder="********"
|
|
96
|
+
type="password"
|
|
97
|
+
autoComplete="off"
|
|
98
|
+
disabled={isLoading}
|
|
99
|
+
/>
|
|
100
|
+
{fieldState.invalid && (
|
|
101
|
+
<FieldError errors={[fieldState.error]} />
|
|
102
|
+
)}
|
|
103
|
+
</Field>
|
|
104
|
+
)}
|
|
105
|
+
/>
|
|
106
|
+
<Controller
|
|
107
|
+
name="confirmPassword"
|
|
108
|
+
control={form.control}
|
|
109
|
+
render={({ field, fieldState }) => (
|
|
110
|
+
<Field data-invalid={fieldState.invalid}>
|
|
111
|
+
<FieldLabel htmlFor="form-login-confirm-password">
|
|
112
|
+
Password
|
|
113
|
+
</FieldLabel>
|
|
114
|
+
<Input
|
|
115
|
+
{...field}
|
|
116
|
+
id="form-login-confirm-password"
|
|
117
|
+
aria-invalid={fieldState.invalid}
|
|
118
|
+
placeholder="********"
|
|
119
|
+
type="password"
|
|
120
|
+
autoComplete="off"
|
|
121
|
+
disabled={isLoading}
|
|
122
|
+
/>
|
|
123
|
+
{fieldState.invalid && (
|
|
124
|
+
<FieldError errors={[fieldState.error]} />
|
|
125
|
+
)}
|
|
126
|
+
</Field>
|
|
127
|
+
)}
|
|
128
|
+
/>
|
|
129
|
+
</FieldGroup>
|
|
130
|
+
</form>
|
|
131
|
+
</CardContent>
|
|
132
|
+
<CardFooter>
|
|
133
|
+
<div className="w-full">
|
|
134
|
+
<Field orientation="horizontal">
|
|
135
|
+
<Button
|
|
136
|
+
type="submit"
|
|
137
|
+
form="form-login"
|
|
138
|
+
className="w-full"
|
|
139
|
+
disabled={isLoading}
|
|
140
|
+
>
|
|
141
|
+
{isLoading ? "Resetting..." : "Reset Password"}
|
|
142
|
+
</Button>
|
|
143
|
+
</Field>
|
|
144
|
+
</div>
|
|
145
|
+
</CardFooter>
|
|
146
|
+
</Card>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export default ResetComponent;
|