101 lines
2.9 KiB
TypeScript
101 lines
2.9 KiB
TypeScript
import { Injectable, UnauthorizedException, ConflictException } from '@nestjs/common';
|
|
import { JwtService } from '@nestjs/jwt';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import * as bcrypt from 'bcrypt';
|
|
import { UsersService } from '../users/users.service';
|
|
import { RegisterDto } from './dto/register.dto';
|
|
import { LoginDto } from './dto/login.dto';
|
|
|
|
@Injectable()
|
|
export class AuthService {
|
|
constructor(
|
|
private usersService: UsersService,
|
|
private jwtService: JwtService,
|
|
private configService: ConfigService,
|
|
) {}
|
|
|
|
async register(registerDto: RegisterDto) {
|
|
const existingUser = await this.usersService.findByEmail(registerDto.email);
|
|
if (existingUser) {
|
|
throw new ConflictException('Email already registered');
|
|
}
|
|
|
|
const hashedPassword = await bcrypt.hash(registerDto.password, 12);
|
|
const user = await this.usersService.create({
|
|
...registerDto,
|
|
password: hashedPassword,
|
|
});
|
|
|
|
const tokens = await this.generateTokens(user.id, user.email, user.role);
|
|
return {
|
|
user: {
|
|
id: user.id,
|
|
email: user.email,
|
|
firstName: user.firstName,
|
|
lastName: user.lastName,
|
|
role: user.role,
|
|
},
|
|
...tokens,
|
|
};
|
|
}
|
|
|
|
async login(loginDto: LoginDto) {
|
|
const user = await this.usersService.findByEmail(loginDto.email);
|
|
if (!user) {
|
|
throw new UnauthorizedException('Invalid credentials');
|
|
}
|
|
|
|
const isPasswordValid = await bcrypt.compare(loginDto.password, user.password);
|
|
if (!isPasswordValid) {
|
|
throw new UnauthorizedException('Invalid credentials');
|
|
}
|
|
|
|
if (!user.isActive) {
|
|
throw new UnauthorizedException('Account is deactivated');
|
|
}
|
|
|
|
const tokens = await this.generateTokens(user.id, user.email, user.role);
|
|
return {
|
|
user: {
|
|
id: user.id,
|
|
email: user.email,
|
|
firstName: user.firstName,
|
|
lastName: user.lastName,
|
|
role: user.role,
|
|
},
|
|
...tokens,
|
|
};
|
|
}
|
|
|
|
async refreshToken(refreshToken: string) {
|
|
try {
|
|
const payload = this.jwtService.verify(refreshToken, {
|
|
secret: this.configService.get('jwt.refreshSecret'),
|
|
});
|
|
|
|
const user = await this.usersService.findById(payload.sub);
|
|
if (!user || !user.isActive) {
|
|
throw new UnauthorizedException();
|
|
}
|
|
|
|
return this.generateTokens(user.id, user.email, user.role);
|
|
} catch {
|
|
throw new UnauthorizedException('Invalid refresh token');
|
|
}
|
|
}
|
|
|
|
private async generateTokens(userId: string, email: string, role: string) {
|
|
const payload = { sub: userId, email, role };
|
|
|
|
const [accessToken, refreshToken] = await Promise.all([
|
|
this.jwtService.signAsync(payload),
|
|
this.jwtService.signAsync(payload, {
|
|
secret: this.configService.get('jwt.refreshSecret'),
|
|
expiresIn: this.configService.get('jwt.refreshExpiresIn'),
|
|
}),
|
|
]);
|
|
|
|
return { accessToken, refreshToken };
|
|
}
|
|
}
|