Add login page visibility controls
This commit is contained in:
@@ -1 +1 @@
|
|||||||
0303261323
|
0303261413
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
BUILD_NUMBER = "0303261323"
|
BUILD_NUMBER = "0303261413"
|
||||||
CHANGELOG = '2026-03-02|Hotfix: add logged-out password reset flow\n2026-03-02|Process 1 build 0203261953\n2026-03-02|Process 1 build 0203261610\n2026-03-02|Process 1 build 0203261608\n2026-03-02|Add dedicated profile invites page and fix mobile admin layout\n2026-03-01|Persist Seerr media failure suppression and reduce sync error noise\n2026-03-01|Add repository line ending policy\n2026-03-01|Finalize diagnostics, logging controls, and email test support\n2026-03-01|Add invite email templates and delivery workflow\n2026-02-28|Finalize dev-1.3 upgrades and Seerr updates\n2026-02-27|admin docs and layout refresh, build 2702261314\n2026-02-27|Build 2702261153: fix jellyfin sync user visibility\n2026-02-26|Build 2602262241: live request page updates\n2026-02-26|Build 2602262204\n2026-02-26|Build 2602262159: restore jellyfin-first user source\n2026-02-26|Build 2602262049: split magent settings and harden local login\n2026-02-26|Build 2602262030: add magent settings and hardening\n2026-02-26|Build 2602261731: fix user resync after nuclear wipe\n2026-02-26|Build 2602261717: master invite policy and self-service invite controls\n2026-02-26|Build 2602261636: self-service invites and count fixes\n2026-02-26|Build 2602261605: invite trace and cross-system user lifecycle\n2026-02-26|Build 2602261536: refine invite layouts and tighten UI\n2026-02-26|Build 2602261523: live updates, invite cleanup and nuclear resync\n2026-02-26|Build 2602261442: tidy users and invite layouts\n2026-02-26|Build 2602261409: unify invite management controls\n2026-02-26|Build 2602260214: invites profiles and expiry admin controls\n2026-02-26|Build 2602260022: enterprise UI refresh and users bulk auto-search\n2026-02-25|Build 2502262321: fix auto-search quality and per-user toggle\n2026-02-02|Build 0202261541: allow FQDN service URLs\n2026-01-30|Build 3001262148: single container\n2026-01-29|Build 2901262244: format changelog\n2026-01-29|Build 2901262240: cache users\n2026-01-29|Tidy full changelog\n2026-01-29|Update full changelog\n2026-01-29|Bake build number and changelog\n2026-01-29|Hardcode build number in backend\n2026-01-29|release: 2901262102\n2026-01-29|release: 2901262044\n2026-01-29|release: 2901262036\n2026-01-27|Hydrate missing artwork from Jellyseerr (build 271261539)\n2026-01-27|Fallback to TMDB when artwork cache fails (build 271261524)\n2026-01-27|Add service test buttons (build 271261335)\n2026-01-27|Bump build number (process 2) 271261322\n2026-01-27|Add cache load spinner (build 271261238)\n2026-01-27|Fix snapshot title fallback (build 271261228)\n2026-01-27|Fix request titles in snapshots (build 271261219)\n2026-01-27|Bump build number to 271261202\n2026-01-27|Clarify request sync settings (build 271261159)\n2026-01-27|Fix backend cache stats import (build 271261149)\n2026-01-27|Improve cache stats performance (build 271261145)\n2026-01-27|Add cache control artwork stats\n2026-01-26|Fix sync progress bar animation\n2026-01-26|Fix cache title hydration\n2026-01-25|Build 2501262041\n2026-01-25|Harden request cache titles and cache-only reads\n2026-01-25|Serve bundled branding assets by default\n2026-01-25|Seed branding logo from bundled assets\n2026-01-25|Tidy request sync controls\n2026-01-25|Add Jellyfin login cache and admin-only stats\n2026-01-25|Add user stats and activity tracking\n2026-01-25|Move account actions into avatar menu\n2026-01-25|Improve mobile header layout\n2026-01-25|Automate build number tagging and sync\n2026-01-25|Add site banner, build number, and changelog\n2026-01-24|Improve request handling and qBittorrent categories\n2026-01-24|Map Prowlarr releases to Arr indexers for manual grab\n2026-01-24|Clarify how-it-works steps and fixes\n2026-01-24|Document fix buttons in how-it-works\n2026-01-24|Route grabs through Sonarr/Radarr only\n2026-01-23|Use backend branding assets for logo and favicon\n2026-01-23|Copy public assets into frontend image\n2026-01-23|Fix backend Dockerfile paths for root context\n2026-01-23|Add Docker Hub compose override\n2026-01-23|Remove password fields from users page\n2026-01-23|Use bundled branding assets\n2026-01-23|Add default branding assets when missing\n2026-01-23|Show available status on landing when in Jellyfin\n2026-01-23|Fix cache titles and move feedback link\n2026-01-23|Add feedback form and webhook\n2026-01-23|Hide header actions when signed out\n2026-01-23|Fallback manual grab to qBittorrent\n2026-01-23|Split search actions and improve download options\n2026-01-23|Fix cache titles via Jellyseerr media lookup\n2026-01-22|Update README with Docker-first guide\n2026-01-22|Update README\n2026-01-22|Ignore build artifacts\n2026-01-22|Initial commit'
|
CHANGELOG = '2026-03-03|Hotfix: expand landing-page search to all requests\n2026-03-02|Hotfix: add logged-out password reset flow\n2026-03-02|Process 1 build 0203261953\n2026-03-02|Process 1 build 0203261610\n2026-03-02|Process 1 build 0203261608\n2026-03-02|Add dedicated profile invites page and fix mobile admin layout\n2026-03-01|Persist Seerr media failure suppression and reduce sync error noise\n2026-03-01|Add repository line ending policy\n2026-03-01|Finalize diagnostics, logging controls, and email test support\n2026-03-01|Add invite email templates and delivery workflow\n2026-02-28|Finalize dev-1.3 upgrades and Seerr updates\n2026-02-27|admin docs and layout refresh, build 2702261314\n2026-02-27|Build 2702261153: fix jellyfin sync user visibility\n2026-02-26|Build 2602262241: live request page updates\n2026-02-26|Build 2602262204\n2026-02-26|Build 2602262159: restore jellyfin-first user source\n2026-02-26|Build 2602262049: split magent settings and harden local login\n2026-02-26|Build 2602262030: add magent settings and hardening\n2026-02-26|Build 2602261731: fix user resync after nuclear wipe\n2026-02-26|Build 2602261717: master invite policy and self-service invite controls\n2026-02-26|Build 2602261636: self-service invites and count fixes\n2026-02-26|Build 2602261605: invite trace and cross-system user lifecycle\n2026-02-26|Build 2602261536: refine invite layouts and tighten UI\n2026-02-26|Build 2602261523: live updates, invite cleanup and nuclear resync\n2026-02-26|Build 2602261442: tidy users and invite layouts\n2026-02-26|Build 2602261409: unify invite management controls\n2026-02-26|Build 2602260214: invites profiles and expiry admin controls\n2026-02-26|Build 2602260022: enterprise UI refresh and users bulk auto-search\n2026-02-25|Build 2502262321: fix auto-search quality and per-user toggle\n2026-02-02|Build 0202261541: allow FQDN service URLs\n2026-01-30|Build 3001262148: single container\n2026-01-29|Build 2901262244: format changelog\n2026-01-29|Build 2901262240: cache users\n2026-01-29|Tidy full changelog\n2026-01-29|Update full changelog\n2026-01-29|Bake build number and changelog\n2026-01-29|Hardcode build number in backend\n2026-01-29|release: 2901262102\n2026-01-29|release: 2901262044\n2026-01-29|release: 2901262036\n2026-01-27|Hydrate missing artwork from Jellyseerr (build 271261539)\n2026-01-27|Fallback to TMDB when artwork cache fails (build 271261524)\n2026-01-27|Add service test buttons (build 271261335)\n2026-01-27|Bump build number (process 2) 271261322\n2026-01-27|Add cache load spinner (build 271261238)\n2026-01-27|Fix snapshot title fallback (build 271261228)\n2026-01-27|Fix request titles in snapshots (build 271261219)\n2026-01-27|Bump build number to 271261202\n2026-01-27|Clarify request sync settings (build 271261159)\n2026-01-27|Fix backend cache stats import (build 271261149)\n2026-01-27|Improve cache stats performance (build 271261145)\n2026-01-27|Add cache control artwork stats\n2026-01-26|Fix sync progress bar animation\n2026-01-26|Fix cache title hydration\n2026-01-25|Build 2501262041\n2026-01-25|Harden request cache titles and cache-only reads\n2026-01-25|Serve bundled branding assets by default\n2026-01-25|Seed branding logo from bundled assets\n2026-01-25|Tidy request sync controls\n2026-01-25|Add Jellyfin login cache and admin-only stats\n2026-01-25|Add user stats and activity tracking\n2026-01-25|Move account actions into avatar menu\n2026-01-25|Improve mobile header layout\n2026-01-25|Automate build number tagging and sync\n2026-01-25|Add site banner, build number, and changelog\n2026-01-24|Improve request handling and qBittorrent categories\n2026-01-24|Map Prowlarr releases to Arr indexers for manual grab\n2026-01-24|Clarify how-it-works steps and fixes\n2026-01-24|Document fix buttons in how-it-works\n2026-01-24|Route grabs through Sonarr/Radarr only\n2026-01-23|Use backend branding assets for logo and favicon\n2026-01-23|Copy public assets into frontend image\n2026-01-23|Fix backend Dockerfile paths for root context\n2026-01-23|Add Docker Hub compose override\n2026-01-23|Remove password fields from users page\n2026-01-23|Use bundled branding assets\n2026-01-23|Add default branding assets when missing\n2026-01-23|Show available status on landing when in Jellyfin\n2026-01-23|Fix cache titles and move feedback link\n2026-01-23|Add feedback form and webhook\n2026-01-23|Hide header actions when signed out\n2026-01-23|Fallback manual grab to qBittorrent\n2026-01-23|Split search actions and improve download options\n2026-01-23|Fix cache titles via Jellyseerr media lookup\n2026-01-22|Update README with Docker-first guide\n2026-01-22|Update README\n2026-01-22|Ignore build artifacts\n2026-01-22|Initial commit'
|
||||||
|
|||||||
@@ -71,6 +71,18 @@ class Settings(BaseSettings):
|
|||||||
site_banner_tone: str = Field(
|
site_banner_tone: str = Field(
|
||||||
default="info", validation_alias=AliasChoices("SITE_BANNER_TONE")
|
default="info", validation_alias=AliasChoices("SITE_BANNER_TONE")
|
||||||
)
|
)
|
||||||
|
site_login_show_jellyfin_login: bool = Field(
|
||||||
|
default=True, validation_alias=AliasChoices("SITE_LOGIN_SHOW_JELLYFIN_LOGIN")
|
||||||
|
)
|
||||||
|
site_login_show_local_login: bool = Field(
|
||||||
|
default=True, validation_alias=AliasChoices("SITE_LOGIN_SHOW_LOCAL_LOGIN")
|
||||||
|
)
|
||||||
|
site_login_show_forgot_password: bool = Field(
|
||||||
|
default=True, validation_alias=AliasChoices("SITE_LOGIN_SHOW_FORGOT_PASSWORD")
|
||||||
|
)
|
||||||
|
site_login_show_signup_link: bool = Field(
|
||||||
|
default=True, validation_alias=AliasChoices("SITE_LOGIN_SHOW_SIGNUP_LINK")
|
||||||
|
)
|
||||||
site_changelog: Optional[str] = Field(default=CHANGELOG)
|
site_changelog: Optional[str] = Field(default=CHANGELOG)
|
||||||
|
|
||||||
magent_application_url: Optional[str] = Field(
|
magent_application_url: Optional[str] = Field(
|
||||||
|
|||||||
@@ -215,6 +215,10 @@ SETTING_KEYS: List[str] = [
|
|||||||
"site_banner_enabled",
|
"site_banner_enabled",
|
||||||
"site_banner_message",
|
"site_banner_message",
|
||||||
"site_banner_tone",
|
"site_banner_tone",
|
||||||
|
"site_login_show_jellyfin_login",
|
||||||
|
"site_login_show_local_login",
|
||||||
|
"site_login_show_forgot_password",
|
||||||
|
"site_login_show_signup_link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ def _build_site_info(include_changelog: bool) -> Dict[str, Any]:
|
|||||||
"message": banner_message,
|
"message": banner_message,
|
||||||
"tone": tone,
|
"tone": tone,
|
||||||
},
|
},
|
||||||
|
"login": {
|
||||||
|
"showJellyfinLogin": bool(runtime.site_login_show_jellyfin_login),
|
||||||
|
"showLocalLogin": bool(runtime.site_login_show_local_login),
|
||||||
|
"showForgotPassword": bool(runtime.site_login_show_forgot_password),
|
||||||
|
"showSignupLink": bool(runtime.site_login_show_signup_link),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if include_changelog:
|
if include_changelog:
|
||||||
info["changelog"] = (CHANGELOG or "").strip()
|
info["changelog"] = (CHANGELOG or "").strip()
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ _BOOL_FIELDS = {
|
|||||||
"magent_notify_webhook_enabled",
|
"magent_notify_webhook_enabled",
|
||||||
"jellyfin_sync_to_arr",
|
"jellyfin_sync_to_arr",
|
||||||
"site_banner_enabled",
|
"site_banner_enabled",
|
||||||
|
"site_login_show_jellyfin_login",
|
||||||
|
"site_login_show_local_login",
|
||||||
|
"site_login_show_forgot_password",
|
||||||
|
"site_login_show_signup_link",
|
||||||
}
|
}
|
||||||
_SKIP_OVERRIDE_FIELDS = {"site_build_number", "site_changelog"}
|
_SKIP_OVERRIDE_FIELDS = {"site_build_number", "site_changelog"}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ const SECTION_LABELS: Record<string, string> = {
|
|||||||
const BOOL_SETTINGS = new Set([
|
const BOOL_SETTINGS = new Set([
|
||||||
'jellyfin_sync_to_arr',
|
'jellyfin_sync_to_arr',
|
||||||
'site_banner_enabled',
|
'site_banner_enabled',
|
||||||
|
'site_login_show_jellyfin_login',
|
||||||
|
'site_login_show_local_login',
|
||||||
|
'site_login_show_forgot_password',
|
||||||
|
'site_login_show_signup_link',
|
||||||
'magent_proxy_enabled',
|
'magent_proxy_enabled',
|
||||||
'magent_proxy_trust_forwarded_headers',
|
'magent_proxy_trust_forwarded_headers',
|
||||||
'magent_ssl_bind_enabled',
|
'magent_ssl_bind_enabled',
|
||||||
@@ -104,7 +108,7 @@ const SECTION_DESCRIPTIONS: Record<string, string> = {
|
|||||||
qbittorrent: 'Downloader connection settings.',
|
qbittorrent: 'Downloader connection settings.',
|
||||||
requests: 'Control how often requests are refreshed and cleaned up.',
|
requests: 'Control how often requests are refreshed and cleaned up.',
|
||||||
log: 'Activity log for troubleshooting.',
|
log: 'Activity log for troubleshooting.',
|
||||||
site: 'Sitewide banner and version details. The changelog is generated from git history during release builds.',
|
site: 'Sitewide banner, login page visibility, and version details. The changelog is generated from git history during release builds.',
|
||||||
}
|
}
|
||||||
|
|
||||||
const SETTINGS_SECTION_MAP: Record<string, string | null> = {
|
const SETTINGS_SECTION_MAP: Record<string, string | null> = {
|
||||||
@@ -280,6 +284,10 @@ const SETTING_LABEL_OVERRIDES: Record<string, string> = {
|
|||||||
magent_notify_push_device: 'Device / target',
|
magent_notify_push_device: 'Device / target',
|
||||||
magent_notify_webhook_enabled: 'Generic webhook notifications enabled',
|
magent_notify_webhook_enabled: 'Generic webhook notifications enabled',
|
||||||
magent_notify_webhook_url: 'Generic webhook URL',
|
magent_notify_webhook_url: 'Generic webhook URL',
|
||||||
|
site_login_show_jellyfin_login: 'Login page: Jellyfin sign-in',
|
||||||
|
site_login_show_local_login: 'Login page: local Magent sign-in',
|
||||||
|
site_login_show_forgot_password: 'Login page: forgot password',
|
||||||
|
site_login_show_signup_link: 'Login page: invite signup link',
|
||||||
log_file_max_bytes: 'Log file max size (bytes)',
|
log_file_max_bytes: 'Log file max size (bytes)',
|
||||||
log_file_backup_count: 'Rotated log files to keep',
|
log_file_backup_count: 'Rotated log files to keep',
|
||||||
log_http_client_level: 'Service HTTP log level',
|
log_http_client_level: 'Service HTTP log level',
|
||||||
@@ -564,6 +572,15 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
|||||||
'requests_cleanup_time',
|
'requests_cleanup_time',
|
||||||
'requests_cleanup_days',
|
'requests_cleanup_days',
|
||||||
]
|
]
|
||||||
|
const siteSettingOrder = [
|
||||||
|
'site_banner_enabled',
|
||||||
|
'site_banner_message',
|
||||||
|
'site_banner_tone',
|
||||||
|
'site_login_show_jellyfin_login',
|
||||||
|
'site_login_show_local_login',
|
||||||
|
'site_login_show_forgot_password',
|
||||||
|
'site_login_show_signup_link',
|
||||||
|
]
|
||||||
const sortByOrder = (items: AdminSetting[], order: string[]) => {
|
const sortByOrder = (items: AdminSetting[], order: string[]) => {
|
||||||
const position = new Map(order.map((key, index) => [key, index]))
|
const position = new Map(order.map((key, index) => [key, index]))
|
||||||
return [...items].sort((a, b) => {
|
return [...items].sort((a, b) => {
|
||||||
@@ -615,6 +632,9 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
|||||||
if (sectionKey === 'requests') {
|
if (sectionKey === 'requests') {
|
||||||
return sortByOrder(filtered, requestSettingOrder)
|
return sortByOrder(filtered, requestSettingOrder)
|
||||||
}
|
}
|
||||||
|
if (sectionKey === 'site') {
|
||||||
|
return sortByOrder(filtered, siteSettingOrder)
|
||||||
|
}
|
||||||
return filtered
|
return filtered
|
||||||
})(),
|
})(),
|
||||||
}))
|
}))
|
||||||
@@ -748,6 +768,10 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
|||||||
site_banner_enabled: 'Enable a sitewide banner for announcements.',
|
site_banner_enabled: 'Enable a sitewide banner for announcements.',
|
||||||
site_banner_message: 'Short banner message for maintenance or updates.',
|
site_banner_message: 'Short banner message for maintenance or updates.',
|
||||||
site_banner_tone: 'Visual tone for the banner.',
|
site_banner_tone: 'Visual tone for the banner.',
|
||||||
|
site_login_show_jellyfin_login: 'Show the Jellyfin login button on the login page.',
|
||||||
|
site_login_show_local_login: 'Show the local Magent login button on the login page.',
|
||||||
|
site_login_show_forgot_password: 'Show the forgot-password link on the login page.',
|
||||||
|
site_login_show_signup_link: 'Show the invite signup link on the login page.',
|
||||||
site_changelog: 'One update per line for the public changelog.',
|
site_changelog: 'One update per line for the public changelog.',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,36 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { getApiBase, setToken, clearToken } from '../lib/auth'
|
import { getApiBase, setToken, clearToken } from '../lib/auth'
|
||||||
import BrandingLogo from '../ui/BrandingLogo'
|
import BrandingLogo from '../ui/BrandingLogo'
|
||||||
|
|
||||||
|
const DEFAULT_LOGIN_OPTIONS = {
|
||||||
|
showJellyfinLogin: true,
|
||||||
|
showLocalLogin: true,
|
||||||
|
showForgotPassword: true,
|
||||||
|
showSignupLink: true,
|
||||||
|
}
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [username, setUsername] = useState('')
|
const [username, setUsername] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [loginOptions, setLoginOptions] = useState(DEFAULT_LOGIN_OPTIONS)
|
||||||
|
const primaryMode: 'jellyfin' | 'local' | null = loginOptions.showJellyfinLogin
|
||||||
|
? 'jellyfin'
|
||||||
|
: loginOptions.showLocalLogin
|
||||||
|
? 'local'
|
||||||
|
: null
|
||||||
|
|
||||||
const submit = async (event: React.FormEvent, mode: 'local' | 'jellyfin') => {
|
const submit = async (event: React.FormEvent, mode: 'local' | 'jellyfin') => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
if (!primaryMode) {
|
||||||
|
setError('Login is currently disabled. Contact an administrator.')
|
||||||
|
return
|
||||||
|
}
|
||||||
setError(null)
|
setError(null)
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
@@ -48,12 +65,63 @@ export default function LoginPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let active = true
|
||||||
|
const loadLoginOptions = async () => {
|
||||||
|
try {
|
||||||
|
const baseUrl = getApiBase()
|
||||||
|
const response = await fetch(`${baseUrl}/site/public`)
|
||||||
|
if (!response.ok) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const data = await response.json()
|
||||||
|
const login = data?.login ?? {}
|
||||||
|
if (!active) return
|
||||||
|
setLoginOptions({
|
||||||
|
showJellyfinLogin: login.showJellyfinLogin !== false,
|
||||||
|
showLocalLogin: login.showLocalLogin !== false,
|
||||||
|
showForgotPassword: login.showForgotPassword !== false,
|
||||||
|
showSignupLink: login.showSignupLink !== false,
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void loadLoginOptions()
|
||||||
|
return () => {
|
||||||
|
active = false
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const loginHelpText = (() => {
|
||||||
|
if (loginOptions.showJellyfinLogin && loginOptions.showLocalLogin) {
|
||||||
|
return 'Use your Jellyfin account, or sign in with a local Magent admin account.'
|
||||||
|
}
|
||||||
|
if (loginOptions.showJellyfinLogin) {
|
||||||
|
return 'Use your Jellyfin account to sign in.'
|
||||||
|
}
|
||||||
|
if (loginOptions.showLocalLogin) {
|
||||||
|
return 'Use your local Magent admin account to sign in.'
|
||||||
|
}
|
||||||
|
return 'No sign-in methods are currently available. Contact an administrator.'
|
||||||
|
})()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="card auth-card">
|
<main className="card auth-card">
|
||||||
<BrandingLogo className="brand-logo brand-logo--login" />
|
<BrandingLogo className="brand-logo brand-logo--login" />
|
||||||
<h1>Sign in</h1>
|
<h1>Sign in</h1>
|
||||||
<p className="lede">Use your Jellyfin account, or sign in with a local Magent admin account.</p>
|
<p className="lede">{loginHelpText}</p>
|
||||||
<form onSubmit={(event) => submit(event, 'jellyfin')} className="auth-form">
|
<form
|
||||||
|
onSubmit={(event) => {
|
||||||
|
if (!primaryMode) {
|
||||||
|
event.preventDefault()
|
||||||
|
setError('Login is currently disabled. Contact an administrator.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
void submit(event, primaryMode)
|
||||||
|
}}
|
||||||
|
className="auth-form"
|
||||||
|
>
|
||||||
<label>
|
<label>
|
||||||
Username
|
Username
|
||||||
<input
|
<input
|
||||||
@@ -73,10 +141,13 @@ export default function LoginPage() {
|
|||||||
</label>
|
</label>
|
||||||
{error && <div className="error-banner">{error}</div>}
|
{error && <div className="error-banner">{error}</div>}
|
||||||
<div className="auth-actions">
|
<div className="auth-actions">
|
||||||
|
{loginOptions.showJellyfinLogin ? (
|
||||||
<button type="submit" disabled={loading}>
|
<button type="submit" disabled={loading}>
|
||||||
{loading ? 'Signing in...' : 'Login with Jellyfin account'}
|
{loading ? 'Signing in...' : 'Login with Jellyfin account'}
|
||||||
</button>
|
</button>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
{loginOptions.showLocalLogin ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="ghost-button"
|
className="ghost-button"
|
||||||
@@ -85,12 +156,20 @@ export default function LoginPage() {
|
|||||||
>
|
>
|
||||||
Sign in with Magent account
|
Sign in with Magent account
|
||||||
</button>
|
</button>
|
||||||
|
) : null}
|
||||||
|
{loginOptions.showForgotPassword ? (
|
||||||
<a className="ghost-button" href="/forgot-password">
|
<a className="ghost-button" href="/forgot-password">
|
||||||
Forgot password?
|
Forgot password?
|
||||||
</a>
|
</a>
|
||||||
|
) : null}
|
||||||
|
{loginOptions.showSignupLink ? (
|
||||||
<a className="ghost-button" href="/signup">
|
<a className="ghost-button" href="/signup">
|
||||||
Have an invite? Create your account (Jellyfin + Magent)
|
Have an invite? Create your account (Jellyfin + Magent)
|
||||||
</a>
|
</a>
|
||||||
|
) : null}
|
||||||
|
{!loginOptions.showJellyfinLogin && !loginOptions.showLocalLogin ? (
|
||||||
|
<div className="error-banner">Login is currently disabled. Contact an administrator.</div>
|
||||||
|
) : null}
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
)
|
)
|
||||||
|
|||||||
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "magent-frontend",
|
"name": "magent-frontend",
|
||||||
"version": "0303261323",
|
"version": "0303261413",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "magent-frontend",
|
"name": "magent-frontend",
|
||||||
"version": "0303261323",
|
"version": "0303261413",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"react": "19.2.4",
|
"react": "19.2.4",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "magent-frontend",
|
"name": "magent-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0303261323",
|
"version": "0303261413",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
|
|||||||
Reference in New Issue
Block a user