Files
twenty_crm/server/src/auth/services/auth.service.ts
Charles Bochet 0f9c6dede7 Clean server post refactor to remove Hasura (#156)
* Clean BE post refactor to remove Hasura

* Add server CI
2023-05-29 22:42:24 +02:00

131 lines
3.3 KiB
TypeScript

import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { JwtPayload } from '../strategies/jwt.auth.strategy';
import { ConfigService } from '@nestjs/config';
import { UserRepository } from 'src/entities/user/user.repository';
import { WorkspaceRepository } from 'src/entities/workspace/workspace.repository';
import { RefreshTokenRepository } from 'src/entities/refresh-token/refresh-token.repository';
import { v4 } from 'uuid';
import { RefreshToken, User } from '@prisma/client';
@Injectable()
export class AuthService {
constructor(
private jwtService: JwtService,
private configService: ConfigService,
private userRepository: UserRepository,
private workspaceRepository: WorkspaceRepository,
private refreshTokenRepository: RefreshTokenRepository,
) {}
async upsertUser(rawUser: {
firstName: string;
lastName: string;
email: string;
}) {
if (!rawUser.email) {
throw new HttpException(
{ reason: 'Email is missing' },
HttpStatus.BAD_REQUEST,
);
}
if (!rawUser.firstName || !rawUser.lastName) {
throw new HttpException(
{ reason: 'Firstname or lastname is missing' },
HttpStatus.BAD_REQUEST,
);
}
const emailDomain = rawUser.email.split('@')[1];
if (!emailDomain) {
throw new HttpException(
{ reason: 'Email is malformed' },
HttpStatus.BAD_REQUEST,
);
}
const workspace = await this.workspaceRepository.findUnique({
where: { domainName: emailDomain },
});
if (!workspace) {
throw new HttpException(
{ reason: 'User email domain does not match an existing workspace' },
HttpStatus.FORBIDDEN,
);
}
const user = await this.userRepository.upsertUser({
data: {
id: v4(),
email: rawUser.email,
displayName: rawUser.firstName + ' ' + rawUser.lastName,
locale: 'en',
},
workspaceId: workspace.id,
});
await this.userRepository.upsertWorkspaceMember({
data: {
id: v4(),
userId: user.id,
workspaceId: workspace.id,
},
});
return user;
}
async generateAccessToken(refreshToken: string): Promise<string | undefined> {
const refreshTokenObject = await this.refreshTokenRepository.findFirst({
where: { refreshToken: refreshToken },
});
if (!refreshTokenObject) {
return;
}
const user = await this.userRepository.findUnique({
where: { id: refreshTokenObject.userId },
});
if (!user) {
return;
}
const workspace = await this.workspaceRepository.findFirst({
where: { WorkspaceMember: { every: { userId: user.id } } },
});
if (!workspace) {
return;
}
const payload: JwtPayload = {
userId: user.id,
workspaceId: workspace.id,
};
return this.jwtService.sign(payload);
}
async registerRefreshToken(user: User): Promise<RefreshToken> {
const refreshToken = await this.refreshTokenRepository.upsertRefreshToken({
data: {
id: v4(),
userId: user.id,
refreshToken: v4(),
},
});
return refreshToken;
}
computeRedirectURI(refreshToken: string): string {
return `${this.configService.get<string>(
'FRONT_AUTH_CALLBACK_URL',
)}?refreshToken=${refreshToken}`;
}
}