remove some anys
This commit is contained in:
parent
9c7820dc94
commit
33080558bc
@ -35,7 +35,7 @@ export class OAuth2Guard implements CanActivate {
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ export class ApiController {
|
||||
// Management scope allows access to basically everything anyway
|
||||
const scopelessAccess = scope.includes('management');
|
||||
|
||||
const userData: Record<string, any> = {
|
||||
const userData: Record<string, unknown> = {
|
||||
id: user.id,
|
||||
uuid: user.uuid,
|
||||
username: user.username,
|
||||
|
@ -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 {
|
||||
|
@ -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<any>[] = [
|
||||
export const configProviders = [
|
||||
{
|
||||
provide: 'CONFIG_PATH',
|
||||
useValue: resolve(__dirname, '..', '..', '..', CONFIG_FILENAME),
|
||||
},
|
||||
} as ValueProvider<string>,
|
||||
{
|
||||
provide: 'DEFAULT_CONFIG',
|
||||
useValue: {
|
||||
@ -57,7 +57,7 @@ export const configProviders: Provider<any>[] = [
|
||||
},
|
||||
},
|
||||
} as Configuration,
|
||||
},
|
||||
} as ValueProvider<Configuration>,
|
||||
{
|
||||
provide: 'CONFIGURATION',
|
||||
useFactory: async (
|
||||
@ -70,11 +70,11 @@ export const configProviders: Provider<any>[] = [
|
||||
...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<Configuration>,
|
||||
];
|
||||
|
@ -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<any>[] = [
|
||||
export const jwtProviders = [
|
||||
{
|
||||
provide: 'PRIVATE_PATH',
|
||||
useValue: join(__dirname, '..', '..', '..', 'private'),
|
||||
},
|
||||
} as ValueProvider<string>,
|
||||
{
|
||||
provide: 'JWT_PRIVATE_KEY',
|
||||
useFactory: async (path: string) => readFile(join(path, 'jwt.private.pem')),
|
||||
inject: ['PRIVATE_PATH'],
|
||||
},
|
||||
} as FactoryProvider<Buffer>,
|
||||
{
|
||||
provide: 'JWT_PUBLIC_KEY',
|
||||
useFactory: async (path: string) => readFile(join(path, 'jwt.public.pem')),
|
||||
inject: ['PRIVATE_PATH'],
|
||||
},
|
||||
} as FactoryProvider<Buffer>,
|
||||
];
|
||||
|
@ -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<string, any>,
|
||||
claims: Record<string, unknown>,
|
||||
subject: string,
|
||||
audience?: string,
|
||||
): string {
|
||||
|
@ -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<any>[] = [
|
||||
export const documentProviders = [
|
||||
{
|
||||
provide: 'DOCUMENT_CACHE',
|
||||
useValue: join(process.cwd(), '.cache'),
|
||||
},
|
||||
} as ValueProvider<string>,
|
||||
{
|
||||
provide: 'DOCUMENT_REPOSITORY',
|
||||
useFactory: (dataSource: DataSource) => dataSource.getRepository(Document),
|
||||
inject: ['DATA_SOURCE'],
|
||||
},
|
||||
} as FactoryProvider<Repository<Document>>,
|
||||
];
|
||||
|
@ -17,7 +17,7 @@ export class EmailService {
|
||||
text: string,
|
||||
html?: string,
|
||||
from = this.config.get<string>('email.from'),
|
||||
): Promise<any> {
|
||||
): Promise<unknown> {
|
||||
return this.transport.sendMail({
|
||||
to,
|
||||
subject,
|
||||
@ -31,7 +31,7 @@ export class EmailService {
|
||||
to: string,
|
||||
subject: string,
|
||||
message: EmailTemplate,
|
||||
): Promise<any> {
|
||||
): Promise<unknown> {
|
||||
return this.sendEmail(to, subject, message.text, message.html);
|
||||
}
|
||||
}
|
||||
|
@ -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<any>[] = [
|
||||
export const clientProviders: FactoryProvider<
|
||||
Repository<OAuth2Client | OAuth2ClientURL | OAuth2ClientAuthorization>
|
||||
>[] = [
|
||||
{
|
||||
provide: 'CLIENT_REPOSITORY',
|
||||
useFactory: (dataSource: DataSource) =>
|
||||
|
@ -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<any>[] = [
|
||||
export const tokenProviders = [
|
||||
{
|
||||
provide: 'TOKEN_REPOSITORY',
|
||||
useFactory: (dataSource: DataSource) =>
|
||||
dataSource.getRepository(OAuth2Token),
|
||||
inject: ['DATA_SOURCE'],
|
||||
},
|
||||
} as FactoryProvider<Repository<OAuth2Token>>,
|
||||
];
|
||||
|
@ -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<any>[] = [
|
||||
export const privilegeProviders = [
|
||||
{
|
||||
provide: 'PRIVILEGE_REPOSITORY',
|
||||
useFactory: (dataSource: DataSource) => dataSource.getRepository(Privilege),
|
||||
inject: ['DATA_SOURCE'],
|
||||
},
|
||||
} as FactoryProvider<Repository<Privilege>>,
|
||||
];
|
||||
|
@ -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<any>[] = [
|
||||
export const uploadProviders = [
|
||||
{
|
||||
provide: 'UPLOAD_REPOSITORY',
|
||||
useFactory: (dataSource: DataSource) => dataSource.getRepository(Upload),
|
||||
inject: ['DATA_SOURCE'],
|
||||
},
|
||||
} as FactoryProvider<Repository<Upload>>,
|
||||
];
|
||||
|
@ -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);
|
||||
|
@ -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<any>[] = [
|
||||
export const userTokenProviders = [
|
||||
{
|
||||
provide: 'USER_TOKEN_REPOSITORY',
|
||||
useFactory: (dataSource: DataSource) => dataSource.getRepository(UserToken),
|
||||
inject: ['DATA_SOURCE'],
|
||||
},
|
||||
} as FactoryProvider<Repository<UserToken>>,
|
||||
];
|
||||
|
@ -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<any>[] = [
|
||||
export const userProviders = [
|
||||
{
|
||||
provide: 'USER_REPOSITORY',
|
||||
useFactory: (dataSource: DataSource) => dataSource.getRepository(User),
|
||||
inject: ['DATA_SOURCE'],
|
||||
},
|
||||
} as FactoryProvider<Repository<User>>,
|
||||
];
|
||||
|
@ -41,7 +41,7 @@ export class LoginController {
|
||||
public loginView(
|
||||
@Req() req: Request,
|
||||
@Query('redirectTo') redirectTo?: string,
|
||||
): Record<string, any> {
|
||||
): Record<string, unknown> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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<Record<string, any>> {
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!user) {
|
||||
throw new NotFoundException('No such user');
|
||||
}
|
||||
|
||||
const userData: Record<string, any> = {
|
||||
const userData: Record<string, unknown> = {
|
||||
id: user.id,
|
||||
uuid: user.uuid,
|
||||
username: user.username,
|
||||
|
@ -29,7 +29,7 @@ export class RegisterController {
|
||||
|
||||
@Get()
|
||||
@Render('register')
|
||||
public registerView(@Req() req: Request): Record<string, any> {
|
||||
public registerView(@Req() req: Request): Record<string, unknown> {
|
||||
return this.formUtil.populateTemplate(req, {
|
||||
registrationAuthorized: this.config.get<boolean>('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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<ChallengeType>(
|
||||
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<ChallengeType>(
|
||||
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;
|
||||
|
@ -13,8 +13,10 @@ export class FormUtilityService {
|
||||
* @param flash Array of objects
|
||||
* @returns Merged object
|
||||
*/
|
||||
public mergeObjectArray(flash: Record<string, any>[]): Record<string, any> {
|
||||
return flash.reduce<Record<string, any>>(
|
||||
public mergeObjectArray(
|
||||
flash: Record<string, unknown>[],
|
||||
): Record<string, unknown> {
|
||||
return flash.reduce<Record<string, unknown>>(
|
||||
(obj, item) => ({ ...obj, ...item }),
|
||||
{},
|
||||
);
|
||||
@ -93,11 +95,11 @@ export class FormUtilityService {
|
||||
*/
|
||||
public populateTemplate(
|
||||
req: Request,
|
||||
additional: Record<string, any> = {},
|
||||
): Record<string, any> {
|
||||
additional: Record<string, unknown> = {},
|
||||
): Record<string, unknown> {
|
||||
const message = req.flash('message')[0] || {};
|
||||
const form = this.mergeObjectArray(
|
||||
(req.flash('form') as Record<string, any>[]) || [],
|
||||
(req.flash('form') as Record<string, unknown>[]) || [],
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -78,18 +78,14 @@ export class TokenService {
|
||||
return decrypted.toString();
|
||||
}
|
||||
|
||||
public async encryptChallenge(
|
||||
challenge: Record<string, any>,
|
||||
): Promise<string> {
|
||||
public async encryptChallenge<T>(challenge: T): Promise<string> {
|
||||
return this.encrypt(
|
||||
JSON.stringify(challenge),
|
||||
this.config.get<string>('app.challenge_secret'),
|
||||
);
|
||||
}
|
||||
|
||||
public async decryptChallenge(
|
||||
challenge: string,
|
||||
): Promise<Record<string, any>> {
|
||||
public async decryptChallenge<T>(challenge: string): Promise<T> {
|
||||
return JSON.parse(
|
||||
this.decrypt(challenge, this.config.get<string>('app.challenge_secret')),
|
||||
);
|
||||
|
Reference in New Issue
Block a user