Avnyr 9f99b80784 feat: implement authentication and database modules with relations and group management
Added new authentication strategies (JWT and GitHub OAuth), guards, and controllers. Implemented database module, schema with relations, and group management features, including CRD operations and person-to-group associations. Integrated validation and CORS configuration.
2025-05-15 17:09:36 +02:00

97 lines
2.6 KiB
TypeScript

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { UsersService } from '../../users/services/users.service';
import { JwtPayload } from '../interfaces/jwt-payload.interface';
import { TokensResponse } from '../interfaces/tokens-response.interface';
@Injectable()
export class AuthService {
constructor(
private readonly usersService: UsersService,
private readonly jwtService: JwtService,
private readonly configService: ConfigService,
) {}
/**
* Validate a user by GitHub ID
*/
async validateGithubUser(
githubId: string,
email: string,
name: string,
avatarUrl: string,
) {
// Try to find the user by GitHub ID
let user = await this.usersService.findByGithubId(githubId);
// If user doesn't exist, create a new one
if (!user) {
user = await this.usersService.create({
githubId,
name,
avatar: avatarUrl,
metadata: { email },
});
}
return user;
}
/**
* Generate JWT tokens (access and refresh)
*/
async generateTokens(userId: string): Promise<TokensResponse> {
const payload: JwtPayload = { sub: userId };
const [accessToken, refreshToken] = await Promise.all([
this.jwtService.signAsync(payload),
this.jwtService.signAsync(
{ ...payload, isRefreshToken: true },
{
expiresIn: this.configService.get<string>('JWT_REFRESH_EXPIRATION') || '7d',
secret: this.configService.get<string>('JWT_REFRESH_SECRET'),
},
),
]);
return {
accessToken,
refreshToken,
};
}
/**
* Refresh tokens using a valid refresh token
*/
async refreshTokens(userId: string, refreshToken: string): Promise<TokensResponse> {
// Verify the refresh token
try {
const payload = await this.jwtService.verifyAsync(refreshToken, {
secret: this.configService.get<string>('JWT_REFRESH_SECRET'),
});
// Check if the token is a refresh token and belongs to the user
if (!payload.isRefreshToken || payload.sub !== userId) {
throw new UnauthorizedException('Invalid refresh token');
}
// Generate new tokens
return this.generateTokens(userId);
} catch (error) {
throw new UnauthorizedException('Invalid refresh token');
}
}
/**
* Validate a user by JWT payload
*/
async validateJwtUser(payload: JwtPayload) {
const user = await this.usersService.findById(payload.sub);
if (!user) {
throw new UnauthorizedException('User not found');
}
return user;
}
}