From ac908026dbb7ca06c0fb520bbb360120d6b87feb Mon Sep 17 00:00:00 2001 From: Gauthier Date: Thu, 2 Jan 2025 16:03:45 +0100 Subject: [PATCH] fix(jellyfinlogin): add proper error message when no admin user exists (#1216) This PR adds an error message when the database has no admin user and Jellyseerr has already been set up (i.e. settings.json is filled in), instead of having a generic error message. --- server/constants/error.ts | 1 + server/routes/auth.ts | 18 ++++++++++++- src/components/Login/JellyfinLogin.tsx | 37 +++++++++++++++++++++----- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/server/constants/error.ts b/server/constants/error.ts index 96fafdc97..664f02c9c 100644 --- a/server/constants/error.ts +++ b/server/constants/error.ts @@ -4,6 +4,7 @@ export enum ApiErrorCode { InvalidAuthToken = 'INVALID_AUTH_TOKEN', InvalidEmail = 'INVALID_EMAIL', NotAdmin = 'NOT_ADMIN', + NoAdminUser = 'NO_ADMIN_USER', SyncErrorGroupedFolders = 'SYNC_ERROR_GROUPED_FOLDERS', SyncErrorNoLibraries = 'SYNC_ERROR_NO_LIBRARIES', Unknown = 'UNKNOWN', diff --git a/server/routes/auth.ts b/server/routes/auth.ts index 19e99a8ed..5fe0174ee 100644 --- a/server/routes/auth.ts +++ b/server/routes/auth.ts @@ -313,7 +313,7 @@ authRoutes.post('/jellyfin', async (req, res, next) => { body.serverType !== MediaServerType.JELLYFIN && body.serverType !== MediaServerType.EMBY ) { - throw new Error('select_server_type'); + throw new ApiError(500, ApiErrorCode.NoAdminUser); } settings.main.mediaServerType = body.serverType; @@ -533,6 +533,22 @@ authRoutes.post('/jellyfin', async (req, res, next) => { message: e.errorCode, }); + case ApiErrorCode.NoAdminUser: + logger.warn( + 'Failed login attempt from user without admin permissions and no admin user exists', + { + label: 'Auth', + account: { + ip: req.ip, + email: body.username, + }, + } + ); + return next({ + status: e.statusCode, + message: e.errorCode, + }); + default: logger.error(e.message, { label: 'Auth' }); return next({ diff --git a/src/components/Login/JellyfinLogin.tsx b/src/components/Login/JellyfinLogin.tsx index 057198e36..93b6a05a0 100644 --- a/src/components/Login/JellyfinLogin.tsx +++ b/src/components/Login/JellyfinLogin.tsx @@ -34,6 +34,7 @@ const messages = defineMessages('components.Login', { validationUrlBaseTrailingSlash: 'URL base must not end in a trailing slash', loginerror: 'Something went wrong while trying to sign in.', adminerror: 'You must use an admin account to sign in.', + noadminerror: 'No admin user found on the server.', credentialerror: 'The username or password is incorrect.', invalidurlerror: 'Unable to connect to {mediaServerName} server.', signingin: 'Signing in…', @@ -157,6 +158,9 @@ const JellyfinLogin: React.FC = ({ case ApiErrorCode.NotAdmin: errorMessage = messages.adminerror; break; + case ApiErrorCode.NoAdminUser: + errorMessage = messages.noadminerror; + break; default: errorMessage = messages.loginerror; break; @@ -388,14 +392,35 @@ const JellyfinLogin: React.FC = ({ email: values.username, }), }); - if (!res.ok) throw new Error(); + if (!res.ok) throw new Error(res.statusText, { cause: res }); } catch (e) { + let errorData; + try { + errorData = await e.cause?.text(); + errorData = JSON.parse(errorData); + } catch { + /* empty */ + } + let errorMessage = null; + switch (errorData?.message) { + case ApiErrorCode.InvalidUrl: + errorMessage = messages.invalidurlerror; + break; + case ApiErrorCode.InvalidCredentials: + errorMessage = messages.credentialerror; + break; + case ApiErrorCode.NotAdmin: + errorMessage = messages.adminerror; + break; + case ApiErrorCode.NoAdminUser: + errorMessage = messages.noadminerror; + break; + default: + errorMessage = messages.loginerror; + break; + } toasts.addToast( - intl.formatMessage( - e.message == 'Request failed with status code 401' - ? messages.credentialerror - : messages.loginerror - ), + intl.formatMessage(errorMessage, mediaServerFormatValues), { autoDismiss: true, appearance: 'error',