feat: migrate runtime backend to node server
This commit is contained in:
70
server-node/src/auth/authService.ts
Normal file
70
server-node/src/auth/authService.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { AppContext } from '../context.js';
|
||||
import { badRequest, unauthorized } from '../errors.js';
|
||||
import { hashPassword, verifyPassword } from './password.js';
|
||||
import { signAccessToken } from './token.js';
|
||||
|
||||
const USERNAME_PATTERN = /^[A-Za-z0-9_]{3,24}$/u;
|
||||
|
||||
function normalizeUsername(username: string) {
|
||||
return username.trim();
|
||||
}
|
||||
|
||||
function validateCredentials(username: string, password: string) {
|
||||
if (!USERNAME_PATTERN.test(username)) {
|
||||
throw badRequest('用户名只允许 3 到 24 位字母、数字、下划线');
|
||||
}
|
||||
if (password.length < 6 || password.length > 128) {
|
||||
throw badRequest('密码长度需要在 6 到 128 位之间');
|
||||
}
|
||||
}
|
||||
|
||||
export async function entryWithPassword(
|
||||
context: AppContext,
|
||||
usernameInput: string,
|
||||
password: string,
|
||||
) {
|
||||
const username = normalizeUsername(usernameInput);
|
||||
validateCredentials(username, password);
|
||||
|
||||
let user = context.userRepository.findByUsername(username);
|
||||
if (!user) {
|
||||
const passwordHash = await hashPassword(password);
|
||||
user = context.userRepository.create(username, passwordHash);
|
||||
} else {
|
||||
const isValid = await verifyPassword(user.passwordHash, password);
|
||||
if (!isValid) {
|
||||
throw unauthorized('用户名或密码错误');
|
||||
}
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
throw new Error('failed to resolve user after auth entry');
|
||||
}
|
||||
|
||||
const token = await signAccessToken(
|
||||
{
|
||||
userId: user.id,
|
||||
tokenVersion: user.tokenVersion,
|
||||
},
|
||||
context.config,
|
||||
);
|
||||
|
||||
return {
|
||||
token,
|
||||
user: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function logoutUser(context: AppContext, userId: string) {
|
||||
const user = context.userRepository.incrementTokenVersion(userId);
|
||||
if (!user) {
|
||||
throw unauthorized('用户不存在');
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true as const,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user