Merge pull request #565 from notquitenothing/custom-jellyfin-password-reset
feat: Custom jellyfin password reset setting
This commit is contained in:
@@ -59,6 +59,7 @@ yarn install --frozen-lockfile --network-timeout 1000000
|
|||||||
yarn run build
|
yarn run build
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
(you can use task scheduler to run a bat script with `@echo off` and `yarn start` to run jellyseerr in the background)
|
(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_
|
_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]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
```
|
```
|
||||||
|
|
||||||
### Packages:
|
### Packages:
|
||||||
|
|
||||||
Archlinux: [AUR](https://aur.archlinux.org/packages/jellyseerr)
|
Archlinux: [AUR](https://aur.archlinux.org/packages/jellyseerr)
|
||||||
|
|||||||
@@ -368,6 +368,9 @@ components:
|
|||||||
externalHostname:
|
externalHostname:
|
||||||
type: string
|
type: string
|
||||||
example: 'http://my.jellyfin.host'
|
example: 'http://my.jellyfin.host'
|
||||||
|
jellyfinForgotPasswordUrl:
|
||||||
|
type: string
|
||||||
|
example: 'http://my.jellyfin.host/web/index.html#!/forgotpassword.html'
|
||||||
adminUser:
|
adminUser:
|
||||||
type: string
|
type: string
|
||||||
example: 'admin'
|
example: 'admin'
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface PublicSettingsResponse {
|
|||||||
jellyfinHost?: string;
|
jellyfinHost?: string;
|
||||||
jellyfinExternalHost?: string;
|
jellyfinExternalHost?: string;
|
||||||
jellyfinServerName?: string;
|
jellyfinServerName?: string;
|
||||||
|
jellyfinForgotPasswordUrl?: string;
|
||||||
initialized: boolean;
|
initialized: boolean;
|
||||||
applicationTitle: string;
|
applicationTitle: string;
|
||||||
applicationUrl: string;
|
applicationUrl: string;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export interface JellyfinSettings {
|
|||||||
name: string;
|
name: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
externalHostname?: string;
|
externalHostname?: string;
|
||||||
|
jellyfinForgotPasswordUrl?: string;
|
||||||
libraries: Library[];
|
libraries: Library[];
|
||||||
serverId: string;
|
serverId: string;
|
||||||
}
|
}
|
||||||
@@ -131,6 +132,7 @@ interface FullPublicSettings extends PublicSettings {
|
|||||||
mediaServerType: number;
|
mediaServerType: number;
|
||||||
jellyfinHost?: string;
|
jellyfinHost?: string;
|
||||||
jellyfinExternalHost?: string;
|
jellyfinExternalHost?: string;
|
||||||
|
jellyfinForgotPasswordUrl?: string;
|
||||||
jellyfinServerName?: string;
|
jellyfinServerName?: string;
|
||||||
partialRequestsEnabled: boolean;
|
partialRequestsEnabled: boolean;
|
||||||
cacheImages: boolean;
|
cacheImages: boolean;
|
||||||
@@ -331,6 +333,7 @@ class Settings {
|
|||||||
name: '',
|
name: '',
|
||||||
hostname: '',
|
hostname: '',
|
||||||
externalHostname: '',
|
externalHostname: '',
|
||||||
|
jellyfinForgotPasswordUrl: '',
|
||||||
libraries: [],
|
libraries: [],
|
||||||
serverId: '',
|
serverId: '',
|
||||||
},
|
},
|
||||||
@@ -534,6 +537,7 @@ class Settings {
|
|||||||
applicationUrl: this.data.main.applicationUrl,
|
applicationUrl: this.data.main.applicationUrl,
|
||||||
hideAvailable: this.data.main.hideAvailable,
|
hideAvailable: this.data.main.hideAvailable,
|
||||||
localLogin: this.data.main.localLogin,
|
localLogin: this.data.main.localLogin,
|
||||||
|
jellyfinForgotPasswordUrl: this.data.jellyfin.jellyfinForgotPasswordUrl,
|
||||||
movie4kEnabled: this.data.radarr.some(
|
movie4kEnabled: this.data.radarr.some(
|
||||||
(radarr) => radarr.is4k && radarr.isDefault
|
(radarr) => radarr.is4k && radarr.isDefault
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -222,6 +222,8 @@ const JellyfinLogin: React.FC<JellyfinLoginProps> = ({
|
|||||||
const baseUrl = settings.currentSettings.jellyfinExternalHost
|
const baseUrl = settings.currentSettings.jellyfinExternalHost
|
||||||
? settings.currentSettings.jellyfinExternalHost
|
? settings.currentSettings.jellyfinExternalHost
|
||||||
: settings.currentSettings.jellyfinHost;
|
: settings.currentSettings.jellyfinHost;
|
||||||
|
const jellyfinForgotPasswordUrl =
|
||||||
|
settings.currentSettings.jellyfinForgotPasswordUrl;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Formik
|
<Formik
|
||||||
@@ -298,11 +300,15 @@ const JellyfinLogin: React.FC<JellyfinLoginProps> = ({
|
|||||||
<Button
|
<Button
|
||||||
as="a"
|
as="a"
|
||||||
buttonType="ghost"
|
buttonType="ghost"
|
||||||
href={`${baseUrl}/web/index.html#!/${
|
href={
|
||||||
|
jellyfinForgotPasswordUrl
|
||||||
|
? `${jellyfinForgotPasswordUrl}`
|
||||||
|
: `${baseUrl}/web/index.html#!/${
|
||||||
process.env.JELLYFIN_TYPE === 'emby'
|
process.env.JELLYFIN_TYPE === 'emby'
|
||||||
? 'startup/'
|
? 'startup/'
|
||||||
: ''
|
: ''
|
||||||
}forgotpassword.html`}
|
}forgotpassword.html`
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.forgotpassword)}
|
{intl.formatMessage(messages.forgotpassword)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ const messages = defineMessages({
|
|||||||
jellyfinSettingsSuccess: '{mediaServerName} settings saved successfully!',
|
jellyfinSettingsSuccess: '{mediaServerName} settings saved successfully!',
|
||||||
jellyfinSettings: '{mediaServerName} Settings',
|
jellyfinSettings: '{mediaServerName} Settings',
|
||||||
jellyfinSettingsDescription:
|
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',
|
externalUrl: 'External URL',
|
||||||
internalUrl: 'Internal URL',
|
internalUrl: 'Internal URL',
|
||||||
|
jellyfinForgotPasswordUrl: 'Forgot Password URL',
|
||||||
validationUrl: 'You must provide a valid URL',
|
validationUrl: 'You must provide a valid URL',
|
||||||
syncing: 'Syncing',
|
syncing: 'Syncing',
|
||||||
syncJellyfin: 'Sync Libraries',
|
syncJellyfin: 'Sync Libraries',
|
||||||
@@ -94,6 +95,10 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
/^(https?:\/\/)?(?:[\w-]+\.)*[\w-]+(?::\d{2,5})?(?:\/[\w-]+)*(?:\/)?$/gm,
|
/^(https?:\/\/)?(?:[\w-]+\.)*[\w-]+(?::\d{2,5})?(?:\/[\w-]+)*(?:\/)?$/gm,
|
||||||
intl.formatMessage(messages.validationUrl)
|
intl.formatMessage(messages.validationUrl)
|
||||||
),
|
),
|
||||||
|
jellyfinForgotPasswordUrl: Yup.string().matches(
|
||||||
|
/^(https?:\/\/)?(?:[\w-]+\.)*[\w-]+(?::\d{2,5})?(?:\/[\w-]+)*(?:\/)?$/gm,
|
||||||
|
intl.formatMessage(messages.validationUrl)
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
const activeLibraries =
|
const activeLibraries =
|
||||||
@@ -353,6 +358,7 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
initialValues={{
|
initialValues={{
|
||||||
jellyfinInternalUrl: data?.hostname || '',
|
jellyfinInternalUrl: data?.hostname || '',
|
||||||
jellyfinExternalUrl: data?.externalHostname || '',
|
jellyfinExternalUrl: data?.externalHostname || '',
|
||||||
|
jellyfinForgotPasswordUrl: data?.jellyfinForgotPasswordUrl || '',
|
||||||
}}
|
}}
|
||||||
validationSchema={JellyfinSettingsSchema}
|
validationSchema={JellyfinSettingsSchema}
|
||||||
onSubmit={async (values) => {
|
onSubmit={async (values) => {
|
||||||
@@ -360,6 +366,7 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
await axios.post('/api/v1/settings/jellyfin', {
|
await axios.post('/api/v1/settings/jellyfin', {
|
||||||
hostname: values.jellyfinInternalUrl,
|
hostname: values.jellyfinInternalUrl,
|
||||||
externalHostname: values.jellyfinExternalUrl,
|
externalHostname: values.jellyfinExternalUrl,
|
||||||
|
jellyfinForgotPasswordUrl: values.jellyfinForgotPasswordUrl,
|
||||||
} as JellyfinSettings);
|
} as JellyfinSettings);
|
||||||
|
|
||||||
addToast(
|
addToast(
|
||||||
@@ -437,6 +444,30 @@ const SettingsJellyfin: React.FC<SettingsJellyfinProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form-row">
|
||||||
|
<label
|
||||||
|
htmlFor="jellyfinForgotPasswordUrl"
|
||||||
|
className="text-label"
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.jellyfinForgotPasswordUrl)}
|
||||||
|
</label>
|
||||||
|
<div className="form-input-area">
|
||||||
|
<div className="form-input-field">
|
||||||
|
<Field
|
||||||
|
type="text"
|
||||||
|
inputMode="url"
|
||||||
|
id="jellyfinForgotPasswordUrl"
|
||||||
|
name="jellyfinForgotPasswordUrl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{errors.jellyfinForgotPasswordUrl &&
|
||||||
|
touched.jellyfinForgotPasswordUrl && (
|
||||||
|
<div className="error">
|
||||||
|
{errors.jellyfinForgotPasswordUrl}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<span className="ml-3 inline-flex rounded-md shadow-sm">
|
<span className="ml-3 inline-flex rounded-md shadow-sm">
|
||||||
|
|||||||
@@ -938,7 +938,7 @@
|
|||||||
"components.Settings.internalUrl": "Internal URL",
|
"components.Settings.internalUrl": "Internal URL",
|
||||||
"components.Settings.is4k": "4K",
|
"components.Settings.is4k": "4K",
|
||||||
"components.Settings.jellyfinSettings": "{mediaServerName} Settings",
|
"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.jellyfinSettingsFailure": "Something went wrong while saving {mediaServerName} settings.",
|
||||||
"components.Settings.jellyfinSettingsSuccess": "{mediaServerName} settings saved successfully!",
|
"components.Settings.jellyfinSettingsSuccess": "{mediaServerName} settings saved successfully!",
|
||||||
"components.Settings.jellyfinlibraries": "{mediaServerName} Libraries",
|
"components.Settings.jellyfinlibraries": "{mediaServerName} Libraries",
|
||||||
|
|||||||
Reference in New Issue
Block a user