feat: add CNB login functionality and user management
- Introduced `cnb-login` route to handle user login via CNB token. - Created `CnbServices` class for managing CNB user interactions. - Added `findByCnbId` method in the User model to retrieve users by CNB ID. - Updated error handling to provide more structured error messages. - Enhanced user creation logic to handle CNB users. - Added tests for the new CNB login functionality.
This commit is contained in:
@@ -7,7 +7,7 @@ import { cryptPwd } from '../oauth/salt.ts';
|
||||
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 { eq, sql, InferSelectModel, InferInsertModel } from 'drizzle-orm';
|
||||
|
||||
@@ -17,6 +17,7 @@ export type UserData = {
|
||||
wxUnionId?: string;
|
||||
phone?: string;
|
||||
canChangeUsername?: boolean;
|
||||
cnbId?: string;
|
||||
};
|
||||
|
||||
export enum UserTypes {
|
||||
@@ -95,7 +96,6 @@ export class User {
|
||||
* @returns
|
||||
*/
|
||||
static async verifyToken(token: string) {
|
||||
const { UserSecret } = await import('./user-secret.ts');
|
||||
return await UserSecret.verifyToken(token);
|
||||
}
|
||||
/**
|
||||
@@ -108,7 +108,6 @@ export class User {
|
||||
return { accessToken: token.accessToken, refreshToken: token.refreshToken, token: token.accessToken };
|
||||
}
|
||||
static async getOauthUser(token: string) {
|
||||
const { UserSecret } = await import('./user-secret.ts');
|
||||
return await UserSecret.verifyToken(token);
|
||||
}
|
||||
/**
|
||||
@@ -126,7 +125,6 @@ export class User {
|
||||
* @returns
|
||||
*/
|
||||
static async getUserByToken(token: string) {
|
||||
const { UserSecret } = await import('./user-secret.ts');
|
||||
const oauthUser = await UserSecret.verifyToken(token);
|
||||
if (!oauthUser) {
|
||||
throw new CustomError('Token is invalid. get UserByToken');
|
||||
@@ -176,6 +174,20 @@ export class User {
|
||||
return users.length > 0 ? new User(users[0]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 CNB ID 查找用户
|
||||
* @param cnbId
|
||||
* @returns
|
||||
*/
|
||||
static async findByCnbId(cnbId: string): Promise<User | null> {
|
||||
const users = await db
|
||||
.select()
|
||||
.from(usersTable)
|
||||
.where(sql`${usersTable.data}->>'cnbId' = ${cnbId}`)
|
||||
.limit(1);
|
||||
return users.length > 0 ? new User(users[0]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件查找一个用户
|
||||
*/
|
||||
@@ -193,7 +205,7 @@ export class User {
|
||||
const users = await query.limit(1);
|
||||
return users.length > 0 ? new User(users[0]) : null;
|
||||
}
|
||||
static findByunionid(){
|
||||
static findByunionid() {
|
||||
|
||||
}
|
||||
|
||||
@@ -345,7 +357,7 @@ export class User {
|
||||
if (this.tokenUser && this.tokenUser.uid) {
|
||||
id = this.tokenUser.uid;
|
||||
} else {
|
||||
throw new CustomError(400, 'Permission denied');
|
||||
throw new CustomError('Permission denied', { code: 400 });
|
||||
}
|
||||
}
|
||||
const cache = await redis.get(`user:${id}:orgs`);
|
||||
|
||||
@@ -147,6 +147,7 @@ export class RedisTokenStore implements Store<OauthUser> {
|
||||
// 计算过期时间,根据opts.expire 和 opts.loginType
|
||||
// 如果expire存在,则使用expire,否则使用opts.loginType 进行计算;
|
||||
let expire = opts?.expire;
|
||||
const day = 24 * 60 * 60; // 一天的秒数
|
||||
if (!expire) {
|
||||
switch (opts.loginType) {
|
||||
case 'day':
|
||||
@@ -170,7 +171,8 @@ export class RedisTokenStore implements Store<OauthUser> {
|
||||
|
||||
await this.set(accessToken, JSON.stringify(value), expire);
|
||||
await this.set(userPrefix + ':token:' + accessToken, accessToken, expire);
|
||||
let refreshTokenExpiresIn = Math.min(expire * 7, 60 * 60 * 24 * 30, 60 * 60 * 24 * 365); // 最大为一年
|
||||
// refreshToken的过期时间比accessToken多2天,确保在accessToken过期后,refreshToken仍然有效
|
||||
let refreshTokenExpiresIn = expire + 2 * day;
|
||||
if (refreshToken) {
|
||||
// 小于7天, 则设置为7天
|
||||
if (refreshTokenExpiresIn < 60 * 60 * 24 * 7) {
|
||||
|
||||
Reference in New Issue
Block a user