diff --git a/backend/src/collections/preference-db/sys-preference-db.service.ts b/backend/src/collections/preference-db/sys-preference-db.service.ts index 00324b5..070dc12 100644 --- a/backend/src/collections/preference-db/sys-preference-db.service.ts +++ b/backend/src/collections/preference-db/sys-preference-db.service.ts @@ -1,22 +1,22 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { - DecodedSysPref, - PrefValueType, - PrefValueTypeStrings + DecodedSysPref, + PrefValueType, + PrefValueTypeStrings } from 'picsur-shared/dist/dto/preferences.dto'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import { Repository } from 'typeorm'; import { - ESysPreferenceBackend, - ESysPreferenceSchema + ESysPreferenceBackend, + ESysPreferenceSchema } from '../../database/entities/sys-preference.entity'; import { - SysPreferenceList, - SysPreferenceValueTypes + SysPreferenceList, + SysPreferenceValueTypes } from '../../models/constants/syspreferences.const'; -import { MutexFallBack } from '../../models/util/mutex-fallback'; +import { MutexFallBack } from '../../util/mutex-fallback'; import { PreferenceCommonService } from './preference-common.service'; import { PreferenceDefaultsService } from './preference-defaults.service'; diff --git a/backend/src/collections/preference-db/usr-preference-db.service.ts b/backend/src/collections/preference-db/usr-preference-db.service.ts index 0bb0361..0053b9c 100644 --- a/backend/src/collections/preference-db/usr-preference-db.service.ts +++ b/backend/src/collections/preference-db/usr-preference-db.service.ts @@ -1,22 +1,22 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { - DecodedUsrPref, - PrefValueType, - PrefValueTypeStrings + DecodedUsrPref, + PrefValueType, + PrefValueTypeStrings } from 'picsur-shared/dist/dto/preferences.dto'; import { UsrPreference } from 'picsur-shared/dist/dto/usr-preferences.enum'; import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import { Repository } from 'typeorm'; import { - EUsrPreferenceBackend, - EUsrPreferenceSchema + EUsrPreferenceBackend, + EUsrPreferenceSchema } from '../../database/entities/usr-preference.entity'; import { - UsrPreferenceList, - UsrPreferenceValueTypes + UsrPreferenceList, + UsrPreferenceValueTypes } from '../../models/constants/usrpreferences.const'; -import { MutexFallBack } from '../../models/util/mutex-fallback'; +import { MutexFallBack } from '../../util/mutex-fallback'; import { PreferenceCommonService } from './preference-common.service'; import { PreferenceDefaultsService } from './preference-defaults.service'; diff --git a/backend/src/collections/user-db/user-db.service.ts b/backend/src/collections/user-db/user-db.service.ts index bd63e80..1196783 100644 --- a/backend/src/collections/user-db/user-db.service.ts +++ b/backend/src/collections/user-db/user-db.service.ts @@ -3,11 +3,11 @@ import { InjectRepository } from '@nestjs/typeorm'; import * as bcrypt from 'bcrypt'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { - AsyncFailable, - Fail, - FT, - HasFailed, - HasSuccess + AsyncFailable, + Fail, + FT, + HasFailed, + HasSuccess } from 'picsur-shared/dist/types'; import { FindResult } from 'picsur-shared/dist/types/find-result'; import { makeUnique } from 'picsur-shared/dist/util/unique'; @@ -15,15 +15,15 @@ import { Repository } from 'typeorm'; import { EUserBackend } from '../../database/entities/user.entity'; import { Permissions } from '../../models/constants/permissions.const'; import { - DefaultRolesList, - SoulBoundRolesList + DefaultRolesList, + SoulBoundRolesList } from '../../models/constants/roles.const'; import { - ImmutableUsersList, - LockedLoginUsersList, - UndeletableUsersList + ImmutableUsersList, + LockedLoginUsersList, + UndeletableUsersList } from '../../models/constants/special-users.const'; -import { GetCols } from '../../models/util/collection'; +import { GetCols } from '../../util/collection'; import { SysPreferenceService } from '../preference-db/sys-preference-db.service'; import { RolesService } from '../role-db/role-db.service'; diff --git a/backend/src/layers/exception/exception.filter.ts b/backend/src/layers/exception/exception.filter.ts index 9684780..94d8ff6 100644 --- a/backend/src/layers/exception/exception.filter.ts +++ b/backend/src/layers/exception/exception.filter.ts @@ -1,4 +1,12 @@ -import { ArgumentsHost, Catch, ExceptionFilter, ForbiddenException, Logger, MethodNotAllowedException, NotFoundException, UnauthorizedException } from '@nestjs/common'; +import { + ArgumentsHost, + Catch, ExceptionFilter, + ForbiddenException, + Logger, + MethodNotAllowedException, + NotFoundException, + UnauthorizedException +} from '@nestjs/common'; import { FastifyReply, FastifyRequest } from 'fastify'; import { ApiErrorResponse } from 'picsur-shared/dist/dto/api/api.dto'; import { diff --git a/backend/src/managers/image/image.service.ts b/backend/src/managers/image/image.service.ts index 82b66e6..32706a6 100644 --- a/backend/src/managers/image/image.service.ts +++ b/backend/src/managers/image/image.service.ts @@ -4,10 +4,10 @@ import { fileTypeFromBuffer, FileTypeResult } from 'file-type'; import { ImageRequestParams } from 'picsur-shared/dist/dto/api/image.dto'; import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum'; import { - AnimFileType, - FileType, - ImageFileType, - Mime2FileType + AnimFileType, + FileType, + ImageFileType, + Mime2FileType } from 'picsur-shared/dist/dto/mimes.dto'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { UsrPreference } from 'picsur-shared/dist/dto/usr-preferences.enum'; @@ -22,7 +22,7 @@ import { UsrPreferenceService } from '../../collections/preference-db/usr-prefer import { EImageDerivativeBackend } from '../../database/entities/image-derivative.entity'; import { EImageFileBackend } from '../../database/entities/image-file.entity'; import { EImageBackend } from '../../database/entities/image.entity'; -import { MutexFallBack } from '../../models/util/mutex-fallback'; +import { MutexFallBack } from '../../util/mutex-fallback'; import { ImageConverterService } from './image-converter.service'; import { ImageProcessorService } from './image-processor.service'; import { WebPInfo } from './webpinfo/webpinfo'; diff --git a/backend/src/routes/image/image.controller.ts b/backend/src/routes/image/image.controller.ts index 754708f..c079144 100644 --- a/backend/src/routes/image/image.controller.ts +++ b/backend/src/routes/image/image.controller.ts @@ -6,7 +6,7 @@ import { } from 'picsur-shared/dist/dto/api/image.dto'; import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum'; import { FileType2Mime } from 'picsur-shared/dist/dto/mimes.dto'; -import { ThrowIfFailed } from 'picsur-shared/dist/types'; +import { FT, IsFailure, ThrowIfFailed } from 'picsur-shared/dist/types'; import { UsersService } from '../../collections/user-db/user-db.service'; import { ImageFullIdParam } from '../../decorators/image-id/image-full-id.decorator'; import { ImageIdParam } from '../../decorators/image-id/image-id.decorator'; @@ -16,6 +16,7 @@ import { ImageManagerService } from '../../managers/image/image.service'; import type { ImageFullId } from '../../models/constants/image-full-id.const'; import { Permission } from '../../models/constants/permissions.const'; import { EUserBackend2EUser } from '../../models/transformers/user.transformer'; +import { BrandMessageType, GetBrandMessage } from '../../util/branding'; // This is the only controller with CORS enabled @Controller('i') @@ -53,21 +54,35 @@ export class ImageController { @ImageFullIdParam() fullid: ImageFullId, @Query() params: ImageRequestParams, ): Promise { - if (fullid.variant === ImageEntryVariant.ORIGINAL) { + try { + if (fullid.variant === ImageEntryVariant.ORIGINAL) { + const image = ThrowIfFailed( + await this.imagesService.getOriginal(fullid.id), + ); + + res.type(ThrowIfFailed(FileType2Mime(image.filetype))); + return image.data; + } + const image = ThrowIfFailed( - await this.imagesService.getOriginal(fullid.id), + await this.imagesService.getConverted( + fullid.id, + fullid.filetype, + params, + ), ); res.type(ThrowIfFailed(FileType2Mime(image.filetype))); return image.data; + } catch (e) { + if (!IsFailure(e) || e.getType() !== FT.NotFound) throw e; + + const message = ThrowIfFailed( + await GetBrandMessage(BrandMessageType.NotFound), + ); + res.type(message.type); + return message.data; } - - const image = ThrowIfFailed( - await this.imagesService.getConverted(fullid.id, fullid.filetype, params), - ); - - res.type(ThrowIfFailed(FileType2Mime(image.filetype))); - return image.data; } @Get('meta/:id') diff --git a/backend/src/util/branding.ts b/backend/src/util/branding.ts new file mode 100644 index 0000000..875b945 --- /dev/null +++ b/backend/src/util/branding.ts @@ -0,0 +1,38 @@ +import { readFile } from 'fs/promises'; +import { resolve } from 'path'; +import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; +import { PackageRoot } from '../config/config.static'; + +export const BrandingPath = resolve(PackageRoot, '../branding'); + +export enum BrandMessageType { + NotFound = 'notfound', +} + +export interface BrandMessage { + type: string; + data: Buffer; +} + +const BrandMessageCache: Record = {}; + +export async function GetBrandMessage( + name: BrandMessageType, +): AsyncFailable { + if (BrandMessageCache[name]) { + return BrandMessageCache[name]; + } + + try { + const file = await readFile( + resolve(BrandingPath, 'messages', name + '.png'), + ); + BrandMessageCache[name] = { + type: 'image/png', + data: file, + } + return BrandMessageCache[name]; + } catch (e) { + return Fail(FT.Internal, e); + } +} diff --git a/backend/src/models/util/collection.ts b/backend/src/util/collection.ts similarity index 100% rename from backend/src/models/util/collection.ts rename to backend/src/util/collection.ts diff --git a/backend/src/models/util/mutex-fallback.ts b/backend/src/util/mutex-fallback.ts similarity index 100% rename from backend/src/models/util/mutex-fallback.ts rename to backend/src/util/mutex-fallback.ts