feat: implement user authentication system
- Add SessionManager for managing user sessions (singleton pattern) - Add BIPUsersDAO for database authentication - Add LoginDialog component for username/password login - Add UserSelectionDialog component for admin user selection - Support silent login by computer name - Implement main page with navigation to Extractor and Cleaner Database: - Table: dbo_BIPUsers - Fields: UserName, Password, UserType, ComputerNmae UI Flow: 1. Silent login on startup via computer name 2. Show login dialog if silent login fails 3. Display main page with user info and navigation 4. Support logout and re-login
This commit is contained in:
223
src/main/ipc/auth-handler.ts
Normal file
223
src/main/ipc/auth-handler.ts
Normal file
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* IPC handlers for User Authentication
|
||||
*
|
||||
* Provides APIs for the renderer process to:
|
||||
* - Login with username and password
|
||||
* - Silent login by computer name
|
||||
* - Logout
|
||||
* - Get current user info
|
||||
* - Get all users (for admin user selection)
|
||||
* - Switch user (admin only)
|
||||
*/
|
||||
|
||||
import { ipcMain } from 'electron'
|
||||
import { SessionManager } from '../services/user/session-manager'
|
||||
import type { UserInfo } from '../types/user.types'
|
||||
|
||||
/**
|
||||
* Login request
|
||||
*/
|
||||
export interface LoginRequest {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Login response
|
||||
*/
|
||||
export interface LoginResponse {
|
||||
success: boolean
|
||||
userInfo?: UserInfo
|
||||
error?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Silent login response
|
||||
*/
|
||||
export interface SilentLoginResponse {
|
||||
success: boolean
|
||||
userInfo?: UserInfo
|
||||
requiresUserSelection?: boolean // True if admin needs to select a user
|
||||
error?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* User selection response
|
||||
*/
|
||||
export interface UserSelectionResponse {
|
||||
success: boolean
|
||||
userInfo?: UserInfo
|
||||
error?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Current user response
|
||||
*/
|
||||
export interface CurrentUserResponse {
|
||||
isAuthenticated: boolean
|
||||
userInfo?: UserInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* Register IPC handlers for user authentication
|
||||
*/
|
||||
export function registerAuthHandlers(): void {
|
||||
const sessionManager = SessionManager.getInstance()
|
||||
|
||||
/**
|
||||
* Get computer name
|
||||
*/
|
||||
ipcMain.handle('auth:getComputerName', async (): Promise<string> => {
|
||||
const os = await import('os')
|
||||
return os.hostname()
|
||||
})
|
||||
|
||||
/**
|
||||
* Silent login by computer name
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'auth:silentLogin',
|
||||
async (): Promise<SilentLoginResponse> => {
|
||||
try {
|
||||
const success = await sessionManager.loginByComputerName()
|
||||
const userInfo = sessionManager.getUserInfo()
|
||||
|
||||
if (success && userInfo) {
|
||||
// Check if admin needs user selection
|
||||
const requiresUserSelection = userInfo.userType === 'Admin'
|
||||
|
||||
return {
|
||||
success: true,
|
||||
userInfo,
|
||||
requiresUserSelection
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
requiresUserSelection: false
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
return {
|
||||
success: false,
|
||||
error: `无感登录失败:${message}`
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Login with username and password
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'auth:login',
|
||||
async (_event, request: LoginRequest): Promise<LoginResponse> => {
|
||||
try {
|
||||
const { username, password } = request
|
||||
|
||||
if (!username || !password) {
|
||||
return {
|
||||
success: false,
|
||||
error: '请输入用户名和密码'
|
||||
}
|
||||
}
|
||||
|
||||
const success = await sessionManager.login(username, password)
|
||||
const userInfo = sessionManager.getUserInfo()
|
||||
|
||||
if (success && userInfo) {
|
||||
return {
|
||||
success: true,
|
||||
userInfo
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: '用户名或密码错误'
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
return {
|
||||
success: false,
|
||||
error: `登录失败:${message}`
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Logout
|
||||
*/
|
||||
ipcMain.handle('auth:logout', async (): Promise<void> => {
|
||||
sessionManager.logout()
|
||||
})
|
||||
|
||||
/**
|
||||
* Get current user
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'auth:getCurrentUser',
|
||||
async (): Promise<CurrentUserResponse> => {
|
||||
const isAuthenticated = sessionManager.isAuthenticated()
|
||||
const userInfo = sessionManager.getUserInfo()
|
||||
|
||||
return {
|
||||
isAuthenticated,
|
||||
userInfo: userInfo ?? undefined
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Get all users (for admin user selection)
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'auth:getAllUsers',
|
||||
async (): Promise<UserInfo[]> => {
|
||||
return await sessionManager.getAllUsers()
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Switch user (admin only)
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'auth:switchUser',
|
||||
async (_event, userInfo: UserInfo): Promise<UserSelectionResponse> => {
|
||||
try {
|
||||
const success = sessionManager.switchUser(userInfo)
|
||||
|
||||
if (success) {
|
||||
const newUser = sessionManager.getUserInfo()
|
||||
return {
|
||||
success: true,
|
||||
userInfo: newUser ?? undefined
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: '用户切换失败'
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
return {
|
||||
success: false,
|
||||
error: `用户切换失败:${message}`
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Check if current user is admin
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'auth:isAdmin',
|
||||
async (): Promise<boolean> => {
|
||||
return sessionManager.isAdmin()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { registerExtractorHandlers } from './extractor-handler'
|
||||
import { registerCleanerHandlers } from './cleaner-handler'
|
||||
import { registerDatabaseHandlers } from './database-handler'
|
||||
import { registerResolverHandlers } from './resolver-handler'
|
||||
import { registerAuthHandlers } from './auth-handler'
|
||||
|
||||
/**
|
||||
* Register all IPC handlers
|
||||
@@ -18,4 +19,5 @@ export function registerIpcHandlers(): void {
|
||||
registerCleanerHandlers()
|
||||
registerDatabaseHandlers()
|
||||
registerResolverHandlers()
|
||||
registerAuthHandlers()
|
||||
}
|
||||
|
||||
298
src/main/services/user/bip-users-dao.ts
Normal file
298
src/main/services/user/bip-users-dao.ts
Normal file
@@ -0,0 +1,298 @@
|
||||
/**
|
||||
* BIPUsers DAO - Data access object for user authentication and management
|
||||
*
|
||||
* Mirrors the Python BIPUsersDAO functionality:
|
||||
* - Authenticate users by username and password
|
||||
* - Authenticate by computer name (silent login)
|
||||
* - Get all users for admin user selection
|
||||
* - Create, update, delete users
|
||||
*/
|
||||
|
||||
import { MySqlService } from '../database/mysql'
|
||||
import type { UserInfo } from '../../types/user.types'
|
||||
|
||||
/**
|
||||
* Database configuration for BIPUsers table
|
||||
*/
|
||||
export const BIP_USERS_CONFIG = {
|
||||
/** Table name in SQL Server: [dbo].[BIPUsers] */
|
||||
TABLE_NAME_SQLSERVER: '[dbo].[BIPUsers]',
|
||||
/** Table name in MySQL: dbo_BIPUsers */
|
||||
TABLE_NAME_MYSQL: 'dbo_BIPUsers',
|
||||
/** Column names */
|
||||
COLUMNS: {
|
||||
ID: 'ID',
|
||||
USERNAME: 'UserName',
|
||||
USER_TYPE: 'UserType',
|
||||
PASSWORD: 'Password',
|
||||
COMPUTER_NAME: 'ComputerNmae', // Note: typo in database schema
|
||||
CREATE_TIME: 'CreateTime'
|
||||
}
|
||||
} as const
|
||||
|
||||
/**
|
||||
* BIPUsers DAO Class
|
||||
*/
|
||||
export class BIPUsersDAO {
|
||||
private mysqlService: MySqlService | null = null
|
||||
|
||||
/**
|
||||
* Get MySQL service instance
|
||||
*/
|
||||
private async getMySqlService(): Promise<MySqlService> {
|
||||
if (this.mysqlService && this.mysqlService.isConnected()) {
|
||||
return this.mysqlService
|
||||
}
|
||||
|
||||
this.mysqlService = new MySqlService({
|
||||
host: process.env.DB_MYSQL_HOST || 'localhost',
|
||||
port: parseInt(process.env.DB_MYSQL_PORT || '3306', 10),
|
||||
user: process.env.DB_USERNAME || 'root',
|
||||
password: process.env.DB_PASSWORD || '',
|
||||
database: process.env.DB_NAME || ''
|
||||
})
|
||||
|
||||
await this.mysqlService.connect()
|
||||
return this.mysqlService
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a user with username and password
|
||||
* @param username - The username to authenticate
|
||||
* @param password - The password to verify
|
||||
* @returns User info if authentication successful, null otherwise
|
||||
*/
|
||||
async authenticate(username: string, password: string): Promise<UserInfo | null> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
const sql = `
|
||||
SELECT ID, UserName, UserType
|
||||
FROM ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
WHERE UserName = ? AND Password = ?
|
||||
`
|
||||
|
||||
const result = await mysqlService.query(sql, [username, password])
|
||||
|
||||
if (result.rows.length > 0) {
|
||||
const row = result.rows[0]
|
||||
return {
|
||||
id: row.ID as number,
|
||||
username: row.UserName as string,
|
||||
userType: row.UserType as 'Admin' | 'User' | 'Guest'
|
||||
}
|
||||
}
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] Authenticate error:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a user using computer name (silent login)
|
||||
* @param computerName - The computer name to authenticate
|
||||
* @returns User info if authentication successful, null otherwise
|
||||
*/
|
||||
async authenticateByComputerName(computerName: string): Promise<UserInfo | null> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
const sql = `
|
||||
SELECT ID, UserName, UserType
|
||||
FROM ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
WHERE ComputerNmae = ?
|
||||
`
|
||||
|
||||
const result = await mysqlService.query(sql, [computerName])
|
||||
|
||||
if (result.rows.length > 0) {
|
||||
const row = result.rows[0]
|
||||
return {
|
||||
id: row.ID as number,
|
||||
username: row.UserName as string,
|
||||
userType: row.UserType as 'Admin' | 'User' | 'Guest'
|
||||
}
|
||||
}
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] Authenticate by computer name error:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all users from the database
|
||||
* @returns List of user information
|
||||
*/
|
||||
async getAllUsers(): Promise<UserInfo[]> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
const sql = `
|
||||
SELECT ID, UserName, UserType, CreateTime
|
||||
FROM ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
ORDER BY UserName
|
||||
`
|
||||
|
||||
const result = await mysqlService.query(sql)
|
||||
|
||||
return result.rows.map(row => ({
|
||||
id: row.ID as number,
|
||||
username: row.UserName as string,
|
||||
userType: row.UserType as 'Admin' | 'User' | 'Guest',
|
||||
createTime: row.CreateTime as Date | undefined
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] Get all users error:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user
|
||||
* @param username - The username (must be unique)
|
||||
* @param password - The password
|
||||
* @param userType - User type ('Admin', 'User', or 'Guest')
|
||||
* @param computerName - Optional computer name for silent login
|
||||
* @returns True if successful
|
||||
*/
|
||||
async createUser(
|
||||
username: string,
|
||||
password: string,
|
||||
userType: string,
|
||||
computerName: string = ''
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
let sql: string
|
||||
let params: any[]
|
||||
|
||||
if (computerName) {
|
||||
sql = `
|
||||
INSERT INTO ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
(UserName, Password, UserType, ComputerNmae)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`
|
||||
params = [username, password, userType, computerName]
|
||||
} else {
|
||||
sql = `
|
||||
INSERT INTO ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
(UserName, Password, UserType)
|
||||
VALUES (?, ?, ?)
|
||||
`
|
||||
params = [username, password, userType]
|
||||
}
|
||||
|
||||
await mysqlService.query(sql, params)
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] Create user error:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a user's type
|
||||
* @param username - The username to update
|
||||
* @param userType - New user type
|
||||
* @returns True if successful
|
||||
*/
|
||||
async updateUserType(username: string, userType: string): Promise<boolean> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
const sql = `
|
||||
UPDATE ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
SET UserType = ?
|
||||
WHERE UserName = ?
|
||||
`
|
||||
|
||||
await mysqlService.query(sql, [userType, username])
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] Update user type error:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a user's password
|
||||
* @param username - The username to update
|
||||
* @param newPassword - The new password
|
||||
* @returns True if successful
|
||||
*/
|
||||
async updatePassword(username: string, newPassword: string): Promise<boolean> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
const sql = `
|
||||
UPDATE ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
SET Password = ?
|
||||
WHERE UserName = ?
|
||||
`
|
||||
|
||||
await mysqlService.query(sql, [newPassword, username])
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] Update password error:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user
|
||||
* @param username - The username to delete
|
||||
* @returns True if successful
|
||||
*/
|
||||
async deleteUser(username: string): Promise<boolean> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
const sql = `
|
||||
DELETE FROM ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
WHERE UserName = ?
|
||||
`
|
||||
|
||||
await mysqlService.query(sql, [username])
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] Delete user error:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a username already exists
|
||||
* @param username - The username to check
|
||||
* @returns True if username exists
|
||||
*/
|
||||
async userExists(username: string): Promise<boolean> {
|
||||
try {
|
||||
const mysqlService = await this.getMySqlService()
|
||||
|
||||
const sql = `
|
||||
SELECT COUNT(*) as count
|
||||
FROM ${BIP_USERS_CONFIG.TABLE_NAME_MYSQL}
|
||||
WHERE UserName = ?
|
||||
`
|
||||
|
||||
const result = await mysqlService.query(sql, [username])
|
||||
return result.rows.length > 0 && (result.rows[0].count as number) > 0
|
||||
} catch (error) {
|
||||
console.error('[BIPUsersDAO] User exists error:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from database
|
||||
*/
|
||||
async disconnect(): Promise<void> {
|
||||
if (this.mysqlService) {
|
||||
await this.mysqlService.disconnect()
|
||||
this.mysqlService = null
|
||||
}
|
||||
}
|
||||
}
|
||||
185
src/main/services/user/session-manager.ts
Normal file
185
src/main/services/user/session-manager.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* User Session Manager - Singleton pattern for managing authenticated user session
|
||||
*
|
||||
* Mimics the Python SessionManager functionality:
|
||||
* - Singleton pattern to maintain user state throughout application lifecycle
|
||||
* - Support for username/password authentication
|
||||
* - Support for silent login by computer name
|
||||
* - Admin user can switch to other users
|
||||
*/
|
||||
|
||||
import type { UserInfo } from '../../types/user.types'
|
||||
|
||||
/**
|
||||
* Session Manager Class
|
||||
*/
|
||||
export class SessionManager {
|
||||
private static instance: SessionManager | null = null
|
||||
private currentUser: UserInfo | null = null
|
||||
private originalAdminUser: UserInfo | null = null
|
||||
private initialized: boolean = false
|
||||
|
||||
private constructor() {
|
||||
if (this.initialized) {
|
||||
return
|
||||
}
|
||||
this.initialized = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton instance
|
||||
*/
|
||||
public static getInstance(): SessionManager {
|
||||
if (SessionManager.instance === null) {
|
||||
SessionManager.instance = new SessionManager()
|
||||
}
|
||||
return SessionManager.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate and login a user
|
||||
* @param username - The username to authenticate
|
||||
* @param password - The password to verify
|
||||
* @returns True if login successful, false otherwise
|
||||
*/
|
||||
public async login(username: string, password: string): Promise<boolean> {
|
||||
try {
|
||||
const { BIPUsersDAO } = await import('./bip-users-dao')
|
||||
const dao = new BIPUsersDAO()
|
||||
const userInfo = await dao.authenticate(username, password)
|
||||
|
||||
if (userInfo) {
|
||||
this.currentUser = {
|
||||
id: userInfo.id,
|
||||
username: userInfo.username,
|
||||
userType: userInfo.userType
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (error) {
|
||||
console.error('[SessionManager] Login error:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt silent login using computer name
|
||||
* @returns True if login successful, false otherwise
|
||||
*/
|
||||
public async loginByComputerName(): Promise<boolean> {
|
||||
try {
|
||||
const { BIPUsersDAO } = await import('./bip-users-dao')
|
||||
const dao = new BIPUsersDAO()
|
||||
const computerName = require('os').hostname()
|
||||
const userInfo = await dao.authenticateByComputerName(computerName)
|
||||
|
||||
if (userInfo) {
|
||||
this.currentUser = {
|
||||
id: userInfo.id,
|
||||
username: userInfo.username,
|
||||
userType: userInfo.userType
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (error) {
|
||||
console.error('[SessionManager] Silent login error:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout the current user and clear session
|
||||
*/
|
||||
public logout(): void {
|
||||
this.currentUser = null
|
||||
this.originalAdminUser = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user is currently authenticated
|
||||
*/
|
||||
public isAuthenticated(): boolean {
|
||||
return this.currentUser !== null
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user is an admin
|
||||
*/
|
||||
public isAdmin(): boolean {
|
||||
return this.currentUser?.userType === 'Admin'
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user is a guest
|
||||
*/
|
||||
public isGuest(): boolean {
|
||||
return this.currentUser?.userType === 'Guest'
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current username
|
||||
*/
|
||||
public getUsername(): string | null {
|
||||
return this.currentUser?.username ?? null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user type
|
||||
*/
|
||||
public getUserType(): string | null {
|
||||
return this.currentUser?.userType ?? null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all current user information
|
||||
*/
|
||||
public getUserInfo(): UserInfo | null {
|
||||
return this.currentUser
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a different user (Admin only feature)
|
||||
* @param userInfo - User info to switch to
|
||||
* @returns True if switch successful
|
||||
*/
|
||||
public switchUser(userInfo: UserInfo): boolean {
|
||||
if (!this.currentUser) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Store original admin user for reference
|
||||
if (!this.originalAdminUser) {
|
||||
this.originalAdminUser = { ...this.currentUser }
|
||||
}
|
||||
|
||||
this.currentUser = {
|
||||
id: userInfo.id,
|
||||
username: userInfo.username,
|
||||
userType: userInfo.userType
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the original Admin user before any user switch
|
||||
*/
|
||||
public getOriginalAdmin(): UserInfo | null {
|
||||
return this.originalAdminUser
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all users from database (for Admin user selection)
|
||||
*/
|
||||
public async getAllUsers(): Promise<UserInfo[]> {
|
||||
try {
|
||||
const { BIPUsersDAO } = await import('./bip-users-dao')
|
||||
const dao = new BIPUsersDAO()
|
||||
return await dao.getAllUsers()
|
||||
} catch (error) {
|
||||
console.error('[SessionManager] Get all users error:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/main/types/user.types.ts
Normal file
36
src/main/types/user.types.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* User types and interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* User type enumeration
|
||||
*/
|
||||
export type UserType = 'Admin' | 'User' | 'Guest'
|
||||
|
||||
/**
|
||||
* User information interface
|
||||
*/
|
||||
export interface UserInfo {
|
||||
/** User ID */
|
||||
id: number
|
||||
/** Username */
|
||||
username: string
|
||||
/** User type */
|
||||
userType: UserType
|
||||
/** Create time */
|
||||
createTime?: Date
|
||||
}
|
||||
|
||||
/**
|
||||
* User session interface
|
||||
*/
|
||||
export interface UserSession {
|
||||
/** Current authenticated user */
|
||||
user: UserInfo | null
|
||||
/** Session token (optional for future use) */
|
||||
token?: string
|
||||
/** Login timestamp */
|
||||
loginTime: Date
|
||||
/** Whether session is active */
|
||||
isActive: boolean
|
||||
}
|
||||
Reference in New Issue
Block a user