@allbluecn/admin-app 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/allblue-ui/package.json +6 -0
- package/allblue-ui/src/components/confirm-dialog.tsx +94 -0
- package/allblue-ui/src/components/infinite-scroll-sentinel.tsx +37 -0
- package/allblue-ui/src/components/notion-avatar.tsx +126 -0
- package/allblue-ui/src/components/user-avatar.tsx +82 -0
- package/{src/components → allblue-ui/src}/data-table/data-table-pagination.tsx +14 -5
- package/{src/components → allblue-ui/src}/data-table/data-table.tsx +1 -1
- package/{src/components → allblue-ui/src}/data-table/table-detail-layout.tsx +5 -6
- package/allblue-ui/src/hooks/use-load-more.ts +57 -0
- package/allblue-ui/src/index.ts +31 -0
- package/allblue-ui/src/lib/datetime.ts +226 -0
- package/allblue-ui/src/lib/sanitize.ts +18 -0
- package/allblue-ui/src/lib/utils.ts +1 -0
- package/{src/components → allblue-ui/src}/ui/alert-dialog.tsx +1 -3
- package/{src/components → allblue-ui/src}/ui/checkbox.tsx +0 -1
- package/{src/components → allblue-ui/src}/ui/dialog.tsx +1 -1
- package/{src/components → allblue-ui/src}/ui/dropdown-menu.tsx +0 -2
- package/{src/components → allblue-ui/src}/ui/field.tsx +2 -2
- package/{src/components → allblue-ui/src}/ui/input-group.tsx +3 -4
- package/allblue-ui/src/ui/input.tsx +19 -0
- package/{src/components → allblue-ui/src}/ui/pagination.tsx +1 -1
- package/{src/components → allblue-ui/src}/ui/select.tsx +0 -2
- package/{src/components → allblue-ui/src}/ui/separator.tsx +1 -0
- package/{src/components → allblue-ui/src}/ui/sheet.tsx +1 -2
- package/{src/components → allblue-ui/src}/ui/sidebar.tsx +7 -7
- package/{src/components → allblue-ui/src}/ui/switch.tsx +1 -0
- package/{src/components → allblue-ui/src}/ui/table.tsx +0 -2
- package/{src/components → allblue-ui/src}/ui/toast.tsx +44 -18
- package/{src/components → allblue-ui/src}/ui/tooltip.tsx +1 -0
- package/package.json +21 -18
- package/src/components/admin/admin-user-menu.tsx +4 -4
- package/src/components/admin/developer-log.tsx +16 -32
- package/src/components/ai-memory/memory-facts-panel.tsx +30 -70
- package/src/components/ai-prompts/preview-panel.tsx +1 -1
- package/src/components/ai-prompts/prompt-editor.tsx +8 -9
- package/src/components/ai-prompts/prompt-table.tsx +6 -6
- package/src/components/ai-prompts/section-editor.tsx +3 -3
- package/src/components/ai-prompts/variable-panel.tsx +2 -2
- package/src/components/ai-prompts/version-history.tsx +21 -41
- package/src/components/ai-provider/model-list-editor.tsx +2 -3
- package/src/components/ai-provider/provider-form.tsx +7 -7
- package/src/components/ai-provider/provider-table.tsx +17 -40
- package/src/components/auth/admin-login-form.tsx +7 -7
- package/src/components/auth/icon-input.tsx +2 -2
- package/src/components/auth/password-input.tsx +2 -2
- package/src/components/component/component-form-dialog.tsx +10 -18
- package/src/components/component/component-import-dialog.tsx +6 -6
- package/src/components/component/component-preview.tsx +311 -0
- package/src/components/component/component-table.tsx +3 -3
- package/src/components/dependency/changelog-dialog.tsx +2 -2
- package/src/components/dependency/columns.tsx +3 -3
- package/src/components/dependency/dependency-table.tsx +7 -7
- package/src/components/dependency/edit-dialog.tsx +8 -8
- package/src/components/invitations/invitations-page.tsx +26 -49
- package/src/components/knowledge-public/bookmark-form-dialog.tsx +6 -6
- package/src/components/knowledge-public/compliance-form-dialog.tsx +6 -6
- package/src/components/knowledge-public/legal-form-dialog.tsx +7 -7
- package/src/components/layout/sidebar-02/app-sidebar.tsx +1 -2
- package/src/components/layout/sidebar-02/index.tsx +1 -1
- package/src/components/layout/sidebar-02/nav-main.tsx +2 -3
- package/src/components/layout/sidebar-02/nav-notifications.tsx +3 -3
- package/src/components/market/columns.tsx +4 -4
- package/src/components/market/market-app-form.tsx +6 -7
- package/src/components/market/market-app-list.tsx +14 -29
- package/src/components/monitoring/error-list.tsx +2 -2
- package/src/components/monitoring/metrics-stats.tsx +1 -1
- package/src/components/monitoring/request-log-table.tsx +2 -2
- package/src/components/oauth-providers/provider-page.tsx +20 -38
- package/src/components/permissions/assign-dialog.tsx +135 -0
- package/src/components/permissions/create-role-dialog.tsx +135 -0
- package/src/components/permissions/types.ts +49 -0
- package/src/components/user/columns.tsx +6 -6
- package/src/components/user/settings-activity-log.tsx +7 -7
- package/src/components/user/settings-profile/avatar-uploader.tsx +118 -0
- package/src/components/user/settings-profile/social-links.tsx +63 -0
- package/src/components/user/settings-profile.tsx +26 -125
- package/src/components/user/user-create-dialog.tsx +6 -6
- package/src/components/user/user-detail/error-boundary.tsx +19 -0
- package/src/components/user/user-detail/user-detail-dialogs.tsx +203 -0
- package/src/components/user/user-filters.tsx +4 -4
- package/src/lib/auth/page-gate.ts +28 -0
- package/src/lib/auth.config.ts +25 -9
- package/src/lib/i18n/detect.ts +1 -1
- package/src/lib/loader-serial.ts +14 -0
- package/src/providers/index.tsx +1 -1
- package/src/routeTree.gen.ts +67 -78
- package/src/routes/__root.tsx +4 -4
- package/src/routes/_nav/audit/route.lazy.tsx +1 -2
- package/src/routes/_nav/compliance/route.lazy.tsx +5 -3
- package/src/routes/_nav/components/route.lazy.tsx +14 -34
- package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +18 -38
- package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +18 -38
- package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +6 -6
- package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +3 -3
- package/src/routes/_nav/licenses/new/route.lazy.tsx +5 -5
- package/src/routes/_nav/licenses/route.lazy.tsx +1 -1
- package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +2 -2
- package/src/routes/_nav/monitoring/errors/route.lazy.tsx +10 -10
- package/src/routes/_nav/monitoring/errors/route.tsx +7 -0
- package/src/routes/_nav/monitoring/health/route.lazy.tsx +13 -15
- package/src/routes/_nav/monitoring/health/route.tsx +14 -0
- package/src/routes/_nav/monitoring/logs/route.lazy.tsx +24 -9
- package/src/routes/_nav/monitoring/logs/route.tsx +13 -0
- package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +12 -14
- package/src/routes/_nav/monitoring/metrics/route.tsx +7 -0
- package/src/routes/_nav/monitoring/overview/route.lazy.tsx +14 -13
- package/src/routes/_nav/monitoring/overview/route.tsx +17 -0
- package/src/routes/_nav/monitoring/route.lazy.tsx +6 -6
- package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +2 -2
- package/src/routes/_nav/permissions/route.lazy.tsx +21 -311
- package/src/routes/_nav/permissions/route.tsx +1 -1
- package/src/routes/_nav/route.tsx +5 -13
- package/src/routes/_nav/sso/route.lazy.tsx +2 -3
- package/src/routes/_nav/users/$userId/route.lazy.tsx +91 -156
- package/src/routes/_nav/users/-components/users-table.tsx +1 -1
- package/src/routes/_nav/users/route.lazy.tsx +1 -1
- package/src/routes/login/route.lazy.tsx +1 -1
- package/src/routes/setup/route.lazy.tsx +2 -2
- package/src/server/__tests__/admin-billing.test.ts +191 -16
- package/src/server/__tests__/compliance.test.ts +44 -7
- package/src/server/__tests__/permissions.test.ts +10 -5
- package/src/server/__tests__/prompt-defaults.test.ts +3 -3
- package/src/server/admin-ai-alerts.ts +2 -1
- package/src/server/admin-ai-usage.ts +2 -1
- package/src/server/ai-memory/store.ts +6 -2
- package/src/server/{serverFns/ai-prompts → ai-prompts}/prompt-defaults.ts +5 -3
- package/src/server/{serverFns/dependency → dependency}/helpers.ts +4 -3
- package/src/server/knowledge-public/github-sync.ts +2 -1
- package/src/server/license-issue.ts +2 -1
- package/src/server/middlewares/auth-rate-limit.ts +117 -0
- package/src/server/observability/health-check.ts +4 -1
- package/src/server/observability/metrics.ts +17 -15
- package/src/server/observability/request-middleware.ts +2 -1
- package/src/server/observability/timing.ts +14 -16
- package/src/server/serverFns/admin-billing.ts +107 -12
- package/src/server/serverFns/ai-memory/list-users.ts +2 -1
- package/src/server/serverFns/ai-prompts/activate.ts +2 -1
- package/src/server/serverFns/ai-prompts/get.ts +3 -2
- package/src/server/serverFns/ai-prompts/list.ts +3 -2
- package/src/server/serverFns/ai-prompts/rollback.ts +3 -1
- package/src/server/serverFns/ai-prompts/save.ts +5 -3
- package/src/server/serverFns/ai-provider/create.ts +4 -1
- package/src/server/serverFns/ai-provider/delete.ts +4 -1
- package/src/server/serverFns/ai-provider/get.ts +4 -1
- package/src/server/serverFns/ai-provider/list.ts +28 -1
- package/src/server/serverFns/ai-provider/seed-from-seed.ts +2 -1
- package/src/server/serverFns/ai-provider/update.ts +4 -1
- package/src/server/serverFns/anyhub/market.ts +8 -1
- package/src/server/serverFns/audit.ts +14 -1
- package/src/server/serverFns/auth/setup.ts +3 -1
- package/src/server/serverFns/compliance.ts +32 -3
- package/src/server/serverFns/components/import.ts +69 -14
- package/src/server/serverFns/components/list.ts +4 -1
- package/src/server/serverFns/components/mutations.ts +9 -1
- package/src/server/serverFns/dependency/list.ts +28 -5
- package/src/server/serverFns/dependency/sync.ts +7 -2
- package/src/server/serverFns/dependency/update.ts +4 -1
- package/src/server/serverFns/developer-log-auto-generate.ts +63 -32
- package/src/server/serverFns/developer-logs.ts +5 -1
- package/src/server/serverFns/invitations.ts +7 -1
- package/src/server/serverFns/knowledge-public/bookmarks/create.ts +2 -1
- package/src/server/serverFns/knowledge-public/bookmarks/delete.ts +2 -1
- package/src/server/serverFns/knowledge-public/bookmarks/detail.ts +2 -1
- package/src/server/serverFns/knowledge-public/bookmarks/list.ts +2 -1
- package/src/server/serverFns/knowledge-public/bookmarks/sync-all-github.ts +2 -1
- package/src/server/serverFns/knowledge-public/bookmarks/update.ts +2 -1
- package/src/server/serverFns/knowledge-public/compliance/create.ts +2 -1
- package/src/server/serverFns/knowledge-public/compliance/delete.ts +2 -1
- package/src/server/serverFns/knowledge-public/compliance/detail.ts +2 -1
- package/src/server/serverFns/knowledge-public/compliance/list.ts +2 -1
- package/src/server/serverFns/knowledge-public/compliance/update.ts +2 -1
- package/src/server/serverFns/knowledge-public/legal/create.ts +2 -1
- package/src/server/serverFns/knowledge-public/legal/delete.ts +2 -1
- package/src/server/serverFns/knowledge-public/legal/detail.ts +2 -1
- package/src/server/serverFns/knowledge-public/legal/list.ts +2 -1
- package/src/server/serverFns/knowledge-public/legal/update.ts +2 -1
- package/src/server/serverFns/licenses.ts +8 -2
- package/src/server/serverFns/monitoring/get-errors.ts +2 -1
- package/src/server/serverFns/monitoring/get-health.ts +2 -1
- package/src/server/serverFns/monitoring/get-metrics.ts +2 -1
- package/src/server/serverFns/monitoring/get-request-logs.ts +2 -1
- package/src/server/serverFns/monitoring/report-error.ts +2 -1
- package/src/server/serverFns/monitoring/reset.ts +2 -1
- package/src/server/serverFns/oauth-providers.ts +4 -1
- package/src/server/serverFns/permissions.ts +18 -11
- package/src/server/serverFns/sentry/config.ts +11 -8
- package/src/server/serverFns/sso-config.ts +17 -2
- package/src/server/serverFns/user/create.ts +6 -1
- package/src/server/serverFns/user/delete.ts +6 -1
- package/src/server/serverFns/user/detail.ts +5 -2
- package/src/server/serverFns/user/list.ts +19 -4
- package/src/server/serverFns/user/reset-password.ts +10 -2
- package/src/server/serverFns/user/update-role.ts +10 -2
- package/src/server/serverFns/user/update-status.ts +10 -2
- package/src/styles/globals.css +4 -0
- package/src/components/ui/input.tsx +0 -19
- /package/{src → allblue-ui/src}/hooks/use-mobile.ts +0 -0
- /package/{src → allblue-ui/src}/lib/avatar.ts +0 -0
- /package/{src/components → allblue-ui/src}/ui/alert.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/avatar.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/badge.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/button.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/card.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/collapsible.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/label.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/skeleton.tsx +0 -0
- /package/{src/components → allblue-ui/src}/ui/textarea.tsx +0 -0
- /package/src/routes/{api.auth.$.ts → api/auth/$.ts} +0 -0
- /package/src/routes/{api.sentry-test.ts → api/sentry-test.ts} +0 -0
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { createServerFn } from '@tanstack/react-start'
|
|
19
19
|
import { z } from 'zod'
|
|
20
|
-
import {
|
|
20
|
+
import { getPrisma } from '@allbluecn/database/get-prisma'
|
|
21
21
|
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
22
|
|
|
23
23
|
const listSubscriptionsInput = z.object({
|
|
@@ -31,11 +31,17 @@ const listSubscriptionsInput = z.object({
|
|
|
31
31
|
export const listAllSubscriptionsFn = createServerFn({ method: 'GET' })
|
|
32
32
|
.validator(listSubscriptionsInput)
|
|
33
33
|
.handler(async ({ data }) => {
|
|
34
|
+
const prisma = await getPrisma()
|
|
34
35
|
await requireAdmin()
|
|
35
36
|
|
|
36
37
|
const where: any = {}
|
|
37
38
|
if (data.search) {
|
|
38
|
-
|
|
39
|
+
// 修复:Subscription 无 workspace 关系(OSS schema 订阅挂在 userId 上),
|
|
40
|
+
// 检索走 user name/email;原 `workspace.name contains` 会 PrismaClientValidationError
|
|
41
|
+
where.OR = [
|
|
42
|
+
{ user: { name: { contains: data.search } } },
|
|
43
|
+
{ user: { email: { contains: data.search } } },
|
|
44
|
+
]
|
|
39
45
|
}
|
|
40
46
|
if (data.plan) {
|
|
41
47
|
where.planId = data.plan
|
|
@@ -44,32 +50,76 @@ export const listAllSubscriptionsFn = createServerFn({ method: 'GET' })
|
|
|
44
50
|
where.status = data.status
|
|
45
51
|
}
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
// DB-05:include 全行(含 provider 凭据 id 等)改白名单 select。
|
|
54
|
+
// 响应 shape 保持消费方键位不变:workspace.name 由 user 映射、seats 由
|
|
55
|
+
// plan.maxSeats + addonSeats 计算(schema 注释的实际上限口径)。
|
|
56
|
+
const [subs, total] = await Promise.all([
|
|
48
57
|
prisma.subscription.findMany({
|
|
49
58
|
where,
|
|
50
|
-
include: { plan: true, workspace: true },
|
|
51
59
|
orderBy: { createdAt: 'desc' },
|
|
52
60
|
skip: (data.page - 1) * data.pageSize,
|
|
53
61
|
take: data.pageSize,
|
|
62
|
+
select: {
|
|
63
|
+
id: true,
|
|
64
|
+
status: true,
|
|
65
|
+
addonSeats: true,
|
|
66
|
+
currentPeriodEnd: true,
|
|
67
|
+
plan: { select: { name: true, maxSeats: true } },
|
|
68
|
+
user: { select: { name: true, email: true } },
|
|
69
|
+
},
|
|
54
70
|
}),
|
|
55
71
|
prisma.subscription.count({ where }),
|
|
56
72
|
])
|
|
57
73
|
|
|
74
|
+
const items = subs.map((s) => ({
|
|
75
|
+
id: s.id,
|
|
76
|
+
workspace: { name: s.user?.name ?? s.user?.email ?? null },
|
|
77
|
+
plan: { name: s.plan?.name ?? null },
|
|
78
|
+
status: s.status,
|
|
79
|
+
seats: (s.plan?.maxSeats ?? 0) + s.addonSeats,
|
|
80
|
+
currentPeriodEnd: s.currentPeriodEnd,
|
|
81
|
+
}))
|
|
82
|
+
|
|
58
83
|
return { items, total, page: data.page, pageSize: data.pageSize }
|
|
59
84
|
})
|
|
60
85
|
|
|
61
86
|
export const getSubscriptionDetailFn = createServerFn({ method: 'GET' })
|
|
62
87
|
.validator(z.object({ subscriptionId: z.string() }))
|
|
63
88
|
.handler(async ({ data }) => {
|
|
89
|
+
const prisma = await getPrisma()
|
|
64
90
|
await requireAdmin()
|
|
65
|
-
|
|
91
|
+
const detail = await prisma.subscription.findUnique({
|
|
66
92
|
where: { id: data.subscriptionId },
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
93
|
+
select: {
|
|
94
|
+
id: true,
|
|
95
|
+
status: true,
|
|
96
|
+
addonSeats: true,
|
|
97
|
+
currentPeriodStart: true,
|
|
98
|
+
currentPeriodEnd: true,
|
|
99
|
+
providerSubscriptionId: true,
|
|
100
|
+
plan: { select: { id: true, name: true, displayName: true, maxSeats: true } },
|
|
101
|
+
user: { select: { id: true, name: true, email: true } },
|
|
102
|
+
invoices: {
|
|
103
|
+
orderBy: { createdAt: 'desc' },
|
|
104
|
+
select: {
|
|
105
|
+
id: true,
|
|
106
|
+
status: true,
|
|
107
|
+
currency: true,
|
|
108
|
+
amountDue: true,
|
|
109
|
+
periodStart: true,
|
|
110
|
+
periodEnd: true,
|
|
111
|
+
createdAt: true,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
71
114
|
},
|
|
72
115
|
})
|
|
116
|
+
if (!detail) return null
|
|
117
|
+
// 同 listAllSubscriptionsFn:workspace/seats 由 user/plan+addonSeats 映射,键位不变
|
|
118
|
+
return {
|
|
119
|
+
...detail,
|
|
120
|
+
workspace: { name: detail.user?.name ?? detail.user?.email ?? null },
|
|
121
|
+
seats: (detail.plan?.maxSeats ?? 0) + detail.addonSeats,
|
|
122
|
+
}
|
|
73
123
|
})
|
|
74
124
|
|
|
75
125
|
export const listAllInvoicesFn = createServerFn({ method: 'GET' })
|
|
@@ -77,18 +127,63 @@ export const listAllInvoicesFn = createServerFn({ method: 'GET' })
|
|
|
77
127
|
z.object({
|
|
78
128
|
page: z.number().default(1),
|
|
79
129
|
pageSize: z.number().default(20),
|
|
130
|
+
// DB-02:补 where 参数化(status 过滤;UI 暂无筛选器,默认不过滤——
|
|
131
|
+
// 账单审计要求全量分页可见,避免默认隐藏历史发票)
|
|
132
|
+
status: z.string().optional(),
|
|
80
133
|
}),
|
|
81
134
|
)
|
|
82
135
|
.handler(async ({ data }) => {
|
|
136
|
+
const prisma = await getPrisma()
|
|
83
137
|
await requireAdmin()
|
|
84
|
-
const
|
|
138
|
+
const where: any = {}
|
|
139
|
+
if (data.status) {
|
|
140
|
+
where.status = data.status
|
|
141
|
+
}
|
|
142
|
+
// DB-05:白名单 select;workspace.name 由 subscription.user 映射(键位不变)
|
|
143
|
+
const [rows, total] = await Promise.all([
|
|
85
144
|
prisma.invoice.findMany({
|
|
145
|
+
where,
|
|
86
146
|
orderBy: { createdAt: 'desc' },
|
|
87
|
-
include: { subscription: { include: { workspace: true, plan: true } } },
|
|
88
147
|
skip: (data.page - 1) * data.pageSize,
|
|
89
148
|
take: data.pageSize,
|
|
149
|
+
select: {
|
|
150
|
+
id: true,
|
|
151
|
+
status: true,
|
|
152
|
+
currency: true,
|
|
153
|
+
amountDue: true,
|
|
154
|
+
amountPaid: true,
|
|
155
|
+
periodStart: true,
|
|
156
|
+
periodEnd: true,
|
|
157
|
+
createdAt: true,
|
|
158
|
+
subscription: {
|
|
159
|
+
select: {
|
|
160
|
+
id: true,
|
|
161
|
+
plan: { select: { name: true } },
|
|
162
|
+
user: { select: { name: true, email: true } },
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
90
166
|
}),
|
|
91
|
-
prisma.invoice.count(),
|
|
167
|
+
prisma.invoice.count({ where }),
|
|
92
168
|
])
|
|
169
|
+
const items = rows.map((inv) => ({
|
|
170
|
+
id: inv.id,
|
|
171
|
+
status: inv.status,
|
|
172
|
+
currency: inv.currency,
|
|
173
|
+
amountDue: inv.amountDue,
|
|
174
|
+
periodStart: inv.periodStart,
|
|
175
|
+
periodEnd: inv.periodEnd,
|
|
176
|
+
createdAt: inv.createdAt,
|
|
177
|
+
subscription: inv.subscription
|
|
178
|
+
? {
|
|
179
|
+
id: inv.subscription.id,
|
|
180
|
+
workspace: {
|
|
181
|
+
name:
|
|
182
|
+
inv.subscription.user?.name ?? inv.subscription.user?.email ?? null,
|
|
183
|
+
},
|
|
184
|
+
plan: { name: inv.subscription.plan?.name ?? null },
|
|
185
|
+
}
|
|
186
|
+
: null,
|
|
187
|
+
}))
|
|
93
188
|
return { items, total, page: data.page, pageSize: data.pageSize }
|
|
94
189
|
})
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-memory/list-users.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import { requireAdmin } from "../../auth-helpers"
|
|
23
23
|
|
|
24
24
|
/** 列出可查询的用户(admin 按 userId 查记忆事实的前置选择) */
|
|
25
25
|
export const listMemoryUsersFn = createServerFn({ method: "GET" })
|
|
26
26
|
.validator(z.object({}))
|
|
27
27
|
.handler(async () => {
|
|
28
|
+
const prisma = await getPrisma()
|
|
28
29
|
await requireAdmin()
|
|
29
30
|
const users = await prisma.user.findMany({
|
|
30
31
|
orderBy: [{ username: "asc" }],
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-prompts/activate.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import { requireAdmin } from "../../auth-helpers"
|
|
23
23
|
|
|
24
24
|
const activateSchema = z.object({
|
|
@@ -30,6 +30,7 @@ const activateSchema = z.object({
|
|
|
30
30
|
export const activatePromptTemplateFn = createServerFn({ method: "POST" })
|
|
31
31
|
.validator(activateSchema)
|
|
32
32
|
.handler(async ({ data }) => {
|
|
33
|
+
const prisma = await getPrisma()
|
|
33
34
|
const session = await requireAdmin()
|
|
34
35
|
const updatedBy = session.user?.id ?? null
|
|
35
36
|
const existing = await prisma.systemPromptTemplate.findUnique({
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-prompts/get.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import type {
|
|
23
23
|
SystemPromptSectionDTO,
|
|
24
24
|
SystemPromptTemplateDTO,
|
|
25
25
|
} from "@allbluecn/kernel"
|
|
26
26
|
import { requireAdmin } from "../../auth-helpers"
|
|
27
|
-
import { backfillMissingPromptTemplates } from "
|
|
27
|
+
import { backfillMissingPromptTemplates } from "@/server/ai-prompts/prompt-defaults"
|
|
28
28
|
|
|
29
29
|
const getInput = z.object({ key: z.string() })
|
|
30
30
|
|
|
@@ -40,6 +40,7 @@ export interface PromptVersionSummary {
|
|
|
40
40
|
export const getPromptTemplateFn = createServerFn({ method: "GET" })
|
|
41
41
|
.validator(getInput)
|
|
42
42
|
.handler(async ({ data }) => {
|
|
43
|
+
const prisma = await getPrisma()
|
|
43
44
|
await requireAdmin()
|
|
44
45
|
await backfillMissingPromptTemplates()
|
|
45
46
|
const template = await prisma.systemPromptTemplate.findUnique({
|
|
@@ -18,15 +18,16 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-prompts/list.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import { requireAdmin } from "../../auth-helpers"
|
|
23
|
-
import { backfillMissingPromptTemplates } from "
|
|
23
|
+
import { backfillMissingPromptTemplates } from "@/server/ai-prompts/prompt-defaults"
|
|
24
24
|
|
|
25
25
|
/** 列出提示词模板(列表页只取轻量字段,详情经 get 加载) */
|
|
26
26
|
export const listPromptTemplatesFn = createServerFn({ method: "GET" })
|
|
27
27
|
.validator(z.object({}))
|
|
28
28
|
.handler(
|
|
29
29
|
async () => {
|
|
30
|
+
const prisma = await getPrisma()
|
|
30
31
|
await requireAdmin()
|
|
31
32
|
await backfillMissingPromptTemplates()
|
|
32
33
|
const templates = await prisma.systemPromptTemplate.findMany({
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-prompts/rollback.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
|
+
import type { Prisma } from "@allbluecn/database"
|
|
22
23
|
import type {
|
|
23
24
|
PromptVariableDefDTO,
|
|
24
25
|
SystemPromptSectionDTO,
|
|
@@ -39,6 +40,7 @@ function toJson(value: unknown): Prisma.InputJsonValue {
|
|
|
39
40
|
export const rollbackPromptTemplateFn = createServerFn({ method: "POST" })
|
|
40
41
|
.validator(rollbackSchema)
|
|
41
42
|
.handler(async ({ data }) => {
|
|
43
|
+
const prisma = await getPrisma()
|
|
42
44
|
const session = await requireAdmin()
|
|
43
45
|
const updatedBy = session.user?.id ?? null
|
|
44
46
|
return prisma.$transaction(async (tx) => {
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-prompts/save.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
|
+
import type { Prisma } from "@allbluecn/database"
|
|
22
23
|
import { requireAdmin } from "../../auth-helpers"
|
|
23
24
|
import { promptSectionSchema, promptVariableSchema } from "./prompt-schemas"
|
|
24
|
-
import { getPromptDefinition } from "@allbluecn/
|
|
25
|
-
import { BACKFILL_SNAPSHOT_NOTE } from "
|
|
25
|
+
import { getPromptDefinition } from "@allbluecn/kernel"
|
|
26
|
+
import { BACKFILL_SNAPSHOT_NOTE } from "@/server/ai-prompts/prompt-defaults"
|
|
26
27
|
|
|
27
28
|
const saveSchema = z.object({
|
|
28
29
|
key: z.string(),
|
|
@@ -42,6 +43,7 @@ function toJson(value: unknown): Prisma.InputJsonValue {
|
|
|
42
43
|
export const savePromptTemplateFn = createServerFn({ method: "POST" })
|
|
43
44
|
.validator(saveSchema)
|
|
44
45
|
.handler(async ({ data }) => {
|
|
46
|
+
const prisma = await getPrisma()
|
|
45
47
|
const session = await requireAdmin()
|
|
46
48
|
const updatedBy = session.user?.id ?? null
|
|
47
49
|
return prisma.$transaction(async (tx) => {
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-provider/create.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import {
|
|
23
23
|
ADAPTER_KIND_VALUES,
|
|
24
24
|
PROVIDER_CATEGORY_VALUES,
|
|
25
25
|
} from "@allbluecn/kernel"
|
|
26
|
+
import { requireAdmin } from "@/server/auth-helpers"
|
|
26
27
|
|
|
27
28
|
const modelSchema = z.object({
|
|
28
29
|
id: z.string().min(1),
|
|
@@ -62,6 +63,8 @@ const createInput = z.object({
|
|
|
62
63
|
export const createAiProviderAdminFn = createServerFn({ method: "POST" })
|
|
63
64
|
.validator(createInput)
|
|
64
65
|
.handler(async ({ data }) => {
|
|
66
|
+
const prisma = await getPrisma()
|
|
67
|
+
await requireAdmin()
|
|
65
68
|
const exists = await prisma.aiProvider.findUnique({
|
|
66
69
|
where: { providerId: data.providerId },
|
|
67
70
|
})
|
|
@@ -18,11 +18,14 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-provider/delete.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
|
+
import { requireAdmin } from "@/server/auth-helpers"
|
|
22
23
|
|
|
23
24
|
export const deleteAiProviderAdminFn = createServerFn({ method: "POST" })
|
|
24
25
|
.validator(z.object({ id: z.string() }))
|
|
25
26
|
.handler(async ({ data }) => {
|
|
27
|
+
const prisma = await getPrisma()
|
|
28
|
+
await requireAdmin()
|
|
26
29
|
const provider = await prisma.aiProvider.findUnique({
|
|
27
30
|
where: { id: data.id },
|
|
28
31
|
select: { providerId: true },
|
|
@@ -18,12 +18,15 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-provider/get.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import type { AiProviderMeta } from "@allbluecn/kernel"
|
|
23
|
+
import { requireAdmin } from "@/server/auth-helpers"
|
|
23
24
|
|
|
24
25
|
export const getAiProviderAdminFn = createServerFn({ method: "GET" })
|
|
25
26
|
.validator(z.object({ id: z.string() }))
|
|
26
27
|
.handler(async ({ data }) => {
|
|
28
|
+
const prisma = await getPrisma()
|
|
29
|
+
await requireAdmin()
|
|
27
30
|
const p = await prisma.aiProvider.findUnique({ where: { id: data.id } })
|
|
28
31
|
if (!p) throw new Error("未找到服务商")
|
|
29
32
|
return {
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-provider/list.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import type { AiProviderRow } from "@allbluecn/kernel"
|
|
23
|
+
import { requireAdmin } from "@/server/auth-helpers"
|
|
23
24
|
|
|
24
25
|
const listInput = z.object({
|
|
25
26
|
search: z.string().optional(),
|
|
@@ -31,6 +32,8 @@ const listInput = z.object({
|
|
|
31
32
|
export const listAiProvidersAdminFn = createServerFn({ method: "GET" })
|
|
32
33
|
.validator(listInput)
|
|
33
34
|
.handler(async ({ data }) => {
|
|
35
|
+
const prisma = await getPrisma()
|
|
36
|
+
await requireAdmin()
|
|
34
37
|
const where: {
|
|
35
38
|
OR?: Array<Record<string, unknown>>
|
|
36
39
|
enabled?: boolean
|
|
@@ -46,9 +49,33 @@ export const listAiProvidersAdminFn = createServerFn({ method: "GET" })
|
|
|
46
49
|
if (data.enabled !== undefined) where.enabled = data.enabled
|
|
47
50
|
if (data.category) where.category = data.category
|
|
48
51
|
|
|
52
|
+
// DB-05:白名单 select——消费方 AiProviderRow 映射用到全部列,显式列出防
|
|
53
|
+
// 未来新增敏感列被整行外泄
|
|
49
54
|
const providers = await prisma.aiProvider.findMany({
|
|
50
55
|
where,
|
|
51
56
|
orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
|
|
57
|
+
select: {
|
|
58
|
+
id: true,
|
|
59
|
+
providerId: true,
|
|
60
|
+
displayName: true,
|
|
61
|
+
brandName: true,
|
|
62
|
+
description: true,
|
|
63
|
+
category: true,
|
|
64
|
+
adapterKind: true,
|
|
65
|
+
defaultBaseUrl: true,
|
|
66
|
+
keyUrl: true,
|
|
67
|
+
docsUrl: true,
|
|
68
|
+
keyPlaceholder: true,
|
|
69
|
+
iconSlug: true,
|
|
70
|
+
brandColor: true,
|
|
71
|
+
badge: true,
|
|
72
|
+
isLocal: true,
|
|
73
|
+
enabled: true,
|
|
74
|
+
models: true,
|
|
75
|
+
sortOrder: true,
|
|
76
|
+
createdAt: true,
|
|
77
|
+
updatedAt: true,
|
|
78
|
+
},
|
|
52
79
|
})
|
|
53
80
|
|
|
54
81
|
const providerIds = providers.map((p) => p.providerId)
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-provider/seed-from-seed.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import { SEED_AI_PROVIDERS } from "@allbluecn/kernel"
|
|
23
23
|
import { requireAdmin } from "../../auth-helpers"
|
|
24
24
|
|
|
25
25
|
export const seedFromSeedFn = createServerFn({ method: "POST" })
|
|
26
26
|
.validator(z.object({}))
|
|
27
27
|
.handler(async () => {
|
|
28
|
+
const prisma = await getPrisma()
|
|
28
29
|
await requireAdmin()
|
|
29
30
|
const created: string[] = []
|
|
30
31
|
const skipped: string[] = []
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
// apps/admin/src/server/serverFns/ai-provider/update.ts
|
|
19
19
|
import { createServerFn } from "@tanstack/react-start"
|
|
20
20
|
import { z } from "zod"
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
22
22
|
import {
|
|
23
23
|
ADAPTER_KIND_VALUES,
|
|
24
24
|
PROVIDER_CATEGORY_VALUES,
|
|
25
25
|
} from "@allbluecn/kernel"
|
|
26
|
+
import { requireAdmin } from "@/server/auth-helpers"
|
|
26
27
|
|
|
27
28
|
const modelSchema = z.object({
|
|
28
29
|
id: z.string().min(1),
|
|
@@ -55,6 +56,8 @@ const updateInput = z.object({
|
|
|
55
56
|
export const updateAiProviderAdminFn = createServerFn({ method: "POST" })
|
|
56
57
|
.validator(updateInput)
|
|
57
58
|
.handler(async ({ data }) => {
|
|
59
|
+
const prisma = await getPrisma()
|
|
60
|
+
await requireAdmin()
|
|
58
61
|
const { id, ...rest } = data
|
|
59
62
|
const update: Record<string, unknown> = {}
|
|
60
63
|
for (const [k, v] of Object.entries(rest)) {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
import { createServerFn } from '@tanstack/react-start'
|
|
19
19
|
import { z } from 'zod'
|
|
20
|
-
import {
|
|
20
|
+
import { getPrisma } from '@allbluecn/database/get-prisma'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
21
22
|
|
|
22
23
|
const listInput = z.object({
|
|
23
24
|
page: z.number().default(1),
|
|
@@ -29,6 +30,8 @@ const listInput = z.object({
|
|
|
29
30
|
export const listMarketAppsFn = createServerFn({ method: 'GET' })
|
|
30
31
|
.validator(listInput)
|
|
31
32
|
.handler(async ({ data }) => {
|
|
33
|
+
const prisma = await getPrisma()
|
|
34
|
+
await requireAdmin()
|
|
32
35
|
const { page, pageSize, search, category } = data
|
|
33
36
|
const where: any = {}
|
|
34
37
|
if (search) where.name = { contains: search, mode: 'insensitive' }
|
|
@@ -52,6 +55,8 @@ const updateInput = z.object({
|
|
|
52
55
|
export const updateMarketAppFn = createServerFn({ method: 'POST' })
|
|
53
56
|
.validator(updateInput)
|
|
54
57
|
.handler(async ({ data }) => {
|
|
58
|
+
const prisma = await getPrisma()
|
|
59
|
+
await requireAdmin()
|
|
55
60
|
const { id, ...update } = data
|
|
56
61
|
return prisma.anyHubMarketApp.update({ where: { id }, data: update })
|
|
57
62
|
})
|
|
@@ -59,6 +64,8 @@ export const updateMarketAppFn = createServerFn({ method: 'POST' })
|
|
|
59
64
|
export const deleteMarketAppFn = createServerFn({ method: 'POST' })
|
|
60
65
|
.validator(z.object({ id: z.string() }))
|
|
61
66
|
.handler(async ({ data }) => {
|
|
67
|
+
const prisma = await getPrisma()
|
|
68
|
+
await requireAdmin()
|
|
62
69
|
await prisma.anyHubMarketApp.delete({ where: { id: data.id } })
|
|
63
70
|
return { success: true }
|
|
64
71
|
})
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { createServerFn } from '@tanstack/react-start'
|
|
19
19
|
import { z } from 'zod'
|
|
20
|
-
import {
|
|
20
|
+
import { getPrisma } from '@allbluecn/database/get-prisma'
|
|
21
21
|
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
22
|
import { requireFeature } from '@/server/entitlements'
|
|
23
23
|
|
|
@@ -34,6 +34,7 @@ const querySchema = z.object({
|
|
|
34
34
|
export const queryAuditLogsFn = createServerFn({ method: 'GET' })
|
|
35
35
|
.validator(querySchema)
|
|
36
36
|
.handler(async ({ data }) => {
|
|
37
|
+
const prisma = await getPrisma()
|
|
37
38
|
await requireAdmin()
|
|
38
39
|
await requireFeature(undefined, 'audit')
|
|
39
40
|
const where: any = {
|
|
@@ -50,6 +51,18 @@ export const queryAuditLogsFn = createServerFn({ method: 'GET' })
|
|
|
50
51
|
orderBy: { createdAt: 'desc' },
|
|
51
52
|
skip: (data.page - 1) * data.pageSize,
|
|
52
53
|
take: data.pageSize,
|
|
54
|
+
// DB-05:metadata Json 载荷列表页不渲染,白名单排除
|
|
55
|
+
select: {
|
|
56
|
+
id: true,
|
|
57
|
+
workspaceId: true,
|
|
58
|
+
userId: true,
|
|
59
|
+
action: true,
|
|
60
|
+
resourceType: true,
|
|
61
|
+
resourceId: true,
|
|
62
|
+
ip: true,
|
|
63
|
+
userAgent: true,
|
|
64
|
+
createdAt: true,
|
|
65
|
+
},
|
|
53
66
|
}),
|
|
54
67
|
prisma.auditLog.count({ where }),
|
|
55
68
|
])
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { createServerFn } from '@tanstack/react-start'
|
|
19
19
|
import { z } from 'zod'
|
|
20
|
-
import {
|
|
20
|
+
import { getPrisma } from '@allbluecn/database/get-prisma'
|
|
21
21
|
import bcrypt from 'bcryptjs'
|
|
22
22
|
import { getRandomConfig, presetBgColors } from '@/components/settings/avatar/avatar-config'
|
|
23
23
|
|
|
@@ -28,6 +28,7 @@ function pickBgColor(seed: string) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export const checkAdminExistsFn = createServerFn({ method: 'GET' }).handler(async () => {
|
|
31
|
+
const prisma = await getPrisma()
|
|
31
32
|
const count = await prisma.user.count({
|
|
32
33
|
where: { role: { in: ['ADMIN', 'SUPER_ADMIN'] } },
|
|
33
34
|
})
|
|
@@ -43,6 +44,7 @@ const setupSchema = z.object({
|
|
|
43
44
|
export const setupAdminFn = createServerFn({ method: 'POST' })
|
|
44
45
|
.validator(setupSchema)
|
|
45
46
|
.handler(async ({ data }) => {
|
|
47
|
+
const prisma = await getPrisma()
|
|
46
48
|
const count = await prisma.user.count({
|
|
47
49
|
where: { role: 'SUPER_ADMIN' },
|
|
48
50
|
})
|
|
@@ -18,14 +18,23 @@
|
|
|
18
18
|
import { createServerFn } from '@tanstack/react-start'
|
|
19
19
|
import { getRequest } from '@tanstack/react-start/server'
|
|
20
20
|
import { z } from 'zod'
|
|
21
|
-
import {
|
|
21
|
+
import { getPrisma } from '@allbluecn/database/get-prisma'
|
|
22
22
|
import { getProService } from '@/server/pro-services'
|
|
23
23
|
import { requireAdmin } from '@/server/auth-helpers'
|
|
24
24
|
import { requireFeature } from '@/server/entitlements'
|
|
25
25
|
|
|
26
26
|
export const listComplianceExportsFn = createServerFn({ method: 'GET' })
|
|
27
|
-
.validator(
|
|
27
|
+
.validator(
|
|
28
|
+
z.object({
|
|
29
|
+
page: z.number().default(1),
|
|
30
|
+
pageSize: z.number().default(20),
|
|
31
|
+
// DB-02:where 参数化(status 过滤);UI 暂无筛选器,默认不过滤——
|
|
32
|
+
// 合规任务列表含已过期项的状态呈现,默认隐藏会破坏审计可见性
|
|
33
|
+
status: z.string().optional(),
|
|
34
|
+
}),
|
|
35
|
+
)
|
|
28
36
|
.handler(async ({ data }) => {
|
|
37
|
+
const prisma = await getPrisma()
|
|
29
38
|
const request = getRequest()
|
|
30
39
|
await requireAdmin()
|
|
31
40
|
await requireFeature(request, 'compliance')
|
|
@@ -33,13 +42,31 @@ export const listComplianceExportsFn = createServerFn({ method: 'GET' })
|
|
|
33
42
|
if (compliance) {
|
|
34
43
|
return compliance.listJobs({ page: data.page, pageSize: data.pageSize })
|
|
35
44
|
}
|
|
45
|
+
const where: any = {}
|
|
46
|
+
if (data.status) {
|
|
47
|
+
where.status = data.status
|
|
48
|
+
}
|
|
49
|
+
// DB-05:content(导出负载,可极大)与 downloadUrl/completedAt 列表页不消费,
|
|
50
|
+
// 白名单排除;下载走 /api/compliance-download/:id,不需要 downloadUrl
|
|
36
51
|
const [items, total] = await Promise.all([
|
|
37
52
|
prisma.complianceExport.findMany({
|
|
53
|
+
where,
|
|
38
54
|
orderBy: { createdAt: 'desc' },
|
|
39
55
|
skip: (data.page - 1) * data.pageSize,
|
|
40
56
|
take: data.pageSize,
|
|
57
|
+
select: {
|
|
58
|
+
id: true,
|
|
59
|
+
type: true,
|
|
60
|
+
scope: true,
|
|
61
|
+
targetId: true,
|
|
62
|
+
status: true,
|
|
63
|
+
expiresAt: true,
|
|
64
|
+
error: true,
|
|
65
|
+
requestedBy: true,
|
|
66
|
+
createdAt: true,
|
|
67
|
+
},
|
|
41
68
|
}),
|
|
42
|
-
prisma.complianceExport.count(),
|
|
69
|
+
prisma.complianceExport.count({ where }),
|
|
43
70
|
])
|
|
44
71
|
return { items, total }
|
|
45
72
|
})
|
|
@@ -54,6 +81,7 @@ export const createComplianceExportFn = createServerFn({ method: 'POST' })
|
|
|
54
81
|
}),
|
|
55
82
|
)
|
|
56
83
|
.handler(async ({ data }) => {
|
|
84
|
+
const prisma = await getPrisma()
|
|
57
85
|
const request = getRequest()
|
|
58
86
|
await requireAdmin()
|
|
59
87
|
await requireFeature(request, 'compliance')
|
|
@@ -70,6 +98,7 @@ export const createComplianceExportFn = createServerFn({ method: 'POST' })
|
|
|
70
98
|
export const executeComplianceJobFn = createServerFn({ method: 'POST' })
|
|
71
99
|
.validator(z.object({ jobId: z.string() }))
|
|
72
100
|
.handler(async ({ data }) => {
|
|
101
|
+
const prisma = await getPrisma()
|
|
73
102
|
const request = getRequest()
|
|
74
103
|
await requireAdmin()
|
|
75
104
|
await requireFeature(request, 'compliance')
|