mirror of
https://github.com/CaramelFur/Picsur.git
synced 2025-11-12 23:05:39 +01:00
refactor backend done
This commit is contained in:
18
backend/src/decorators/returns.decorator.ts
Normal file
18
backend/src/decorators/returns.decorator.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
import { Newable } from 'picsur-shared/dist/types/newable';
|
||||||
|
|
||||||
|
// Not yet used, but can be used for outgoing data validation
|
||||||
|
|
||||||
|
type ReturnsMethodDecorator<ReturnType> = <
|
||||||
|
T extends (...args: any) => ReturnType | Promise<ReturnType>,
|
||||||
|
>(
|
||||||
|
target: Object,
|
||||||
|
propertyKey: string | symbol,
|
||||||
|
descriptor: TypedPropertyDescriptor<T>,
|
||||||
|
) => TypedPropertyDescriptor<T> | void;
|
||||||
|
|
||||||
|
export function Returns<N extends Object>(
|
||||||
|
newable: Newable<N>,
|
||||||
|
): ReturnsMethodDecorator<N> {
|
||||||
|
return SetMetadata('returns', newable);
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
import { JwtService } from '@nestjs/jwt';
|
import { JwtService } from '@nestjs/jwt';
|
||||||
import { instanceToPlain, plainToClass } from 'class-transformer';
|
import { instanceToPlain, plainToClass } from 'class-transformer';
|
||||||
import { JwtDataDto } from 'picsur-shared/dist/dto/jwt.dto';
|
import { JwtDataDto } from 'picsur-shared/dist/dto/jwt.dto';
|
||||||
|
import { AsyncFailable, Fail } from 'picsur-shared/dist/types';
|
||||||
import { strictValidate } from 'picsur-shared/dist/util/validate';
|
import { strictValidate } from 'picsur-shared/dist/util/validate';
|
||||||
import { EUserBackend } from '../../models/entities/user.entity';
|
import { EUserBackend } from '../../models/entities/user.entity';
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ export class AuthManagerService {
|
|||||||
|
|
||||||
constructor(private jwtService: JwtService) {}
|
constructor(private jwtService: JwtService) {}
|
||||||
|
|
||||||
async createToken(user: EUserBackend): Promise<string> {
|
async createToken(user: EUserBackend): AsyncFailable<string> {
|
||||||
const jwtData: JwtDataDto = plainToClass(JwtDataDto, {
|
const jwtData: JwtDataDto = plainToClass(JwtDataDto, {
|
||||||
user: {
|
user: {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
@@ -23,10 +24,13 @@ export class AuthManagerService {
|
|||||||
// in case of any failures
|
// in case of any failures
|
||||||
const errors = await strictValidate(jwtData);
|
const errors = await strictValidate(jwtData);
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
this.logger.warn(errors);
|
return Fail('Invalid JWT: ' + errors);
|
||||||
throw new Error('Invalid jwt token generated');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.jwtService.signAsync(instanceToPlain(jwtData));
|
try {
|
||||||
|
return await this.jwtService.signAsync(instanceToPlain(jwtData));
|
||||||
|
} catch (e) {
|
||||||
|
return Fail("Couldn't create JWT: " + e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { strictValidate } from 'picsur-shared/dist/util/validate';
|
|||||||
import { UserRolesService } from '../../../collections/userdb/userrolesdb.service';
|
import { UserRolesService } from '../../../collections/userdb/userrolesdb.service';
|
||||||
import { Permissions } from '../../../models/dto/permissions.dto';
|
import { Permissions } from '../../../models/dto/permissions.dto';
|
||||||
import { EUserBackend } from '../../../models/entities/user.entity';
|
import { EUserBackend } from '../../../models/entities/user.entity';
|
||||||
import { isPermissionsArray } from '../../../models/util/permissions.validator';
|
import { isPermissionsArray } from '../../../models/validators/permissions.validator';
|
||||||
|
|
||||||
// This guard extends both the jwt authenticator and the guest authenticator
|
// This guard extends both the jwt authenticator and the guest authenticator
|
||||||
// The order matters here, because this results in the guest authenticator being used as a fallback
|
// The order matters here, because this results in the guest authenticator being used as a fallback
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { IsMultiPartFile } from '../validators/multipart.validator';
|
||||||
import { MultiPartFileDto } from './multipart.dto';
|
import { MultiPartFileDto } from './multipart.dto';
|
||||||
import { IsMultiPartFile } from './multipart.validator';
|
|
||||||
|
|
||||||
// A validation class for form based file upload of an image
|
// A validation class for form based file upload of an image
|
||||||
export class ImageUploadDto {
|
export class ImageUploadDto {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsDefined, ValidateNested } from 'class-validator';
|
import { IsDefined, ValidateNested } from 'class-validator';
|
||||||
import { CombinePDecorators } from 'picsur-shared/dist/util/decorator';
|
import { CombinePDecorators } from 'picsur-shared/dist/util/decorator';
|
||||||
import { MultiPartFieldDto, MultiPartFileDto } from './multipart.dto';
|
import { MultiPartFieldDto, MultiPartFileDto } from '../requests/multipart.dto';
|
||||||
|
|
||||||
|
|
||||||
export const IsMultiPartFile = CombinePDecorators(
|
export const IsMultiPartFile = CombinePDecorators(
|
||||||
IsDefined(),
|
IsDefined(),
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Controller, Get, Request } from '@nestjs/common';
|
import { Controller, Get, Request } from '@nestjs/common';
|
||||||
import AuthFasityRequest from '../../../models/requests/authrequest.dto';
|
import AuthFasityRequest from '../../../models/requests/authrequest.dto';
|
||||||
|
|
||||||
|
|
||||||
@Controller('api/experiment')
|
@Controller('api/experiment')
|
||||||
export class ExperimentController {
|
export class ExperimentController {
|
||||||
@Get()
|
@Get()
|
||||||
// @Guest()
|
|
||||||
async testRoute(@Request() req: AuthFasityRequest) {
|
async testRoute(@Request() req: AuthFasityRequest) {
|
||||||
return {
|
return {
|
||||||
message: req.user,
|
message: req.user,
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ExperimentController } from './experiment.controller';
|
import { ExperimentController } from './experiment.controller';
|
||||||
|
|
||||||
|
// This is comletely useless module, but is used for testing
|
||||||
|
// TODO: remove when out of beta
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [ExperimentController]
|
controllers: [ExperimentController]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { Controller, Get } from '@nestjs/common';
|
import { Controller, Get } from '@nestjs/common';
|
||||||
import { plainToClass } from 'class-transformer';
|
import { plainToClass } from 'class-transformer';
|
||||||
import { AllPermissionsResponse, InfoResponse } from 'picsur-shared/dist/dto/api/info.dto';
|
import {
|
||||||
|
AllPermissionsResponse,
|
||||||
|
InfoResponse
|
||||||
|
} from 'picsur-shared/dist/dto/api/info.dto';
|
||||||
import { HostConfigService } from '../../../config/early/host.config.service';
|
import { HostConfigService } from '../../../config/early/host.config.service';
|
||||||
import { NoPermissions } from '../../../decorators/permissions.decorator';
|
import { NoPermissions } from '../../../decorators/permissions.decorator';
|
||||||
import { PermissionsList } from '../../../models/dto/permissions.dto';
|
import { PermissionsList } from '../../../models/dto/permissions.dto';
|
||||||
@@ -20,7 +23,7 @@ export class InfoController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List all available permissions
|
// List all available permissions
|
||||||
@Get('/permissions')
|
@Get('permissions')
|
||||||
async getPermissions(): Promise<AllPermissionsResponse> {
|
async getPermissions(): Promise<AllPermissionsResponse> {
|
||||||
const result: AllPermissionsResponse = {
|
const result: AllPermissionsResponse = {
|
||||||
Permissions: PermissionsList,
|
Permissions: PermissionsList,
|
||||||
|
|||||||
@@ -7,12 +7,9 @@ import {
|
|||||||
Param,
|
Param,
|
||||||
Post
|
Post
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { plainToClass } from 'class-transformer';
|
|
||||||
import {
|
import {
|
||||||
GetSyspreferenceResponse,
|
GetSyspreferenceResponse,
|
||||||
MultipleSysPreferencesResponse,
|
MultipleSysPreferencesResponse, UpdateSysPreferenceRequest,
|
||||||
SysPreferenceBaseResponse,
|
|
||||||
UpdateSysPreferenceRequest,
|
|
||||||
UpdateSysPreferenceResponse
|
UpdateSysPreferenceResponse
|
||||||
} from 'picsur-shared/dist/dto/api/pref.dto';
|
} from 'picsur-shared/dist/dto/api/pref.dto';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
@@ -35,14 +32,10 @@ export class PrefController {
|
|||||||
throw new InternalServerErrorException('Could not get preferences');
|
throw new InternalServerErrorException('Could not get preferences');
|
||||||
}
|
}
|
||||||
|
|
||||||
const returned: MultipleSysPreferencesResponse = {
|
return {
|
||||||
preferences: prefs.map((pref) =>
|
preferences: prefs,
|
||||||
plainToClass(SysPreferenceBaseResponse, pref),
|
|
||||||
),
|
|
||||||
total: prefs.length,
|
total: prefs.length,
|
||||||
};
|
};
|
||||||
|
|
||||||
return plainToClass(MultipleSysPreferencesResponse, returned);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('sys/:key')
|
@Get('sys/:key')
|
||||||
@@ -55,7 +48,7 @@ export class PrefController {
|
|||||||
throw new InternalServerErrorException('Could not get preference');
|
throw new InternalServerErrorException('Could not get preference');
|
||||||
}
|
}
|
||||||
|
|
||||||
return plainToClass(GetSyspreferenceResponse, pref);
|
return pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('sys/:key')
|
@Post('sys/:key')
|
||||||
@@ -71,12 +64,10 @@ export class PrefController {
|
|||||||
throw new InternalServerErrorException('Could not set preference');
|
throw new InternalServerErrorException('Could not set preference');
|
||||||
}
|
}
|
||||||
|
|
||||||
const returned = {
|
return {
|
||||||
key,
|
key,
|
||||||
value: pref.value,
|
value: pref.value,
|
||||||
type: pref.type,
|
type: pref.type,
|
||||||
};
|
};
|
||||||
|
|
||||||
return plainToClass(UpdateSysPreferenceResponse, returned);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {
|
|||||||
Logger,
|
Logger,
|
||||||
Post
|
Post
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { plainToClass } from 'class-transformer';
|
|
||||||
import {
|
import {
|
||||||
RoleCreateRequest,
|
RoleCreateRequest,
|
||||||
RoleCreateResponse,
|
RoleCreateResponse,
|
||||||
@@ -22,16 +21,14 @@ import {
|
|||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { RolesService } from '../../../collections/roledb/roledb.service';
|
import { RolesService } from '../../../collections/roledb/roledb.service';
|
||||||
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
||||||
import {
|
import { Permission } from '../../../models/dto/permissions.dto';
|
||||||
Permission
|
|
||||||
} from '../../../models/dto/permissions.dto';
|
|
||||||
import {
|
import {
|
||||||
DefaultRolesList,
|
DefaultRolesList,
|
||||||
ImmutableRolesList,
|
ImmutableRolesList,
|
||||||
SoulBoundRolesList,
|
SoulBoundRolesList,
|
||||||
UndeletableRolesList
|
UndeletableRolesList
|
||||||
} from '../../../models/dto/roles.dto';
|
} from '../../../models/dto/roles.dto';
|
||||||
import { isPermissionsArray } from '../../../models/util/permissions.validator';
|
import { isPermissionsArray } from '../../../models/validators/permissions.validator';
|
||||||
|
|
||||||
@Controller('api/roles')
|
@Controller('api/roles')
|
||||||
@RequiredPermissions(Permission.RoleManage)
|
@RequiredPermissions(Permission.RoleManage)
|
||||||
@@ -40,7 +37,7 @@ export class RolesController {
|
|||||||
|
|
||||||
constructor(private rolesService: RolesService) {}
|
constructor(private rolesService: RolesService) {}
|
||||||
|
|
||||||
@Get('/list')
|
@Get('list')
|
||||||
async getRoles(): Promise<RoleListResponse> {
|
async getRoles(): Promise<RoleListResponse> {
|
||||||
const roles = await this.rolesService.findAll();
|
const roles = await this.rolesService.findAll();
|
||||||
if (HasFailed(roles)) {
|
if (HasFailed(roles)) {
|
||||||
@@ -54,7 +51,7 @@ export class RolesController {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/info')
|
@Post('info')
|
||||||
async getRole(@Body() body: RoleInfoRequest): Promise<RoleInfoResponse> {
|
async getRole(@Body() body: RoleInfoRequest): Promise<RoleInfoResponse> {
|
||||||
const role = await this.rolesService.findOne(body.name);
|
const role = await this.rolesService.findOne(body.name);
|
||||||
if (HasFailed(role)) {
|
if (HasFailed(role)) {
|
||||||
@@ -65,13 +62,13 @@ export class RolesController {
|
|||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/update')
|
@Post('update')
|
||||||
async updateRole(
|
async updateRole(
|
||||||
@Body() body: RoleUpdateRequest,
|
@Body() body: RoleUpdateRequest,
|
||||||
): Promise<RoleUpdateResponse> {
|
): Promise<RoleUpdateResponse> {
|
||||||
const permissions = body.permissions;
|
const permissions = body.permissions;
|
||||||
if (!isPermissionsArray(permissions)) {
|
if (!isPermissionsArray(permissions)) {
|
||||||
throw new InternalServerErrorException('Invalid permissions array');
|
throw new InternalServerErrorException('Invalid permissions');
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedRole = await this.rolesService.setPermissions(
|
const updatedRole = await this.rolesService.setPermissions(
|
||||||
@@ -86,7 +83,7 @@ export class RolesController {
|
|||||||
return updatedRole;
|
return updatedRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/create')
|
@Post('create')
|
||||||
async createRole(
|
async createRole(
|
||||||
@Body() role: RoleCreateRequest,
|
@Body() role: RoleCreateRequest,
|
||||||
): Promise<RoleCreateResponse> {
|
): Promise<RoleCreateResponse> {
|
||||||
@@ -104,7 +101,7 @@ export class RolesController {
|
|||||||
return newRole;
|
return newRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/delete')
|
@Post('delete')
|
||||||
async deleteRole(
|
async deleteRole(
|
||||||
@Body() role: RoleDeleteRequest,
|
@Body() role: RoleDeleteRequest,
|
||||||
): Promise<RoleDeleteResponse> {
|
): Promise<RoleDeleteResponse> {
|
||||||
@@ -117,16 +114,13 @@ export class RolesController {
|
|||||||
return deletedRole;
|
return deletedRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('/special')
|
@Get('special')
|
||||||
async getSpecialRoles(): Promise<SpecialRolesResponse> {
|
async getSpecialRoles(): Promise<SpecialRolesResponse> {
|
||||||
const result: SpecialRolesResponse = {
|
return {
|
||||||
SoulBoundRoles: SoulBoundRolesList,
|
SoulBoundRoles: SoulBoundRolesList,
|
||||||
ImmutableRoles: ImmutableRolesList,
|
ImmutableRoles: ImmutableRolesList,
|
||||||
UndeletableRoles: UndeletableRolesList,
|
UndeletableRoles: UndeletableRolesList,
|
||||||
DefaultRoles: DefaultRolesList,
|
DefaultRoles: DefaultRolesList,
|
||||||
};
|
};
|
||||||
|
|
||||||
return plainToClass(SpecialRolesResponse, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,13 @@ export class UserController {
|
|||||||
@Post('login')
|
@Post('login')
|
||||||
@UseLocalAuth(Permission.UserLogin)
|
@UseLocalAuth(Permission.UserLogin)
|
||||||
async login(@Request() req: AuthFasityRequest): Promise<UserLoginResponse> {
|
async login(@Request() req: AuthFasityRequest): Promise<UserLoginResponse> {
|
||||||
return {
|
const jwt_token = await this.authService.createToken(req.user);
|
||||||
jwt_token: await this.authService.createToken(req.user),
|
if (HasFailed(jwt_token)) {
|
||||||
};
|
this.logger.warn(jwt_token.getReason());
|
||||||
|
throw new InternalServerErrorException('Could not get new token');
|
||||||
|
}
|
||||||
|
|
||||||
|
return { jwt_token };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('register')
|
@Post('register')
|
||||||
@@ -71,10 +75,13 @@ export class UserController {
|
|||||||
throw new InternalServerErrorException('Could not get user');
|
throw new InternalServerErrorException('Could not get user');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const token = await this.authService.createToken(user);
|
||||||
user,
|
if (HasFailed(token)) {
|
||||||
token: await this.authService.createToken(user),
|
this.logger.warn(token.getReason());
|
||||||
};
|
throw new InternalServerErrorException('Could not get new token');
|
||||||
|
}
|
||||||
|
|
||||||
|
return { user, token };
|
||||||
}
|
}
|
||||||
|
|
||||||
// You can always check your permissions
|
// You can always check your permissions
|
||||||
|
|||||||
17
backend/src/routes/image/imageid.validator.ts
Normal file
17
backend/src/routes/image/imageid.validator.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import {
|
||||||
|
ArgumentMetadata,
|
||||||
|
BadRequestException,
|
||||||
|
Injectable,
|
||||||
|
PipeTransform
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { isHash } from 'class-validator';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ImageIdValidator implements PipeTransform<string, string> {
|
||||||
|
transform(value: string, metadata: ArgumentMetadata): string {
|
||||||
|
if (isHash(value, 'sha256')) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
throw new BadRequestException('Invalid image id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
BadRequestException,
|
|
||||||
Controller,
|
Controller,
|
||||||
Get,
|
Get,
|
||||||
InternalServerErrorException,
|
InternalServerErrorException,
|
||||||
Logger,
|
Logger,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
Param,
|
Param,
|
||||||
Post,
|
Post, Res
|
||||||
Req,
|
|
||||||
Res
|
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { isHash } from 'class-validator';
|
import { FastifyReply } from 'fastify';
|
||||||
import { FastifyReply, FastifyRequest } from 'fastify';
|
|
||||||
import { ImageMetaResponse } from 'picsur-shared/dist/dto/api/image.dto';
|
import { ImageMetaResponse } from 'picsur-shared/dist/dto/api/image.dto';
|
||||||
import { HasFailed } from 'picsur-shared/dist/types';
|
import { HasFailed } from 'picsur-shared/dist/types';
|
||||||
import { MultiPart } from '../../decorators/multipart.decorator';
|
import { MultiPart } from '../../decorators/multipart.decorator';
|
||||||
@@ -19,6 +15,7 @@ import { RequiredPermissions } from '../../decorators/permissions.decorator';
|
|||||||
import { ImageManagerService } from '../../managers/imagemanager/imagemanager.service';
|
import { ImageManagerService } from '../../managers/imagemanager/imagemanager.service';
|
||||||
import { Permission } from '../../models/dto/permissions.dto';
|
import { Permission } from '../../models/dto/permissions.dto';
|
||||||
import { ImageUploadDto } from '../../models/requests/imageroute.dto';
|
import { ImageUploadDto } from '../../models/requests/imageroute.dto';
|
||||||
|
import { ImageIdValidator } from './imageid.validator';
|
||||||
|
|
||||||
@Controller('i')
|
@Controller('i')
|
||||||
@RequiredPermissions(Permission.ImageView)
|
@RequiredPermissions(Permission.ImageView)
|
||||||
@@ -29,11 +26,11 @@ export class ImageController {
|
|||||||
|
|
||||||
@Get(':hash')
|
@Get(':hash')
|
||||||
async getImage(
|
async getImage(
|
||||||
|
// Usually passthrough is for manually sending the response,
|
||||||
|
// But we need it here to set the mime type
|
||||||
@Res({ passthrough: true }) res: FastifyReply,
|
@Res({ passthrough: true }) res: FastifyReply,
|
||||||
@Param('hash') hash: string,
|
@Param('hash', ImageIdValidator) hash: string,
|
||||||
): Promise<Buffer> {
|
): Promise<Buffer> {
|
||||||
if (!isHash(hash, 'sha256')) throw new BadRequestException('Invalid hash');
|
|
||||||
|
|
||||||
const image = await this.imagesService.retrieveComplete(hash);
|
const image = await this.imagesService.retrieveComplete(hash);
|
||||||
if (HasFailed(image)) {
|
if (HasFailed(image)) {
|
||||||
this.logger.warn(image.getReason());
|
this.logger.warn(image.getReason());
|
||||||
@@ -45,9 +42,9 @@ export class ImageController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get('meta/:hash')
|
@Get('meta/:hash')
|
||||||
async getImageMeta(@Param('hash') hash: string): Promise<ImageMetaResponse> {
|
async getImageMeta(
|
||||||
if (!isHash(hash, 'sha256')) throw new BadRequestException('Invalid hash');
|
@Param('hash', ImageIdValidator) hash: string,
|
||||||
|
): Promise<ImageMetaResponse> {
|
||||||
const image = await this.imagesService.retrieveInfo(hash);
|
const image = await this.imagesService.retrieveInfo(hash);
|
||||||
if (HasFailed(image)) {
|
if (HasFailed(image)) {
|
||||||
this.logger.warn(image.getReason());
|
this.logger.warn(image.getReason());
|
||||||
@@ -60,7 +57,6 @@ export class ImageController {
|
|||||||
@Post()
|
@Post()
|
||||||
@RequiredPermissions(Permission.ImageUpload)
|
@RequiredPermissions(Permission.ImageUpload)
|
||||||
async uploadImage(
|
async uploadImage(
|
||||||
@Req() req: FastifyRequest,
|
|
||||||
@MultiPart(ImageUploadDto) multipart: ImageUploadDto,
|
@MultiPart(ImageUploadDto) multipart: ImageUploadDto,
|
||||||
): Promise<ImageMetaResponse> {
|
): Promise<ImageMetaResponse> {
|
||||||
const fileBuffer = await multipart.image.toBuffer();
|
const fileBuffer = await multipart.image.toBuffer();
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { DecoratorsModule } from '../../decorators/decorators.module';
|
import { DecoratorsModule } from '../../decorators/decorators.module';
|
||||||
import { ImageManagerModule } from '../../managers/imagemanager/imagemanager.module';
|
import { ImageManagerModule } from '../../managers/imagemanager/imagemanager.module';
|
||||||
|
import { ImageIdValidator } from './imageid.validator';
|
||||||
import { ImageController } from './imageroute.controller';
|
import { ImageController } from './imageroute.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ImageManagerModule, DecoratorsModule],
|
imports: [ImageManagerModule, DecoratorsModule],
|
||||||
|
providers: [ImageIdValidator],
|
||||||
controllers: [ImageController],
|
controllers: [ImageController],
|
||||||
})
|
})
|
||||||
export class ImageModule {}
|
export class ImageModule {}
|
||||||
|
|||||||
Reference in New Issue
Block a user