优化用户查找逻辑,新增根据微信 UnionId 查找用户的方法,简化数据库查询

This commit is contained in:
2026-02-07 02:36:29 +08:00
parent 885e04e301
commit 0be7627bd1
6 changed files with 72 additions and 72 deletions

View File

@@ -164,21 +164,38 @@ export class User {
return users.length > 0 ? new User(users[0]) : null; return users.length > 0 ? new User(users[0]) : null;
} }
/**
* 根据微信 UnionId 查找用户
*/
static async findByUnionId(unionId: string): Promise<User | null> {
const users = await db
.select()
.from(usersTable)
.where(sql`${usersTable.data}->>'wxUnionId' = ${unionId}`)
.limit(1);
return users.length > 0 ? new User(users[0]) : null;
}
/** /**
* 根据条件查找一个用户 * 根据条件查找一个用户
*/ */
static async findOne(where: { username?: string; id?: string }): Promise<User | null> { static async findOne(where: { username?: string; id?: string; email?: string }): Promise<User | null> {
let query = db.select().from(usersTable); let query = db.select().from(usersTable);
if (where.username) { if (where.username) {
query = query.where(eq(usersTable.username, where.username)) as any; query = query.where(eq(usersTable.username, where.username)) as any;
} else if (where.id) { } else if (where.id) {
query = query.where(eq(usersTable.id, where.id)) as any; query = query.where(eq(usersTable.id, where.id)) as any;
} else if (where.email) {
query = query.where(eq(usersTable.email, where.email)) as any;
} }
const users = await query.limit(1); const users = await query.limit(1);
return users.length > 0 ? new User(users[0]) : null; return users.length > 0 ? new User(users[0]) : null;
} }
static findByunionid(){
}
static async createUser(username: string, password?: string, description?: string) { static async createUser(username: string, password?: string, description?: string) {
const user = await User.findOne({ username }); const user = await User.findOne({ username });
@@ -324,7 +341,6 @@ export class User {
*/ */
async getOrgs() { async getOrgs() {
let id = this.id; let id = this.id;
console.log('type', this.type, this.tokenUser)
if (this.type === 'org') { if (this.type === 'org') {
if (this.tokenUser && this.tokenUser.uid) { if (this.tokenUser && this.tokenUser.uid) {
id = this.tokenUser.uid; id = this.tokenUser.uid;

View File

@@ -3,19 +3,8 @@ import { sql, sum } from "drizzle-orm"
export const enumCfRouterCodeType = pgEnum("enum_cf_router_code_type", ['route', 'middleware']) export const enumCfRouterCodeType = pgEnum("enum_cf_router_code_type", ['route', 'middleware'])
export const testPromptTools = pgTable("TestPromptTools", {
id: serial().primaryKey().notNull(),
template: text().notNull(),
args: jsonb().notNull(),
process: jsonb().notNull(),
type: varchar({ length: 255 }).notNull(),
createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
});
export const aiAgent = pgTable("ai_agent", { export const aiAgent = pgTable("ai_agent", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
type: varchar({ length: 255 }).notNull(), type: varchar({ length: 255 }).notNull(),
baseUrl: varchar({ length: 255 }).notNull(), baseUrl: varchar({ length: 255 }).notNull(),
apiKey: varchar({ length: 255 }).notNull(), apiKey: varchar({ length: 255 }).notNull(),
@@ -35,7 +24,7 @@ export const aiAgent = pgTable("ai_agent", {
]); ]);
export const appsTrades = pgTable("apps_trades", { export const appsTrades = pgTable("apps_trades", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
outTradeNo: varchar("out_trade_no", { length: 255 }).notNull(), outTradeNo: varchar("out_trade_no", { length: 255 }).notNull(),
money: integer().notNull(), money: integer().notNull(),
subject: text().notNull(), subject: text().notNull(),
@@ -63,7 +52,7 @@ export const cfOrgs = pgTable("cf_orgs", {
]); ]);
export const cfRouterCode = pgTable("cf_router_code", { export const cfRouterCode = pgTable("cf_router_code", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
path: varchar({ length: 255 }).notNull(), path: varchar({ length: 255 }).notNull(),
key: varchar({ length: 255 }).notNull(), key: varchar({ length: 255 }).notNull(),
active: boolean().default(false), active: boolean().default(false),
@@ -116,7 +105,7 @@ export const cfUserSecrets = pgTable("cf_user_secrets", {
}); });
export const chatHistories = pgTable("chat_histories", { export const chatHistories = pgTable("chat_histories", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
data: json(), data: json(),
chatId: uuid(), chatId: uuid(),
chatPromptId: uuid(), chatPromptId: uuid(),
@@ -129,7 +118,7 @@ export const chatHistories = pgTable("chat_histories", {
}); });
export const chatPrompts = pgTable("chat_prompts", { export const chatPrompts = pgTable("chat_prompts", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
title: varchar({ length: 255 }).notNull(), title: varchar({ length: 255 }).notNull(),
description: text(), description: text(),
data: json(), data: json(),
@@ -141,7 +130,7 @@ export const chatPrompts = pgTable("chat_prompts", {
}); });
export const chatSessions = pgTable("chat_sessions", { export const chatSessions = pgTable("chat_sessions", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
data: json().default({}), data: json().default({}),
chatPromptId: uuid(), chatPromptId: uuid(),
type: varchar({ length: 255 }).default('production'), type: varchar({ length: 255 }).default('production'),
@@ -153,7 +142,7 @@ export const chatSessions = pgTable("chat_sessions", {
}); });
export const fileSync = pgTable("file_sync", { export const fileSync = pgTable("file_sync", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
name: varchar({ length: 255 }), name: varchar({ length: 255 }),
hash: varchar({ length: 255 }), hash: varchar({ length: 255 }),
stat: jsonb().default({}), stat: jsonb().default({}),
@@ -166,7 +155,7 @@ export const fileSync = pgTable("file_sync", {
]); ]);
export const kvAiChatHistory = pgTable("kv_ai_chat_history", { export const kvAiChatHistory = pgTable("kv_ai_chat_history", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
username: varchar({ length: 255 }).default('').notNull(), username: varchar({ length: 255 }).default('').notNull(),
model: varchar({ length: 255 }).default('').notNull(), model: varchar({ length: 255 }).default('').notNull(),
group: varchar({ length: 255 }).default('').notNull(), group: varchar({ length: 255 }).default('').notNull(),
@@ -184,7 +173,7 @@ export const kvAiChatHistory = pgTable("kv_ai_chat_history", {
}); });
export const kvApp = pgTable("kv_app", { export const kvApp = pgTable("kv_app", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
data: jsonb().default({}), data: jsonb().default({}),
version: varchar({ length: 255 }).default(''), version: varchar({ length: 255 }).default(''),
key: varchar({ length: 255 }), key: varchar({ length: 255 }),
@@ -204,7 +193,7 @@ export const kvApp = pgTable("kv_app", {
]); ]);
export const kvAppDomain = pgTable("kv_app_domain", { export const kvAppDomain = pgTable("kv_app_domain", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
domain: varchar({ length: 255 }).notNull(), domain: varchar({ length: 255 }).notNull(),
appId: varchar({ length: 255 }), appId: varchar({ length: 255 }),
uid: varchar({ length: 255 }), uid: varchar({ length: 255 }),
@@ -218,7 +207,7 @@ export const kvAppDomain = pgTable("kv_app_domain", {
]); ]);
export const kvAppList = pgTable("kv_app_list", { export const kvAppList = pgTable("kv_app_list", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
data: json().default({}), data: json().default({}),
version: varchar({ length: 255 }).default(''), version: varchar({ length: 255 }).default(''),
uid: uuid(), uid: uuid(),
@@ -230,7 +219,7 @@ export const kvAppList = pgTable("kv_app_list", {
}); });
export const kvConfig = pgTable("kv_config", { export const kvConfig = pgTable("kv_config", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
title: text().default(''), title: text().default(''),
key: text().default(''), key: text().default(''),
description: text().default(''), description: text().default(''),
@@ -268,7 +257,7 @@ export const kvGithub = pgTable("kv_github", {
}); });
export const kvPackages = pgTable("kv_packages", { export const kvPackages = pgTable("kv_packages", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
title: text().default(''), title: text().default(''),
description: text().default(''), description: text().default(''),
tags: jsonb().default([]), tags: jsonb().default([]),
@@ -282,7 +271,7 @@ export const kvPackages = pgTable("kv_packages", {
}); });
export const kvPage = pgTable("kv_page", { export const kvPage = pgTable("kv_page", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
title: varchar({ length: 255 }).default(''), title: varchar({ length: 255 }).default(''),
description: text().default(''), description: text().default(''),
type: varchar({ length: 255 }).default(''), type: varchar({ length: 255 }).default(''),
@@ -295,7 +284,7 @@ export const kvPage = pgTable("kv_page", {
}); });
export const kvResource = pgTable("kv_resource", { export const kvResource = pgTable("kv_resource", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
name: varchar({ length: 255 }).default(''), name: varchar({ length: 255 }).default(''),
description: text().default(''), description: text().default(''),
source: varchar({ length: 255 }).default(''), source: varchar({ length: 255 }).default(''),
@@ -309,7 +298,7 @@ export const kvResource = pgTable("kv_resource", {
}); });
export const kvVip = pgTable("kv_vip", { export const kvVip = pgTable("kv_vip", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
userId: uuid().notNull(), userId: uuid().notNull(),
level: varchar({ length: 255 }).default('free'), level: varchar({ length: 255 }).default('free'),
category: varchar({ length: 255 }).notNull(), category: varchar({ length: 255 }).notNull(),
@@ -324,7 +313,7 @@ export const kvVip = pgTable("kv_vip", {
}); });
export const microAppsUpload = pgTable("micro_apps_upload", { export const microAppsUpload = pgTable("micro_apps_upload", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
title: varchar({ length: 255 }).default(''), title: varchar({ length: 255 }).default(''),
description: varchar({ length: 255 }).default(''), description: varchar({ length: 255 }).default(''),
tags: jsonb().default([]), tags: jsonb().default([]),
@@ -339,7 +328,7 @@ export const microAppsUpload = pgTable("micro_apps_upload", {
}); });
export const microMark = pgTable("micro_mark", { export const microMark = pgTable("micro_mark", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
title: text().default(''), title: text().default(''),
description: text().default(''), description: text().default(''),
tags: jsonb().default([]), tags: jsonb().default([]),
@@ -362,7 +351,7 @@ export const microMark = pgTable("micro_mark", {
}); });
export const workShareMark = pgTable("work_share_mark", { export const workShareMark = pgTable("work_share_mark", {
id: uuid().primaryKey().notNull(), id: uuid().primaryKey().defaultRandom(),
title: text().default(''), title: text().default(''),
key: text().default(''), key: text().default(''),
markType: text().default('md'), markType: text().default('md'),

View File

@@ -29,7 +29,7 @@ app
path: 'config', path: 'config',
key: 'update', key: 'update',
middleware: ['auth'], middleware: ['auth'],
description: '创建或更新用户配置参数在data中传入', description: '创建或更新用户配置参数在data中传入'
}) })
.define(async (ctx) => { .define(async (ctx) => {
const tokernUser = ctx.state.tokenUser; const tokernUser = ctx.state.tokenUser;
@@ -90,16 +90,21 @@ app
config = updated[0]; config = updated[0];
ctx.body = config; ctx.body = config;
} else { } else {
try {
// 根据key创建一个配置 // 根据key创建一个配置
const inserted = await db.insert(schema.kvConfig).values({ const inserted = await db.insert(schema.kvConfig).values({
id: nanoid(),
key, key,
...rest, ...rest,
data: data, data: data || {},
uid: tuid, uid: tuid,
}).returning(); }).returning();
config = inserted[0]; config = inserted[0];
ctx.body = config; ctx.body = config;
} catch (e) {
console.log(e)
throw e;
}
} }
} }
const key = config?.key; const key = config?.key;

View File

@@ -101,9 +101,7 @@ app
.define(async (ctx) => { .define(async (ctx) => {
const tokenUser = ctx.state?.tokenUser || {}; const tokenUser = ctx.state?.tokenUser || {};
const { id } = tokenUser; const { id } = tokenUser;
const user = await User.findByPk(id, { const user = await User.findByPk(id);
logging: false,
});
if (!user) { if (!user) {
ctx.throw(500, 'user not found'); ctx.throw(500, 'user not found');
} }
@@ -126,10 +124,10 @@ app
} }
let user: User | null = null; let user: User | null = null;
if (username) { if (username) {
user = await User.findOne({ where: { username }, logging: false }); user = await User.findOne({ username });
} }
if (!user && email) { if (!user && email) {
user = await User.findOne({ where: { email } }); user = await User.findOne({ email });
} }
if (!user) { if (!user) {
ctx.throw(500, 'Login Failed'); ctx.throw(500, 'Login Failed');
@@ -242,7 +240,7 @@ app
if (email) { if (email) {
user.email = email; user.email = email;
} }
await user.save({ fields: ['username', 'nickname', 'data', 'password', 'description', 'avatar', 'email'] }); await user.save();
ctx.body = await user.getInfo(); ctx.body = await user.getInfo();
}) })
.addTo(app); .addTo(app);
@@ -336,7 +334,7 @@ app
await User.oauth.delToken(token); await User.oauth.delToken(token);
ctx.body = result; ctx.body = result;
} else { } else {
const user = await User.findOne({ where: { username } }); const user = await User.findOne({ username });
const result = await user.createToken(userId, 'default'); const result = await user.createToken(userId, 'default');
createCookie({ createCookie({
token: result.accessToken, token: result.accessToken,

View File

@@ -22,9 +22,7 @@ export class WxServices {
} }
async checkUserExist(username: string) { async checkUserExist(username: string) {
const user = await User.findOne({ const user = await User.findOne({
where: {
username, username,
},
}); });
return !!user; return !!user;
} }
@@ -60,21 +58,16 @@ export class WxServices {
} }
this.wxToken = token; this.wxToken = token;
const unionid = token.unionid; const unionid = token.unionid;
let user = await User.findOne({ let user = await User.findByUnionId(unionid);
where: {
data: {
wxUnionId: unionid,
},
},
});
// @ts-ignore // @ts-ignore
if (type === 'mp' && user && user.data.wxmpOpenid !== token.openid) { if (type === 'mp' && user && user.data.wxmpOpenid !== token.openid) {
user.data = { const updatedData = {
...user.data, ...user.data,
// @ts-ignore // @ts-ignore
wxmpOpenid: token.openid, wxmpOpenid: token.openid,
}; };
user = await user.update({ data: user.data }); await user.update({ data: updatedData });
user = await User.findByPk(user.id);
} }
if (!user) { if (!user) {
const username = await this.randomUsername(); const username = await this.randomUsername();
@@ -92,7 +85,7 @@ export class WxServices {
// @ts-ignore // @ts-ignore
data.wxOpenid = token.openid; data.wxOpenid = token.openid;
} }
this.user = await user.save({ fields: ['data'] }); this.user = await user.save();
await this.getUserInfo(); await this.getUserInfo();
this.isNew = true; this.isNew = true;
@@ -134,13 +127,7 @@ export class WxServices {
}; };
const userInfo = await getUserInfoByMp(access_token, openid); const userInfo = await getUserInfoByMp(access_token, openid);
const { unionid } = userInfo; const { unionid } = userInfo;
let user = await User.findOne({ let user = await User.findByUnionId(unionid);
where: {
data: {
wxUnionId: unionid,
},
},
});
if (!user) { if (!user) {
const username = await this.randomUsername(); const username = await this.randomUsername();
user = await User.createUser(username, nanoid(10)); user = await User.createUser(username, nanoid(10));
@@ -164,7 +151,7 @@ export class WxServices {
fileds.push('avatar'); fileds.push('avatar');
} }
this.isNew = true; this.isNew = true;
this.user = await user.save({ fields: fileds }); this.user = await user.save();
} }
this.user = user; this.user = user;
const tokenInfo = await user.createToken(null, 'plugin', { const tokenInfo = await user.createToken(null, 'plugin', {

View File

@@ -3,11 +3,15 @@ import { useConfig } from '@kevisual/use-config';
export const config = useConfig() export const config = useConfig()
const wxOpen = { const wxOpen = {
// @ts-ignore
appId: config.WX_OPEN_APP_ID, appId: config.WX_OPEN_APP_ID,
// @ts-ignore
appSecret: config.WX_OPEN_APP_SECRET, appSecret: config.WX_OPEN_APP_SECRET,
} }
const wx = { const wx = {
// @ts-ignore
appId: config.WX_MP_APP_ID, appId: config.WX_MP_APP_ID,
// @ts-ignore
appSecret: config.WX_MP_APP_SECRET, appSecret: config.WX_MP_APP_SECRET,
} }
export type WxTokenResponse = { export type WxTokenResponse = {
@@ -139,7 +143,8 @@ type RefreshToken = {
scope: string; scope: string;
}; };
export const refreshToken = async (refreshToken: string): Promise<RefreshToken> => { export const refreshToken = async (refreshToken: string): Promise<RefreshToken> => {
const { appId } = config.wx; // @ts-ignore
const { appId } = config?.wx;
const refreshUrl = `https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${appId}&grant_type=refresh_token&refresh_token=${refreshToken}`; const refreshUrl = `https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${appId}&grant_type=refresh_token&refresh_token=${refreshToken}`;
const res = await fetch(refreshUrl); const res = await fetch(refreshUrl);
const data = await res.json(); const data = await res.json();