@allbluecn/admin-app 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +86 -0
- package/src/client.tsx +31 -0
- package/src/components/admin/admin-user-menu.tsx +90 -0
- package/src/components/admin/developer-log.tsx +356 -0
- package/src/components/ai-provider/model-list-editor.tsx +147 -0
- package/src/components/ai-provider/provider-form.tsx +434 -0
- package/src/components/ai-provider/provider-icon.tsx +43 -0
- package/src/components/ai-provider/provider-logo.tsx +87 -0
- package/src/components/ai-provider/provider-table.tsx +258 -0
- package/src/components/auth/admin-login-form.tsx +214 -0
- package/src/components/auth/auth-brand-panel.tsx +60 -0
- package/src/components/auth/auth-header.tsx +38 -0
- package/src/components/auth/auth-layout.tsx +66 -0
- package/src/components/auth/auth-providers.tsx +34 -0
- package/src/components/auth/icon-input.tsx +46 -0
- package/src/components/auth/oauth-section.tsx +51 -0
- package/src/components/auth/password-input.tsx +67 -0
- package/src/components/common/page-header.tsx +42 -0
- package/src/components/common/placeholder-page.tsx +42 -0
- package/src/components/component/component-form-dialog.tsx +348 -0
- package/src/components/component/component-import-dialog.tsx +235 -0
- package/src/components/component/component-table.tsx +153 -0
- package/src/components/data-table/data-table-pagination.tsx +114 -0
- package/src/components/data-table/data-table.tsx +218 -0
- package/src/components/data-table/table-detail-layout.tsx +99 -0
- package/src/components/dependency/changelog-dialog.tsx +108 -0
- package/src/components/dependency/columns.tsx +232 -0
- package/src/components/dependency/dependency-table.tsx +368 -0
- package/src/components/dependency/edit-dialog.tsx +200 -0
- package/src/components/knowledge-public/bookmark-form-dialog.tsx +215 -0
- package/src/components/knowledge-public/compliance-form-dialog.tsx +308 -0
- package/src/components/knowledge-public/legal-form-dialog.tsx +315 -0
- package/src/components/layout/sidebar-02/app-sidebar.tsx +160 -0
- package/src/components/layout/sidebar-02/index.tsx +33 -0
- package/src/components/layout/sidebar-02/logo.tsx +40 -0
- package/src/components/layout/sidebar-02/nav-main.tsx +153 -0
- package/src/components/layout/sidebar-02/nav-notifications.tsx +78 -0
- package/src/components/layout/sidebar-02/team-switcher.tsx +106 -0
- package/src/components/magicui/animated-theme-toggler.tsx +272 -0
- package/src/components/magicui/rainbow-button.tsx +78 -0
- package/src/components/market/columns.tsx +151 -0
- package/src/components/market/market-app-form.tsx +237 -0
- package/src/components/market/market-app-list.tsx +156 -0
- package/src/components/monitoring/error-list.tsx +143 -0
- package/src/components/monitoring/health-cards.tsx +152 -0
- package/src/components/monitoring/metrics-stats.tsx +184 -0
- package/src/components/monitoring/request-log-table.tsx +179 -0
- package/src/components/providers/theme-toggle.tsx +59 -0
- package/src/components/settings/avatar/avatar-config.ts +46 -0
- package/src/components/ui/alert-dialog.tsx +216 -0
- package/src/components/ui/alert.tsx +76 -0
- package/src/components/ui/avatar.tsx +129 -0
- package/src/components/ui/badge.tsx +66 -0
- package/src/components/ui/button.tsx +84 -0
- package/src/components/ui/card.tsx +120 -0
- package/src/components/ui/checkbox.tsx +50 -0
- package/src/components/ui/collapsible.tsx +50 -0
- package/src/components/ui/dialog.tsx +185 -0
- package/src/components/ui/dropdown-menu.tsx +286 -0
- package/src/components/ui/field.tsx +255 -0
- package/src/components/ui/input-group.tsx +171 -0
- package/src/components/ui/input.tsx +36 -0
- package/src/components/ui/label.tsx +41 -0
- package/src/components/ui/pagination.tsx +146 -0
- package/src/components/ui/select.tsx +209 -0
- package/src/components/ui/separator.tsx +45 -0
- package/src/components/ui/sheet.tsx +164 -0
- package/src/components/ui/sidebar.tsx +719 -0
- package/src/components/ui/skeleton.tsx +30 -0
- package/src/components/ui/sonner.tsx +37 -0
- package/src/components/ui/switch.tsx +48 -0
- package/src/components/ui/table.tsx +133 -0
- package/src/components/ui/textarea.tsx +35 -0
- package/src/components/ui/tooltip.tsx +74 -0
- package/src/components/user/columns.tsx +153 -0
- package/src/components/user/settings-activity-log.tsx +358 -0
- package/src/components/user/settings-profile/constants.ts +42 -0
- package/src/components/user/settings-profile/types.ts +47 -0
- package/src/components/user/settings-profile.tsx +664 -0
- package/src/components/user/user-create-dialog.tsx +137 -0
- package/src/components/user/user-filters.tsx +117 -0
- package/src/hooks/use-mobile.ts +36 -0
- package/src/instrument.client.ts +34 -0
- package/src/lib/anyhub/capabilities.ts +59 -0
- package/src/lib/anyhub/types.ts +43 -0
- package/src/lib/auth-client.ts +83 -0
- package/src/lib/auth-utils.ts +24 -0
- package/src/lib/auth.config.ts +264 -0
- package/src/lib/avatar.ts +41 -0
- package/src/lib/i18n/client.ts +32 -0
- package/src/lib/i18n/config.ts +40 -0
- package/src/lib/i18n/detect.ts +43 -0
- package/src/lib/i18n/locales/en/admin-ai.json +128 -0
- package/src/lib/i18n/locales/en/admin-billing.json +56 -0
- package/src/lib/i18n/locales/en/admin-users.json +88 -0
- package/src/lib/i18n/locales/en/common.json +877 -0
- package/src/lib/i18n/locales/en/enterprise.json +208 -0
- package/src/lib/i18n/locales/zh/admin-ai.json +128 -0
- package/src/lib/i18n/locales/zh/admin-billing.json +56 -0
- package/src/lib/i18n/locales/zh/admin-users.json +88 -0
- package/src/lib/i18n/locales/zh/common.json +877 -0
- package/src/lib/i18n/locales/zh/enterprise.json +208 -0
- package/src/lib/i18n/server.ts +18 -0
- package/src/lib/i18n/types.ts +5 -0
- package/src/lib/monitoring-benchmarks.ts +85 -0
- package/src/lib/monitoring-descriptions.ts +78 -0
- package/src/lib/prisma.ts +18 -0
- package/src/lib/router-context.ts +38 -0
- package/src/lib/session.ts +38 -0
- package/src/lib/utils.ts +23 -0
- package/src/providers/index.tsx +45 -0
- package/src/routeTree.gen.ts +1199 -0
- package/src/router.tsx +51 -0
- package/src/routes/__root.tsx +170 -0
- package/src/routes/_nav/ai-providers/$id/edit/route.lazy.tsx +74 -0
- package/src/routes/_nav/ai-providers/$id/edit/route.tsx +35 -0
- package/src/routes/_nav/ai-providers/index/route.lazy.tsx +33 -0
- package/src/routes/_nav/ai-providers/new/route.lazy.tsx +31 -0
- package/src/routes/_nav/ai-providers/new/route.tsx +20 -0
- package/src/routes/_nav/ai-providers/route.lazy.tsx +26 -0
- package/src/routes/_nav/ai-providers/route.tsx +31 -0
- package/src/routes/_nav/apps/route.lazy.tsx +30 -0
- package/src/routes/_nav/apps/route.tsx +20 -0
- package/src/routes/_nav/audit/route.lazy.tsx +100 -0
- package/src/routes/_nav/audit/route.tsx +25 -0
- package/src/routes/_nav/billing/invoices/route.lazy.tsx +86 -0
- package/src/routes/_nav/billing/invoices/route.tsx +25 -0
- package/src/routes/_nav/billing/route.lazy.tsx +48 -0
- package/src/routes/_nav/billing/route.tsx +27 -0
- package/src/routes/_nav/billing/subscriptions/$subscriptionId/route.lazy.tsx +160 -0
- package/src/routes/_nav/billing/subscriptions/$subscriptionId/route.tsx +25 -0
- package/src/routes/_nav/billing/subscriptions/route.lazy.tsx +113 -0
- package/src/routes/_nav/billing/subscriptions/route.tsx +28 -0
- package/src/routes/_nav/compliance/route.lazy.tsx +184 -0
- package/src/routes/_nav/compliance/route.tsx +25 -0
- package/src/routes/_nav/components/route.lazy.tsx +184 -0
- package/src/routes/_nav/components/route.tsx +40 -0
- package/src/routes/_nav/dashboard/route.lazy.tsx +33 -0
- package/src/routes/_nav/dashboard/route.tsx +20 -0
- package/src/routes/_nav/dependencies/route.lazy.tsx +66 -0
- package/src/routes/_nav/dependencies/route.tsx +32 -0
- package/src/routes/_nav/developer-logs/route.lazy.tsx +6 -0
- package/src/routes/_nav/developer-logs/route.tsx +14 -0
- package/src/routes/_nav/docs/route.lazy.tsx +30 -0
- package/src/routes/_nav/docs/route.tsx +20 -0
- package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +355 -0
- package/src/routes/_nav/knowledge-public/bookmarks/route.tsx +40 -0
- package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +245 -0
- package/src/routes/_nav/knowledge-public/compliance/route.tsx +40 -0
- package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +242 -0
- package/src/routes/_nav/knowledge-public/legal/route.tsx +40 -0
- package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +235 -0
- package/src/routes/_nav/licenses/$licenseId/route.tsx +25 -0
- package/src/routes/_nav/licenses/new/route.lazy.tsx +237 -0
- package/src/routes/_nav/licenses/route.lazy.tsx +143 -0
- package/src/routes/_nav/licenses/route.tsx +25 -0
- package/src/routes/_nav/market/route.lazy.tsx +31 -0
- package/src/routes/_nav/market/route.tsx +20 -0
- package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +305 -0
- package/src/routes/_nav/monitoring/ai-usage/route.tsx +3 -0
- package/src/routes/_nav/monitoring/errors/route.lazy.tsx +111 -0
- package/src/routes/_nav/monitoring/health/route.lazy.tsx +260 -0
- package/src/routes/_nav/monitoring/logs/route.lazy.tsx +165 -0
- package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +240 -0
- package/src/routes/_nav/monitoring/overview/route.lazy.tsx +138 -0
- package/src/routes/_nav/monitoring/route.lazy.tsx +68 -0
- package/src/routes/_nav/monitoring/route.tsx +20 -0
- package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +399 -0
- package/src/routes/_nav/monitoring/sentry/route.tsx +20 -0
- package/src/routes/_nav/permissions/route.lazy.tsx +504 -0
- package/src/routes/_nav/permissions/route.tsx +26 -0
- package/src/routes/_nav/route.lazy.tsx +31 -0
- package/src/routes/_nav/route.tsx +34 -0
- package/src/routes/_nav/settings/route.lazy.tsx +30 -0
- package/src/routes/_nav/settings/route.tsx +20 -0
- package/src/routes/_nav/sso/route.lazy.tsx +145 -0
- package/src/routes/_nav/sso/route.tsx +25 -0
- package/src/routes/_nav/users/$userId/route.lazy.tsx +432 -0
- package/src/routes/_nav/users/$userId/route.tsx +27 -0
- package/src/routes/_nav/users/-components/users-table.tsx +38 -0
- package/src/routes/_nav/users/route.lazy.tsx +74 -0
- package/src/routes/_nav/users/route.tsx +43 -0
- package/src/routes/api/compliance-download/$jobId.ts +35 -0
- package/src/routes/api/observability/errors.ts +41 -0
- package/src/routes/api/observability/health.ts +30 -0
- package/src/routes/api.auth.$.ts +31 -0
- package/src/routes/api.sentry-test.ts +33 -0
- package/src/routes/index/route.lazy.tsx +22 -0
- package/src/routes/index/route.tsx +24 -0
- package/src/routes/login/route.lazy.tsx +46 -0
- package/src/routes/login/route.tsx +28 -0
- package/src/routes/sentry-tunnel.ts +61 -0
- package/src/routes/setup/route.lazy.tsx +94 -0
- package/src/routes/setup/route.tsx +28 -0
- package/src/server/__tests__/admin-ai-alerts.test.ts +113 -0
- package/src/server/__tests__/licenses-issue.test.ts +98 -0
- package/src/server/admin-ai-alerts.ts +177 -0
- package/src/server/admin-ai-usage.ts +134 -0
- package/src/server/auth-helpers.ts +51 -0
- package/src/server/entitlements.ts +24 -0
- package/src/server/knowledge-public/canonical-id.ts +55 -0
- package/src/server/knowledge-public/github-sync.ts +86 -0
- package/src/server/license-issue.ts +78 -0
- package/src/server/middlewares/request.ts +26 -0
- package/src/server/observability/debug-middleware.ts +39 -0
- package/src/server/observability/error-reporter.ts +99 -0
- package/src/server/observability/health-check.ts +140 -0
- package/src/server/observability/index.ts +33 -0
- package/src/server/observability/logger.ts +49 -0
- package/src/server/observability/metrics.ts +105 -0
- package/src/server/observability/request-middleware.ts +125 -0
- package/src/server/observability/timing.ts +42 -0
- package/src/server/pro-services.ts +32 -0
- package/src/server/serverFns/admin-billing.ts +94 -0
- package/src/server/serverFns/ai-provider/create.ts +92 -0
- package/src/server/serverFns/ai-provider/delete.ts +42 -0
- package/src/server/serverFns/ai-provider/get.ts +35 -0
- package/src/server/serverFns/ai-provider/list.ts +92 -0
- package/src/server/serverFns/ai-provider/update.ts +73 -0
- package/src/server/serverFns/anyhub/market.ts +64 -0
- package/src/server/serverFns/audit.ts +57 -0
- package/src/server/serverFns/auth/session.ts +26 -0
- package/src/server/serverFns/auth/setup.ts +73 -0
- package/src/server/serverFns/compliance.ts +85 -0
- package/src/server/serverFns/components/import.ts +197 -0
- package/src/server/serverFns/components/list.ts +51 -0
- package/src/server/serverFns/components/mutations.ts +84 -0
- package/src/server/serverFns/dependency/helpers.ts +245 -0
- package/src/server/serverFns/dependency/list.ts +127 -0
- package/src/server/serverFns/dependency/sync.ts +123 -0
- package/src/server/serverFns/dependency/update.ts +51 -0
- package/src/server/serverFns/developer-log-auto-generate.ts +176 -0
- package/src/server/serverFns/developer-logs.ts +132 -0
- package/src/server/serverFns/knowledge-public/bookmarks/create.ts +53 -0
- package/src/server/serverFns/knowledge-public/bookmarks/delete.ts +31 -0
- package/src/server/serverFns/knowledge-public/bookmarks/detail.ts +32 -0
- package/src/server/serverFns/knowledge-public/bookmarks/list.ts +66 -0
- package/src/server/serverFns/knowledge-public/bookmarks/sync-all-github.ts +56 -0
- package/src/server/serverFns/knowledge-public/bookmarks/update.ts +50 -0
- package/src/server/serverFns/knowledge-public/compliance/create.ts +58 -0
- package/src/server/serverFns/knowledge-public/compliance/delete.ts +31 -0
- package/src/server/serverFns/knowledge-public/compliance/detail.ts +32 -0
- package/src/server/serverFns/knowledge-public/compliance/list.ts +59 -0
- package/src/server/serverFns/knowledge-public/compliance/update.ts +53 -0
- package/src/server/serverFns/knowledge-public/legal/create.ts +62 -0
- package/src/server/serverFns/knowledge-public/legal/delete.ts +31 -0
- package/src/server/serverFns/knowledge-public/legal/detail.ts +32 -0
- package/src/server/serverFns/knowledge-public/legal/list.ts +60 -0
- package/src/server/serverFns/knowledge-public/legal/update.ts +55 -0
- package/src/server/serverFns/licenses.ts +92 -0
- package/src/server/serverFns/locale.ts +10 -0
- package/src/server/serverFns/monitoring/check-ai-alerts.ts +13 -0
- package/src/server/serverFns/monitoring/get-ai-usage-overview.ts +25 -0
- package/src/server/serverFns/monitoring/get-errors.ts +43 -0
- package/src/server/serverFns/monitoring/get-health-settings.ts +35 -0
- package/src/server/serverFns/monitoring/get-health.ts +55 -0
- package/src/server/serverFns/monitoring/get-metrics.ts +46 -0
- package/src/server/serverFns/monitoring/get-request-logs.ts +66 -0
- package/src/server/serverFns/monitoring/report-error.ts +55 -0
- package/src/server/serverFns/monitoring/reset.ts +70 -0
- package/src/server/serverFns/permissions.ts +214 -0
- package/src/server/serverFns/sentry/config.ts +88 -0
- package/src/server/serverFns/sso-config.ts +83 -0
- package/src/server/serverFns/user/create.ts +40 -0
- package/src/server/serverFns/user/delete.ts +29 -0
- package/src/server/serverFns/user/detail.ts +45 -0
- package/src/server/serverFns/user/list.ts +56 -0
- package/src/server/serverFns/user/reset-password.ts +28 -0
- package/src/server/serverFns/user/update-role.ts +26 -0
- package/src/server/serverFns/user/update-status.ts +26 -0
- package/src/server.ts +27 -0
- package/src/start.ts +85 -0
- package/src/styles/_keyframe-animations.scss +91 -0
- package/src/styles/_variables.scss +296 -0
- package/src/styles/globals.css +200 -0
- package/src/types/start-authjs.d.ts +27 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
|
|
23
|
+
export const adminDeleteComplianceFn = createServerFn({ method: 'POST' })
|
|
24
|
+
.validator(z.object({ id: z.string() }))
|
|
25
|
+
.handler(async ({ data }) => {
|
|
26
|
+
await requireAdmin()
|
|
27
|
+
const existing = await prisma.industryCompliance.findUnique({ where: { id: data.id } })
|
|
28
|
+
if (!existing) throw new Error('未找到')
|
|
29
|
+
await prisma.industryCompliance.update({ where: { id: data.id }, data: { isDeleted: true } })
|
|
30
|
+
return { success: true }
|
|
31
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
|
|
23
|
+
export const adminGetComplianceDetailFn = createServerFn({ method: 'GET' })
|
|
24
|
+
.validator(z.object({ id: z.string() }))
|
|
25
|
+
.handler(async ({ data }) => {
|
|
26
|
+
await requireAdmin()
|
|
27
|
+
const item = await prisma.industryCompliance.findFirst({
|
|
28
|
+
where: { id: data.id, visibility: 'public', isDeleted: false },
|
|
29
|
+
})
|
|
30
|
+
if (!item) throw new Error('未找到')
|
|
31
|
+
return item
|
|
32
|
+
})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
|
|
23
|
+
const listSchema = z.object({
|
|
24
|
+
search: z.string().optional(),
|
|
25
|
+
industry: z.string().optional(),
|
|
26
|
+
region: z.string().optional(),
|
|
27
|
+
page: z.number().int().min(1).default(1),
|
|
28
|
+
pageSize: z.number().int().min(1).max(60).default(24),
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export const adminListComplianceFn = createServerFn({ method: 'GET' })
|
|
32
|
+
.validator(listSchema)
|
|
33
|
+
.handler(async ({ data }) => {
|
|
34
|
+
await requireAdmin()
|
|
35
|
+
const where: any = { visibility: 'public', isDeleted: false }
|
|
36
|
+
if (data.search) {
|
|
37
|
+
where.OR = [
|
|
38
|
+
{ title: { contains: data.search, mode: 'insensitive' } },
|
|
39
|
+
{ summary: { contains: data.search, mode: 'insensitive' } },
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
if (data.industry) where.industry = data.industry
|
|
43
|
+
if (data.region) where.region = data.region
|
|
44
|
+
const [items, total] = await Promise.all([
|
|
45
|
+
prisma.industryCompliance.findMany({
|
|
46
|
+
where,
|
|
47
|
+
select: {
|
|
48
|
+
id: true, canonicalId: true, title: true, industry: true,
|
|
49
|
+
regulatoryBody: true, region: true, summary: true, requirements: true,
|
|
50
|
+
sourceUrl: true, tags: true, visibility: true, userId: true, createdAt: true,
|
|
51
|
+
},
|
|
52
|
+
orderBy: { createdAt: 'desc' },
|
|
53
|
+
skip: (data.page - 1) * data.pageSize,
|
|
54
|
+
take: data.pageSize,
|
|
55
|
+
}),
|
|
56
|
+
prisma.industryCompliance.count({ where }),
|
|
57
|
+
])
|
|
58
|
+
return { items, total, page: data.page, pageSize: data.pageSize }
|
|
59
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
import { complianceCanonicalId } from '@/server/knowledge-public/canonical-id'
|
|
23
|
+
|
|
24
|
+
const updateSchema = z.object({
|
|
25
|
+
id: z.string(),
|
|
26
|
+
title: z.string().min(1).max(200).optional(),
|
|
27
|
+
code: z.string().max(100).optional(),
|
|
28
|
+
industry: z.string().optional(),
|
|
29
|
+
regulatoryBody: z.string().nullable().optional(),
|
|
30
|
+
region: z.string().nullable().optional(),
|
|
31
|
+
summary: z.string().max(1000).nullable().optional(),
|
|
32
|
+
content: z.string().nullable().optional(),
|
|
33
|
+
requirements: z.array(z.object({ title: z.string(), detail: z.string() })).optional(),
|
|
34
|
+
sourceUrl: z.string().url().nullable().or(z.literal('')).optional(),
|
|
35
|
+
tags: z.array(z.string()).optional(),
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
export const adminUpdateComplianceFn = createServerFn({ method: 'POST' })
|
|
39
|
+
.validator(updateSchema)
|
|
40
|
+
.handler(async ({ data }) => {
|
|
41
|
+
await requireAdmin()
|
|
42
|
+
const { id, code, ...rest } = data
|
|
43
|
+
const existing = await prisma.industryCompliance.findUnique({ where: { id } })
|
|
44
|
+
if (!existing) throw new Error('未找到')
|
|
45
|
+
const updateData: any = { ...rest }
|
|
46
|
+
if (code !== undefined || data.title !== undefined) {
|
|
47
|
+
updateData.canonicalId = complianceCanonicalId({
|
|
48
|
+
title: data.title ?? existing.title,
|
|
49
|
+
code: code ?? undefined,
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
return prisma.industryCompliance.update({ where: { id }, data: updateData, select: { id: true } })
|
|
53
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
import { legalCanonicalId } from '@/server/knowledge-public/canonical-id'
|
|
23
|
+
|
|
24
|
+
const createSchema = z.object({
|
|
25
|
+
title: z.string().min(1).max(200),
|
|
26
|
+
code: z.string().max(100).optional(),
|
|
27
|
+
jurisdiction: z.enum(['CN_NATIONAL', 'CN_LOCAL', 'OVERSEAS']),
|
|
28
|
+
region: z.string().optional(),
|
|
29
|
+
country: z.string().optional(),
|
|
30
|
+
category: z.string().min(1),
|
|
31
|
+
issuingAuthority: z.string().optional(),
|
|
32
|
+
effectiveDate: z.coerce.date().nullable().optional(),
|
|
33
|
+
summary: z.string().max(1000).optional(),
|
|
34
|
+
content: z.string().optional(),
|
|
35
|
+
sourceUrl: z.string().url().optional().or(z.literal('')),
|
|
36
|
+
tags: z.array(z.string()).default([]),
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
export const adminCreateLegalFn = createServerFn({ method: 'POST' })
|
|
40
|
+
.validator(createSchema)
|
|
41
|
+
.handler(async ({ data }) => {
|
|
42
|
+
const session = await requireAdmin()
|
|
43
|
+
return prisma.legalRegulation.create({
|
|
44
|
+
data: {
|
|
45
|
+
canonicalId: legalCanonicalId({ title: data.title, code: data.code }),
|
|
46
|
+
title: data.title,
|
|
47
|
+
jurisdiction: data.jurisdiction,
|
|
48
|
+
region: data.region || null,
|
|
49
|
+
country: data.country || null,
|
|
50
|
+
category: data.category,
|
|
51
|
+
issuingAuthority: data.issuingAuthority || null,
|
|
52
|
+
effectiveDate: data.effectiveDate ?? null,
|
|
53
|
+
summary: data.summary || null,
|
|
54
|
+
content: data.content || null,
|
|
55
|
+
sourceUrl: data.sourceUrl || null,
|
|
56
|
+
tags: data.tags,
|
|
57
|
+
visibility: 'public',
|
|
58
|
+
userId: session.user!.id!,
|
|
59
|
+
},
|
|
60
|
+
select: { id: true },
|
|
61
|
+
})
|
|
62
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
|
|
23
|
+
export const adminDeleteLegalFn = createServerFn({ method: 'POST' })
|
|
24
|
+
.validator(z.object({ id: z.string() }))
|
|
25
|
+
.handler(async ({ data }) => {
|
|
26
|
+
await requireAdmin()
|
|
27
|
+
const existing = await prisma.legalRegulation.findUnique({ where: { id: data.id } })
|
|
28
|
+
if (!existing) throw new Error('未找到')
|
|
29
|
+
await prisma.legalRegulation.update({ where: { id: data.id }, data: { isDeleted: true } })
|
|
30
|
+
return { success: true }
|
|
31
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
|
|
23
|
+
export const adminGetLegalDetailFn = createServerFn({ method: 'GET' })
|
|
24
|
+
.validator(z.object({ id: z.string() }))
|
|
25
|
+
.handler(async ({ data }) => {
|
|
26
|
+
await requireAdmin()
|
|
27
|
+
const item = await prisma.legalRegulation.findFirst({
|
|
28
|
+
where: { id: data.id, visibility: 'public', isDeleted: false },
|
|
29
|
+
})
|
|
30
|
+
if (!item) throw new Error('未找到')
|
|
31
|
+
return item
|
|
32
|
+
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
|
|
23
|
+
const listSchema = z.object({
|
|
24
|
+
search: z.string().optional(),
|
|
25
|
+
jurisdiction: z.string().optional(),
|
|
26
|
+
category: z.string().optional(),
|
|
27
|
+
page: z.number().int().min(1).default(1),
|
|
28
|
+
pageSize: z.number().int().min(1).max(60).default(24),
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export const adminListLegalFn = createServerFn({ method: 'GET' })
|
|
32
|
+
.validator(listSchema)
|
|
33
|
+
.handler(async ({ data }) => {
|
|
34
|
+
await requireAdmin()
|
|
35
|
+
const where: any = { visibility: 'public', isDeleted: false }
|
|
36
|
+
if (data.search) {
|
|
37
|
+
where.OR = [
|
|
38
|
+
{ title: { contains: data.search, mode: 'insensitive' } },
|
|
39
|
+
{ summary: { contains: data.search, mode: 'insensitive' } },
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
if (data.jurisdiction) where.jurisdiction = data.jurisdiction
|
|
43
|
+
if (data.category) where.category = data.category
|
|
44
|
+
const [items, total] = await Promise.all([
|
|
45
|
+
prisma.legalRegulation.findMany({
|
|
46
|
+
where,
|
|
47
|
+
select: {
|
|
48
|
+
id: true, canonicalId: true, title: true, jurisdiction: true,
|
|
49
|
+
region: true, country: true, category: true, summary: true,
|
|
50
|
+
issuingAuthority: true, effectiveDate: true, sourceUrl: true,
|
|
51
|
+
tags: true, visibility: true, userId: true, createdAt: true,
|
|
52
|
+
},
|
|
53
|
+
orderBy: { createdAt: 'desc' },
|
|
54
|
+
skip: (data.page - 1) * data.pageSize,
|
|
55
|
+
take: data.pageSize,
|
|
56
|
+
}),
|
|
57
|
+
prisma.legalRegulation.count({ where }),
|
|
58
|
+
])
|
|
59
|
+
return { items, total, page: data.page, pageSize: data.pageSize }
|
|
60
|
+
})
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
import { legalCanonicalId } from '@/server/knowledge-public/canonical-id'
|
|
23
|
+
|
|
24
|
+
const updateSchema = z.object({
|
|
25
|
+
id: z.string(),
|
|
26
|
+
title: z.string().min(1).max(200).optional(),
|
|
27
|
+
code: z.string().max(100).optional(),
|
|
28
|
+
jurisdiction: z.enum(['CN_NATIONAL', 'CN_LOCAL', 'OVERSEAS']).optional(),
|
|
29
|
+
region: z.string().nullable().optional(),
|
|
30
|
+
country: z.string().nullable().optional(),
|
|
31
|
+
category: z.string().optional(),
|
|
32
|
+
issuingAuthority: z.string().nullable().optional(),
|
|
33
|
+
effectiveDate: z.coerce.date().nullable().optional(),
|
|
34
|
+
summary: z.string().max(1000).nullable().optional(),
|
|
35
|
+
content: z.string().nullable().optional(),
|
|
36
|
+
sourceUrl: z.string().url().nullable().or(z.literal('')).optional(),
|
|
37
|
+
tags: z.array(z.string()).optional(),
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
export const adminUpdateLegalFn = createServerFn({ method: 'POST' })
|
|
41
|
+
.validator(updateSchema)
|
|
42
|
+
.handler(async ({ data }) => {
|
|
43
|
+
await requireAdmin()
|
|
44
|
+
const { id, code, ...rest } = data
|
|
45
|
+
const existing = await prisma.legalRegulation.findUnique({ where: { id } })
|
|
46
|
+
if (!existing) throw new Error('未找到')
|
|
47
|
+
const updateData: any = { ...rest }
|
|
48
|
+
if (code !== undefined || data.title !== undefined) {
|
|
49
|
+
updateData.canonicalId = legalCanonicalId({
|
|
50
|
+
title: data.title ?? existing.title,
|
|
51
|
+
code: code ?? undefined,
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
return prisma.legalRegulation.update({ where: { id }, data: updateData, select: { id: true } })
|
|
55
|
+
})
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { z } from 'zod'
|
|
20
|
+
import { prisma } from '@allbluecn/database'
|
|
21
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
22
|
+
import { issueLicense } from '@/server/license-issue'
|
|
23
|
+
|
|
24
|
+
const listSchema = z.object({
|
|
25
|
+
page: z.number().default(1),
|
|
26
|
+
pageSize: z.number().default(20),
|
|
27
|
+
search: z.string().optional(),
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
export const listLicensesFn = createServerFn({ method: 'GET' })
|
|
31
|
+
.validator(listSchema)
|
|
32
|
+
.handler(async ({ data }) => {
|
|
33
|
+
await requireAdmin()
|
|
34
|
+
const where: any = data.search
|
|
35
|
+
? {
|
|
36
|
+
OR: [
|
|
37
|
+
{ customerName: { contains: data.search } },
|
|
38
|
+
{ customerEmail: { contains: data.search } },
|
|
39
|
+
{ key: { contains: data.search } },
|
|
40
|
+
],
|
|
41
|
+
}
|
|
42
|
+
: {}
|
|
43
|
+
|
|
44
|
+
const [items, total] = await Promise.all([
|
|
45
|
+
prisma.licenseKey.findMany({
|
|
46
|
+
where,
|
|
47
|
+
include: { _count: { select: { activations: true } } },
|
|
48
|
+
orderBy: { issuedAt: 'desc' },
|
|
49
|
+
skip: (data.page - 1) * data.pageSize,
|
|
50
|
+
take: data.pageSize,
|
|
51
|
+
}),
|
|
52
|
+
prisma.licenseKey.count({ where }),
|
|
53
|
+
])
|
|
54
|
+
return { items, total }
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
export const getLicenseDetailFn = createServerFn({ method: 'GET' })
|
|
58
|
+
.validator(z.object({ licenseId: z.string() }))
|
|
59
|
+
.handler(async ({ data }) => {
|
|
60
|
+
await requireAdmin()
|
|
61
|
+
const license = await prisma.licenseKey.findUnique({
|
|
62
|
+
where: { id: data.licenseId },
|
|
63
|
+
include: { activations: true, issuedBy: true },
|
|
64
|
+
})
|
|
65
|
+
if (!license) throw new Error('License 不存在')
|
|
66
|
+
return license
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
export const revokeLicenseFn = createServerFn({ method: 'POST' })
|
|
70
|
+
.validator(z.object({ licenseId: z.string() }))
|
|
71
|
+
.handler(async ({ data }) => {
|
|
72
|
+
await requireAdmin()
|
|
73
|
+
await prisma.licenseKey.update({
|
|
74
|
+
where: { id: data.licenseId },
|
|
75
|
+
data: { revokedAt: new Date() },
|
|
76
|
+
})
|
|
77
|
+
return { success: true }
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
export const issueLicenseFn = createServerFn({ method: 'POST' })
|
|
81
|
+
.validator(
|
|
82
|
+
z.object({
|
|
83
|
+
customerName: z.string().min(1),
|
|
84
|
+
customerEmail: z.string().email(),
|
|
85
|
+
customerId: z.string().min(1),
|
|
86
|
+
plan: z.string().min(1),
|
|
87
|
+
seats: z.number().int().min(1).max(10000),
|
|
88
|
+
features: z.record(z.string(), z.boolean()),
|
|
89
|
+
expiresAt: z.string().datetime().nullable(),
|
|
90
|
+
}),
|
|
91
|
+
)
|
|
92
|
+
.handler(async ({ data }) => issueLicense(data))
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
3
|
+
import { getRequest } from '@tanstack/react-start/server'
|
|
4
|
+
import { detectLocale } from '@/lib/i18n/detect'
|
|
5
|
+
import type { AppLocale } from '@/lib/i18n/config'
|
|
6
|
+
|
|
7
|
+
export const getLocaleFn = createServerFn({ method: 'GET' }).handler(async (): Promise<AppLocale> => {
|
|
8
|
+
const request = getRequest()
|
|
9
|
+
return request ? detectLocale(request, null) : 'zh'
|
|
10
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { checkAiAlerts } from '@/server/admin-ai-alerts'
|
|
4
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
5
|
+
|
|
6
|
+
export const checkAiAlertsFn = createServerFn({ method: 'GET' })
|
|
7
|
+
.validator(z.object({
|
|
8
|
+
hours: z.number().default(24),
|
|
9
|
+
}))
|
|
10
|
+
.handler(async ({ data }) => {
|
|
11
|
+
await requireAdmin()
|
|
12
|
+
return await checkAiAlerts({ hours: data.hours })
|
|
13
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { getAiUsageOverview } from '@/server/admin-ai-usage'
|
|
4
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
5
|
+
|
|
6
|
+
export const getAiUsageOverviewFn = createServerFn({ method: 'GET' })
|
|
7
|
+
.validator(z.object({
|
|
8
|
+
days: z.number().default(30).optional(),
|
|
9
|
+
workspace: z.object({
|
|
10
|
+
page: z.number().default(1),
|
|
11
|
+
perPage: z.number().default(10),
|
|
12
|
+
}).optional(),
|
|
13
|
+
user: z.object({
|
|
14
|
+
page: z.number().default(1),
|
|
15
|
+
perPage: z.number().default(10),
|
|
16
|
+
}).optional(),
|
|
17
|
+
}))
|
|
18
|
+
.handler(async ({ data }) => {
|
|
19
|
+
await requireAdmin()
|
|
20
|
+
return await getAiUsageOverview({
|
|
21
|
+
days: data.days,
|
|
22
|
+
workspace: data.workspace,
|
|
23
|
+
user: data.user,
|
|
24
|
+
})
|
|
25
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { prisma } from '@allbluecn/database'
|
|
20
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
21
|
+
|
|
22
|
+
export const getErrors = createServerFn({ method: 'GET' })
|
|
23
|
+
.handler(async () => {
|
|
24
|
+
await requireAdmin()
|
|
25
|
+
|
|
26
|
+
const errors = await prisma.monitoringErrorReport.findMany({
|
|
27
|
+
orderBy: { lastSeen: 'desc' },
|
|
28
|
+
take: 200,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const totalErrors = await prisma.monitoringErrorReport.aggregate({
|
|
32
|
+
_count: { _all: true },
|
|
33
|
+
_sum: { count: true },
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
errors,
|
|
38
|
+
summary: {
|
|
39
|
+
uniqueErrors: totalErrors._count._all,
|
|
40
|
+
totalOccurrences: totalErrors._sum.count || 0,
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
19
|
+
import { requireAdmin } from '@/server/auth-helpers'
|
|
20
|
+
import { getHealthCheckEnabled, setHealthCheckEnabled } from '@/server/observability'
|
|
21
|
+
|
|
22
|
+
export const getHealthCheckSettings = createServerFn({ method: 'GET' })
|
|
23
|
+
.handler(async () => {
|
|
24
|
+
await requireAdmin()
|
|
25
|
+
const enabled = await getHealthCheckEnabled()
|
|
26
|
+
return { enabled }
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
export const updateHealthCheckSettings = createServerFn({ method: 'POST' })
|
|
30
|
+
.validator((data: { enabled: boolean }) => data)
|
|
31
|
+
.handler(async ({ data }) => {
|
|
32
|
+
await requireAdmin()
|
|
33
|
+
await setHealthCheckEnabled(data.enabled)
|
|
34
|
+
return { ok: true, enabled: data.enabled }
|
|
35
|
+
})
|