Listory/src/auth/auth.service.ts

118 lines
3.1 KiB
TypeScript
Raw Normal View History

2020-09-05 23:35:53 +02:00
import { ForbiddenException, Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { JwtService } from "@nestjs/jwt";
2020-02-01 16:11:48 +01:00
import { User } from "../users/user.entity";
import { UsersService } from "../users/users.service";
2020-09-05 23:35:53 +02:00
import { AuthSession } from "./auth-session.entity";
import { AuthSessionRepository } from "./auth-session.repository";
2020-02-01 16:11:48 +01:00
import { LoginDto } from "./dto/login.dto";
@Injectable()
export class AuthService {
private readonly userFilter: null | string;
2020-09-05 23:35:53 +02:00
private readonly sessionExpirationTime: string;
2020-02-01 16:11:48 +01:00
constructor(
private readonly config: ConfigService,
2020-02-01 16:11:48 +01:00
private readonly usersService: UsersService,
2020-09-05 23:35:53 +02:00
private readonly jwtService: JwtService,
private readonly authSessionRepository: AuthSessionRepository
) {
this.userFilter = this.config.get<string>("SPOTIFY_USER_FILTER");
2020-09-05 23:35:53 +02:00
this.sessionExpirationTime = this.config.get<string>(
"SESSION_EXPIRATION_TIME"
);
}
2020-02-01 16:11:48 +01:00
async spotifyLogin({
accessToken,
refreshToken,
2020-05-02 17:17:20 +02:00
profile,
2020-02-01 16:11:48 +01:00
}: LoginDto): Promise<User> {
if (!this.allowedByUserFilter(profile.id)) {
throw new ForbiddenException("UserNotInUserFilter");
}
2020-02-01 16:11:48 +01:00
const user = await this.usersService.createOrUpdate({
displayName: profile.displayName,
photo: profile.photos.length > 0 ? profile.photos[0].value : null,
2020-02-01 16:11:48 +01:00
spotify: {
id: profile.id,
accessToken,
2020-05-02 17:17:20 +02:00
refreshToken,
},
2020-02-01 16:11:48 +01:00
});
return user;
}
2021-05-25 16:01:55 +02:00
async createSession(user: User): Promise<{
2020-09-05 23:35:53 +02:00
session: AuthSession;
refreshToken: string;
}> {
const session = this.authSessionRepository.create();
session.user = user;
await this.authSessionRepository.save(session);
const { refreshToken } = await this.createRefreshToken(session);
2020-09-05 23:35:53 +02:00
return { session, refreshToken };
}
/**
* createRefreshToken should only be used while creating a new session.
* @param session
*/
private async createRefreshToken(
session: AuthSession
): Promise<{ refreshToken }> {
const payload = {
sub: session.user.id,
name: session.user.displayName,
};
const token = await this.jwtService.signAsync(payload, {
jwtid: session.id,
// jwtService uses the shorter access token time as a default
expiresIn: this.sessionExpirationTime,
});
return { refreshToken: token };
}
async createAccessToken(session: AuthSession): Promise<{ accessToken }> {
if (session.revokedAt) {
throw new ForbiddenException("SessionIsRevoked");
}
const payload = {
sub: session.user.id,
name: session.user.displayName,
picture: session.user.photo,
};
const token = await this.jwtService.signAsync(payload);
return { accessToken: token };
}
async findSession(id: string): Promise<AuthSession> {
return this.authSessionRepository.findOne(id);
}
2020-02-01 16:11:48 +01:00
async findUser(id: string): Promise<User> {
return this.usersService.findById(id);
}
allowedByUserFilter(spotifyID: string) {
if (!this.userFilter) {
return true;
}
const whitelistedIDs = this.userFilter.split(",");
return whitelistedIDs.includes(spotifyID);
}
2020-02-01 16:11:48 +01:00
}