From ce9802d5d43d116f221f37ce99fe6e762d7df7bc Mon Sep 17 00:00:00 2001 From: Derek Paschal Date: Tue, 14 Nov 2023 08:20:28 -0600 Subject: [PATCH 01/34] Adding Jellyfin Setting for Custom "Forgot Password" URL Adding Jellyfin Setting for Custom "Forgot Password" URL. Useful in cases where you are using a custom authentication provider such as the LDAP plugin, Authelia, lldap, or any other external auth scheme with its own password reset page. --- overseerr-api.yml | 3 + server/interfaces/api/settingsInterfaces.ts | 1 + server/lib/settings.ts | 4 + src/components/Login/JellyfinLogin.tsx | 7 +- src/components/Settings/SettingsJellyfin.tsx | 80 +++++++++++++------- src/i18n/locale/en.json | 4 +- 6 files changed, 68 insertions(+), 31 deletions(-) diff --git a/overseerr-api.yml b/overseerr-api.yml index e070361be..7a7ea490a 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -368,6 +368,9 @@ components: externalHostname: type: string example: 'http://my.jellyfin.host' + jellyfinForgotPasswordUrl: + type: string + example: 'http://my.jellyfin.host/web/index.html#!/forgotpassword.html' adminUser: type: string example: 'admin' diff --git a/server/interfaces/api/settingsInterfaces.ts b/server/interfaces/api/settingsInterfaces.ts index b709a0c4b..7e714fdae 100644 --- a/server/interfaces/api/settingsInterfaces.ts +++ b/server/interfaces/api/settingsInterfaces.ts @@ -41,6 +41,7 @@ export interface PublicSettingsResponse { locale: string; emailEnabled: boolean; newPlexLogin: boolean; + jellyfinForgotPasswordUrl: string; } export interface CacheItem { diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 133d0e327..60e327dbb 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -42,6 +42,7 @@ export interface JellyfinSettings { externalHostname?: string; libraries: Library[]; serverId: string; + jellyfinForgotPasswordUrl: string; } export interface TautulliSettings { hostname?: string; @@ -124,6 +125,7 @@ interface FullPublicSettings extends PublicSettings { applicationUrl: string; hideAvailable: boolean; localLogin: boolean; + jellyfinForgotPasswordUrl: string; movie4kEnabled: boolean; series4kEnabled: boolean; region: string; @@ -331,6 +333,7 @@ class Settings { name: '', hostname: '', externalHostname: '', + jellyfinForgotPasswordUrl: '', libraries: [], serverId: '', }, @@ -534,6 +537,7 @@ class Settings { applicationUrl: this.data.main.applicationUrl, hideAvailable: this.data.main.hideAvailable, localLogin: this.data.main.localLogin, + jellyfinForgotPasswordUrl: this.data.jellyfin.jellyfinForgotPasswordUrl, movie4kEnabled: this.data.radarr.some( (radarr) => radarr.is4k && radarr.isDefault ), diff --git a/src/components/Login/JellyfinLogin.tsx b/src/components/Login/JellyfinLogin.tsx index 126fa4f76..8a6370c24 100644 --- a/src/components/Login/JellyfinLogin.tsx +++ b/src/components/Login/JellyfinLogin.tsx @@ -222,6 +222,7 @@ const JellyfinLogin: React.FC = ({ const baseUrl = settings.currentSettings.jellyfinExternalHost ? settings.currentSettings.jellyfinExternalHost : settings.currentSettings.jellyfinHost; + const jellyfinForgotPasswordUrl = settings.currentSettings.jellyfinForgotPasswordUrl; return (
= ({ diff --git a/src/components/Settings/SettingsJellyfin.tsx b/src/components/Settings/SettingsJellyfin.tsx index 5d56431fb..2c7a9d772 100644 --- a/src/components/Settings/SettingsJellyfin.tsx +++ b/src/components/Settings/SettingsJellyfin.tsx @@ -30,9 +30,10 @@ const messages = defineMessages({ jellyfinSettingsSuccess: '{mediaServerName} settings saved successfully!', jellyfinSettings: '{mediaServerName} Settings', jellyfinSettingsDescription: - 'Optionally configure the internal and external endpoints for your {mediaServerName} server. In most cases, the external URL is different to the internal URL.', + 'Optionally configure the internal and external endpoints for your {mediaServerName} server. In most cases, the external URL is different to the internal URL. A custom password reset URL can also be set for {mediaServerName} login, in case you would like to redirect to a different password reset page.', externalUrl: 'External URL', internalUrl: 'Internal URL', + jellyfinForgotPasswordUrl: 'Forgot Password URL', validationUrl: 'You must provide a valid URL', syncing: 'Syncing', syncJellyfin: 'Sync Libraries', @@ -94,6 +95,10 @@ const SettingsJellyfin: React.FC = ({ /^(https?:\/\/)?(?:[\w-]+\.)*[\w-]+(?::\d{2,5})?(?:\/[\w-]+)*(?:\/)?$/gm, intl.formatMessage(messages.validationUrl) ), + jellyfinForgotPasswordUrl: Yup.string().matches( + /^(https?:\/\/)?(?:[\w-]+\.)*[\w-]+(?::\d{2,5})?(?:\/[\w-]+)*(?:\/)?$/gm, + intl.formatMessage(messages.validationUrl) + ), }); const activeLibraries = @@ -171,20 +176,20 @@ const SettingsJellyfin: React.FC = ({

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinlibraries, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinlibraries, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinlibrariesDescription, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinlibrariesDescription, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

@@ -223,11 +228,11 @@ const SettingsJellyfin: React.FC = ({

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.manualscanDescriptionJellyfin, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.manualscanDescriptionJellyfin, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

@@ -271,11 +276,11 @@ const SettingsJellyfin: React.FC = ({ values={{ count: dataSync.currentLibrary ? dataSync.libraries.slice( - dataSync.libraries.findIndex( - (library) => - library.id === dataSync.currentLibrary?.id - ) + 1 - ).length + dataSync.libraries.findIndex( + (library) => + library.id === dataSync.currentLibrary?.id + ) + 1 + ).length : 0, }} /> @@ -333,26 +338,27 @@ const SettingsJellyfin: React.FC = ({

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinSettings, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinSettings, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinSettingsDescription, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinSettingsDescription, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

{ @@ -360,6 +366,7 @@ const SettingsJellyfin: React.FC = ({ await axios.post('/api/v1/settings/jellyfin', { hostname: values.jellyfinInternalUrl, externalHostname: values.jellyfinExternalUrl, + jellyfinForgotPasswordUrl: values.jellyfinForgotPasswordUrl, } as JellyfinSettings); addToast( @@ -437,6 +444,27 @@ const SettingsJellyfin: React.FC = ({ )} +
+ +
+
+ +
+ {errors.jellyfinForgotPasswordUrl && + touched.jellyfinForgotPasswordUrl && ( +
+ {errors.jellyfinForgotPasswordUrl} +
+ )} +
+
diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 906892b04..07d4356cb 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -938,7 +938,7 @@ "components.Settings.internalUrl": "Internal URL", "components.Settings.is4k": "4K", "components.Settings.jellyfinSettings": "{mediaServerName} Settings", - "components.Settings.jellyfinSettingsDescription": "Optionally configure the internal and external endpoints for your {mediaServerName} server. In most cases, the external URL is different to the internal URL.", + "components.Settings.jellyfinSettingsDescription": "Optionally configure the internal and external endpoints for your {mediaServerName} server. In most cases, the external URL is different to the internal URL. A custom password reset URL can also be set for {mediaServerName} login, in case you would like to redirect to a different password reset page.", "components.Settings.jellyfinSettingsFailure": "Something went wrong while saving {mediaServerName} settings.", "components.Settings.jellyfinSettingsSuccess": "{mediaServerName} settings saved successfully!", "components.Settings.jellyfinlibraries": "{mediaServerName} Libraries", @@ -1305,4 +1305,4 @@ "pages.returnHome": "Return Home", "pages.serviceunavailable": "Service Unavailable", "pages.somethingwentwrong": "Something Went Wrong" -} +} \ No newline at end of file From 13dd3cad5481bd74fcb8d20db949b5c561154b88 Mon Sep 17 00:00:00 2001 From: Derek Paschal Date: Tue, 14 Nov 2023 08:51:29 -0600 Subject: [PATCH 02/34] Making the new setting optional --- server/interfaces/api/settingsInterfaces.ts | 2 +- server/lib/settings.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/interfaces/api/settingsInterfaces.ts b/server/interfaces/api/settingsInterfaces.ts index 7e714fdae..1bf40cdbc 100644 --- a/server/interfaces/api/settingsInterfaces.ts +++ b/server/interfaces/api/settingsInterfaces.ts @@ -24,6 +24,7 @@ export interface PublicSettingsResponse { jellyfinHost?: string; jellyfinExternalHost?: string; jellyfinServerName?: string; + jellyfinForgotPasswordUrl?: string; initialized: boolean; applicationTitle: string; applicationUrl: string; @@ -41,7 +42,6 @@ export interface PublicSettingsResponse { locale: string; emailEnabled: boolean; newPlexLogin: boolean; - jellyfinForgotPasswordUrl: string; } export interface CacheItem { diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 60e327dbb..63f952363 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -40,9 +40,9 @@ export interface JellyfinSettings { name: string; hostname: string; externalHostname?: string; + jellyfinForgotPasswordUrl?: string; libraries: Library[]; serverId: string; - jellyfinForgotPasswordUrl: string; } export interface TautulliSettings { hostname?: string; @@ -125,7 +125,6 @@ interface FullPublicSettings extends PublicSettings { applicationUrl: string; hideAvailable: boolean; localLogin: boolean; - jellyfinForgotPasswordUrl: string; movie4kEnabled: boolean; series4kEnabled: boolean; region: string; @@ -133,6 +132,7 @@ interface FullPublicSettings extends PublicSettings { mediaServerType: number; jellyfinHost?: string; jellyfinExternalHost?: string; + jellyfinForgotPasswordUrl?: string; jellyfinServerName?: string; partialRequestsEnabled: boolean; cacheImages: boolean; From 0dfe050ba10061a57151825d8881662c8bb29a50 Mon Sep 17 00:00:00 2001 From: Derek Paschal Date: Wed, 15 Nov 2023 06:59:02 -0600 Subject: [PATCH 03/34] Fixing code formatting, prettier --- .github/FUNDING.yml | 2 +- README.md | 4 +- src/components/Login/JellyfinLogin.tsx | 17 +++--- src/components/Settings/SettingsJellyfin.tsx | 55 +++++++++++--------- src/i18n/locale/en.json | 2 +- 5 files changed, 45 insertions(+), 35 deletions(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 0189cafb4..6e08dfb2a 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: [Fallenbagel] \ No newline at end of file +github: [Fallenbagel] diff --git a/README.md b/README.md index 0dc45fe73..d05c93cdb 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ https://hub.docker.com/r/fallenbagel/jellyseerr Pre-requisites: - Nodejs [v18](https://nodejs.org/download/release/v18.18.2) -- [Yarn](https://classic.yarnpkg.com/lang/en/docs/install) +- [Yarn](https://classic.yarnpkg.com/lang/en/docs/install) - Download/git clone the source code from the github (Either develop branch or main for stable) ```cmd @@ -59,6 +59,7 @@ yarn install --frozen-lockfile --network-timeout 1000000 yarn run build yarn start ``` + (you can use task scheduler to run a bat script with `@echo off` and `yarn start` to run jellyseerr in the background) _to set env variables such as `JELLYFIN_TYPE=emby` create a file called `.env` in the root directory of jellyseerr_ @@ -136,6 +137,7 @@ ExecStart=/usr/bin/node dist/index.js [Install] WantedBy=multi-user.target ``` + ### Packages: Archlinux: [AUR](https://aur.archlinux.org/packages/jellyseerr) diff --git a/src/components/Login/JellyfinLogin.tsx b/src/components/Login/JellyfinLogin.tsx index 8a6370c24..594a6ff66 100644 --- a/src/components/Login/JellyfinLogin.tsx +++ b/src/components/Login/JellyfinLogin.tsx @@ -222,7 +222,8 @@ const JellyfinLogin: React.FC = ({ const baseUrl = settings.currentSettings.jellyfinExternalHost ? settings.currentSettings.jellyfinExternalHost : settings.currentSettings.jellyfinHost; - const jellyfinForgotPasswordUrl = settings.currentSettings.jellyfinForgotPasswordUrl; + const jellyfinForgotPasswordUrl = + settings.currentSettings.jellyfinForgotPasswordUrl; return (
= ({ diff --git a/src/components/Settings/SettingsJellyfin.tsx b/src/components/Settings/SettingsJellyfin.tsx index 2c7a9d772..584a98fde 100644 --- a/src/components/Settings/SettingsJellyfin.tsx +++ b/src/components/Settings/SettingsJellyfin.tsx @@ -176,20 +176,20 @@ const SettingsJellyfin: React.FC = ({

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinlibraries, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinlibraries, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinlibrariesDescription, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinlibrariesDescription, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

@@ -228,11 +228,11 @@ const SettingsJellyfin: React.FC = ({

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.manualscanDescriptionJellyfin, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.manualscanDescriptionJellyfin, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

@@ -276,11 +276,11 @@ const SettingsJellyfin: React.FC = ({ values={{ count: dataSync.currentLibrary ? dataSync.libraries.slice( - dataSync.libraries.findIndex( - (library) => - library.id === dataSync.currentLibrary?.id - ) + 1 - ).length + dataSync.libraries.findIndex( + (library) => + library.id === dataSync.currentLibrary?.id + ) + 1 + ).length : 0, }} /> @@ -338,20 +338,20 @@ const SettingsJellyfin: React.FC = ({

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinSettings, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinSettings, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

{publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinSettingsDescription, { - mediaServerName: 'Emby', - }) + mediaServerName: 'Emby', + }) : intl.formatMessage(messages.jellyfinSettingsDescription, { - mediaServerName: 'Jellyfin', - })} + mediaServerName: 'Jellyfin', + })}

= ({
-