switch to zod

This commit is contained in:
rubikscraft
2022-04-04 10:36:59 +02:00
parent bcd427f5a7
commit 380b9d3456
65 changed files with 867 additions and 864 deletions

View File

@@ -1,10 +1,8 @@
import { Injectable, Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { instanceToPlain, plainToClass } from 'class-transformer';
import { JwtDataDto } from 'picsur-shared/dist/dto/jwt.dto';
import { JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto';
import { EUser } from 'picsur-shared/dist/entities/user.entity';
import { AsyncFailable, Fail } from 'picsur-shared/dist/types';
import { strictValidate } from 'picsur-shared/dist/util/validate';
import { EUserBackend } from '../../models/entities/user.entity';
@Injectable()
export class AuthManagerService {
@@ -12,20 +10,20 @@ export class AuthManagerService {
constructor(private jwtService: JwtService) {}
async createToken(user: EUserBackend): AsyncFailable<string> {
const jwtData: JwtDataDto = plainToClass(JwtDataDto, {
async createToken(user: EUser): AsyncFailable<string> {
const jwtData = {
user,
});
};
// Validate to be sure, this makes client experience better
// in case of any failures
const errors = await strictValidate(jwtData);
if (errors.length > 0) {
return Fail('Invalid JWT: ' + errors);
const result = JwtDataSchema.safeParse(jwtData);
if (!result.success) {
return Fail('Invalid JWT: ' + result.error);
}
try {
return await this.jwtService.signAsync(instanceToPlain(jwtData));
return await this.jwtService.signAsync(result.data);
} catch (e) {
return Fail("Couldn't create JWT: " + e);
}

View File

@@ -1,14 +1,8 @@
import {
Inject,
Injectable,
Logger
} from '@nestjs/common';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { plainToClass } from 'class-transformer';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { JwtDataDto } from 'picsur-shared/dist/dto/jwt.dto';
import { strictValidate } from 'picsur-shared/dist/util/validate';
import { EUserBackend } from '../../../models/entities/user.entity';
import { JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto';
import { EUser } from 'picsur-shared/dist/entities/user.entity';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
@@ -23,17 +17,14 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
});
}
async validate(payload: any): Promise<EUserBackend | false> {
const jwt = plainToClass(JwtDataDto, payload);
// This then validates the data inside the jwt token
const errors = await strictValidate(jwt);
if (errors.length > 0) {
this.logger.warn(errors);
async validate(payload: any): Promise<EUser | false> {
const result = JwtDataSchema.safeParse(payload);
if (!result.success) {
this.logger.error('JWT could not be parsed: ' + result.error);
return false;
}
// And return the user
return jwt.user;
return result.data.user;
}
}

View File

@@ -1,9 +1,10 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { EUser } from 'picsur-shared/dist/entities/user.entity';
import { AsyncFailable, HasFailed } from 'picsur-shared/dist/types';
import { UsersService } from '../../../collections/userdb/userdb.service';
import { EUserBackend } from '../../../models/entities/user.entity';
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';
@Injectable()
export class LocalAuthStrategy extends PassportStrategy(Strategy, 'local') {
@@ -11,16 +12,13 @@ export class LocalAuthStrategy extends PassportStrategy(Strategy, 'local') {
super();
}
async validate(
username: string,
password: string,
): AsyncFailable<EUserBackend> {
async validate(username: string, password: string): AsyncFailable<EUser> {
// All this does is call the usersservice authenticate for authentication
const user = await this.usersService.authenticate(username, password);
if (HasFailed(user)) {
throw new UnauthorizedException();
}
return user;
return EUserBackend2EUser(user);
}
}

View File

@@ -7,12 +7,10 @@ import {
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { plainToClass } from 'class-transformer';
import { EUser, EUserSchema } from 'picsur-shared/dist/entities/user.entity';
import { Fail, Failable, HasFailed } from 'picsur-shared/dist/types';
import { strictValidate } from 'picsur-shared/dist/util/validate';
import { UsersService } from '../../../collections/userdb/userdb.service';
import { Permissions } from '../../../models/dto/permissions.dto';
import { EUserBackend } from '../../../models/entities/user.entity';
import { isPermissionsArray } from '../../../models/validators/permissions.validator';
// This guard extends both the jwt authenticator and the guest authenticator
@@ -84,16 +82,15 @@ export class MainAuthGuard extends AuthGuard(['jwt', 'guest']) {
return permissions;
}
private async validateUser(user: EUserBackend): Promise<EUserBackend> {
const userClass = plainToClass(EUserBackend, user);
const errors = await strictValidate(userClass);
if (errors.length > 0) {
this.logger.error(
'Invalid user object, where it should always be valid: ' + errors,
private async validateUser(user: EUser): Promise<EUser> {
const result = EUserSchema.safeParse(user);
if (!result.success) {
this.logger.warn(
`Invalid user object, where it should always be valid: ${result.error}`,
);
throw new InternalServerErrorException();
}
return userClass;
return result.data;
}
}