fix: use fs/promises for settings (#1057)

* fix: use fs/promises for settings

This PR switches from synchronous operations with the 'fs' module to asynchronous operations with
the 'fs/promises' module. It also corrects a small error with hostname migration.

* fix: add missing merge function of default and current config

* refactor: add more logs to migration
This commit is contained in:
Gauthier
2024-10-31 15:51:57 +01:00
committed by GitHub
parent 4b4eeb6ec7
commit f2ed101e52
12 changed files with 128 additions and 121 deletions

View File

@@ -2,7 +2,7 @@ import { MediaServerType } from '@server/constants/server';
import { Permission } from '@server/lib/permissions';
import { runMigrations } from '@server/lib/settings/migrator';
import { randomUUID } from 'crypto';
import fs from 'fs';
import fs from 'fs/promises';
import { merge } from 'lodash';
import path from 'path';
import webpush from 'web-push';
@@ -481,10 +481,6 @@ class Settings {
}
get main(): MainSettings {
if (!this.data.main.apiKey) {
this.data.main.apiKey = this.generateApiKey();
this.save();
}
return this.data.main;
}
@@ -586,29 +582,20 @@ class Settings {
}
get clientId(): string {
if (!this.data.clientId) {
this.data.clientId = randomUUID();
this.save();
}
return this.data.clientId;
}
get vapidPublic(): string {
this.generateVapidKeys();
return this.data.vapidPublic;
}
get vapidPrivate(): string {
this.generateVapidKeys();
return this.data.vapidPrivate;
}
public regenerateApiKey(): MainSettings {
public async regenerateApiKey(): Promise<MainSettings> {
this.main.apiKey = this.generateApiKey();
this.save();
await this.save();
return this.main;
}
@@ -620,15 +607,6 @@ class Settings {
}
}
private generateVapidKeys(force = false): void {
if (!this.data.vapidPublic || !this.data.vapidPrivate || force) {
const vapidKeys = webpush.generateVAPIDKeys();
this.data.vapidPrivate = vapidKeys.privateKey;
this.data.vapidPublic = vapidKeys.publicKey;
this.save();
}
}
/**
* Settings Load
*
@@ -643,30 +621,51 @@ class Settings {
return this;
}
if (!fs.existsSync(SETTINGS_PATH)) {
this.save();
let data;
try {
data = await fs.readFile(SETTINGS_PATH, 'utf-8');
} catch {
await this.save();
}
const data = fs.readFileSync(SETTINGS_PATH, 'utf-8');
if (data) {
const parsedJson = JSON.parse(data);
this.data = await runMigrations(parsedJson, SETTINGS_PATH);
this.data = merge(this.data, parsedJson);
if (process.env.API_KEY) {
if (this.main.apiKey != process.env.API_KEY) {
this.main.apiKey = process.env.API_KEY;
}
}
this.save();
const migratedData = await runMigrations(parsedJson, SETTINGS_PATH);
this.data = merge(this.data, migratedData);
}
// generate keys and ids if it's missing
let change = false;
if (!this.data.main.apiKey) {
this.data.main.apiKey = this.generateApiKey();
change = true;
} else if (process.env.API_KEY) {
if (this.main.apiKey != process.env.API_KEY) {
this.main.apiKey = process.env.API_KEY;
}
}
if (!this.data.clientId) {
this.data.clientId = randomUUID();
change = true;
}
if (!this.data.vapidPublic || !this.data.vapidPrivate) {
const vapidKeys = webpush.generateVAPIDKeys();
this.data.vapidPrivate = vapidKeys.privateKey;
this.data.vapidPublic = vapidKeys.publicKey;
change = true;
}
if (change) {
await this.save();
}
return this;
}
public save(): void {
fs.writeFileSync(SETTINGS_PATH, JSON.stringify(this.data, undefined, ' '));
public async save(): Promise<void> {
await fs.writeFile(
SETTINGS_PATH,
JSON.stringify(this.data, undefined, ' ')
);
}
}