Skip to content

Commit

Permalink
refactor: create a separate section for network settings
Browse files Browse the repository at this point in the history
  • Loading branch information
gauthier-th committed Jan 20, 2025
1 parent c619c45 commit c32a470
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 45 deletions.
46 changes: 40 additions & 6 deletions overseerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,6 @@ components:
applicationUrl:
type: string
example: https://os.example.com
trustProxy:
type: boolean
example: true
csrfProtection:
type: boolean
example: false
hideAvailable:
type: boolean
example: false
Expand All @@ -191,12 +185,21 @@ components:
enableSpecialEpisodes:
type: boolean
example: false
NetworkSettings:
type: object
properties:
csrfProtection:
type: boolean
example: false
forceIpv4First:
type: boolean
example: false
dnsServers:
type: string
example: '1.1.1.1'
trustProxy:
type: boolean
example: true
PlexLibrary:
type: object
properties:
Expand Down Expand Up @@ -2045,6 +2048,37 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/MainSettings'
/settings/network:
get:
summary: Get network settings
description: Retrieves all network settings in a JSON object.
tags:
- settings
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/MainSettings'
post:
summary: Update network settings
description: Updates network settings with the provided values.
tags:
- settings
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NetworkSettings'
responses:
'200':
description: 'Values were sucessfully updated'
content:
application/json:
schema:
$ref: '#/components/schemas/NetworkSettings'
/settings/main/regenerate:
post:
summary: Get main settings with newly-generated API key
Expand Down
21 changes: 12 additions & 9 deletions server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,26 @@ app

// Load Settings
const settings = await getSettings().load();
restartFlag.initializeSettings(settings.main);
restartFlag.initializeSettings(settings);

// Check if we force IPv4 first
if (process.env.forceIpv4First === 'true' || settings.main.forceIpv4First) {
if (
process.env.forceIpv4First === 'true' ||
settings.network.forceIpv4First
) {
dns.setDefaultResultOrder('ipv4first');
net.setDefaultAutoSelectFamily(false);
}

if (settings.main.dnsServers.trim() !== '') {
if (settings.network.dnsServers.trim() !== '') {
dns.setServers(
settings.main.dnsServers.split(',').map((server) => server.trim())
settings.network.dnsServers.split(',').map((server) => server.trim())
);
}

// Register HTTP proxy
if (settings.main.proxy.enabled) {
await createCustomProxyAgent(settings.main.proxy);
if (settings.network.proxy.enabled) {
await createCustomProxyAgent(settings.network.proxy);
}

// Migrate library types
Expand Down Expand Up @@ -143,7 +146,7 @@ app
await DiscoverSlider.bootstrapSliders();

const server = express();
if (settings.main.trustProxy) {
if (settings.network.trustProxy) {
server.enable('trust proxy');
}
server.use(cookieParser());
Expand All @@ -164,7 +167,7 @@ app
next();
}
});
if (settings.main.csrfProtection) {
if (settings.network.csrfProtection) {
server.use(
csurf({
cookie: {
Expand Down Expand Up @@ -194,7 +197,7 @@ app
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 30,
httpOnly: true,
sameSite: settings.main.csrfProtection ? 'strict' : 'lax',
sameSite: settings.network.csrfProtection ? 'strict' : 'lax',
secure: 'auto',
},
store: new TypeormStore({
Expand Down
48 changes: 31 additions & 17 deletions server/lib/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ export interface MainSettings {
apiKey: string;
applicationTitle: string;
applicationUrl: string;
csrfProtection: boolean;
cacheImages: boolean;
defaultPermissions: number;
defaultQuotas: {
Expand All @@ -128,13 +127,17 @@ export interface MainSettings {
discoverRegion: string;
streamingRegion: string;
originalLanguage: string;
trustProxy: boolean;
mediaServerType: number;
partialRequestsEnabled: boolean;
enableSpecialEpisodes: boolean;
locale: string;
}

export interface NetworkSettings {
csrfProtection: boolean;
forceIpv4First: boolean;
dnsServers: string;
locale: string;
trustProxy: boolean;
proxy: ProxySettings;
}

Expand Down Expand Up @@ -313,6 +316,7 @@ export interface AllSettings {
public: PublicSettings;
notifications: NotificationSettings;
jobs: Record<JobId, JobSettings>;
network: NetworkSettings;
}

const SETTINGS_PATH = process.env.CONFIG_DIRECTORY
Expand All @@ -331,7 +335,6 @@ class Settings {
apiKey: '',
applicationTitle: 'Jellyseerr',
applicationUrl: '',
csrfProtection: false,
cacheImages: false,
defaultPermissions: Permission.REQUEST,
defaultQuotas: {
Expand All @@ -344,23 +347,10 @@ class Settings {
discoverRegion: '',
streamingRegion: '',
originalLanguage: '',
trustProxy: false,
mediaServerType: MediaServerType.NOT_CONFIGURED,
partialRequestsEnabled: true,
enableSpecialEpisodes: false,
forceIpv4First: false,
dnsServers: '',
locale: 'en',
proxy: {
enabled: false,
hostname: '',
port: 8080,
useSsl: false,
user: '',
password: '',
bypassFilter: '',
bypassLocalAddresses: true,
},
},
plex: {
name: '',
Expand Down Expand Up @@ -513,6 +503,22 @@ class Settings {
schedule: '0 0 5 * * *',
},
},
network: {
csrfProtection: false,
trustProxy: false,
forceIpv4First: false,
dnsServers: '',
proxy: {
enabled: false,
hostname: '',
port: 8080,
useSsl: false,
user: '',
password: '',
bypassFilter: '',
bypassLocalAddresses: true,
},
},
};
if (initialSettings) {
this.data = merge(this.data, initialSettings);
Expand Down Expand Up @@ -622,6 +628,14 @@ class Settings {
this.data.jobs = data;
}

get network(): NetworkSettings {
return this.data.network;
}

set network(data: NetworkSettings) {
this.data.network = data;
}

get clientId(): string {
return this.data.clientId;
}
Expand Down
33 changes: 33 additions & 0 deletions server/lib/settings/migrations/0005_migrate_network_settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { AllSettings } from '@server/lib/settings';

const migrateNetworkSettings = (settings: any): AllSettings => {
if (settings.network) {
return settings;
}
const newSettings = { ...settings };
newSettings.network = {
...settings.network,
csrfProtection: settings.main.csrfProtection ?? false,
trustProxy: settings.main.trustProxy ?? false,
forceIpv4First: settings.main.forceIpv4First ?? false,
dnsServers: settings.main.dnsServers ?? '',
proxy: settings.main.proxy ?? {
enabled: false,
hostname: '',
port: 8080,
useSsl: false,
user: '',
password: '',
bypassFilter: '',
bypassLocalAddresses: true,
},
};
delete settings.main.csrfProtection;
delete settings.main.trustProxy;
delete settings.main.forceIpv4First;
delete settings.main.dnsServers;
delete settings.main.proxy;
return newSettings;
};

export default migrateNetworkSettings;
15 changes: 15 additions & 0 deletions server/routes/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ settingsRoutes.post('/main', async (req, res) => {
return res.status(200).json(settings.main);
});

settingsRoutes.get('/network', (req, res) => {
const settings = getSettings();

res.status(200).json(settings.network);
});

settingsRoutes.post('/network', async (req, res) => {
const settings = getSettings();

settings.network = merge(settings.network, req.body);
await settings.save();

return res.status(200).json(settings.network);
});

settingsRoutes.post('/main/regenerate', async (req, res, next) => {
const settings = getSettings();

Expand Down
23 changes: 13 additions & 10 deletions server/utils/restartFlag.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import type { MainSettings } from '@server/lib/settings';
import type { AllSettings, NetworkSettings } from '@server/lib/settings';
import { getSettings } from '@server/lib/settings';

class RestartFlag {
private settings: MainSettings;
private networkSettings: NetworkSettings;

public initializeSettings(settings: MainSettings): void {
this.settings = { ...settings };
public initializeSettings(settings: AllSettings): void {
this.networkSettings = {
...settings.network,
proxy: { ...settings.network.proxy },
};
}

public isSet(): boolean {
const settings = getSettings().main;
const networkSettings = getSettings().network;

return (
this.settings.csrfProtection !== settings.csrfProtection ||
this.settings.trustProxy !== settings.trustProxy ||
this.settings.proxy.enabled !== settings.proxy.enabled ||
this.settings.forceIpv4First !== settings.forceIpv4First ||
this.settings.dnsServers !== settings.dnsServers
this.networkSettings.csrfProtection !== networkSettings.csrfProtection ||
this.networkSettings.trustProxy !== networkSettings.trustProxy ||
this.networkSettings.proxy.enabled !== networkSettings.proxy.enabled ||
this.networkSettings.forceIpv4First !== networkSettings.forceIpv4First ||
this.networkSettings.dnsServers !== networkSettings.dnsServers
);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/Settings/SettingsNetwork/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import SettingsBadge from '@app/components/Settings/SettingsBadge';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import type { MainSettings } from '@server/lib/settings';
import type { NetworkSettings } from '@server/lib/settings';
import { Field, Form, Formik } from 'formik';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
Expand Down Expand Up @@ -53,7 +53,7 @@ const SettingsMain = () => {
data,
error,
mutate: revalidate,
} = useSWR<MainSettings>('/api/v1/settings/main');
} = useSWR<NetworkSettings>('/api/v1/settings/network');

const NetworkSettingsSchema = Yup.object().shape({
proxyPort: Yup.number().when('proxyEnabled', {
Expand Down Expand Up @@ -104,7 +104,7 @@ const SettingsMain = () => {
validationSchema={NetworkSettingsSchema}
onSubmit={async (values) => {
try {
const res = await fetch('/api/v1/settings/main', {
const res = await fetch('/api/v1/settings/network', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand Down

0 comments on commit c32a470

Please sign in to comment.