Files
sct-overseerr/server/lib/settings.ts
sct a8393707fe feat: generate real api key
This also hides the api key from users without the ADMIN permission. It will not be returned from
the api for them. Regenerate functionality is not in the commit.
2020-12-08 05:04:15 +00:00

259 lines
5.1 KiB
TypeScript

import fs from 'fs';
import path from 'path';
import { merge } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
export interface Library {
id: string;
name: string;
enabled: boolean;
}
export interface PlexSettings {
name: string;
machineId?: string;
ip: string;
port: number;
libraries: Library[];
}
interface DVRSettings {
id: number;
name: string;
hostname: string;
port: number;
apiKey: string;
useSsl: boolean;
baseUrl?: string;
activeProfileId: number;
activeProfileName: string;
activeDirectory: string;
is4k: boolean;
isDefault: boolean;
}
export interface RadarrSettings extends DVRSettings {
minimumAvailability: string;
}
export interface SonarrSettings extends DVRSettings {
activeAnimeProfileId?: number;
activeAnimeProfileName?: string;
activeAnimeDirectory?: string;
enableSeasonFolders: boolean;
}
export interface MainSettings {
apiKey: string;
applicationUrl: string;
}
interface PublicSettings {
initialized: boolean;
}
interface NotificationAgent {
enabled: boolean;
types: number;
options: Record<string, unknown>;
}
interface NotificationAgentDiscord extends NotificationAgent {
options: {
webhookUrl: string;
};
}
interface NotificationAgentEmail extends NotificationAgent {
options: {
emailFrom: string;
smtpHost: string;
smtpPort: number;
secure: boolean;
authUser?: string;
authPass?: string;
};
}
interface NotificationAgents {
email: NotificationAgentEmail;
discord: NotificationAgentDiscord;
}
interface NotificationSettings {
agents: NotificationAgents;
}
interface AllSettings {
clientId: string;
main: MainSettings;
plex: PlexSettings;
radarr: RadarrSettings[];
sonarr: SonarrSettings[];
public: PublicSettings;
notifications: NotificationSettings;
}
const SETTINGS_PATH = path.join(__dirname, '../../config/settings.json');
class Settings {
private data: AllSettings;
constructor(initialSettings?: AllSettings) {
this.data = {
clientId: '',
main: {
apiKey: '',
applicationUrl: '',
},
plex: {
name: '',
ip: '127.0.0.1',
port: 32400,
libraries: [],
},
radarr: [],
sonarr: [],
public: {
initialized: false,
},
notifications: {
agents: {
email: {
enabled: false,
types: 0,
options: {
emailFrom: '',
smtpHost: '127.0.0.1',
smtpPort: 465,
secure: false,
},
},
discord: {
enabled: false,
types: 0,
options: {
webhookUrl: '',
},
},
},
},
};
if (initialSettings) {
this.data = merge(this.data, initialSettings);
}
}
get main(): MainSettings {
if (!this.data.main.apiKey) {
this.data.main.apiKey = this.generateApiKey();
this.save();
}
return this.data.main;
}
set main(data: MainSettings) {
this.data.main = data;
}
get plex(): PlexSettings {
return this.data.plex;
}
set plex(data: PlexSettings) {
this.data.plex = data;
}
get radarr(): RadarrSettings[] {
return this.data.radarr;
}
set radarr(data: RadarrSettings[]) {
this.data.radarr = data;
}
get sonarr(): SonarrSettings[] {
return this.data.sonarr;
}
set sonarr(data: SonarrSettings[]) {
this.data.sonarr = data;
}
get public(): PublicSettings {
return this.data.public;
}
set public(data: PublicSettings) {
this.data.public = data;
}
get notifications(): NotificationSettings {
return this.data.notifications;
}
set notifications(data: NotificationSettings) {
this.data.notifications = data;
}
get clientId(): string {
if (!this.data.clientId) {
this.data.clientId = uuidv4();
this.save();
}
return this.data.clientId;
}
public regenerateApiKey(): MainSettings {
this.main.apiKey = this.generateApiKey();
this.save();
return this.main;
}
private generateApiKey(): string {
return Buffer.from(`${Date.now()}${this.clientId}`).toString('base64');
}
/**
* Settings Load
*
* This will load settings from file unless an optional argument of the object structure
* is passed in.
* @param overrideSettings If passed in, will override all existing settings with these
* values
*/
public load(overrideSettings?: AllSettings): AllSettings {
if (overrideSettings) {
this.data = overrideSettings;
return this.data;
}
if (!fs.existsSync(SETTINGS_PATH)) {
this.save();
}
const data = fs.readFileSync(SETTINGS_PATH, 'utf-8');
if (data) {
this.data = merge(this.data, JSON.parse(data));
this.save();
}
return this.data;
}
public save(): void {
fs.writeFileSync(SETTINGS_PATH, JSON.stringify(this.data, undefined, ' '));
}
}
let settings: Settings | undefined;
export const getSettings = (initialSettings?: AllSettings): Settings => {
if (!settings) {
settings = new Settings(initialSettings);
}
return settings;
};
export default Settings;