add log for sign in, sign out, change password, remove upload file

This commit is contained in:
2026-01-09 19:38:54 +07:00
parent 427a1040cf
commit ae39cc111f
32 changed files with 1991 additions and 212 deletions

View File

@@ -33,10 +33,9 @@
"@tanstack/react-router-ssr-query": "^1.131.7", "@tanstack/react-router-ssr-query": "^1.131.7",
"@tanstack/react-start": "^1.132.0", "@tanstack/react-start": "^1.132.0",
"@tanstack/router-plugin": "^1.132.0", "@tanstack/router-plugin": "^1.132.0",
"better-auth": "^1.4.7", "better-auth": "^1.4.10",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"i18next": "^25.7.3",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"prisma": "^7.1.0", "prisma": "^7.1.0",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",

47
pnpm-lock.yaml generated
View File

@@ -54,17 +54,14 @@ importers:
specifier: ^1.132.0 specifier: ^1.132.0
version: 1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.0(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) version: 1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.0(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))
better-auth: better-auth:
specifier: ^1.4.7 specifier: ^1.4.10
version: 1.4.9(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@7.3.0(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(mysql2@3.15.3)(pg@8.16.3)(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)(vitest@3.2.4(@types/node@22.19.3)(jiti@2.6.1)(jsdom@27.3.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@22.19.3)(typescript@5.9.3))(tsx@4.21.0)) version: 1.4.10(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@7.3.0(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(mysql2@3.15.3)(pg@8.16.3)(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)(vitest@3.2.4(@types/node@22.19.3)(jiti@2.6.1)(jsdom@27.3.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@22.19.3)(typescript@5.9.3))(tsx@4.21.0))
class-variance-authority: class-variance-authority:
specifier: ^0.7.1 specifier: ^0.7.1
version: 0.7.1 version: 0.7.1
clsx: clsx:
specifier: ^2.1.1 specifier: ^2.1.1
version: 2.1.1 version: 2.1.1
i18next:
specifier: ^25.7.3
version: 25.7.3(typescript@5.9.3)
next-themes: next-themes:
specifier: ^0.4.6 specifier: ^0.4.6
version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -342,8 +339,8 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
'@better-auth/core@1.4.9': '@better-auth/core@1.4.10':
resolution: {integrity: sha512-JT2q4NDkQzN22KclUEoZ7qU6tl9HUTfK1ctg2oWlT87SEagkwJcnrUwS9VznL+u9ziOIfY27P0f7/jSnmvLcoQ==} resolution: {integrity: sha512-AThrfb6CpG80wqkanfrbN2/fGOYzhGladHFf3JhaWt/3/Vtf4h084T6PJLrDE7M/vCCGYvDI1DkvP3P1OB2HAg==}
peerDependencies: peerDependencies:
'@better-auth/utils': 0.3.0 '@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21 '@better-fetch/fetch': 1.1.21
@@ -352,10 +349,10 @@ packages:
kysely: ^0.28.5 kysely: ^0.28.5
nanostores: ^1.0.1 nanostores: ^1.0.1
'@better-auth/telemetry@1.4.9': '@better-auth/telemetry@1.4.10':
resolution: {integrity: sha512-Tthy1/Gmx+pYlbvRQPBTKfVei8+pJwvH1NZp+5SbhwA6K2EXIaoonx/K6N/AXYs2aKUpyR4/gzqDesDjL7zd6A==} resolution: {integrity: sha512-Dq4XJX6EKsUu0h3jpRagX739p/VMOTcnJYWRrLtDYkqtZFg+sFiFsSWVcfapZoWpRSUGYX9iKwl6nDHn6Ju2oQ==}
peerDependencies: peerDependencies:
'@better-auth/core': 1.4.9 '@better-auth/core': 1.4.10
'@better-auth/utils@0.3.0': '@better-auth/utils@0.3.0':
resolution: {integrity: sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==} resolution: {integrity: sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==}
@@ -2435,8 +2432,8 @@ packages:
resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==}
hasBin: true hasBin: true
better-auth@1.4.9: better-auth@1.4.10:
resolution: {integrity: sha512-usSdjuyTzZwIvM8fjF8YGhPncxV3MAg3dHUO9uPUnf0yklXUSYISiH1+imk6/Z+UBqsscyyPRnbIyjyK97p7YA==} resolution: {integrity: sha512-0kqwEBJLe8eyFzbUspRG/htOriCf9uMLlnpe34dlIJGdmDfPuQISd4shShvUrvIVhPxsY1dSTXdXPLpqISYOYg==}
peerDependencies: peerDependencies:
'@lynx-js/react': '*' '@lynx-js/react': '*'
'@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
@@ -3320,14 +3317,6 @@ packages:
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
engines: {node: '>=18.18.0'} engines: {node: '>=18.18.0'}
i18next@25.7.3:
resolution: {integrity: sha512-2XaT+HpYGuc2uTExq9TVRhLsso+Dxym6PWaKpn36wfBmTI779OQ7iP/XaZHzrnGyzU4SHpFrTYLKfVyBfAhVNA==}
peerDependencies:
typescript: ^5
peerDependenciesMeta:
typescript:
optional: true
iconv-lite@0.6.3: iconv-lite@0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -5119,7 +5108,7 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/react': 19.2.7 '@types/react': 19.2.7
'@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)': '@better-auth/core@1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)':
dependencies: dependencies:
'@better-auth/utils': 0.3.0 '@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21 '@better-fetch/fetch': 1.1.21
@@ -5130,9 +5119,9 @@ snapshots:
nanostores: 1.1.0 nanostores: 1.1.0
zod: 4.2.1 zod: 4.2.1
'@better-auth/telemetry@1.4.9(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))': '@better-auth/telemetry@1.4.10(@better-auth/core@1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))':
dependencies: dependencies:
'@better-auth/core': 1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0) '@better-auth/core': 1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)
'@better-auth/utils': 0.3.0 '@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21 '@better-fetch/fetch': 1.1.21
@@ -7340,10 +7329,10 @@ snapshots:
baseline-browser-mapping@2.9.11: {} baseline-browser-mapping@2.9.11: {}
better-auth@1.4.9(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@7.3.0(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(mysql2@3.15.3)(pg@8.16.3)(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)(vitest@3.2.4(@types/node@22.19.3)(jiti@2.6.1)(jsdom@27.3.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@22.19.3)(typescript@5.9.3))(tsx@4.21.0)): better-auth@1.4.10(@prisma/client@7.2.0(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(@tanstack/react-start@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@7.3.0(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(mysql2@3.15.3)(pg@8.16.3)(prisma@7.2.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)(vitest@3.2.4(@types/node@22.19.3)(jiti@2.6.1)(jsdom@27.3.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@22.19.3)(typescript@5.9.3))(tsx@4.21.0)):
dependencies: dependencies:
'@better-auth/core': 1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0) '@better-auth/core': 1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)
'@better-auth/telemetry': 1.4.9(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)) '@better-auth/telemetry': 1.4.10(@better-auth/core@1.4.10(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.2.1))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))
'@better-auth/utils': 0.3.0 '@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21 '@better-fetch/fetch': 1.1.21
'@noble/ciphers': 2.1.1 '@noble/ciphers': 2.1.1
@@ -8249,12 +8238,6 @@ snapshots:
human-signals@8.0.1: {} human-signals@8.0.1: {}
i18next@25.7.3(typescript@5.9.3):
dependencies:
'@babel/runtime': 7.28.4
optionalDependencies:
typescript: 5.9.3
iconv-lite@0.6.3: iconv-lite@0.6.3:
dependencies: dependencies:
safer-buffer: 2.1.2 safer-buffer: 2.1.2

View File

@@ -0,0 +1,16 @@
-- CreateTable
CREATE TABLE "audit" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"action" TEXT NOT NULL,
"tableName" TEXT NOT NULL,
"recordId" TEXT NOT NULL,
"oldValue" TEXT,
"newValue" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "audit_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "audit" ADD CONSTRAINT "audit_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -18,6 +18,7 @@ model User {
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
sessions Session[] sessions Session[]
accounts Account[] accounts Account[]
audit Audit[]
role String? role String?
banned Boolean? @default(false) banned Boolean? @default(false)
@@ -142,3 +143,18 @@ model Setting {
@@map("setting") @@map("setting")
} }
model Audit {
id String @id @default(uuid())
userId String
action String
tableName String
recordId String
oldValue String?
newValue String?
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("audit")
}

View File

@@ -4,13 +4,9 @@
"locales": ["en", "vi"], "locales": ["en", "vi"],
"modules": [ "modules": [
"https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js"
"https://cdn.jsdelivr.net/npm/@inlang/plugin-i18next@latest/dist/index.js"
], ],
"plugin.inlang.messageFormat": { "plugin.inlang.messageFormat": {
"pathPattern": "./messages/{locale}.json" "pathPattern": "./messages/{locale}.json"
},
"plugin.inlang.i18next": {
"pathPattern": "./messages/{locale}.json"
} }
} }

View File

@@ -73,17 +73,6 @@ export default function Header() {
)} )}
</div> </div>
</header> </header>
{/* <Link
to="/demo/start/ssr"
onClick={() => setIsOpen(false)}
className="flex-1 flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2"
activeProps={{
className:
'flex-1 flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',
}}
>
<span className="font-medium">Start - SSR Demos</span>
</Link> */}
</> </>
); );
} }

View File

@@ -2,7 +2,6 @@ import { authClient } from '@/lib/auth-client';
import { m } from '@/paraglide/messages'; import { m } from '@/paraglide/messages';
import { KeyIcon } from '@phosphor-icons/react'; import { KeyIcon } from '@phosphor-icons/react';
import { useForm } from '@tanstack/react-form'; import { useForm } from '@tanstack/react-form';
import i18next from 'i18next';
import { toast } from 'sonner'; import { toast } from 'sonner';
import z from 'zod'; import z from 'zod';
import { Button } from '../ui/button'; import { Button } from '../ui/button';
@@ -72,9 +71,14 @@ const ChangePasswordForm = () => {
}, },
onError: (ctx) => { onError: (ctx) => {
console.log(ctx.error.code); console.log(ctx.error.code);
toast.error(i18next.t(`backend_${ctx.error.code}` as any), { toast.error(
(
m[`backend_${ctx.error.code}` as keyof typeof m] as () => string
)(),
{
richColors: true, richColors: true,
}); },
);
}, },
}, },
); );

View File

@@ -1,11 +1,9 @@
import { authClient } from '@/lib/auth-client'; import { authClient } from '@/lib/auth-client';
import { m } from '@/paraglide/messages'; import { m } from '@/paraglide/messages';
import { uploadProfileImage } from '@/service/profile.api';
import { ProfileInput, profileUpdateSchema } from '@/service/profile.schema'; import { ProfileInput, profileUpdateSchema } from '@/service/profile.schema';
import { UserCircleIcon } from '@phosphor-icons/react'; import { UserCircleIcon } from '@phosphor-icons/react';
import { useForm } from '@tanstack/react-form'; import { useForm } from '@tanstack/react-form';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import i18next from 'i18next';
import { useRef } from 'react'; import { useRef } from 'react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { useAuth } from '../auth/auth-provider'; import { useAuth } from '../auth/auth-provider';
@@ -37,21 +35,9 @@ const ProfileForm = () => {
}, },
onSubmit: async ({ value }) => { onSubmit: async ({ value }) => {
try { try {
let imageKey;
if (value.image) {
// upload image
const formData = new FormData();
formData.set('file', value.image);
const { imageKey: uploadedKey } = await uploadProfileImage({
data: formData,
});
imageKey = uploadedKey;
}
await authClient.updateUser( await authClient.updateUser(
{ {
name: value.name, name: value.name,
image: imageKey,
}, },
{ {
onSuccess: () => { onSuccess: () => {
@@ -67,9 +53,16 @@ const ProfileForm = () => {
}); });
}, },
onError: (ctx) => { onError: (ctx) => {
toast.error(i18next.t(`backend.${ctx.error.code}` as any), { toast.error(
(
m[
`backend_${ctx.error.code}` as keyof typeof m
] as () => string
)(),
{
richColors: true, richColors: true,
}); },
);
}, },
}, },
); );

View File

@@ -27,10 +27,7 @@ const SettingsForm = () => {
const updateMutation = useMutation({ const updateMutation = useMutation({
mutationFn: updateAdminSettings, mutationFn: updateAdminSettings,
onSuccess: () => { onSuccess: () => {
// setLocale(variables.data.site_language as Locale); queryClient.invalidateQueries(settingQueries.listAdmin());
queryClient.invalidateQueries({
queryKey: [...settingQueries.all, 'list'],
});
toast.success(m.settings_messages_update_success(), { toast.success(m.settings_messages_update_success(), {
richColors: true, richColors: true,
}); });

View File

@@ -3,7 +3,6 @@ import { m } from '@/paraglide/messages';
import { useForm } from '@tanstack/react-form'; import { useForm } from '@tanstack/react-form';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { createLink, useNavigate } from '@tanstack/react-router'; import { createLink, useNavigate } from '@tanstack/react-router';
import i18next from 'i18next';
import { toast } from 'sonner'; import { toast } from 'sonner';
import z from 'zod'; import z from 'zod';
import { Button } from '../ui/button'; import { Button } from '../ui/button';
@@ -14,7 +13,7 @@ import { Input } from '../ui/input';
const SignInFormSchema = z.object({ const SignInFormSchema = z.object({
email: z email: z
.string() .string()
.nonempty(m.common_is_required({ field: m.login_page_form_email })) .nonempty(m.common_is_required({ field: m.login_page_form_email() }))
.email(m.login_page_messages_email_invalid()), .email(m.login_page_messages_email_invalid()),
password: z.string().nonempty( password: z.string().nonempty(
m.common_is_required({ m.common_is_required({
@@ -52,9 +51,14 @@ const SignInForm = () => {
}); });
}, },
onError: (ctx) => { onError: (ctx) => {
toast.error(i18next.t(`backend.${ctx.error.code}` as any), { toast.error(
(
m[`backend_${ctx.error.code}` as keyof typeof m] as () => string
)(),
{
richColors: true, richColors: true,
}); },
);
}, },
}, },
); );

View File

@@ -9,7 +9,6 @@ import {
} from '@phosphor-icons/react'; } from '@phosphor-icons/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { createLink, Link, useNavigate } from '@tanstack/react-router'; import { createLink, Link, useNavigate } from '@tanstack/react-router';
import i18next from 'i18next';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { useAuth } from '../auth/auth-provider'; import { useAuth } from '../auth/auth-provider';
import AvatarUser from '../avatar/AvatarUser'; import AvatarUser from '../avatar/AvatarUser';
@@ -49,9 +48,14 @@ const NavUser = () => {
}); });
}, },
onError: (ctx) => { onError: (ctx) => {
toast.error(i18next.t(`backend_${ctx.error.code}` as any), { toast.error(
(
m[`backend_${ctx.error.code}` as keyof typeof m] as () => string
)(),
{
richColors: true, richColors: true,
}); },
);
}, },
}, },
}); });

View File

@@ -1,13 +0,0 @@
import { createServerFn } from '@tanstack/react-start'
export const getPunkSongs = createServerFn({
method: 'GET',
}).handler(async () => [
{ id: 1, name: 'Teenage Dirtbag', artist: 'Wheatus' },
{ id: 2, name: 'Smells Like Teen Spirit', artist: 'Nirvana' },
{ id: 3, name: 'The Middle', artist: 'Jimmy Eat World' },
{ id: 4, name: 'My Own Worst Enemy', artist: 'Lit' },
{ id: 5, name: 'Fat Lip', artist: 'Sum 41' },
{ id: 6, name: 'All the Small Things', artist: 'blink-182' },
{ id: 7, name: 'Beverly Hills', artist: 'Weezer' },
])

View File

@@ -57,3 +57,8 @@ export type Invitation = Prisma.InvitationModel
* *
*/ */
export type Setting = Prisma.SettingModel export type Setting = Prisma.SettingModel
/**
* Model Audit
*
*/
export type Audit = Prisma.AuditModel

View File

@@ -79,3 +79,8 @@ export type Invitation = Prisma.InvitationModel
* *
*/ */
export type Setting = Prisma.SettingModel export type Setting = Prisma.SettingModel
/**
* Model Audit
*
*/
export type Audit = Prisma.AuditModel

File diff suppressed because one or more lines are too long

View File

@@ -391,7 +391,8 @@ export const ModelName = {
Organization: 'Organization', Organization: 'Organization',
Member: 'Member', Member: 'Member',
Invitation: 'Invitation', Invitation: 'Invitation',
Setting: 'Setting' Setting: 'Setting',
Audit: 'Audit'
} as const } as const
export type ModelName = (typeof ModelName)[keyof typeof ModelName] export type ModelName = (typeof ModelName)[keyof typeof ModelName]
@@ -407,7 +408,7 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
omit: GlobalOmitOptions omit: GlobalOmitOptions
} }
meta: { meta: {
modelProps: "user" | "session" | "account" | "verification" | "organization" | "member" | "invitation" | "setting" modelProps: "user" | "session" | "account" | "verification" | "organization" | "member" | "invitation" | "setting" | "audit"
txIsolationLevel: TransactionIsolationLevel txIsolationLevel: TransactionIsolationLevel
} }
model: { model: {
@@ -1003,6 +1004,80 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
} }
} }
} }
Audit: {
payload: Prisma.$AuditPayload<ExtArgs>
fields: Prisma.AuditFieldRefs
operations: {
findUnique: {
args: Prisma.AuditFindUniqueArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload> | null
}
findUniqueOrThrow: {
args: Prisma.AuditFindUniqueOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>
}
findFirst: {
args: Prisma.AuditFindFirstArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload> | null
}
findFirstOrThrow: {
args: Prisma.AuditFindFirstOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>
}
findMany: {
args: Prisma.AuditFindManyArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>[]
}
create: {
args: Prisma.AuditCreateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>
}
createMany: {
args: Prisma.AuditCreateManyArgs<ExtArgs>
result: BatchPayload
}
createManyAndReturn: {
args: Prisma.AuditCreateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>[]
}
delete: {
args: Prisma.AuditDeleteArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>
}
update: {
args: Prisma.AuditUpdateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>
}
deleteMany: {
args: Prisma.AuditDeleteManyArgs<ExtArgs>
result: BatchPayload
}
updateMany: {
args: Prisma.AuditUpdateManyArgs<ExtArgs>
result: BatchPayload
}
updateManyAndReturn: {
args: Prisma.AuditUpdateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>[]
}
upsert: {
args: Prisma.AuditUpsertArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$AuditPayload>
}
aggregate: {
args: Prisma.AuditAggregateArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.AggregateAudit>
}
groupBy: {
args: Prisma.AuditGroupByArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.AuditGroupByOutputType>[]
}
count: {
args: Prisma.AuditCountArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.AuditCountAggregateOutputType> | number
}
}
}
} }
} & { } & {
other: { other: {
@@ -1157,6 +1232,20 @@ export const SettingScalarFieldEnum = {
export type SettingScalarFieldEnum = (typeof SettingScalarFieldEnum)[keyof typeof SettingScalarFieldEnum] export type SettingScalarFieldEnum = (typeof SettingScalarFieldEnum)[keyof typeof SettingScalarFieldEnum]
export const AuditScalarFieldEnum = {
id: 'id',
userId: 'userId',
action: 'action',
tableName: 'tableName',
recordId: 'recordId',
oldValue: 'oldValue',
newValue: 'newValue',
createdAt: 'createdAt'
} as const
export type AuditScalarFieldEnum = (typeof AuditScalarFieldEnum)[keyof typeof AuditScalarFieldEnum]
export const SortOrder = { export const SortOrder = {
asc: 'asc', asc: 'asc',
desc: 'desc' desc: 'desc'
@@ -1338,6 +1427,7 @@ export type GlobalOmitConfig = {
member?: Prisma.MemberOmit member?: Prisma.MemberOmit
invitation?: Prisma.InvitationOmit invitation?: Prisma.InvitationOmit
setting?: Prisma.SettingOmit setting?: Prisma.SettingOmit
audit?: Prisma.AuditOmit
} }
/* Types for Logging */ /* Types for Logging */

View File

@@ -58,7 +58,8 @@ export const ModelName = {
Organization: 'Organization', Organization: 'Organization',
Member: 'Member', Member: 'Member',
Invitation: 'Invitation', Invitation: 'Invitation',
Setting: 'Setting' Setting: 'Setting',
Audit: 'Audit'
} as const } as const
export type ModelName = (typeof ModelName)[keyof typeof ModelName] export type ModelName = (typeof ModelName)[keyof typeof ModelName]
@@ -192,6 +193,20 @@ export const SettingScalarFieldEnum = {
export type SettingScalarFieldEnum = (typeof SettingScalarFieldEnum)[keyof typeof SettingScalarFieldEnum] export type SettingScalarFieldEnum = (typeof SettingScalarFieldEnum)[keyof typeof SettingScalarFieldEnum]
export const AuditScalarFieldEnum = {
id: 'id',
userId: 'userId',
action: 'action',
tableName: 'tableName',
recordId: 'recordId',
oldValue: 'oldValue',
newValue: 'newValue',
createdAt: 'createdAt'
} as const
export type AuditScalarFieldEnum = (typeof AuditScalarFieldEnum)[keyof typeof AuditScalarFieldEnum]
export const SortOrder = { export const SortOrder = {
asc: 'asc', asc: 'asc',
desc: 'desc' desc: 'desc'

View File

@@ -16,4 +16,5 @@ export type * from './models/Organization.ts'
export type * from './models/Member.ts' export type * from './models/Member.ts'
export type * from './models/Invitation.ts' export type * from './models/Invitation.ts'
export type * from './models/Setting.ts' export type * from './models/Setting.ts'
export type * from './models/Audit.ts'
export type * from './commonInputTypes.ts' export type * from './commonInputTypes.ts'

File diff suppressed because it is too large Load Diff

View File

@@ -232,6 +232,7 @@ export type UserWhereInput = {
banExpires?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null banExpires?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
sessions?: Prisma.SessionListRelationFilter sessions?: Prisma.SessionListRelationFilter
accounts?: Prisma.AccountListRelationFilter accounts?: Prisma.AccountListRelationFilter
audit?: Prisma.AuditListRelationFilter
members?: Prisma.MemberListRelationFilter members?: Prisma.MemberListRelationFilter
invitations?: Prisma.InvitationListRelationFilter invitations?: Prisma.InvitationListRelationFilter
} }
@@ -250,6 +251,7 @@ export type UserOrderByWithRelationInput = {
banExpires?: Prisma.SortOrderInput | Prisma.SortOrder banExpires?: Prisma.SortOrderInput | Prisma.SortOrder
sessions?: Prisma.SessionOrderByRelationAggregateInput sessions?: Prisma.SessionOrderByRelationAggregateInput
accounts?: Prisma.AccountOrderByRelationAggregateInput accounts?: Prisma.AccountOrderByRelationAggregateInput
audit?: Prisma.AuditOrderByRelationAggregateInput
members?: Prisma.MemberOrderByRelationAggregateInput members?: Prisma.MemberOrderByRelationAggregateInput
invitations?: Prisma.InvitationOrderByRelationAggregateInput invitations?: Prisma.InvitationOrderByRelationAggregateInput
} }
@@ -271,6 +273,7 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{
banExpires?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null banExpires?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
sessions?: Prisma.SessionListRelationFilter sessions?: Prisma.SessionListRelationFilter
accounts?: Prisma.AccountListRelationFilter accounts?: Prisma.AccountListRelationFilter
audit?: Prisma.AuditListRelationFilter
members?: Prisma.MemberListRelationFilter members?: Prisma.MemberListRelationFilter
invitations?: Prisma.InvitationListRelationFilter invitations?: Prisma.InvitationListRelationFilter
}, "id" | "email"> }, "id" | "email">
@@ -323,6 +326,7 @@ export type UserCreateInput = {
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionCreateNestedManyWithoutUserInput sessions?: Prisma.SessionCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
audit?: Prisma.AuditCreateNestedManyWithoutUserInput
members?: Prisma.MemberCreateNestedManyWithoutUserInput members?: Prisma.MemberCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput
} }
@@ -341,6 +345,7 @@ export type UserUncheckedCreateInput = {
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
audit?: Prisma.AuditUncheckedCreateNestedManyWithoutUserInput
members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput
} }
@@ -359,6 +364,7 @@ export type UserUpdateInput = {
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUpdateManyWithoutUserNestedInput members?: Prisma.MemberUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput
} }
@@ -377,6 +383,7 @@ export type UserUncheckedUpdateInput = {
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUncheckedUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput
} }
@@ -550,6 +557,20 @@ export type UserUpdateOneRequiredWithoutInvitationsNestedInput = {
update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutInvitationsInput, Prisma.UserUpdateWithoutInvitationsInput>, Prisma.UserUncheckedUpdateWithoutInvitationsInput> update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutInvitationsInput, Prisma.UserUpdateWithoutInvitationsInput>, Prisma.UserUncheckedUpdateWithoutInvitationsInput>
} }
export type UserCreateNestedOneWithoutAuditInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutAuditInput, Prisma.UserUncheckedCreateWithoutAuditInput>
connectOrCreate?: Prisma.UserCreateOrConnectWithoutAuditInput
connect?: Prisma.UserWhereUniqueInput
}
export type UserUpdateOneRequiredWithoutAuditNestedInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutAuditInput, Prisma.UserUncheckedCreateWithoutAuditInput>
connectOrCreate?: Prisma.UserCreateOrConnectWithoutAuditInput
upsert?: Prisma.UserUpsertWithoutAuditInput
connect?: Prisma.UserWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutAuditInput, Prisma.UserUpdateWithoutAuditInput>, Prisma.UserUncheckedUpdateWithoutAuditInput>
}
export type UserCreateWithoutSessionsInput = { export type UserCreateWithoutSessionsInput = {
id?: string id?: string
name: string name: string
@@ -563,6 +584,7 @@ export type UserCreateWithoutSessionsInput = {
banReason?: string | null banReason?: string | null
banExpires?: Date | string | null banExpires?: Date | string | null
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
audit?: Prisma.AuditCreateNestedManyWithoutUserInput
members?: Prisma.MemberCreateNestedManyWithoutUserInput members?: Prisma.MemberCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput
} }
@@ -580,6 +602,7 @@ export type UserUncheckedCreateWithoutSessionsInput = {
banReason?: string | null banReason?: string | null
banExpires?: Date | string | null banExpires?: Date | string | null
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
audit?: Prisma.AuditUncheckedCreateNestedManyWithoutUserInput
members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput
} }
@@ -613,6 +636,7 @@ export type UserUpdateWithoutSessionsInput = {
banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUpdateManyWithoutUserNestedInput members?: Prisma.MemberUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput
} }
@@ -630,6 +654,7 @@ export type UserUncheckedUpdateWithoutSessionsInput = {
banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUncheckedUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput
} }
@@ -647,6 +672,7 @@ export type UserCreateWithoutAccountsInput = {
banReason?: string | null banReason?: string | null
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionCreateNestedManyWithoutUserInput sessions?: Prisma.SessionCreateNestedManyWithoutUserInput
audit?: Prisma.AuditCreateNestedManyWithoutUserInput
members?: Prisma.MemberCreateNestedManyWithoutUserInput members?: Prisma.MemberCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput
} }
@@ -664,6 +690,7 @@ export type UserUncheckedCreateWithoutAccountsInput = {
banReason?: string | null banReason?: string | null
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
audit?: Prisma.AuditUncheckedCreateNestedManyWithoutUserInput
members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput
} }
@@ -697,6 +724,7 @@ export type UserUpdateWithoutAccountsInput = {
banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUpdateManyWithoutUserNestedInput members?: Prisma.MemberUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput
} }
@@ -714,6 +742,7 @@ export type UserUncheckedUpdateWithoutAccountsInput = {
banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUncheckedUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput
} }
@@ -732,6 +761,7 @@ export type UserCreateWithoutMembersInput = {
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionCreateNestedManyWithoutUserInput sessions?: Prisma.SessionCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
audit?: Prisma.AuditCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput
} }
@@ -749,6 +779,7 @@ export type UserUncheckedCreateWithoutMembersInput = {
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
audit?: Prisma.AuditUncheckedCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput
} }
@@ -782,6 +813,7 @@ export type UserUpdateWithoutMembersInput = {
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput
} }
@@ -799,6 +831,7 @@ export type UserUncheckedUpdateWithoutMembersInput = {
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUncheckedUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput
} }
@@ -816,6 +849,7 @@ export type UserCreateWithoutInvitationsInput = {
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionCreateNestedManyWithoutUserInput sessions?: Prisma.SessionCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
audit?: Prisma.AuditCreateNestedManyWithoutUserInput
members?: Prisma.MemberCreateNestedManyWithoutUserInput members?: Prisma.MemberCreateNestedManyWithoutUserInput
} }
@@ -833,6 +867,7 @@ export type UserUncheckedCreateWithoutInvitationsInput = {
banExpires?: Date | string | null banExpires?: Date | string | null
sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
audit?: Prisma.AuditUncheckedCreateNestedManyWithoutUserInput
members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput
} }
@@ -866,6 +901,7 @@ export type UserUpdateWithoutInvitationsInput = {
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUpdateManyWithoutUserNestedInput members?: Prisma.MemberUpdateManyWithoutUserNestedInput
} }
@@ -883,9 +919,98 @@ export type UserUncheckedUpdateWithoutInvitationsInput = {
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
audit?: Prisma.AuditUncheckedUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput
} }
export type UserCreateWithoutAuditInput = {
id?: string
name: string
email: string
emailVerified?: boolean
image?: string | null
createdAt?: Date | string
updatedAt?: Date | string
role?: string | null
banned?: boolean | null
banReason?: string | null
banExpires?: Date | string | null
sessions?: Prisma.SessionCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
members?: Prisma.MemberCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationCreateNestedManyWithoutUserInput
}
export type UserUncheckedCreateWithoutAuditInput = {
id?: string
name: string
email: string
emailVerified?: boolean
image?: string | null
createdAt?: Date | string
updatedAt?: Date | string
role?: string | null
banned?: boolean | null
banReason?: string | null
banExpires?: Date | string | null
sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
members?: Prisma.MemberUncheckedCreateNestedManyWithoutUserInput
invitations?: Prisma.InvitationUncheckedCreateNestedManyWithoutUserInput
}
export type UserCreateOrConnectWithoutAuditInput = {
where: Prisma.UserWhereUniqueInput
create: Prisma.XOR<Prisma.UserCreateWithoutAuditInput, Prisma.UserUncheckedCreateWithoutAuditInput>
}
export type UserUpsertWithoutAuditInput = {
update: Prisma.XOR<Prisma.UserUpdateWithoutAuditInput, Prisma.UserUncheckedUpdateWithoutAuditInput>
create: Prisma.XOR<Prisma.UserCreateWithoutAuditInput, Prisma.UserUncheckedCreateWithoutAuditInput>
where?: Prisma.UserWhereInput
}
export type UserUpdateToOneWithWhereWithoutAuditInput = {
where?: Prisma.UserWhereInput
data: Prisma.XOR<Prisma.UserUpdateWithoutAuditInput, Prisma.UserUncheckedUpdateWithoutAuditInput>
}
export type UserUpdateWithoutAuditInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
role?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banned?: Prisma.NullableBoolFieldUpdateOperationsInput | boolean | null
banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUpdateManyWithoutUserNestedInput
}
export type UserUncheckedUpdateWithoutAuditInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
email?: Prisma.StringFieldUpdateOperationsInput | string
emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
role?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banned?: Prisma.NullableBoolFieldUpdateOperationsInput | boolean | null
banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
banExpires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
members?: Prisma.MemberUncheckedUpdateManyWithoutUserNestedInput
invitations?: Prisma.InvitationUncheckedUpdateManyWithoutUserNestedInput
}
/** /**
* Count Type UserCountOutputType * Count Type UserCountOutputType
@@ -894,6 +1019,7 @@ export type UserUncheckedUpdateWithoutInvitationsInput = {
export type UserCountOutputType = { export type UserCountOutputType = {
sessions: number sessions: number
accounts: number accounts: number
audit: number
members: number members: number
invitations: number invitations: number
} }
@@ -901,6 +1027,7 @@ export type UserCountOutputType = {
export type UserCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type UserCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
sessions?: boolean | UserCountOutputTypeCountSessionsArgs sessions?: boolean | UserCountOutputTypeCountSessionsArgs
accounts?: boolean | UserCountOutputTypeCountAccountsArgs accounts?: boolean | UserCountOutputTypeCountAccountsArgs
audit?: boolean | UserCountOutputTypeCountAuditArgs
members?: boolean | UserCountOutputTypeCountMembersArgs members?: boolean | UserCountOutputTypeCountMembersArgs
invitations?: boolean | UserCountOutputTypeCountInvitationsArgs invitations?: boolean | UserCountOutputTypeCountInvitationsArgs
} }
@@ -929,6 +1056,13 @@ export type UserCountOutputTypeCountAccountsArgs<ExtArgs extends runtime.Types.E
where?: Prisma.AccountWhereInput where?: Prisma.AccountWhereInput
} }
/**
* UserCountOutputType without action
*/
export type UserCountOutputTypeCountAuditArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
where?: Prisma.AuditWhereInput
}
/** /**
* UserCountOutputType without action * UserCountOutputType without action
*/ */
@@ -958,6 +1092,7 @@ export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = r
banExpires?: boolean banExpires?: boolean
sessions?: boolean | Prisma.User$sessionsArgs<ExtArgs> sessions?: boolean | Prisma.User$sessionsArgs<ExtArgs>
accounts?: boolean | Prisma.User$accountsArgs<ExtArgs> accounts?: boolean | Prisma.User$accountsArgs<ExtArgs>
audit?: boolean | Prisma.User$auditArgs<ExtArgs>
members?: boolean | Prisma.User$membersArgs<ExtArgs> members?: boolean | Prisma.User$membersArgs<ExtArgs>
invitations?: boolean | Prisma.User$invitationsArgs<ExtArgs> invitations?: boolean | Prisma.User$invitationsArgs<ExtArgs>
_count?: boolean | Prisma.UserCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.UserCountOutputTypeDefaultArgs<ExtArgs>
@@ -1009,6 +1144,7 @@ export type UserOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = run
export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
sessions?: boolean | Prisma.User$sessionsArgs<ExtArgs> sessions?: boolean | Prisma.User$sessionsArgs<ExtArgs>
accounts?: boolean | Prisma.User$accountsArgs<ExtArgs> accounts?: boolean | Prisma.User$accountsArgs<ExtArgs>
audit?: boolean | Prisma.User$auditArgs<ExtArgs>
members?: boolean | Prisma.User$membersArgs<ExtArgs> members?: boolean | Prisma.User$membersArgs<ExtArgs>
invitations?: boolean | Prisma.User$invitationsArgs<ExtArgs> invitations?: boolean | Prisma.User$invitationsArgs<ExtArgs>
_count?: boolean | Prisma.UserCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.UserCountOutputTypeDefaultArgs<ExtArgs>
@@ -1021,6 +1157,7 @@ export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs =
objects: { objects: {
sessions: Prisma.$SessionPayload<ExtArgs>[] sessions: Prisma.$SessionPayload<ExtArgs>[]
accounts: Prisma.$AccountPayload<ExtArgs>[] accounts: Prisma.$AccountPayload<ExtArgs>[]
audit: Prisma.$AuditPayload<ExtArgs>[]
members: Prisma.$MemberPayload<ExtArgs>[] members: Prisma.$MemberPayload<ExtArgs>[]
invitations: Prisma.$InvitationPayload<ExtArgs>[] invitations: Prisma.$InvitationPayload<ExtArgs>[]
} }
@@ -1432,6 +1569,7 @@ export interface Prisma__UserClient<T, Null = never, ExtArgs extends runtime.Typ
readonly [Symbol.toStringTag]: "PrismaPromise" readonly [Symbol.toStringTag]: "PrismaPromise"
sessions<T extends Prisma.User$sessionsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$sessionsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$SessionPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> sessions<T extends Prisma.User$sessionsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$sessionsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$SessionPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
accounts<T extends Prisma.User$accountsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$accountsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$AccountPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> accounts<T extends Prisma.User$accountsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$accountsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$AccountPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
audit<T extends Prisma.User$auditArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$auditArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$AuditPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
members<T extends Prisma.User$membersArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$membersArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$MemberPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> members<T extends Prisma.User$membersArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$membersArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$MemberPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
invitations<T extends Prisma.User$invitationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$invitationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$InvitationPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> invitations<T extends Prisma.User$invitationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$invitationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$InvitationPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
/** /**
@@ -1909,6 +2047,30 @@ export type User$accountsArgs<ExtArgs extends runtime.Types.Extensions.InternalA
distinct?: Prisma.AccountScalarFieldEnum | Prisma.AccountScalarFieldEnum[] distinct?: Prisma.AccountScalarFieldEnum | Prisma.AccountScalarFieldEnum[]
} }
/**
* User.audit
*/
export type User$auditArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the Audit
*/
select?: Prisma.AuditSelect<ExtArgs> | null
/**
* Omit specific fields from the Audit
*/
omit?: Prisma.AuditOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AuditInclude<ExtArgs> | null
where?: Prisma.AuditWhereInput
orderBy?: Prisma.AuditOrderByWithRelationInput | Prisma.AuditOrderByWithRelationInput[]
cursor?: Prisma.AuditWhereUniqueInput
take?: number
skip?: number
distinct?: Prisma.AuditScalarFieldEnum | Prisma.AuditScalarFieldEnum[]
}
/** /**
* User.members * User.members
*/ */

View File

@@ -8,6 +8,7 @@ import {
owner, owner,
} from '@/lib/auth/organization-permissions'; } from '@/lib/auth/organization-permissions';
import { ac, admin, user } from '@/lib/auth/permissions'; import { ac, admin, user } from '@/lib/auth/permissions';
import { createAuditLog } from '@/service/audit.api';
import { betterAuth } from 'better-auth'; import { betterAuth } from 'better-auth';
import { prismaAdapter } from 'better-auth/adapters/prisma'; import { prismaAdapter } from 'better-auth/adapters/prisma';
import { admin as adminPlugin, organization } from 'better-auth/plugins'; import { admin as adminPlugin, organization } from 'better-auth/plugins';
@@ -67,6 +68,73 @@ export const auth = betterAuth({
}); });
}, },
}, },
update: {
before: async (user, ctx) => {
if (ctx?.context.session && ctx?.path === '/update-user') {
const newUser = JSON.parse(JSON.stringify(user));
const keys = Object.keys(newUser);
const oldUser = Object.fromEntries(
Object.entries(ctx?.context.session?.user).filter(([key]) =>
keys.includes(key),
),
);
await createAuditLog({
action: 'update',
tableName: 'user',
recordId: ctx?.context.session?.user.id,
oldValue: JSON.stringify(oldUser),
newValue: JSON.stringify(newUser),
userId: ctx?.context.session?.user.id,
});
}
},
},
},
account: {
update: {
after: async (account, context) => {
if (context?.path === '/change-password') {
await createAuditLog({
action: 'change_password',
tableName: 'account',
recordId: account.id,
oldValue: 'Change Password',
newValue: 'Change Password',
userId: account.userId,
});
}
},
},
},
session: {
create: {
after: async (session, context) => {
if (context?.path.includes('/sign-in')) {
await createAuditLog({
action: 'sign_in',
tableName: 'session',
recordId: session.id,
oldValue: '',
newValue: JSON.stringify(session),
userId: session.userId,
});
}
},
},
delete: {
after: async (session, context) => {
if (context?.path === '/sign-out') {
await createAuditLog({
action: 'sign_out',
tableName: 'session',
recordId: session.id,
oldValue: JSON.stringify(session),
newValue: '',
userId: session.userId,
});
}
},
},
}, },
}, },
}); });

View File

@@ -1,7 +1,6 @@
import { createServerFn } from '@tanstack/react-start'; import { createServerFn } from '@tanstack/react-start';
import { getRequestHeaders } from '@tanstack/react-start/server'; import { getRequestHeaders } from '@tanstack/react-start/server';
import { auth } from '../auth'; import { auth } from '../auth';
import { authClient } from '../auth-client';
export type Session = typeof auth.$Infer.Session; export type Session = typeof auth.$Infer.Session;
@@ -12,8 +11,3 @@ export const getSession = createServerFn({ method: 'GET' }).handler(
return session; return session;
}, },
); );
export const sessionPush = () => {
const session = authClient.getSession();
return session;
};

View File

@@ -14,7 +14,7 @@ import { Route as appIndexRouteImport } from './routes/(app)/index'
import { Route as authSignUpRouteImport } from './routes/(auth)/sign-up' import { Route as authSignUpRouteImport } from './routes/(auth)/sign-up'
import { Route as authSignInRouteImport } from './routes/(auth)/sign-in' import { Route as authSignInRouteImport } from './routes/(auth)/sign-in'
import { Route as appauthRouteRouteImport } from './routes/(app)/(auth)/route' import { Route as appauthRouteRouteImport } from './routes/(app)/(auth)/route'
import { Route as ApiAuthSplatRouteImport } from './routes/api/auth.$' import { Route as ApiAuthSplatRouteImport } from './routes/api.auth.$'
import { Route as appauthSettingsRouteImport } from './routes/(app)/(auth)/settings' import { Route as appauthSettingsRouteImport } from './routes/(app)/(auth)/settings'
import { Route as appauthDashboardRouteImport } from './routes/(app)/(auth)/dashboard' import { Route as appauthDashboardRouteImport } from './routes/(app)/(auth)/dashboard'
import { Route as appauthAccountRouteRouteImport } from './routes/(app)/(auth)/account/route' import { Route as appauthAccountRouteRouteImport } from './routes/(app)/(auth)/account/route'

View File

@@ -1,11 +1,11 @@
import { createFileRoute, Outlet, redirect } from '@tanstack/react-router'; import { createFileRoute, Outlet } from '@tanstack/react-router';
export const Route = createFileRoute('/(app)/(auth)')({ export const Route = createFileRoute('/(app)/(auth)')({
beforeLoad: async ({ context }) => { // beforeLoad: async ({ context }) => {
if (!context.userSession) { // if (!context.userSession) {
throw redirect({ to: '/sign-in' }); // throw redirect({ to: '/sign-in' });
} // }
}, // },
component: RouteComponent, component: RouteComponent,
}); });

View File

@@ -1,7 +1,6 @@
import NotFound from '@/components/NotFound'; import NotFound from '@/components/NotFound';
import { Toaster } from '@/components/ui/sonner'; import { Toaster } from '@/components/ui/sonner';
import { getLocale } from '@/paraglide/runtime'; import { getLocale } from '@/paraglide/runtime';
import { sessionQueries } from '@/service/queries';
import { import {
CheckIcon, CheckIcon,
InfoIcon, InfoIcon,
@@ -20,17 +19,14 @@ import React from 'react';
import TanStackQueryDevtools from '../integrations/tanstack-query/devtools'; import TanStackQueryDevtools from '../integrations/tanstack-query/devtools';
import appCss from '../styles.css?url'; import appCss from '../styles.css?url';
interface MyRouterContext { export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()(
queryClient: QueryClient; {
} // beforeLoad: async ({ context }) => {
// const userSession = await context.queryClient.fetchQuery(
export const Route = createRootRouteWithContext<MyRouterContext>()({ // sessionQueries.user(),
beforeLoad: async ({ context }) => { // );
const userSession = await context.queryClient.fetchQuery( // return { userSession };
sessionQueries.user(), // },
);
return { userSession };
},
head: () => ({ head: () => ({
meta: [ meta: [
{ {
@@ -56,7 +52,8 @@ export const Route = createRootRouteWithContext<MyRouterContext>()({
}), }),
shellComponent: RootDocument, shellComponent: RootDocument,
notFoundComponent: () => <NotFound />, notFoundComponent: () => <NotFound />,
}); },
);
function RootDocument({ children }: { children: React.ReactNode }) { function RootDocument({ children }: { children: React.ReactNode }) {
return ( return (
@@ -79,7 +76,7 @@ function RootDocument({ children }: { children: React.ReactNode }) {
warning: <WarningIcon className="text-yellow-500" size={16} />, warning: <WarningIcon className="text-yellow-500" size={16} />,
}} }}
/> />
<React.Suspense> {/* <React.Suspense> */}
<TanStackDevtools <TanStackDevtools
config={{ config={{
position: 'bottom-right', position: 'bottom-right',
@@ -92,7 +89,7 @@ function RootDocument({ children }: { children: React.ReactNode }) {
TanStackQueryDevtools, TanStackQueryDevtools,
]} ]}
/> />
</React.Suspense> {/* </React.Suspense> */}
<Scripts /> <Scripts />
</body> </body>
</html> </html>

15
src/service/audit.api.ts Normal file
View File

@@ -0,0 +1,15 @@
import { prisma } from '@/db';
import { Audit } from '@/generated/prisma/client';
export async function createAuditLog(data: Omit<Audit, 'id' | 'createdAt'>) {
try {
await prisma.audit.create({
data: {
...data,
},
});
} catch (error) {
console.log(error);
throw error;
}
}

View File

@@ -1,17 +0,0 @@
import { authMiddleware } from '@/lib/middleware';
import { saveFile } from '@/utils/disk-storage';
import { createServerFn } from '@tanstack/react-start';
import z from 'zod';
export const uploadProfileImage = createServerFn({ method: 'POST' })
.middleware([authMiddleware])
.inputValidator(z.instanceof(FormData))
.handler(async ({ data: formData }) => {
const uuid = crypto.randomUUID();
const file = formData.get('file') as File;
if (!(file instanceof File)) throw new Error('File not found');
const imageKey = `${uuid}.${file.type.split('/')[1]}`;
const buffer = Buffer.from(await file.arrayBuffer());
await saveFile(imageKey, buffer);
return { imageKey };
});

View File

@@ -1,5 +1,4 @@
import { getSession } from '@/lib/auth/session'; import { getSession } from '@/lib/auth/session';
// import { sessionPush } from '@/lib/auth/session';
import { queryOptions } from '@tanstack/react-query'; import { queryOptions } from '@tanstack/react-query';
import { getAdminSettings, getUserSettings } from './setting.api'; import { getAdminSettings, getUserSettings } from './setting.api';
@@ -9,7 +8,6 @@ export const sessionQueries = {
queryOptions({ queryOptions({
queryKey: [...sessionQueries.all, 'session'], queryKey: [...sessionQueries.all, 'session'],
queryFn: () => getSession(), queryFn: () => getSession(),
// queryFn: () => sessionPush(),
staleTime: 1000 * 60 * 20, staleTime: 1000 * 60 * 20,
retry: false, retry: false,
}), }),

View File

@@ -3,7 +3,6 @@ import { Setting } from '@/generated/prisma/client';
import { authMiddleware } from '@/lib/middleware'; import { authMiddleware } from '@/lib/middleware';
import { createServerFn } from '@tanstack/react-start'; import { createServerFn } from '@tanstack/react-start';
import { settingSchema, userSettingSchema } from './setting.schema'; import { settingSchema, userSettingSchema } from './setting.schema';
// import { settingSchema } from './setting.schema';
type AdminSettingReturn = { type AdminSettingReturn = {
[key: string]: Setting; [key: string]: Setting;
@@ -13,6 +12,7 @@ type AdminSettingReturn = {
export const getAdminSettings = createServerFn({ method: 'GET' }) export const getAdminSettings = createServerFn({ method: 'GET' })
.middleware([authMiddleware]) .middleware([authMiddleware])
.handler(async () => { .handler(async () => {
console.log('first');
const settings = await prisma.setting.findMany({ const settings = await prisma.setting.findMany({
where: { where: {
relation: 'admin', relation: 'admin',
@@ -48,6 +48,17 @@ export const updateAdminSettings = createServerFn({ method: 'POST' })
await prisma.$transaction(updates); await prisma.$transaction(updates);
// console.log(updates);
// await createAuditLog({
// action: 'update',
// tableName: 'setting',
// recordId: '',
// oldValue: '',
// newValue: JSON.stringify(data),
// userId: '',
// });
return { success: true }; return { success: true };
}); });
@@ -93,6 +104,15 @@ export const updateUserSettings = createServerFn({ method: 'POST' })
}, },
}); });
// await createAuditLog({
// action: 'update',
// tableName: 'setting',
// recordId: '',
// oldValue: '',
// newValue: '',
// userId: '',
// });
return { success: true }; return { success: true };
} catch (error) { } catch (error) {
throw error; throw error;

View File

@@ -1,26 +0,0 @@
import fs, { writeFile } from 'fs/promises';
import path from 'path';
const uploadDir = './data/avatar';
export async function saveFile(key: string, file: Buffer | File) {
if (!uploadDir) {
throw new Error('Upload directory not found');
}
const fileBuffer =
file instanceof File ? Buffer.from(await file.arrayBuffer()) : file;
const filePath = path.join(uploadDir, key);
try {
await fs.mkdir(uploadDir, { recursive: true });
await writeFile(filePath, fileBuffer);
return key;
} catch (error) {
console.error(`Error saving file: ${key}`, error);
throw new Error(
`Failed to save file: ${error instanceof Error ? error.message : 'Unknown error'}`,
);
}
}

9
src/utils/help.ts Normal file
View File

@@ -0,0 +1,9 @@
export function jsonSupport(jsonSTR: string) {
try {
const data = JSON.parse(jsonSTR);
return JSON.stringify(data, undefined, 2);
} catch {
return jsonSTR;
}
}