Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
|
||||
import * as plugins from '../plugins.ts';
|
||||
import type { IUser, TUserStatus } from '../interfaces/auth.interfaces.ts';
|
||||
import { getDb } from './db.ts';
|
||||
import { db } from './db.ts';
|
||||
|
||||
@plugins.smartdata.Collection(() => getDb())
|
||||
@plugins.smartdata.Collection(() => db)
|
||||
export class User extends plugins.smartdata.SmartDataDbDoc<User, User> implements IUser {
|
||||
@plugins.smartdata.unI()
|
||||
public id: string = '';
|
||||
@@ -112,4 +112,119 @@ export class User extends plugins.smartdata.SmartDataDbDoc<User, User> implement
|
||||
this.id = await User.getNewId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is active (status === 'active')
|
||||
*/
|
||||
public get isActive(): boolean {
|
||||
return this.status === 'active';
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for isPlatformAdmin for backward compatibility
|
||||
*/
|
||||
public get isSystemAdmin(): boolean {
|
||||
return this.isPlatformAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find user by ID
|
||||
*/
|
||||
public static async findById(id: string): Promise<User | null> {
|
||||
return await User.getInstance({ id });
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify password against stored hash
|
||||
*/
|
||||
public async verifyPassword(password: string): Promise<boolean> {
|
||||
if (!this.passwordHash) return false;
|
||||
|
||||
const [saltHex, expectedHash] = this.passwordHash.split(':');
|
||||
if (!saltHex || !expectedHash) return false;
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(saltHex + password);
|
||||
|
||||
let hash = data;
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
hash = new Uint8Array(await crypto.subtle.digest('SHA-256', hash));
|
||||
}
|
||||
|
||||
const hashHex = Array.from(hash)
|
||||
.map((b) => b.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
|
||||
return hashHex === expectedHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a password for storage
|
||||
*/
|
||||
public static async hashPassword(password: string): Promise<string> {
|
||||
const salt = crypto.getRandomValues(new Uint8Array(16));
|
||||
const saltHex = Array.from(salt)
|
||||
.map((b) => b.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(saltHex + password);
|
||||
|
||||
let hash = data;
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
hash = new Uint8Array(await crypto.subtle.digest('SHA-256', hash));
|
||||
}
|
||||
|
||||
const hashHex = Array.from(hash)
|
||||
.map((b) => b.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
|
||||
return `${saltHex}:${hashHex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default admin user if no admin exists
|
||||
*/
|
||||
public static async seedDefaultAdmin(): Promise<User | null> {
|
||||
const adminEmail = Deno.env.get('ADMIN_EMAIL') || 'admin@stack.gallery';
|
||||
const adminPassword = Deno.env.get('ADMIN_PASSWORD') || 'admin';
|
||||
|
||||
// Check if any platform admin exists
|
||||
const existingAdmin = await User.getInstance({ isPlatformAdmin: true });
|
||||
if (existingAdmin) {
|
||||
console.log('[User] Platform admin already exists, skipping seed');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if admin email already exists
|
||||
const existingUser = await User.findByEmail(adminEmail);
|
||||
if (existingUser) {
|
||||
console.log('[User] User with admin email already exists, promoting to admin');
|
||||
existingUser.isPlatformAdmin = true;
|
||||
existingUser.status = 'active';
|
||||
await existingUser.save();
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
// Create new admin user
|
||||
console.log('[User] Creating default admin user:', adminEmail);
|
||||
const passwordHash = await User.hashPassword(adminPassword);
|
||||
|
||||
const admin = new User();
|
||||
admin.id = await User.getNewId();
|
||||
admin.email = adminEmail.toLowerCase();
|
||||
admin.username = 'admin';
|
||||
admin.passwordHash = passwordHash;
|
||||
admin.displayName = 'System Administrator';
|
||||
admin.status = 'active';
|
||||
admin.emailVerified = true;
|
||||
admin.isPlatformAdmin = true;
|
||||
admin.createdAt = new Date();
|
||||
admin.updatedAt = new Date();
|
||||
|
||||
await admin.save();
|
||||
console.log('[User] Default admin user created successfully');
|
||||
|
||||
return admin;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user