import { Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { TenantDatabaseService } from '../tenant/tenant-database.service'; import { getCentralPrisma } from '../prisma/central-prisma.service'; import * as bcrypt from 'bcrypt'; @Injectable() export class AuthService { constructor( private tenantDbService: TenantDatabaseService, private jwtService: JwtService, ) {} private isCentralSubdomain(subdomain: string): boolean { const centralSubdomains = (process.env.CENTRAL_SUBDOMAINS || 'central,admin').split(','); return centralSubdomains.includes(subdomain); } async validateUser( tenantId: string, email: string, password: string, subdomain?: string, ): Promise { // Check if this is a central subdomain if (subdomain && this.isCentralSubdomain(subdomain)) { return this.validateCentralUser(email, password); } // Otherwise, validate as tenant user const tenantDb = await this.tenantDbService.getTenantKnex(tenantId); const user = await tenantDb('users') .where({ email }) .first(); if (!user) { return null; } if (await bcrypt.compare(password, user.password)) { // Load user roles and permissions const userRoles = await tenantDb('user_roles') .where({ userId: user.id }) .join('roles', 'user_roles.roleId', 'roles.id') .select('roles.*'); const { password: _, ...result } = user; return { ...result, tenantId, userRoles, }; } return null; } private async validateCentralUser( email: string, password: string, ): Promise { const centralPrisma = getCentralPrisma(); const user = await centralPrisma.user.findUnique({ where: { email }, }); if (!user) { return null; } if (await bcrypt.compare(password, user.password)) { const { password: _, ...result } = user; return { ...result, isCentralAdmin: true, }; } return null; } async login(user: any) { const payload = { sub: user.id, email: user.email, }; return { access_token: this.jwtService.sign(payload), user: { id: user.id, email: user.email, firstName: user.firstName, lastName: user.lastName, }, }; } async register( tenantId: string, email: string, password: string, firstName?: string, lastName?: string, subdomain?: string, ) { // Check if this is a central subdomain if (subdomain && this.isCentralSubdomain(subdomain)) { return this.registerCentralUser(email, password, firstName, lastName); } // Otherwise, register as tenant user const tenantDb = await this.tenantDbService.getTenantKnex(tenantId); const hashedPassword = await bcrypt.hash(password, 10); const [userId] = await tenantDb('users').insert({ email, password: hashedPassword, firstName, lastName, isActive: true, created_at: new Date(), updated_at: new Date(), }); const user = await tenantDb('users') .where({ id: userId }) .first(); const { password: _, ...result } = user; return result; } private async registerCentralUser( email: string, password: string, firstName?: string, lastName?: string, ) { const centralPrisma = getCentralPrisma(); const hashedPassword = await bcrypt.hash(password, 10); const user = await centralPrisma.user.create({ data: { email, password: hashedPassword, firstName: firstName || null, lastName: lastName || null, isActive: true, }, }); const { password: _, ...result } = user; return result; } }