mirror of
https://github.com/CaramelFur/Picsur.git
synced 2026-02-26 16:10:45 +01:00
change way auth keys behave
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto';
|
||||
import { JwtData, JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto';
|
||||
import { EUser } from 'picsur-shared/dist/entities/user.entity';
|
||||
import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types';
|
||||
|
||||
@@ -11,8 +11,8 @@ export class AuthManagerService {
|
||||
constructor(private readonly jwtService: JwtService) {}
|
||||
|
||||
async createToken(user: EUser): AsyncFailable<string> {
|
||||
const jwtData = {
|
||||
user,
|
||||
const jwtData: JwtData = {
|
||||
uid: user.id,
|
||||
};
|
||||
|
||||
// Validate to be sure, this makes client experience better
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Strategy } from 'passport-strategy';
|
||||
import { EUser } from 'picsur-shared/dist/entities/user.entity';
|
||||
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';
|
||||
import { GuestService } from '../guest.service';
|
||||
import { ReqType } from './reqtype';
|
||||
|
||||
@@ -26,7 +28,7 @@ export class GuestStrategy extends PassportStrategy(
|
||||
}
|
||||
|
||||
// Return the guest user created by the guestservice
|
||||
override async validate(payload: any) {
|
||||
return await this.guestService.getGuestUser();
|
||||
override async validate(payload: any): Promise<EUser> {
|
||||
return EUserBackend2EUser(await this.guestService.getGuestUser());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,18 @@ import { PassportStrategy } from '@nestjs/passport';
|
||||
import { ExtractJwt, Strategy as JwtPassportStrategy } from 'passport-jwt';
|
||||
import { JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto';
|
||||
import { EUser } from 'picsur-shared/dist/entities/user.entity';
|
||||
import { ThrowIfFailed } from 'picsur-shared/dist/types';
|
||||
import { UserDbService } from '../../../collections/user-db/user-db.service';
|
||||
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';
|
||||
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(JwtPassportStrategy, 'jwt') {
|
||||
private readonly logger = new Logger(JwtStrategy.name);
|
||||
|
||||
constructor(@Inject('JWT_SECRET') jwtSecret: string) {
|
||||
constructor(
|
||||
@Inject('JWT_SECRET') jwtSecret: string,
|
||||
private readonly usersService: UserDbService,
|
||||
) {
|
||||
// This will validate the jwt token itself
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
@@ -24,7 +30,11 @@ export class JwtStrategy extends PassportStrategy(JwtPassportStrategy, 'jwt') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const backendUser = ThrowIfFailed(
|
||||
await this.usersService.findOne(result.data.uid),
|
||||
);
|
||||
|
||||
// And return the user
|
||||
return result.data.user;
|
||||
return EUserBackend2EUser(backendUser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,14 @@ import { ExecutionContext, Injectable, Logger } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { EUser, EUserSchema } from 'picsur-shared/dist/entities/user.entity';
|
||||
import { Fail, Failable, FT, HasFailed } from 'picsur-shared/dist/types';
|
||||
import {
|
||||
AsyncFailable,
|
||||
Fail,
|
||||
Failable,
|
||||
FT,
|
||||
HasFailed,
|
||||
ThrowIfFailed,
|
||||
} from 'picsur-shared/dist/types';
|
||||
import { makeUnique } from 'picsur-shared/dist/util/unique';
|
||||
import { UserDbService } from '../../../collections/user-db/user-db.service';
|
||||
import { Permissions } from '../../../models/constants/permissions.const';
|
||||
@@ -34,9 +41,10 @@ export class MainAuthGuard extends AuthGuard(['apikey', 'jwt', 'guest']) {
|
||||
);
|
||||
}
|
||||
|
||||
const user = await this.validateUser(
|
||||
context.switchToHttp().getRequest().user,
|
||||
);
|
||||
const unsafeUser: EUser = context.switchToHttp().getRequest().user;
|
||||
|
||||
const user = ThrowIfFailed(await this.validateUser(unsafeUser));
|
||||
|
||||
if (!user.id) {
|
||||
throw Fail(
|
||||
FT.Internal,
|
||||
@@ -62,6 +70,7 @@ export class MainAuthGuard extends AuthGuard(['apikey', 'jwt', 'guest']) {
|
||||
}
|
||||
|
||||
context.switchToHttp().getRequest().userPermissions = userPermissions;
|
||||
context.switchToHttp().getRequest().user = user;
|
||||
|
||||
if (permissions.every((permission) => userPermissions.includes(permission)))
|
||||
return true;
|
||||
@@ -100,10 +109,10 @@ export class MainAuthGuard extends AuthGuard(['apikey', 'jwt', 'guest']) {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
private async validateUser(user: EUser): Promise<EUser> {
|
||||
private async validateUser(user: EUser): AsyncFailable<EUser> {
|
||||
const result = EUserSchema.safeParse(user);
|
||||
if (!result.success) {
|
||||
throw Fail(
|
||||
return Fail(
|
||||
FT.Internal,
|
||||
undefined,
|
||||
`Invalid user object, where it should always be valid: ${result.error}`,
|
||||
|
||||
@@ -53,15 +53,6 @@ export class UserService {
|
||||
const apikey = await this.key.get();
|
||||
if (!apikey) return;
|
||||
|
||||
const user = await this.extractUser(apikey);
|
||||
if (HasFailed(user)) {
|
||||
this.logger.error(user.getReason());
|
||||
await this.logout();
|
||||
return;
|
||||
}
|
||||
|
||||
this.userSubject.next(user);
|
||||
|
||||
const fetchedUser = await this.fetchUser();
|
||||
if (HasFailed(fetchedUser)) {
|
||||
this.logger.error(fetchedUser.getReason());
|
||||
@@ -137,7 +128,7 @@ export class UserService {
|
||||
}
|
||||
|
||||
// This extracts the available userdata from the jwt token
|
||||
private async extractUser(token: string): AsyncFailable<EUser> {
|
||||
private async extractUserID(token: string): AsyncFailable<string> {
|
||||
let decoded: any;
|
||||
try {
|
||||
decoded = jwt_decode(token);
|
||||
@@ -151,7 +142,7 @@ export class UserService {
|
||||
return Fail(FT.UsrValidation, 'Invalid token data');
|
||||
}
|
||||
|
||||
return result.data.user;
|
||||
return result.data.uid;
|
||||
}
|
||||
|
||||
// This actually fetches up to date information from the server
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { z } from 'zod';
|
||||
import { EUserSchema } from '../entities/user.entity';
|
||||
import { IsEntityID } from '../validators/entity-id.validator';
|
||||
|
||||
export const JwtDataSchema = z.object({
|
||||
user: EUserSchema.required(),
|
||||
uid: IsEntityID(),
|
||||
iat: z.number().int().optional(),
|
||||
exp: z.number().int().optional(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user