import { Injectable, UnauthorizedException, ConflictException } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { JwtService } from '@nestjs/jwt'; import * as bcrypt from 'bcryptjs'; import { User, UserDocument } from './schemas/user.schema'; import { RegisterDto } from './dto/register.dto'; import { LoginDto } from './dto/login.dto'; @Injectable() export class AuthService { constructor( @InjectModel(User.name) private userModel: Model, private jwtService: JwtService, ) {} async register(dto: RegisterDto) { const exists = await this.userModel.findOne({ email: dto.email }); if (exists) throw new ConflictException('Email already registered'); const hashed = await bcrypt.hash(dto.password, 12); const user = await this.userModel.create({ ...dto, password: hashed }); return this.signToken(user); } async login(dto: LoginDto) { const user = await this.userModel.findOne({ email: dto.email }).select('+password'); if (!user) throw new UnauthorizedException('Invalid credentials'); const valid = await bcrypt.compare(dto.password, user.password); if (!valid) throw new UnauthorizedException('Invalid credentials'); user.lastLogin = new Date(); await user.save(); return this.signToken(user); } async validateUser(id: string): Promise { const user = await this.userModel.findById(id); if (!user || !user.isActive) throw new UnauthorizedException(); return user; } private signToken(user: UserDocument) { const payload = { sub: user._id, email: user.email, role: user.role }; return { access_token: this.jwtService.sign(payload), user: { id: user._id, name: user.name, email: user.email, role: user.role, }, }; } }