@proofkit/cli 1.1.8 → 1.2.0-beta.0
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/dist/external-DCpQkgKf.js +1 -0
- package/dist/index.js +102 -124
- package/package.json +15 -10
- package/template/extras/config/query-provider-vite.tsx +0 -2
- package/template/extras/emailProviders/none/email.tsx +4 -4
- package/template/extras/emailProviders/plunk/email.tsx +5 -4
- package/template/extras/emailProviders/plunk/service.ts +1 -1
- package/template/extras/emailProviders/resend/email.tsx +1 -0
- package/template/extras/emailProviders/resend/service.ts +1 -1
- package/template/extras/emailTemplates/auth-code.tsx +156 -0
- package/template/extras/emailTemplates/generic.tsx +136 -0
- package/template/extras/fmaddon-auth/app/(main)/auth/profile/actions.ts +13 -9
- package/template/extras/fmaddon-auth/app/(main)/auth/profile/page.tsx +2 -0
- package/template/extras/fmaddon-auth/app/(main)/auth/profile/profile-form.tsx +7 -5
- package/template/extras/fmaddon-auth/app/(main)/auth/profile/reset-password-form.tsx +8 -6
- package/template/extras/fmaddon-auth/app/auth/forgot-password/actions.ts +7 -5
- package/template/extras/fmaddon-auth/app/auth/forgot-password/forgot-form.tsx +3 -2
- package/template/extras/fmaddon-auth/app/auth/forgot-password/page.tsx +1 -0
- package/template/extras/fmaddon-auth/app/auth/login/actions.ts +5 -4
- package/template/extras/fmaddon-auth/app/auth/login/login-form.tsx +7 -5
- package/template/extras/fmaddon-auth/app/auth/login/page.tsx +1 -0
- package/template/extras/fmaddon-auth/app/auth/reset-password/actions.ts +11 -8
- package/template/extras/fmaddon-auth/app/auth/reset-password/page.tsx +3 -2
- package/template/extras/fmaddon-auth/app/auth/reset-password/reset-password-form.tsx +5 -4
- package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/actions.ts +3 -2
- package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/page.tsx +3 -2
- package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/verify-email-form.tsx +3 -2
- package/template/extras/fmaddon-auth/app/auth/signup/actions.ts +10 -9
- package/template/extras/fmaddon-auth/app/auth/signup/page.tsx +1 -0
- package/template/extras/fmaddon-auth/app/auth/signup/signup-form.tsx +7 -6
- package/template/extras/fmaddon-auth/app/auth/verify-email/actions.ts +7 -8
- package/template/extras/fmaddon-auth/app/auth/verify-email/email-verification-form.tsx +5 -4
- package/template/extras/fmaddon-auth/app/auth/verify-email/page.tsx +5 -3
- package/template/extras/fmaddon-auth/app/auth/verify-email/resend-button.tsx +4 -2
- package/template/extras/fmaddon-auth/components/auth/actions.ts +4 -1
- package/template/extras/fmaddon-auth/components/auth/protect.tsx +2 -1
- package/template/extras/fmaddon-auth/components/auth/redirect.tsx +2 -2
- package/template/extras/fmaddon-auth/components/auth/use-user.ts +3 -2
- package/template/extras/fmaddon-auth/components/auth/user-menu.tsx +3 -2
- package/template/extras/fmaddon-auth/middleware.ts +0 -1
- package/template/extras/fmaddon-auth/server/auth/utils/email-verification.ts +8 -7
- package/template/extras/fmaddon-auth/server/auth/utils/encryption.ts +2 -2
- package/template/extras/fmaddon-auth/server/auth/utils/password-reset.ts +5 -4
- package/template/extras/fmaddon-auth/server/auth/utils/redirect.ts +1 -1
- package/template/extras/fmaddon-auth/server/auth/utils/session.ts +6 -7
- package/template/extras/fmaddon-auth/server/auth/utils/user.ts +1 -2
- package/template/extras/src/app/next-auth/signin/page.tsx +2 -1
- package/template/fm-addon/ProofKitAuth/info.json +6 -9
- package/template/fm-addon/ProofKitAuth/info_de.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_es.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_fr.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_it.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_ja.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_ko.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_nl.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_pt.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_sv.json +5 -12
- package/template/fm-addon/ProofKitAuth/info_zh.json +5 -12
- package/template/fm-addon/ProofKitWV/info.json +6 -9
- package/template/fm-addon/ProofKitWV/info_de.json +5 -12
- package/template/fm-addon/ProofKitWV/info_en.json +1 -5
- package/template/fm-addon/ProofKitWV/info_es.json +5 -12
- package/template/fm-addon/ProofKitWV/info_fr.json +5 -12
- package/template/fm-addon/ProofKitWV/info_it.json +5 -12
- package/template/fm-addon/ProofKitWV/info_ja.json +5 -12
- package/template/fm-addon/ProofKitWV/info_ko.json +5 -12
- package/template/fm-addon/ProofKitWV/info_nl.json +5 -12
- package/template/fm-addon/ProofKitWV/info_pt.json +5 -12
- package/template/fm-addon/ProofKitWV/info_sv.json +5 -12
- package/template/fm-addon/ProofKitWV/info_zh.json +5 -12
- package/template/{nextjs → nextjs-mantine}/proofkit.json +2 -1
- package/template/{nextjs → nextjs-mantine}/src/components/AppShell/internal/HeaderNavLink.tsx +5 -1
- package/template/{nextjs → nextjs-mantine}/src/utils/notification-helpers.ts +1 -1
- package/template/nextjs-mantine/tsconfig.json +27 -0
- package/template/nextjs-shadcn/.claude/CLAUDE.md +327 -0
- package/template/nextjs-shadcn/.cursor/rules/ultracite.mdc +333 -0
- package/template/nextjs-shadcn/.prettierrc +3 -0
- package/template/nextjs-shadcn/.vscode/settings.json +35 -0
- package/template/nextjs-shadcn/README.md +27 -0
- package/template/nextjs-shadcn/_gitignore +37 -0
- package/template/nextjs-shadcn/biome.json +43 -0
- package/template/nextjs-shadcn/components.json +21 -0
- package/template/nextjs-shadcn/next.config.ts +8 -0
- package/template/nextjs-shadcn/package.json +35 -0
- package/template/nextjs-shadcn/postcss.config.mjs +5 -0
- package/template/nextjs-shadcn/proofkit.json +6 -0
- package/template/nextjs-shadcn/public/favicon.ico +0 -0
- package/template/nextjs-shadcn/public/proofkit.png +0 -0
- package/template/nextjs-shadcn/src/app/(main)/layout.tsx +6 -0
- package/template/nextjs-shadcn/src/app/(main)/page.tsx +124 -0
- package/template/nextjs-shadcn/src/app/globals.css +122 -0
- package/template/nextjs-shadcn/src/app/layout.tsx +35 -0
- package/template/nextjs-shadcn/src/app/navigation.tsx +12 -0
- package/template/nextjs-shadcn/src/components/AppLogo.tsx +6 -0
- package/template/nextjs-shadcn/src/components/AppShell/internal/AppShell.tsx +23 -0
- package/template/nextjs-shadcn/src/components/AppShell/internal/Header.module.css +33 -0
- package/template/nextjs-shadcn/src/components/AppShell/internal/Header.tsx +30 -0
- package/template/nextjs-shadcn/src/components/AppShell/internal/HeaderMobileMenu.tsx +25 -0
- package/template/nextjs-shadcn/src/components/AppShell/internal/HeaderNavLink.tsx +35 -0
- package/template/nextjs-shadcn/src/components/AppShell/internal/config.ts +1 -0
- package/template/nextjs-shadcn/src/components/AppShell/slot-header-center.tsx +13 -0
- package/template/nextjs-shadcn/src/components/AppShell/slot-header-left.tsx +23 -0
- package/template/nextjs-shadcn/src/components/AppShell/slot-header-mobile-content.tsx +43 -0
- package/template/nextjs-shadcn/src/components/AppShell/slot-header-right.tsx +25 -0
- package/template/nextjs-shadcn/src/components/providers.tsx +13 -0
- package/template/nextjs-shadcn/src/components/theme-provider.tsx +11 -0
- package/template/nextjs-shadcn/src/lib/env.ts +12 -0
- package/template/nextjs-shadcn/src/lib/utils.ts +6 -0
- package/template/{nextjs → nextjs-shadcn}/tsconfig.json +3 -2
- package/template/pages/nextjs/table-edit/page.tsx +5 -5
- package/template/pages/nextjs/table-edit/table.tsx +5 -3
- package/template/pages/nextjs/table-infinite/query.ts +4 -3
- package/template/pages/nextjs/table-infinite/table.tsx +3 -2
- package/template/pages/nextjs/table-infinite-edit/page.tsx +6 -6
- package/template/pages/nextjs/table-infinite-edit/query.ts +8 -2
- package/template/pages/vite-wv/table/index.tsx +5 -4
- package/template/pages/vite-wv/table-edit/index.tsx +6 -6
- package/template/vite-wv/src/main.tsx +1 -1
- package/template/vite-wv/src/routeTree.gen.ts +41 -41
- /package/template/{nextjs → nextjs-mantine}/.prettierrc +0 -0
- /package/template/{nextjs → nextjs-mantine}/README.md +0 -0
- /package/template/{nextjs → nextjs-mantine}/_gitignore +0 -0
- /package/template/{nextjs → nextjs-mantine}/components.json +0 -0
- /package/template/{nextjs → nextjs-mantine}/next.config.ts +0 -0
- /package/template/{nextjs → nextjs-mantine}/package.json +0 -0
- /package/template/{nextjs → nextjs-mantine}/postcss.config.cjs +0 -0
- /package/template/{nextjs → nextjs-mantine}/public/favicon.ico +0 -0
- /package/template/{nextjs → nextjs-mantine}/public/proofkit.png +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/app/(main)/layout.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/app/(main)/page.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/app/layout.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/app/navigation.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppLogo.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/internal/AppShell.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/internal/Header.module.css +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/internal/Header.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/internal/HeaderMobileMenu.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/internal/config.ts +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/slot-header-center.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/slot-header-left.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/slot-header-mobile-content.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/components/AppShell/slot-header-right.tsx +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/config/env.ts +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/config/theme/globals.css +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/config/theme/mantine-theme.ts +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/server/safe-action.ts +0 -0
- /package/template/{nextjs → nextjs-mantine}/src/utils/styles.ts +0 -0
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { resetPasswordSchema } from "./schema";
|
|
3
|
+
import { verifyPasswordStrength } from "@/server/auth/utils/password";
|
|
5
4
|
import {
|
|
6
5
|
deletePasswordResetSessionTokenCookie,
|
|
7
6
|
invalidateUserPasswordResetSessions,
|
|
7
|
+
validatePasswordResetSessionRequest,
|
|
8
8
|
} from "@/server/auth/utils/password-reset";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
import {
|
|
10
|
+
createSession,
|
|
11
|
+
generateSessionToken,
|
|
12
|
+
invalidateUserSessions,
|
|
13
|
+
setSessionTokenCookie,
|
|
14
|
+
} from "@/server/auth/utils/session";
|
|
15
15
|
import { updateUserPassword } from "@/server/auth/utils/user";
|
|
16
|
+
import { actionClient } from "@/server/safe-action";
|
|
16
17
|
import { redirect } from "next/navigation";
|
|
17
18
|
|
|
19
|
+
import { resetPasswordSchema } from "./schema";
|
|
20
|
+
|
|
18
21
|
export const resetPasswordAction = actionClient
|
|
19
22
|
.schema(resetPasswordSchema)
|
|
20
23
|
.action(async ({ parsedInput }) => {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Alert, Anchor, Container, Text, Title } from "@mantine/core";
|
|
2
|
-
import ResetPasswordForm from "./reset-password-form";
|
|
3
1
|
import { env } from "@/config/env";
|
|
4
2
|
import { validatePasswordResetSessionRequest } from "@/server/auth/utils/password-reset";
|
|
3
|
+
import { Alert, Anchor, Container, Text, Title } from "@mantine/core";
|
|
5
4
|
import { redirect } from "next/navigation";
|
|
6
5
|
|
|
6
|
+
import ResetPasswordForm from "./reset-password-form";
|
|
7
|
+
|
|
7
8
|
export default async function Page() {
|
|
8
9
|
const { session, user } = await validatePasswordResetSessionRequest();
|
|
9
10
|
if (session === null) {
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useHookFormAction } from "@next-safe-action/adapter-react-hook-form/hooks";
|
|
4
3
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
5
4
|
import {
|
|
6
|
-
TextInput,
|
|
7
5
|
Button,
|
|
8
|
-
Stack,
|
|
9
6
|
Paper,
|
|
10
|
-
Text,
|
|
11
7
|
PasswordInput,
|
|
8
|
+
Stack,
|
|
9
|
+
Text,
|
|
10
|
+
TextInput,
|
|
12
11
|
} from "@mantine/core";
|
|
12
|
+
import { useHookFormAction } from "@next-safe-action/adapter-react-hook-form/hooks";
|
|
13
|
+
|
|
13
14
|
import { resetPasswordAction } from "./actions";
|
|
14
15
|
import { resetPasswordSchema } from "./schema";
|
|
15
16
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
-
import { actionClient } from "@/server/safe-action";
|
|
4
|
-
import { verifyEmailSchema } from "./schema";
|
|
5
3
|
import {
|
|
6
4
|
setPasswordResetSessionAsEmailVerified,
|
|
7
5
|
validatePasswordResetSessionRequest,
|
|
8
6
|
} from "@/server/auth/utils/password-reset";
|
|
9
7
|
import { setUserAsEmailVerifiedIfEmailMatches } from "@/server/auth/utils/user";
|
|
8
|
+
import { actionClient } from "@/server/safe-action";
|
|
10
9
|
import { redirect } from "next/navigation";
|
|
11
10
|
|
|
11
|
+
import { verifyEmailSchema } from "./schema";
|
|
12
|
+
|
|
12
13
|
export const verifyEmailAction = actionClient
|
|
13
14
|
.schema(verifyEmailSchema)
|
|
14
15
|
.action(async ({ parsedInput }) => {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Alert, Anchor, Container, Text, Title } from "@mantine/core";
|
|
2
|
-
import VerifyEmailForm from "./verify-email-form";
|
|
3
1
|
import { env } from "@/config/env";
|
|
4
2
|
import { validatePasswordResetSessionRequest } from "@/server/auth/utils/password-reset";
|
|
3
|
+
import { Alert, Anchor, Container, Text, Title } from "@mantine/core";
|
|
5
4
|
import { redirect } from "next/navigation";
|
|
6
5
|
|
|
6
|
+
import VerifyEmailForm from "./verify-email-form";
|
|
7
|
+
|
|
7
8
|
export default async function Page() {
|
|
8
9
|
const { session } = await validatePasswordResetSessionRequest();
|
|
9
10
|
if (session === null) {
|
package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/verify-email-form.tsx
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useHookFormAction } from "@next-safe-action/adapter-react-hook-form/hooks";
|
|
4
3
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
5
|
-
import { Button,
|
|
4
|
+
import { Button, Paper, PinInput, Stack, Text } from "@mantine/core";
|
|
5
|
+
import { useHookFormAction } from "@next-safe-action/adapter-react-hook-form/hooks";
|
|
6
|
+
|
|
6
7
|
import { verifyEmailAction } from "./actions";
|
|
7
8
|
import { verifyEmailSchema } from "./schema";
|
|
8
9
|
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
createEmailVerificationRequest,
|
|
5
|
+
sendVerificationEmail,
|
|
6
|
+
setEmailVerificationRequestCookie,
|
|
7
|
+
} from "@/server/auth/utils/email-verification";
|
|
6
8
|
import { verifyPasswordStrength } from "@/server/auth/utils/password";
|
|
7
9
|
import {
|
|
8
10
|
createSession,
|
|
11
|
+
generateSessionToken,
|
|
9
12
|
setSessionTokenCookie,
|
|
10
13
|
} from "@/server/auth/utils/session";
|
|
11
|
-
import {
|
|
14
|
+
import { checkEmailAvailability, createUser } from "@/server/auth/utils/user";
|
|
15
|
+
import { actionClient } from "@/server/safe-action";
|
|
12
16
|
import { redirect } from "next/navigation";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
sendVerificationEmail,
|
|
16
|
-
setEmailVerificationRequestCookie,
|
|
17
|
-
} from "@/server/auth/utils/email-verification";
|
|
17
|
+
|
|
18
|
+
import { signupSchema } from "./schema";
|
|
18
19
|
|
|
19
20
|
export const signupAction = actionClient
|
|
20
21
|
.schema(signupSchema)
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useHookFormAction } from "@next-safe-action/adapter-react-hook-form/hooks";
|
|
4
|
-
import { signupAction } from "./actions";
|
|
5
3
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
6
|
-
import { signupSchema } from "./schema";
|
|
7
4
|
import {
|
|
8
5
|
Anchor,
|
|
9
|
-
PasswordInput,
|
|
10
|
-
TextInput,
|
|
11
6
|
Button,
|
|
12
7
|
Group,
|
|
13
|
-
Stack,
|
|
14
8
|
Paper,
|
|
9
|
+
PasswordInput,
|
|
10
|
+
Stack,
|
|
15
11
|
Text,
|
|
12
|
+
TextInput,
|
|
16
13
|
} from "@mantine/core";
|
|
14
|
+
import { useHookFormAction } from "@next-safe-action/adapter-react-hook-form/hooks";
|
|
15
|
+
|
|
16
|
+
import { signupAction } from "./actions";
|
|
17
|
+
import { signupSchema } from "./schema";
|
|
17
18
|
|
|
18
19
|
export default function SignupForm() {
|
|
19
20
|
const { form, handleSubmitWithAction, action } = useHookFormAction(
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
-
import { getCurrentSession } from "@/server/auth/utils/session";
|
|
4
|
-
import { actionClient } from "@/server/safe-action";
|
|
5
|
-
import { emailVerificationSchema } from "./schema";
|
|
6
3
|
import {
|
|
4
|
+
createEmailVerificationRequest,
|
|
7
5
|
deleteEmailVerificationRequestCookie,
|
|
8
6
|
deleteUserEmailVerificationRequest,
|
|
7
|
+
getUserEmailVerificationRequestFromRequest,
|
|
9
8
|
sendVerificationEmail,
|
|
10
9
|
setEmailVerificationRequestCookie,
|
|
11
10
|
} from "@/server/auth/utils/email-verification";
|
|
12
|
-
import {
|
|
13
|
-
createEmailVerificationRequest,
|
|
14
|
-
getUserEmailVerificationRequestFromRequest,
|
|
15
|
-
} from "@/server/auth/utils/email-verification";
|
|
16
11
|
import { invalidateUserPasswordResetSessions } from "@/server/auth/utils/password-reset";
|
|
12
|
+
import { getRedirectCookie } from "@/server/auth/utils/redirect";
|
|
13
|
+
import { getCurrentSession } from "@/server/auth/utils/session";
|
|
17
14
|
import { updateUserEmailAndSetEmailAsVerified } from "@/server/auth/utils/user";
|
|
15
|
+
import { actionClient } from "@/server/safe-action";
|
|
18
16
|
import { redirect } from "next/navigation";
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
import { emailVerificationSchema } from "./schema";
|
|
20
19
|
|
|
21
20
|
export const verifyEmailAction = actionClient
|
|
22
21
|
.schema(emailVerificationSchema)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
|
|
3
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
4
|
+
import { Button, Paper, PinInput, Stack, Text } from "@mantine/core";
|
|
2
5
|
import { useHookFormAction } from "@next-safe-action/adapter-react-hook-form/hooks";
|
|
3
|
-
|
|
6
|
+
|
|
4
7
|
import { verifyEmailAction } from "./actions";
|
|
5
|
-
import {
|
|
6
|
-
import { Button, Paper, PinInput, Text } from "@mantine/core";
|
|
7
|
-
import { Stack } from "@mantine/core";
|
|
8
|
+
import { emailVerificationSchema } from "./schema";
|
|
8
9
|
|
|
9
10
|
export default function LoginForm() {
|
|
10
11
|
const { form, handleSubmitWithAction, action } = useHookFormAction(
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { getUserEmailVerificationRequestFromRequest } from "@/server/auth/utils/email-verification";
|
|
2
|
+
import { getRedirectCookie } from "@/server/auth/utils/redirect";
|
|
1
3
|
import { getCurrentSession } from "@/server/auth/utils/session";
|
|
2
4
|
import { Anchor, Container, Text, Title } from "@mantine/core";
|
|
3
5
|
import { redirect } from "next/navigation";
|
|
6
|
+
|
|
4
7
|
import EmailVerificationForm from "./email-verification-form";
|
|
5
8
|
import ResendButton from "./resend-button";
|
|
6
|
-
import { getUserEmailVerificationRequestFromRequest } from "@/server/auth/utils/email-verification";
|
|
7
|
-
import { getRedirectCookie } from "@/server/auth/utils/redirect";
|
|
8
9
|
|
|
9
10
|
export default async function Page() {
|
|
10
11
|
const { user } = await getCurrentSession();
|
|
@@ -15,7 +16,8 @@ export default async function Page() {
|
|
|
15
16
|
|
|
16
17
|
// TODO: Ideally we'd sent a new verification email automatically if the previous one is expired,
|
|
17
18
|
// but we can't set cookies inside server components.
|
|
18
|
-
const verificationRequest =
|
|
19
|
+
const verificationRequest =
|
|
20
|
+
await getUserEmailVerificationRequestFromRequest();
|
|
19
21
|
if (verificationRequest === null && user.emailVerified) {
|
|
20
22
|
const redirectTo = await getRedirectCookie();
|
|
21
23
|
return redirect(redirectTo);
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
|
|
2
3
|
import { Alert, Anchor, Button, Group, Stack, Text } from "@mantine/core";
|
|
3
|
-
import { resendEmailVerificationAction } from "./actions";
|
|
4
4
|
import { useAction } from "next-safe-action/hooks";
|
|
5
5
|
|
|
6
|
+
import { resendEmailVerificationAction } from "./actions";
|
|
7
|
+
|
|
6
8
|
export default function ResendButton() {
|
|
7
9
|
const action = useAction(resendEmailVerificationAction);
|
|
8
10
|
return (
|
|
9
11
|
<Stack>
|
|
10
12
|
<Group gap={4} justify="center" mt={5}>
|
|
11
13
|
<Text c="dimmed" size="sm">
|
|
12
|
-
|
|
14
|
+
{"Didn't receive the email?"}
|
|
13
15
|
</Text>
|
|
14
16
|
<Button
|
|
15
17
|
size="compact-sm"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getCurrentSession,
|
|
5
|
+
invalidateSession,
|
|
6
|
+
} from "@/server/auth/utils/session";
|
|
4
7
|
import { redirect } from "next/navigation";
|
|
5
8
|
|
|
6
9
|
export async function currentSessionAction() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getCurrentSession } from "@/server/auth/utils/session";
|
|
2
|
+
|
|
2
3
|
import AuthRedirect from "./redirect";
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -14,4 +15,4 @@ export default async function Protect({
|
|
|
14
15
|
if (!session) return <AuthRedirect path="/auth/login" />;
|
|
15
16
|
if (!user.emailVerified) return <AuthRedirect path="/auth/verify-email" />;
|
|
16
17
|
return <>{children}</>;
|
|
17
|
-
}
|
|
18
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { redirect } from "next/navigation";
|
|
4
3
|
import { Center, Loader } from "@mantine/core";
|
|
5
|
-
import { useEffect } from "react";
|
|
6
4
|
import Cookies from "js-cookie";
|
|
5
|
+
import { redirect } from "next/navigation";
|
|
6
|
+
import { useEffect } from "react";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A client-side component that redirects to the given path, but saves the current path in the redirectTo cookie.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
2
|
-
import { currentSessionAction, logoutAction } from "./actions";
|
|
3
1
|
import { Session } from "@/server/auth/utils/session";
|
|
4
2
|
import { User } from "@/server/auth/utils/user";
|
|
3
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
|
+
|
|
5
|
+
import { currentSessionAction, logoutAction } from "./actions";
|
|
5
6
|
|
|
6
7
|
type LogoutAction = () => Promise<void>;
|
|
7
8
|
type UseUserResult =
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { Button, Menu, px, Skeleton } from "@mantine/core";
|
|
4
|
-
import { useUser } from "./use-user";
|
|
5
|
-
import Link from "next/link";
|
|
6
4
|
import { IconChevronDown, IconLogout, IconUser } from "@tabler/icons-react";
|
|
5
|
+
import Link from "next/link";
|
|
6
|
+
|
|
7
|
+
import { useUser } from "./use-user";
|
|
7
8
|
|
|
8
9
|
export default function UserMenu() {
|
|
9
10
|
const { state, session, user, logout } = useUser();
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { generateRandomOTP } from "./index";
|
|
2
1
|
import { encodeBase32 } from "@oslojs/encoding";
|
|
3
2
|
import { cookies } from "next/headers";
|
|
4
|
-
|
|
3
|
+
|
|
5
4
|
import { emailVerificationLayout } from "../db/client";
|
|
6
5
|
import { TemailVerification } from "../db/emailVerification";
|
|
7
6
|
import { sendEmail } from "../email";
|
|
7
|
+
import { generateRandomOTP } from "./index";
|
|
8
|
+
import { getCurrentSession } from "./session";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* An Email Verification Request is a record in the email verification table that is created when a user requests to change their email address. It's like a temporary session which can expire if the user doesn't verify the new email address within a certain amount of time.
|
|
@@ -18,7 +19,7 @@ import { sendEmail } from "../email";
|
|
|
18
19
|
*/
|
|
19
20
|
export async function getUserEmailVerificationRequest(
|
|
20
21
|
userId: string,
|
|
21
|
-
id: string
|
|
22
|
+
id: string
|
|
22
23
|
): Promise<TemailVerification | null> {
|
|
23
24
|
const result = await emailVerificationLayout.maybeFindFirst({
|
|
24
25
|
query: { id_user: `==${userId}`, id: `==${id}` },
|
|
@@ -34,7 +35,7 @@ export async function getUserEmailVerificationRequest(
|
|
|
34
35
|
*/
|
|
35
36
|
export async function createEmailVerificationRequest(
|
|
36
37
|
id_user: string,
|
|
37
|
-
email: string
|
|
38
|
+
email: string
|
|
38
39
|
): Promise<TemailVerification> {
|
|
39
40
|
deleteUserEmailVerificationRequest(id_user);
|
|
40
41
|
const idBytes = new Uint8Array(20);
|
|
@@ -64,7 +65,7 @@ export async function createEmailVerificationRequest(
|
|
|
64
65
|
* @param id_user - The ID of the user.
|
|
65
66
|
*/
|
|
66
67
|
export async function deleteUserEmailVerificationRequest(
|
|
67
|
-
id_user: string
|
|
68
|
+
id_user: string
|
|
68
69
|
): Promise<void> {
|
|
69
70
|
const result = await emailVerificationLayout.maybeFindFirst({
|
|
70
71
|
query: { id_user: `==${id_user}` },
|
|
@@ -81,7 +82,7 @@ export async function deleteUserEmailVerificationRequest(
|
|
|
81
82
|
*/
|
|
82
83
|
export async function sendVerificationEmail(
|
|
83
84
|
email: string,
|
|
84
|
-
code: string
|
|
85
|
+
code: string
|
|
85
86
|
): Promise<void> {
|
|
86
87
|
await sendEmail({ to: email, code, type: "verification" });
|
|
87
88
|
}
|
|
@@ -91,7 +92,7 @@ export async function sendVerificationEmail(
|
|
|
91
92
|
* @param request - The email verification request.
|
|
92
93
|
*/
|
|
93
94
|
export async function setEmailVerificationRequestCookie(
|
|
94
|
-
request: TemailVerification
|
|
95
|
+
request: TemailVerification
|
|
95
96
|
): Promise<void> {
|
|
96
97
|
(await cookies()).set("email_verification", request.id, {
|
|
97
98
|
httpOnly: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { decodeBase64 } from "@oslojs/encoding";
|
|
2
1
|
import { createCipheriv, createDecipheriv } from "crypto";
|
|
3
2
|
import { DynamicBuffer } from "@oslojs/binary";
|
|
3
|
+
import { decodeBase64 } from "@oslojs/encoding";
|
|
4
4
|
|
|
5
5
|
const key = decodeBase64(process.env.ENCRYPTION_KEY ?? "");
|
|
6
6
|
|
|
@@ -40,7 +40,7 @@ export function decrypt(encrypted: Uint8Array): Uint8Array {
|
|
|
40
40
|
decipher.setAuthTag(encrypted.slice(encrypted.byteLength - 16));
|
|
41
41
|
const decrypted = new DynamicBuffer(0);
|
|
42
42
|
decrypted.write(
|
|
43
|
-
decipher.update(encrypted.slice(16, encrypted.byteLength - 16))
|
|
43
|
+
decipher.update(encrypted.slice(16, encrypted.byteLength - 16))
|
|
44
44
|
);
|
|
45
45
|
decrypted.write(decipher.final());
|
|
46
46
|
return decrypted.bytes();
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { encodeHexLowerCase } from "@oslojs/encoding";
|
|
2
|
-
import { generateRandomOTP } from "./index";
|
|
3
1
|
import { sha256 } from "@oslojs/crypto/sha2";
|
|
2
|
+
import { encodeHexLowerCase } from "@oslojs/encoding";
|
|
4
3
|
import { cookies } from "next/headers";
|
|
4
|
+
|
|
5
5
|
import { passwordResetLayout } from "../db/client";
|
|
6
6
|
import { TpasswordReset } from "../db/passwordReset";
|
|
7
|
-
|
|
8
|
-
import type { User } from "./user";
|
|
9
7
|
import { sendEmail } from "../email";
|
|
8
|
+
import { generateRandomOTP } from "./index";
|
|
9
|
+
import type { User } from "./user";
|
|
10
|
+
|
|
10
11
|
type PasswordResetSession = Omit<
|
|
11
12
|
TpasswordReset,
|
|
12
13
|
| "proofkit_auth_users::email"
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { sha256 } from "@oslojs/crypto/sha2";
|
|
1
2
|
import {
|
|
2
3
|
encodeBase32LowerCaseNoPadding,
|
|
3
4
|
encodeHexLowerCase,
|
|
4
5
|
} from "@oslojs/encoding";
|
|
5
|
-
import { sha256 } from "@oslojs/crypto/sha2";
|
|
6
6
|
import { cookies } from "next/headers";
|
|
7
7
|
import { cache } from "react";
|
|
8
|
-
import type { User } from "./user";
|
|
9
8
|
|
|
10
9
|
import { sessionsLayout } from "../db/client";
|
|
11
10
|
import { Tsessions as _Session } from "../db/sessions";
|
|
11
|
+
import type { User } from "./user";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Generate a random session token with sufficient entropy for a session ID.
|
|
@@ -29,7 +29,7 @@ export function generateSessionToken(): string {
|
|
|
29
29
|
*/
|
|
30
30
|
export async function createSession(
|
|
31
31
|
token: string,
|
|
32
|
-
userId: string
|
|
32
|
+
userId: string
|
|
33
33
|
): Promise<Session> {
|
|
34
34
|
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
|
|
35
35
|
const session: Session = {
|
|
@@ -70,7 +70,7 @@ export async function invalidateSession(sessionId: string): Promise<void> {
|
|
|
70
70
|
* @returns The session, or null if it doesn't exist.
|
|
71
71
|
*/
|
|
72
72
|
export async function validateSessionToken(
|
|
73
|
-
token: string
|
|
73
|
+
token: string
|
|
74
74
|
): Promise<SessionValidationResult> {
|
|
75
75
|
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
|
|
76
76
|
|
|
@@ -133,7 +133,7 @@ export const getCurrentSession = cache(
|
|
|
133
133
|
}
|
|
134
134
|
const result = await validateSessionToken(token);
|
|
135
135
|
return result;
|
|
136
|
-
}
|
|
136
|
+
}
|
|
137
137
|
);
|
|
138
138
|
|
|
139
139
|
/**
|
|
@@ -156,7 +156,7 @@ export async function invalidateUserSessions(userId: string): Promise<void> {
|
|
|
156
156
|
*/
|
|
157
157
|
export async function setSessionTokenCookie(
|
|
158
158
|
token: string,
|
|
159
|
-
expiresAt: Date
|
|
159
|
+
expiresAt: Date
|
|
160
160
|
): Promise<void> {
|
|
161
161
|
(await cookies()).set("session", token, {
|
|
162
162
|
httpOnly: true,
|
|
@@ -167,7 +167,6 @@ export async function setSessionTokenCookie(
|
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
|
|
171
170
|
/**
|
|
172
171
|
* Delete the session cookie.
|
|
173
172
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { usersLayout } from "../db/client";
|
|
2
2
|
import { Tusers as _User } from "../db/users";
|
|
3
|
+
import { hashPassword, verifyPasswordHash } from "./password";
|
|
3
4
|
|
|
4
5
|
export type User = Partial<
|
|
5
6
|
Omit<_User, "id" | "password_hash" | "recovery_code" | "emailVerified">
|
|
@@ -9,8 +10,6 @@ export type User = Partial<
|
|
|
9
10
|
emailVerified: boolean;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
import { hashPassword, verifyPasswordHash } from "./password";
|
|
13
|
-
|
|
14
13
|
/** An internal helper function to fetch a user from the database. */
|
|
15
14
|
async function fetchUser(userId: string) {
|
|
16
15
|
const { data } = await usersLayout.findOne({
|
|
@@ -75,7 +75,8 @@ export default async function SignInPage(props: {
|
|
|
75
75
|
)}
|
|
76
76
|
|
|
77
77
|
<Text size="sm" c="dimmed">
|
|
78
|
-
{"Don't have an account? "}
|
|
78
|
+
{"Don't have an account? "}
|
|
79
|
+
<Link href="/auth/signup">Sign up</Link>
|
|
79
80
|
</Text>
|
|
80
81
|
</Stack>
|
|
81
82
|
);
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"URL" : "https://proofkit.dev/auth/fm-addon",
|
|
9
|
-
"Icon_Color" : "#7F7F7F",
|
|
10
|
-
"Version" : "1.0"
|
|
2
|
+
"GUID": "77BDB4D6-5CF8-4740-AB5F-19837A831C21",
|
|
3
|
+
"Clients": ["ProofKit"],
|
|
4
|
+
"Attribution": "Proof+Geist",
|
|
5
|
+
"URL": "https://proofkit.dev/auth/fm-addon",
|
|
6
|
+
"Icon_Color": "#7F7F7F",
|
|
7
|
+
"Version": "1.0"
|
|
11
8
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"Title": "FileMaker Add-on Auth",
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
"Description": "*** DESCRIPTION MISSING *** - DNL",
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
"Category": "Web",
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
[
|
|
10
|
-
|
|
11
|
-
],
|
|
8
|
+
"Features": [],
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
[
|
|
15
|
-
"Desktop", "Tablet", "Mobile"
|
|
16
|
-
|
|
17
|
-
]
|
|
10
|
+
"Optimized": ["Desktop", "Tablet", "Mobile"]
|
|
18
11
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"Title": "FileMaker Add-on Auth",
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
"Description": "*** DESCRIPTION MISSING *** - DNL",
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
"Category": "Web",
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
[
|
|
10
|
-
|
|
11
|
-
],
|
|
8
|
+
"Features": [],
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
[
|
|
15
|
-
"Desktop", "Tablet", "Mobile"
|
|
16
|
-
|
|
17
|
-
]
|
|
10
|
+
"Optimized": ["Desktop", "Tablet", "Mobile"]
|
|
18
11
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"Title": "FileMaker Add-on Auth",
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
"Description": "*** DESCRIPTION MISSING *** - DNL",
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
"Category": "Web",
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
[
|
|
10
|
-
|
|
11
|
-
],
|
|
8
|
+
"Features": [],
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
[
|
|
15
|
-
"Desktop", "Tablet", "Mobile"
|
|
16
|
-
|
|
17
|
-
]
|
|
10
|
+
"Optimized": ["Desktop", "Tablet", "Mobile"]
|
|
18
11
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"Title": "FileMaker Add-on Auth",
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
"Description": "*** DESCRIPTION MISSING *** - DNL",
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
"Category": "Web",
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
[
|
|
10
|
-
|
|
11
|
-
],
|
|
8
|
+
"Features": [],
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
[
|
|
15
|
-
"Desktop", "Tablet", "Mobile"
|
|
16
|
-
|
|
17
|
-
]
|
|
10
|
+
"Optimized": ["Desktop", "Tablet", "Mobile"]
|
|
18
11
|
}
|