From 33080558bc61aa65a48a14b75080274f360f2e57 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sun, 18 Sep 2022 10:22:57 +0300 Subject: [PATCH] remove some anys --- src/guards/oauth2.guard.ts | 2 +- src/middleware/flash.middleware.ts | 2 +- .../api/admin/user-admin.controller.ts | 4 ++-- src/modules/api/api.controller.ts | 2 +- src/modules/config/config.interfaces.ts | 5 +++++ src/modules/config/config.providers.ts | 14 ++++++------ src/modules/jwt/jwt.providers.ts | 10 ++++----- src/modules/jwt/jwt.service.ts | 6 ++--- .../objects/document/document.providers.ts | 10 ++++----- src/modules/objects/email/email.service.ts | 4 ++-- .../oauth2-client/oauth2-client.providers.ts | 8 ++++--- .../oauth2-token/oauth2-token.providers.ts | 8 +++---- .../objects/privilege/privilege.providers.ts | 8 +++---- .../objects/upload/upload.providers.ts | 8 +++---- src/modules/objects/upload/upload.service.ts | 4 ++-- .../user-token/user-token.providers.ts | 8 +++---- src/modules/objects/user/user.providers.ts | 8 +++---- .../login/login.controller.ts | 20 ++++++++++------- .../oauth2-router/oauth2-router.controller.ts | 9 ++++---- .../register/register.controller.ts | 6 ++--- .../settings/settings.controller.ts | 12 +++++----- .../two-factor/two-factor.controller.ts | 22 ++++++++++++++----- .../utility/services/form-utility.service.ts | 12 +++++----- src/modules/utility/services/token.service.ts | 8 ++----- 24 files changed, 110 insertions(+), 90 deletions(-) diff --git a/src/guards/oauth2.guard.ts b/src/guards/oauth2.guard.ts index 6cd11af..59b6c01 100644 --- a/src/guards/oauth2.guard.ts +++ b/src/guards/oauth2.guard.ts @@ -35,7 +35,7 @@ export class OAuth2Guard implements CanActivate { }) .catch(reject); }); - } catch (e: any) { + } catch (e: unknown) { reject(e); } }); diff --git a/src/middleware/flash.middleware.ts b/src/middleware/flash.middleware.ts index ed09875..71e3d6e 100644 --- a/src/middleware/flash.middleware.ts +++ b/src/middleware/flash.middleware.ts @@ -22,7 +22,7 @@ export class FlashMiddleware implements NestMiddleware { return msgs; } else { - result = msg.length > 1 ? format(...msg) : msg[0]; + result = (msg.length > 1 ? format(...msg) : msg[0]) as string; } return (msgs[type] = msgs[type] || []).push(result); diff --git a/src/modules/api/admin/user-admin.controller.ts b/src/modules/api/admin/user-admin.controller.ts index 1168851..4f0270f 100644 --- a/src/modules/api/admin/user-admin.controller.ts +++ b/src/modules/api/admin/user-admin.controller.ts @@ -204,7 +204,7 @@ export class UserAdminController { try { await this._user.sendActivationEmail(user); - } catch (e: any) { + } catch (e: unknown) { error = e as Error; } @@ -229,7 +229,7 @@ export class UserAdminController { try { await this._user.sendPasswordEmail(user); - } catch (e: any) { + } catch (e: unknown) { error = e as Error; } diff --git a/src/modules/api/api.controller.ts b/src/modules/api/api.controller.ts index 7df4feb..cec6411 100644 --- a/src/modules/api/api.controller.ts +++ b/src/modules/api/api.controller.ts @@ -55,7 +55,7 @@ export class ApiController { // Management scope allows access to basically everything anyway const scopelessAccess = scope.includes('management'); - const userData: Record = { + const userData: Record = { id: user.id, uuid: user.uuid, username: user.username, diff --git a/src/modules/config/config.interfaces.ts b/src/modules/config/config.interfaces.ts index eeeb209..cfb7c28 100644 --- a/src/modules/config/config.interfaces.ts +++ b/src/modules/config/config.interfaces.ts @@ -23,8 +23,13 @@ export interface EmailConfiguration { export interface AppConfiguration { base_url: string; + host: string; + port: number; + session_name: string; session_secret: string; challenge_secret: string; + registrations: boolean; + redis_url?: string; } export interface Configuration { diff --git a/src/modules/config/config.providers.ts b/src/modules/config/config.providers.ts index f9a05fa..6e33905 100644 --- a/src/modules/config/config.providers.ts +++ b/src/modules/config/config.providers.ts @@ -2,16 +2,16 @@ import * as toml from 'toml'; import { resolve } from 'path'; import { readFile } from 'fs/promises'; import { Configuration } from './config.interfaces'; -import { Provider } from '@nestjs/common'; +import { FactoryProvider, ValueProvider } from '@nestjs/common'; const CONFIG_ENV = process.env.NODE_ENV === 'production' ? 'prod' : 'dev'; const CONFIG_FILENAME = process.env.CONFIG || `config.${CONFIG_ENV}.toml`; -export const configProviders: Provider[] = [ +export const configProviders = [ { provide: 'CONFIG_PATH', useValue: resolve(__dirname, '..', '..', '..', CONFIG_FILENAME), - }, + } as ValueProvider, { provide: 'DEFAULT_CONFIG', useValue: { @@ -57,7 +57,7 @@ export const configProviders: Provider[] = [ }, }, } as Configuration, - }, + } as ValueProvider, { provide: 'CONFIGURATION', useFactory: async ( @@ -70,11 +70,11 @@ export const configProviders: Provider[] = [ ...defaultConfig, ...JSON.parse(JSON.stringify(toml.parse(file))), }; - } catch (e: any) { - console.error('Failed to load configuration:', e.message); + } catch (e: unknown) { + console.error('Failed to load configuration:', (e as Error).message); return defaultConfig; } }, inject: ['CONFIG_PATH', 'DEFAULT_CONFIG'], - }, + } as FactoryProvider, ]; diff --git a/src/modules/jwt/jwt.providers.ts b/src/modules/jwt/jwt.providers.ts index ee102d5..dd7e3a6 100644 --- a/src/modules/jwt/jwt.providers.ts +++ b/src/modules/jwt/jwt.providers.ts @@ -1,20 +1,20 @@ import { join } from 'path'; import { readFile } from 'fs/promises'; -import { Provider } from '@nestjs/common'; +import { FactoryProvider, ValueProvider } from '@nestjs/common'; -export const jwtProviders: Provider[] = [ +export const jwtProviders = [ { provide: 'PRIVATE_PATH', useValue: join(__dirname, '..', '..', '..', 'private'), - }, + } as ValueProvider, { provide: 'JWT_PRIVATE_KEY', useFactory: async (path: string) => readFile(join(path, 'jwt.private.pem')), inject: ['PRIVATE_PATH'], - }, + } as FactoryProvider, { provide: 'JWT_PUBLIC_KEY', useFactory: async (path: string) => readFile(join(path, 'jwt.public.pem')), inject: ['PRIVATE_PATH'], - }, + } as FactoryProvider, ]; diff --git a/src/modules/jwt/jwt.service.ts b/src/modules/jwt/jwt.service.ts index 8c922d7..943272d 100644 --- a/src/modules/jwt/jwt.service.ts +++ b/src/modules/jwt/jwt.service.ts @@ -10,13 +10,13 @@ import * as jwt from 'jsonwebtoken'; @Injectable() export class JWTService { constructor( - @Inject('JWT_PRIVATE_KEY') private _privateKey: string, - @Inject('JWT_PUBLIC_KEY') private _publicKey: string, + @Inject('JWT_PRIVATE_KEY') private _privateKey: Buffer, + @Inject('JWT_PUBLIC_KEY') private _publicKey: Buffer, private _config: ConfigurationService, ) {} public issue( - claims: Record, + claims: Record, subject: string, audience?: string, ): string { diff --git a/src/modules/objects/document/document.providers.ts b/src/modules/objects/document/document.providers.ts index 3cc8872..104dc18 100644 --- a/src/modules/objects/document/document.providers.ts +++ b/src/modules/objects/document/document.providers.ts @@ -1,17 +1,17 @@ -import { Provider } from '@nestjs/common'; +import { FactoryProvider, ValueProvider } from '@nestjs/common'; import { join } from 'path'; -import { DataSource } from 'typeorm'; +import { DataSource, Repository } from 'typeorm'; import { Document } from './document.entity'; -export const documentProviders: Provider[] = [ +export const documentProviders = [ { provide: 'DOCUMENT_CACHE', useValue: join(process.cwd(), '.cache'), - }, + } as ValueProvider, { provide: 'DOCUMENT_REPOSITORY', useFactory: (dataSource: DataSource) => dataSource.getRepository(Document), inject: ['DATA_SOURCE'], - }, + } as FactoryProvider>, ]; diff --git a/src/modules/objects/email/email.service.ts b/src/modules/objects/email/email.service.ts index 4b741c4..e5fc4e0 100644 --- a/src/modules/objects/email/email.service.ts +++ b/src/modules/objects/email/email.service.ts @@ -17,7 +17,7 @@ export class EmailService { text: string, html?: string, from = this.config.get('email.from'), - ): Promise { + ): Promise { return this.transport.sendMail({ to, subject, @@ -31,7 +31,7 @@ export class EmailService { to: string, subject: string, message: EmailTemplate, - ): Promise { + ): Promise { return this.sendEmail(to, subject, message.text, message.html); } } diff --git a/src/modules/objects/oauth2-client/oauth2-client.providers.ts b/src/modules/objects/oauth2-client/oauth2-client.providers.ts index dae4a08..3ec7944 100644 --- a/src/modules/objects/oauth2-client/oauth2-client.providers.ts +++ b/src/modules/objects/oauth2-client/oauth2-client.providers.ts @@ -1,10 +1,12 @@ -import { Provider } from '@nestjs/common'; -import { DataSource } from 'typeorm'; +import { FactoryProvider } from '@nestjs/common'; +import { DataSource, Repository } from 'typeorm'; import { OAuth2ClientAuthorization } from './oauth2-client-authorization.entity'; import { OAuth2ClientURL } from './oauth2-client-url.entity'; import { OAuth2Client } from './oauth2-client.entity'; -export const clientProviders: Provider[] = [ +export const clientProviders: FactoryProvider< + Repository +>[] = [ { provide: 'CLIENT_REPOSITORY', useFactory: (dataSource: DataSource) => diff --git a/src/modules/objects/oauth2-token/oauth2-token.providers.ts b/src/modules/objects/oauth2-token/oauth2-token.providers.ts index 5ca44df..c0c874c 100644 --- a/src/modules/objects/oauth2-token/oauth2-token.providers.ts +++ b/src/modules/objects/oauth2-token/oauth2-token.providers.ts @@ -1,12 +1,12 @@ -import { Provider } from '@nestjs/common'; -import { DataSource } from 'typeorm'; +import { FactoryProvider } from '@nestjs/common'; +import { DataSource, Repository } from 'typeorm'; import { OAuth2Token } from './oauth2-token.entity'; -export const tokenProviders: Provider[] = [ +export const tokenProviders = [ { provide: 'TOKEN_REPOSITORY', useFactory: (dataSource: DataSource) => dataSource.getRepository(OAuth2Token), inject: ['DATA_SOURCE'], - }, + } as FactoryProvider>, ]; diff --git a/src/modules/objects/privilege/privilege.providers.ts b/src/modules/objects/privilege/privilege.providers.ts index c1a5394..981d0d6 100644 --- a/src/modules/objects/privilege/privilege.providers.ts +++ b/src/modules/objects/privilege/privilege.providers.ts @@ -1,11 +1,11 @@ -import { Provider } from '@nestjs/common'; -import { DataSource } from 'typeorm'; +import { FactoryProvider } from '@nestjs/common'; +import { DataSource, Repository } from 'typeorm'; import { Privilege } from './privilege.entity'; -export const privilegeProviders: Provider[] = [ +export const privilegeProviders = [ { provide: 'PRIVILEGE_REPOSITORY', useFactory: (dataSource: DataSource) => dataSource.getRepository(Privilege), inject: ['DATA_SOURCE'], - }, + } as FactoryProvider>, ]; diff --git a/src/modules/objects/upload/upload.providers.ts b/src/modules/objects/upload/upload.providers.ts index 0f690a0..49e3891 100644 --- a/src/modules/objects/upload/upload.providers.ts +++ b/src/modules/objects/upload/upload.providers.ts @@ -1,11 +1,11 @@ -import { Provider } from '@nestjs/common'; -import { DataSource } from 'typeorm'; +import { FactoryProvider } from '@nestjs/common'; +import { DataSource, Repository } from 'typeorm'; import { Upload } from './upload.entity'; -export const uploadProviders: Provider[] = [ +export const uploadProviders = [ { provide: 'UPLOAD_REPOSITORY', useFactory: (dataSource: DataSource) => dataSource.getRepository(Upload), inject: ['DATA_SOURCE'], - }, + } as FactoryProvider>, ]; diff --git a/src/modules/objects/upload/upload.service.ts b/src/modules/objects/upload/upload.service.ts index 9e05051..8dc4410 100644 --- a/src/modules/objects/upload/upload.service.ts +++ b/src/modules/objects/upload/upload.service.ts @@ -56,8 +56,8 @@ export class UploadService { try { await unlink(path); - } catch (e: any) { - console.error('Failed to unlink avatar file:', e.stack); + } catch (e: unknown) { + console.error('Failed to unlink avatar file:', (e as Error).stack); } await this.uploadRepository.remove(upload); diff --git a/src/modules/objects/user-token/user-token.providers.ts b/src/modules/objects/user-token/user-token.providers.ts index 78ac427..59b16db 100644 --- a/src/modules/objects/user-token/user-token.providers.ts +++ b/src/modules/objects/user-token/user-token.providers.ts @@ -1,11 +1,11 @@ -import { Provider } from '@nestjs/common'; -import { DataSource } from 'typeorm'; +import { FactoryProvider } from '@nestjs/common'; +import { DataSource, Repository } from 'typeorm'; import { UserToken } from './user-token.entity'; -export const userTokenProviders: Provider[] = [ +export const userTokenProviders = [ { provide: 'USER_TOKEN_REPOSITORY', useFactory: (dataSource: DataSource) => dataSource.getRepository(UserToken), inject: ['DATA_SOURCE'], - }, + } as FactoryProvider>, ]; diff --git a/src/modules/objects/user/user.providers.ts b/src/modules/objects/user/user.providers.ts index f9abafe..e690d9b 100644 --- a/src/modules/objects/user/user.providers.ts +++ b/src/modules/objects/user/user.providers.ts @@ -1,11 +1,11 @@ -import { Provider } from '@nestjs/common'; -import { DataSource } from 'typeorm'; +import { FactoryProvider } from '@nestjs/common'; +import { DataSource, Repository } from 'typeorm'; import { User } from './user.entity'; -export const userProviders: Provider[] = [ +export const userProviders = [ { provide: 'USER_REPOSITORY', useFactory: (dataSource: DataSource) => dataSource.getRepository(User), inject: ['DATA_SOURCE'], - }, + } as FactoryProvider>, ]; diff --git a/src/modules/static-front-end/login/login.controller.ts b/src/modules/static-front-end/login/login.controller.ts index d4ff92a..292abaa 100644 --- a/src/modules/static-front-end/login/login.controller.ts +++ b/src/modules/static-front-end/login/login.controller.ts @@ -41,7 +41,7 @@ export class LoginController { public loginView( @Req() req: Request, @Query('redirectTo') redirectTo?: string, - ): Record { + ): Record { return this.formUtil.populateTemplate(req, { query: redirectTo ? new URLSearchParams({ redirectTo }).toString() @@ -141,7 +141,11 @@ export class LoginController { throw new Error('No challenge'); } - const decrypted = await this.token.decryptChallenge(query.challenge); + const decrypted = await this.token.decryptChallenge<{ + type: 'verify'; + user: string; + remember: boolean; + }>(query.challenge); if (!decrypted || decrypted.type !== 'verify' || !decrypted.user) { throw new Error('Bad challenge'); } @@ -152,7 +156,7 @@ export class LoginController { } remember = decrypted.remember; - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, text: 'An unexpected error occured, please log in again.', @@ -173,10 +177,10 @@ export class LoginController { if (!this.totpService.validateTOTP(totp.token, body.totp)) { throw new Error('Invalid code!'); } - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, - text: e.message, + text: (e as Error).message, }); res.redirect(req.originalUrl); return; @@ -220,7 +224,7 @@ export class LoginController { } user = token.user; - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, text: 'Invalid or expired activation link.', @@ -355,8 +359,8 @@ export class LoginController { }); res.redirect('/login'); - } catch (e: any) { - req.flash('message', { error: true, text: e.message }); + } catch (e: unknown) { + req.flash('message', { error: true, text: (e as Error).message }); res.redirect(req.originalUrl); } } diff --git a/src/modules/static-front-end/oauth2-router/oauth2-router.controller.ts b/src/modules/static-front-end/oauth2-router/oauth2-router.controller.ts index 1f2245f..034a017 100644 --- a/src/modules/static-front-end/oauth2-router/oauth2-router.controller.ts +++ b/src/modules/static-front-end/oauth2-router/oauth2-router.controller.ts @@ -8,7 +8,7 @@ import { Res, UseGuards, } from '@nestjs/common'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiExcludeEndpoint, ApiTags } from '@nestjs/swagger'; import { NextFunction, Request, Response } from 'express'; import { Scope } from 'src/decorators/scope.decorator'; import { CurrentUser } from 'src/decorators/user.decorator'; @@ -36,6 +36,7 @@ export class OAuth2Controller { return this._service.oauth.controller.authorization(req, res, next); } + @ApiExcludeEndpoint() @Post('authorize') public authorizePostWrapper( @Req() req: Request, @@ -66,18 +67,18 @@ export class OAuth2Controller { // User information endpoint - @ApiBearerAuth() + @ApiExcludeEndpoint() @Get('user') @UseGuards(OAuth2Guard) public async userInfo( @CurrentUser() user: User, @Scope() scope: string, - ): Promise> { + ): Promise> { if (!user) { throw new NotFoundException('No such user'); } - const userData: Record = { + const userData: Record = { id: user.id, uuid: user.uuid, username: user.username, diff --git a/src/modules/static-front-end/register/register.controller.ts b/src/modules/static-front-end/register/register.controller.ts index 3a9fb24..50bd17a 100644 --- a/src/modules/static-front-end/register/register.controller.ts +++ b/src/modules/static-front-end/register/register.controller.ts @@ -29,7 +29,7 @@ export class RegisterController { @Get() @Render('register') - public registerView(@Req() req: Request): Record { + public registerView(@Req() req: Request): Record { return this.formUtil.populateTemplate(req, { registrationAuthorized: this.config.get('app.registrations'), }); @@ -99,8 +99,8 @@ export class RegisterController { }); res.redirect('/login' + (redirectTo ? '?redirectTo=' + redirectTo : '')); - } catch (e: any) { - req.flash('message', { error: true, text: e.message }); + } catch (e: unknown) { + req.flash('message', { error: true, text: (e as Error).message }); req.flash('form', { ...body, password_repeat: undefined }); res.redirect(req.originalUrl); } diff --git a/src/modules/static-front-end/settings/settings.controller.ts b/src/modules/static-front-end/settings/settings.controller.ts index 8cec108..9da8853 100644 --- a/src/modules/static-front-end/settings/settings.controller.ts +++ b/src/modules/static-front-end/settings/settings.controller.ts @@ -80,10 +80,10 @@ export class SettingsController { error: false, text: 'Display name has been changed!', }); - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, - text: e.message, + text: (e as Error).message, }); } res.redirect('/account/general'); @@ -222,10 +222,10 @@ export class SettingsController { if (new_password !== password_repeat) { throw new Error('The passwords do not match.'); } - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, - text: e.message, + text: (e as Error).message, }); res.redirect('/account/security'); return; @@ -288,10 +288,10 @@ export class SettingsController { 'There is already an existing user with this email address.', ); } - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, - text: e.message, + text: (e as Error).message, }); res.redirect('/account/security'); return; diff --git a/src/modules/static-front-end/two-factor/two-factor.controller.ts b/src/modules/static-front-end/two-factor/two-factor.controller.ts index f03ba1e..f8ee049 100644 --- a/src/modules/static-front-end/two-factor/two-factor.controller.ts +++ b/src/modules/static-front-end/two-factor/two-factor.controller.ts @@ -8,6 +8,12 @@ import { FormUtilityService } from 'src/modules/utility/services/form-utility.se import { QRCodeService } from 'src/modules/utility/services/qr-code.service'; import { TokenService } from 'src/modules/utility/services/token.service'; +interface ChallengeType { + secret: string; + type: 'totp'; + user: string; +} + @Controller('/account/two-factor') export class TwoFactorController { constructor( @@ -27,7 +33,9 @@ export class TwoFactorController { if (!twoFA) { const challengeString = req.query.challenge as string; if (challengeString) { - const challenge = await this.token.decryptChallenge(challengeString); + const challenge = await this.token.decryptChallenge( + challengeString, + ); if (challenge.type === 'totp' && challenge.user === req.user.uuid) { secret = challenge.secret; } @@ -69,7 +77,9 @@ export class TwoFactorController { throw new Error('Invalid request'); } - const challenge = await this.token.decryptChallenge(challengeString); + const challenge = await this.token.decryptChallenge( + challengeString, + ); secret = challenge.secret; if ( @@ -84,10 +94,10 @@ export class TwoFactorController { if (!verify) { throw new Error('Invalid code! Try again.'); } - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, - text: e.message, + text: (e as Error).message, }); res.redirect('/two-factor'); return; @@ -137,10 +147,10 @@ export class TwoFactorController { await this.totp.deactivateTOTP(twoFA); await this.audit.auditRequest(req, AuditAction.TOTP_DEACTIVATE); - } catch (e: any) { + } catch (e: unknown) { req.flash('message', { error: true, - text: e.message, + text: (e as Error).message, }); res.redirect('/account/two-factor/disable'); return; diff --git a/src/modules/utility/services/form-utility.service.ts b/src/modules/utility/services/form-utility.service.ts index bd76cc5..ffcb660 100644 --- a/src/modules/utility/services/form-utility.service.ts +++ b/src/modules/utility/services/form-utility.service.ts @@ -13,8 +13,10 @@ export class FormUtilityService { * @param flash Array of objects * @returns Merged object */ - public mergeObjectArray(flash: Record[]): Record { - return flash.reduce>( + public mergeObjectArray( + flash: Record[], + ): Record { + return flash.reduce>( (obj, item) => ({ ...obj, ...item }), {}, ); @@ -93,11 +95,11 @@ export class FormUtilityService { */ public populateTemplate( req: Request, - additional: Record = {}, - ): Record { + additional: Record = {}, + ): Record { const message = req.flash('message')[0] || {}; const form = this.mergeObjectArray( - (req.flash('form') as Record[]) || [], + (req.flash('form') as Record[]) || [], ); return { diff --git a/src/modules/utility/services/token.service.ts b/src/modules/utility/services/token.service.ts index c9467b3..eda8264 100644 --- a/src/modules/utility/services/token.service.ts +++ b/src/modules/utility/services/token.service.ts @@ -78,18 +78,14 @@ export class TokenService { return decrypted.toString(); } - public async encryptChallenge( - challenge: Record, - ): Promise { + public async encryptChallenge(challenge: T): Promise { return this.encrypt( JSON.stringify(challenge), this.config.get('app.challenge_secret'), ); } - public async decryptChallenge( - challenge: string, - ): Promise> { + public async decryptChallenge(challenge: string): Promise { return JSON.parse( this.decrypt(challenge, this.config.get('app.challenge_secret')), );