diff --git a/src/auth/models/org.ts b/src/auth/models/org.ts index 63d6063..01b9828 100644 --- a/src/auth/models/org.ts +++ b/src/auth/models/org.ts @@ -1,7 +1,7 @@ import { useContextKey } from '@kevisual/context'; import { User } from './user.ts'; import { db } from '../../modules/db.ts'; -import { cfOrgs, cfUser } from '../../db/drizzle/schema.ts'; +import { cfOrgs, cfUser } from '../../db/schema.ts'; import { eq, inArray, sql, InferSelectModel, InferInsertModel } from 'drizzle-orm'; const orgsTable = cfOrgs; diff --git a/src/auth/models/user-secret.ts b/src/auth/models/user-secret.ts index 46880c2..5d154e4 100644 --- a/src/auth/models/user-secret.ts +++ b/src/auth/models/user-secret.ts @@ -4,7 +4,7 @@ import { User } from './user.ts'; import { oauth, jwksManager } from '../oauth/auth.ts'; import { OauthUser } from '../oauth/oauth.ts'; import { db } from '../../modules/db.ts'; -import { cfUserSecrets, cfUser } from '../../db/drizzle/schema.ts'; +import { cfUserSecrets, cfUser } from '../../db/schema.ts'; import { eq, InferSelectModel, InferInsertModel } from 'drizzle-orm'; const userSecretsTable = cfUserSecrets; diff --git a/src/auth/models/user.ts b/src/auth/models/user.ts index 04c5be9..8480396 100644 --- a/src/auth/models/user.ts +++ b/src/auth/models/user.ts @@ -8,7 +8,7 @@ import { OauthUser } from '../oauth/oauth.ts'; import { db } from '../../modules/db.ts'; import { Org } from './org.ts'; import { UserSecret } from './user-secret.ts'; -import { cfUser, cfOrgs, cfUserSecrets } from '../../db/drizzle/schema.ts'; +import { cfUser, cfOrgs, cfUserSecrets } from '../../db/schema.ts'; import { eq, sql, InferSelectModel, InferInsertModel } from 'drizzle-orm'; // 类型定义 diff --git a/src/db/drizzle/schema.ts b/src/db/drizzle/schema.ts index ccb2cbd..9c18cdd 100644 --- a/src/db/drizzle/schema.ts +++ b/src/db/drizzle/schema.ts @@ -39,18 +39,6 @@ export const appsTrades = pgTable("apps_trades", { unique("apps_trades_out_trade_no_key").on(table.outTradeNo), ]); -export const cfOrgs = pgTable("cf_orgs", { - id: uuid().primaryKey().notNull().defaultRandom(), - username: varchar({ length: 255 }).notNull(), - users: jsonb().default([]), - createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), - updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), - deletedAt: timestamp({ withTimezone: true, mode: 'string' }), - description: varchar({ length: 255 }), -}, (table) => [ - unique("cf_orgs_username_key").on(table.username), -]); - export const cfRouterCode = pgTable("cf_router_code", { id: uuid().primaryKey().defaultRandom(), path: varchar({ length: 255 }).notNull(), @@ -69,40 +57,6 @@ export const cfRouterCode = pgTable("cf_router_code", { deletedAt: timestamp({ withTimezone: true, mode: 'string' }), }); -export const cfUser = pgTable("cf_user", { - id: uuid().primaryKey().notNull().defaultRandom(), - username: varchar({ length: 255 }).notNull(), - password: varchar({ length: 255 }), - salt: varchar({ length: 255 }), - needChangePassword: boolean().default(false), - createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), - updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), - description: text(), - data: jsonb().default({}), - deletedAt: timestamp({ withTimezone: true, mode: 'string' }), - type: varchar({ length: 255 }).default('user'), - owner: uuid(), - orgId: uuid(), - email: varchar({ length: 255 }), - avatar: text(), - nickname: text(), -}, (table) => [ - unique("cf_user_username_key").on(table.username), -]); - -export const cfUserSecrets = pgTable("cf_user_secrets", { - id: uuid().primaryKey().notNull().defaultRandom(), - description: text(), - status: varchar({ length: 255 }).default('active'), - title: text(), - expiredTime: timestamp({ withTimezone: true, mode: 'string' }), - token: varchar({ length: 255 }).default('').notNull(), - userId: uuid(), - data: jsonb().default({}), - orgId: uuid(), - createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), - updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), -}); export const chatHistories = pgTable("chat_histories", { id: uuid().primaryKey().defaultRandom(), diff --git a/src/db/schema.ts b/src/db/schema.ts index 2e90063..60d35ee 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -4,4 +4,6 @@ export * from './drizzle/schema.ts'; export * from './schemas/n-code-schema.ts' -export * from './schemas/life-schema.ts' \ No newline at end of file +export * from './schemas/life-schema.ts' + +export * from './schemas/user.ts' \ No newline at end of file diff --git a/src/db/schemas/user.ts b/src/db/schemas/user.ts new file mode 100644 index 0000000..d405c13 --- /dev/null +++ b/src/db/schemas/user.ts @@ -0,0 +1,66 @@ + +import { pgTable, serial, text, jsonb, varchar, timestamp, unique, uuid, doublePrecision, json, integer, boolean, index, uniqueIndex, pgEnum } from "drizzle-orm/pg-core" +import { sql, sum } from "drizzle-orm" +import { last } from "es-toolkit"; + +// cf 是 code flow 的缩写; +export const cfOrgs = pgTable("cf_orgs", { + id: uuid().primaryKey().notNull().defaultRandom(), + username: varchar({ length: 255 }).notNull(), + users: jsonb().default([]), + createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), + updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), + deletedAt: timestamp({ withTimezone: true, mode: 'string' }), + description: varchar({ length: 255 }), +}, (table) => [ + unique("cf_orgs_username_key").on(table.username), +]); + +export const cfUser = pgTable("cf_user", { + id: uuid().primaryKey().notNull().defaultRandom(), + username: varchar({ length: 255 }).notNull(), + password: varchar({ length: 255 }), + salt: varchar({ length: 255 }), + needChangePassword: boolean().default(false), + createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), + updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), + description: text(), + data: jsonb().default({}), + deletedAt: timestamp({ withTimezone: true, mode: 'string' }), + type: varchar({ length: 255 }).default('user'), + owner: uuid(), + orgId: uuid(), + email: varchar({ length: 255 }), + avatar: text(), + nickname: text(), +}, (table) => [ + unique("cf_user_username_key").on(table.username), +]); + +export const cfUserSecrets = pgTable("cf_user_secrets", { + id: uuid().primaryKey().notNull().defaultRandom(), + description: text(), + status: varchar({ length: 255 }).default('active'), + title: text(), + expiredTime: timestamp({ withTimezone: true, mode: 'string' }), + token: varchar({ length: 255 }).default('').notNull(), + userId: uuid(), + data: jsonb().default({}), + orgId: uuid(), + createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), + updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), +}); + +// 用户活动日志 +export const cfUserActivity = pgTable("cf_user_activity", { + id: uuid().primaryKey().notNull().defaultRandom(), + userId: uuid(), + // 上次登录时间 + lastLoginAt: timestamp({ withTimezone: true, mode: 'string' }), + // 上次活动时间 + lastActivityAt: timestamp({ withTimezone: true, mode: 'string' }), + // 上次使用时间 + lastUsedAt: timestamp({ withTimezone: true, mode: 'string' }), + createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), + updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), +}); \ No newline at end of file diff --git a/src/routes/app-manager/list.ts b/src/routes/app-manager/list.ts index 6a29cbe..ea2f0fc 100644 --- a/src/routes/app-manager/list.ts +++ b/src/routes/app-manager/list.ts @@ -550,9 +550,10 @@ app const checkUsername = username || tokenUser.username; const files = await getMinioListAndSetToAppList({ username: checkUsername, appKey, version }); const newFiles = files.map((item) => { + const name = item.name.replace(`data/${uid}/`, checkUsername + '/'); return { - name: item.name.replace(`${checkUsername}/${appKey}/${version}/`, ''), - path: item.name, + name: name.replace(`${checkUsername}/${appKey}/${version}/`, ''), + path: name, }; }); const appListData = appList.data as AppData; diff --git a/src/routes/app-manager/module/app-domain-drizzle.ts b/src/routes/app-manager/module/app-domain-drizzle.ts index 179903e..23889b3 100644 --- a/src/routes/app-manager/module/app-domain-drizzle.ts +++ b/src/routes/app-manager/module/app-domain-drizzle.ts @@ -1,5 +1,5 @@ import { InferSelectModel, InferInsertModel } from 'drizzle-orm'; -import { kvAppDomain } from '@/db/drizzle/schema.ts'; +import { kvAppDomain } from '@/db/schema.ts'; import { redis } from '@/modules/redis.ts'; // 审核,通过,驳回 diff --git a/src/routes/app-manager/module/app-drizzle.ts b/src/routes/app-manager/module/app-drizzle.ts index 78a258d..ed66973 100644 --- a/src/routes/app-manager/module/app-drizzle.ts +++ b/src/routes/app-manager/module/app-drizzle.ts @@ -1,5 +1,5 @@ import { InferSelectModel, InferInsertModel } from 'drizzle-orm'; -import { kvApp, kvAppList } from '@/db/drizzle/schema.ts'; +import { kvApp, kvAppList } from '@/db/schema.ts'; type AppPermissionType = 'public' | 'private' | 'protected';