fix service
All checks were successful
Deploy Production / deploy (push) Successful in 54s

This commit is contained in:
parent 6a4acfd7a4
commit febe51db9c

View File

@ -1,9 +1,13 @@
import { Injectable, UnauthorizedException, BadRequestException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { UsersService } from '../users/users.service';
import { LoginDto, ChangePasswordDto, SetupPasswordDto } from './dto';
import { TokenPair } from './interfaces';
import {
Injectable,
UnauthorizedException,
BadRequestException,
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { JwtService } from "@nestjs/jwt";
import { UsersService } from "../users/users.service";
import { LoginDto, ChangePasswordDto, SetupPasswordDto } from "./dto";
import { TokenPair } from "./interfaces";
@Injectable()
export class AuthService {
@ -13,44 +17,55 @@ export class AuthService {
private usersService: UsersService,
) {}
async validateUser(loginDto: LoginDto): Promise<{ id: string; username: string }> {
async validateUser(
loginDto: LoginDto,
): Promise<{ id: string; username: string }> {
const { username, password } = loginDto;
const user = await this.usersService.findByUsername(username);
if (!user) {
throw new UnauthorizedException('Invalid credentials');
throw new UnauthorizedException("Invalid credentials");
}
if (!user.isPasswordSet) {
throw new BadRequestException('Password not set. Please use /auth/setup endpoint first.');
throw new BadRequestException(
"Password not set. Please use /auth/setup endpoint first.",
);
}
const isPasswordValid = await this.usersService.validatePassword(user, password);
const isPasswordValid = await this.usersService.validatePassword(
user,
password,
);
if (!isPasswordValid) {
throw new UnauthorizedException('Invalid credentials');
throw new UnauthorizedException("Invalid credentials");
}
if (!user.isAdmin) {
throw new UnauthorizedException('Access denied');
throw new UnauthorizedException("Access denied");
}
return { id: user.id, username: user.username };
}
async setupPassword(setupPasswordDto: SetupPasswordDto): Promise<{ id: string; username: string }> {
async setupPassword(
setupPasswordDto: SetupPasswordDto,
): Promise<{ id: string; username: string }> {
const { username, password } = setupPasswordDto;
const user = await this.usersService.findByUsername(username);
if (!user) {
throw new UnauthorizedException('User not found');
throw new UnauthorizedException("User not found");
}
if (!user.isAdmin) {
throw new UnauthorizedException('Access denied');
throw new UnauthorizedException("Access denied");
}
if (user.isPasswordSet) {
throw new BadRequestException('Password already set. Use /auth/change-password to change it.');
throw new BadRequestException(
"Password already set. Use /auth/change-password to change it.",
);
}
await this.usersService.setupPassword(username, password);
@ -65,26 +80,29 @@ export class AuthService {
const accessPayload = {
sub: userId,
username,
type: 'access',
type: "access",
};
const refreshPayload = {
sub: userId,
username,
type: 'refresh',
type: "refresh",
};
const accessSecret = this.configService.get<string>('JWT_ACCESS_SECRET') || 'default-secret';
const refreshSecret = this.configService.get<string>('JWT_REFRESH_SECRET') || 'default-refresh-secret';
const accessSecret =
this.configService.get<string>("JWT_ACCESS_SECRET") || "default-secret";
const refreshSecret =
this.configService.get<string>("JWT_REFRESH_SECRET") ||
"default-refresh-secret";
const [accessToken, refreshToken] = await Promise.all([
this.jwtService.signAsync(accessPayload, {
secret: accessSecret,
expiresIn: '15m',
expiresIn: "15m",
}),
this.jwtService.signAsync(refreshPayload, {
secret: refreshSecret,
expiresIn: '7d',
expiresIn: "7d",
}),
]);
@ -92,51 +110,60 @@ export class AuthService {
}
async refreshTokens(userId: string, username: string): Promise<TokenPair> {
// Verify user still exists and is admin
const user = await this.usersService.findById(userId);
if (!user || !user.isAdmin) {
throw new UnauthorizedException('User not found or no longer authorized');
throw new UnauthorizedException("User not found or no longer authorized");
}
return this.generateTokens(userId, username);
}
getCookieOptions(isRefreshToken = false) {
const isProduction = this.configService.get<string>('NODE_ENV') === 'production';
const cookieSecure = this.configService.get<string>('COOKIE_SECURE') === 'true';
const isProduction =
this.configService.get<string>("NODE_ENV") === "production";
const cookieSecure =
this.configService.get<string>("COOKIE_SECURE") === "true";
const domain = this.configService.get<string>("COOKIE_DOMAIN");
return {
httpOnly: true,
secure: isProduction || cookieSecure,
sameSite: 'lax' as const,
path: isRefreshToken ? '/auth/refresh' : '/',
maxAge: isRefreshToken
? 7 * 24 * 60 * 60 * 1000 // 7 days for refresh token
: 15 * 60 * 1000, // 15 minutes for access token
sameSite: "none" as const,
path: isRefreshToken ? "/auth/refresh" : "/",
domain: domain,
maxAge: isRefreshToken ? 7 * 24 * 60 * 60 * 1000 : 15 * 60 * 1000,
};
}
getClearCookieOptions(isRefreshToken = false) {
return {
httpOnly: true,
path: isRefreshToken ? '/auth/refresh' : '/',
path: isRefreshToken ? "/auth/refresh" : "/",
};
}
async changePassword(userId: string, changePasswordDto: ChangePasswordDto): Promise<void> {
async changePassword(
userId: string,
changePasswordDto: ChangePasswordDto,
): Promise<void> {
const { currentPassword, newPassword } = changePasswordDto;
const user = await this.usersService.findById(userId);
if (!user) {
throw new UnauthorizedException('User not found');
throw new UnauthorizedException("User not found");
}
const isCurrentPasswordValid = await this.usersService.validatePassword(user, currentPassword);
const isCurrentPasswordValid = await this.usersService.validatePassword(
user,
currentPassword,
);
if (!isCurrentPasswordValid) {
throw new BadRequestException('Current password is incorrect');
throw new BadRequestException("Current password is incorrect");
}
if (currentPassword === newPassword) {
throw new BadRequestException('New password must be different from current password');
throw new BadRequestException(
"New password must be different from current password",
);
}
await this.usersService.updatePassword(userId, newPassword);