refactor: encode at point of usage

This commit is contained in:
izzy 2025-11-06 17:58:13 +00:00
parent 5c6e04cc8f
commit 8676a042eb
No known key found for this signature in database
GPG key ID: 5059F398521BB0F6
4 changed files with 17 additions and 21 deletions

View file

@ -49,12 +49,12 @@ export class MaintenanceWorkerRepository implements OnGatewayConnection, OnGatew
}
async exitMaintenanceMode(): Promise<void> {
const state: MaintenanceModeState<string> = { isMaintenanceMode: false as const };
const state: MaintenanceModeState = { isMaintenanceMode: false as const };
await this.systemMetadataRepository.set(SystemMetadataKey.MaintenanceMode, state);
this.restartApp(state);
}
async maintenanceSecret(): Promise<Uint8Array> {
async maintenanceSecret(): Promise<string> {
const result = await this.systemMetadataRepository.get(SystemMetadataKey.MaintenanceMode);
if (!result) {
throw new Error('Unreachable: Missing metadata for maintenance mode.');
@ -64,7 +64,7 @@ export class MaintenanceWorkerRepository implements OnGatewayConnection, OnGatew
throw new Error('Unreachable: Not in maintenance mode.');
}
return new TextEncoder().encode(result.secret);
return result.secret;
}
async logSecret(): Promise<void> {
@ -101,7 +101,7 @@ export class MaintenanceWorkerRepository implements OnGatewayConnection, OnGatew
try {
const secret = await this.maintenanceSecret();
const result = await jose.jwtVerify<MaintenanceAuthDto>(jwtToken, secret);
const result = await jose.jwtVerify<MaintenanceAuthDto>(jwtToken, new TextEncoder().encode(secret));
return result.payload;
} catch {
throw new UnauthorizedException('Invalid JWT Token');

View file

@ -21,17 +21,13 @@ export class MaintenanceRepository {
private systemMetadataRepository: SystemMetadataRepository,
) {}
getMaintenanceMode(): Promise<MaintenanceModeState<Uint8Array>> {
getMaintenanceMode(): Promise<MaintenanceModeState> {
return this.systemMetadataRepository
.get(SystemMetadataKey.MaintenanceMode)
.then((state) =>
state?.isMaintenanceMode
? { isMaintenanceMode: true, secret: new TextEncoder().encode(state.secret) }
: { isMaintenanceMode: false as const },
);
.then((state) => state ?? { isMaintenanceMode: false as const });
}
async setMaintenanceMode(state: MaintenanceModeState<string>) {
async setMaintenanceMode(state: MaintenanceModeState) {
await this.systemMetadataRepository.set(SystemMetadataKey.MaintenanceMode, state);
await this.eventRepository.emit('AppRestart', state);
}
@ -51,14 +47,14 @@ export class MaintenanceRepository {
});
}
async enterMaintenanceMode(): Promise<{ secret: Uint8Array }> {
async enterMaintenanceMode(): Promise<{ secret: string }> {
const secret = randomBytes(64).toString('hex');
const state: MaintenanceModeState<string> = { isMaintenanceMode: true, secret };
const state: MaintenanceModeState = { isMaintenanceMode: true, secret };
await this.systemMetadataRepository.set(SystemMetadataKey.MaintenanceMode, state);
await this.eventRepository.emit('AppRestart', state);
return { secret: new TextEncoder().encode(secret) };
return { secret };
}
exitApp() {
@ -70,7 +66,7 @@ export class MaintenanceRepository {
/* eslint-enable unicorn/no-process-exit */
}
async createLoginUrl(baseUrl: string, auth: MaintenanceAuthDto, secret?: Uint8Array) {
async createLoginUrl(baseUrl: string, auth: MaintenanceAuthDto, secret?: string) {
secret ??= await this.getMaintenanceMode().then((state) => {
if (!state.isMaintenanceMode) {
throw new Error('Not in maintenance mode.');
@ -82,18 +78,18 @@ export class MaintenanceRepository {
return await MaintenanceRepository.createLoginUrl(baseUrl, auth, secret!);
}
static async createLoginUrl(baseUrl: string, auth: MaintenanceAuthDto, secret: Uint8Array) {
static async createLoginUrl(baseUrl: string, auth: MaintenanceAuthDto, secret: string) {
return `${baseUrl}/maintenance?token=${encodeURIComponent(await MaintenanceRepository.createJwt(secret!, auth))}`;
}
static async createJwt(secret: Uint8Array, data: MaintenanceAuthDto) {
static async createJwt(secret: string, data: MaintenanceAuthDto) {
const alg = 'HS256';
return await new SignJWT({ ...data })
.setProtectedHeader({ alg })
.setIssuedAt()
.setExpirationTime('4h')
.sign(secret);
.sign(new TextEncoder().encode(secret));
}
setCloseFn(fn: () => Promise<void>) {

View file

@ -7,7 +7,7 @@ import { BaseService } from 'src/services/base.service';
*/
@Injectable()
export class MaintenanceService extends BaseService {
async startMaintenance(): Promise<{ secret: Uint8Array }> {
async startMaintenance(): Promise<{ secret: string }> {
const { isMaintenanceMode } = await this.maintenanceRepository.getMaintenanceMode();
if (isMaintenanceMode) {
throw new BadRequestException('Already in maintenance mode');

View file

@ -469,7 +469,7 @@ export interface MemoryData {
export type VersionCheckMetadata = { checkedAt: string; releaseVersion: string };
export type SystemFlags = { mountChecks: Record<StorageFolder, boolean> };
export type MaintenanceModeState<S> = { isMaintenanceMode: true; secret: S } | { isMaintenanceMode: false };
export type MaintenanceModeState = { isMaintenanceMode: true; secret: string } | { isMaintenanceMode: false };
export type MemoriesState = {
/** memories have already been created through this date */
lastOnThisDayDate: string;
@ -480,7 +480,7 @@ export interface SystemMetadata extends Record<SystemMetadataKey, Record<string,
[SystemMetadataKey.AdminOnboarding]: { isOnboarded: boolean };
[SystemMetadataKey.FacialRecognitionState]: { lastRun?: string };
[SystemMetadataKey.License]: { licenseKey: string; activationKey: string; activatedAt: Date };
[SystemMetadataKey.MaintenanceMode]: MaintenanceModeState<string>;
[SystemMetadataKey.MaintenanceMode]: MaintenanceModeState;
[SystemMetadataKey.MediaLocation]: MediaLocation;
[SystemMetadataKey.ReverseGeocodingState]: { lastUpdate?: string; lastImportFileName?: string };
[SystemMetadataKey.SystemConfig]: DeepPartial<SystemConfig>;