Administrator 8117958bd6 feat: add user center with RBAC, OAuth2 multi-mode and collapsible sidebar
- Add user management with roles and permissions (RBAC)
- Implement OAuth2 service provider supporting 4 grant types:
  authorization_code, password, client_credentials, refresh_token
- Add JWT authentication with 7-day expiry
- Add admin API for users, roles and OAuth clients management
- Add CLI tool for user management (scripts/user-cli.js)
- Add collapsible sidebar layout with login dialog
- Add user management page and OAuth client management page
- Add server middleware for auth token verification
- Add seed script for initial data (admin/admin123)
2026-03-19 17:19:57 +08:00

46 lines
1.3 KiB
TypeScript

import jwt from 'jsonwebtoken'
import type { JWTPayload } from '../modules/auth/types'
const JWT_SECRET = process.env.JWT_SECRET || 'sport-meeting-admin-secret-key-2026'
const ACCESS_TOKEN_EXPIRY = '7d'
const REFRESH_TOKEN_EXPIRY = '30d'
export function generateAccessToken(payload: Omit<JWTPayload, 'iat' | 'exp' | 'type'>): string {
return jwt.sign({ ...payload, type: 'access' }, JWT_SECRET, { expiresIn: ACCESS_TOKEN_EXPIRY })
}
export function generateRefreshToken(payload: Omit<JWTPayload, 'iat' | 'exp' | 'type'>): string {
return jwt.sign({ ...payload, type: 'refresh' }, JWT_SECRET, { expiresIn: REFRESH_TOKEN_EXPIRY })
}
export function verifyToken(token: string): JWTPayload | null {
try {
const decoded = jwt.verify(token, JWT_SECRET) as JWTPayload
return decoded
} catch {
return null
}
}
export function decodeToken(token: string): JWTPayload | null {
try {
return jwt.decode(token) as JWTPayload
} catch {
return null
}
}
export function isAccessToken(token: JWTPayload): boolean {
return token.type === 'access'
}
export function isRefreshToken(token: JWTPayload): boolean {
return token.type === 'refresh'
}
export function getTokenExpiry(token: string): Date | null {
const decoded = decodeToken(token)
if (!decoded?.exp) return null
return new Date(decoded.exp * 1000)
}