fix(server): improve error handling and API spec
This commit is contained in:
@@ -4427,6 +4427,8 @@ paths:
|
||||
responses:
|
||||
'204':
|
||||
description: Unlinking account succeeded
|
||||
'400':
|
||||
description: Unlink request invalid
|
||||
'404':
|
||||
description: User does not exist
|
||||
/user/{userId}/settings/linked-accounts/jellyfin:
|
||||
@@ -4475,6 +4477,8 @@ paths:
|
||||
responses:
|
||||
'204':
|
||||
description: Unlinking account succeeded
|
||||
'400':
|
||||
description: Unlink request invalid
|
||||
'404':
|
||||
description: User does not exist
|
||||
/user/{userId}/settings/notifications:
|
||||
|
||||
@@ -7,5 +7,6 @@ export enum ApiErrorCode {
|
||||
NoAdminUser = 'NO_ADMIN_USER',
|
||||
SyncErrorGroupedFolders = 'SYNC_ERROR_GROUPED_FOLDERS',
|
||||
SyncErrorNoLibraries = 'SYNC_ERROR_NO_LIBRARIES',
|
||||
Unauthorized = 'UNAUTHORIZED',
|
||||
Unknown = 'UNKNOWN',
|
||||
}
|
||||
|
||||
@@ -200,9 +200,8 @@ userSettingsRoutes.post<
|
||||
status: e.statusCode,
|
||||
message: e.errorCode,
|
||||
});
|
||||
} else {
|
||||
return next({ status: 500, message: e.message });
|
||||
}
|
||||
return next({ status: 500, message: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -310,16 +309,16 @@ userSettingsRoutes.post<
|
||||
userSettingsRoutes.post<{ authToken: string }>(
|
||||
'/linked-accounts/plex',
|
||||
isOwnProfile(),
|
||||
async (req, res, next) => {
|
||||
async (req, res) => {
|
||||
const settings = getSettings();
|
||||
const userRepository = getRepository(User);
|
||||
|
||||
if (!req.user) {
|
||||
return next({ status: 404, message: 'Unauthorized' });
|
||||
return res.status(404).json({ code: ApiErrorCode.Unauthorized });
|
||||
}
|
||||
// Make sure Plex login is enabled
|
||||
if (settings.main.mediaServerType !== MediaServerType.PLEX) {
|
||||
return res.status(500).json({ error: 'Plex login is disabled' });
|
||||
return res.status(500).json({ message: 'Plex login is disabled' });
|
||||
}
|
||||
|
||||
// First we need to use this auth token to get the user's email from plex.tv
|
||||
@@ -329,7 +328,7 @@ userSettingsRoutes.post<{ authToken: string }>(
|
||||
// Do not allow linking of an already linked account
|
||||
if (await userRepository.exist({ where: { plexId: account.id } })) {
|
||||
return res.status(422).json({
|
||||
error: 'This Plex account is already linked to a Jellyseerr user',
|
||||
message: 'This Plex account is already linked to a Jellyseerr user',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -338,7 +337,7 @@ userSettingsRoutes.post<{ authToken: string }>(
|
||||
// Emails do not match
|
||||
if (user.email !== account.email) {
|
||||
return res.status(422).json({
|
||||
error:
|
||||
message:
|
||||
'This Plex account is registered under a different email address.',
|
||||
});
|
||||
}
|
||||
@@ -357,13 +356,13 @@ userSettingsRoutes.post<{ authToken: string }>(
|
||||
userSettingsRoutes.delete<{ id: string }>(
|
||||
'/linked-accounts/plex',
|
||||
isOwnProfileOrAdmin(),
|
||||
async (req, res, next) => {
|
||||
async (req, res) => {
|
||||
const settings = getSettings();
|
||||
const userRepository = getRepository(User);
|
||||
|
||||
// Make sure Plex login is enabled
|
||||
if (settings.main.mediaServerType !== MediaServerType.PLEX) {
|
||||
return res.status(500).json({ error: 'Plex login is disabled' });
|
||||
return res.status(500).json({ message: 'Plex login is disabled' });
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -372,12 +371,11 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return next({ status: 404, message: 'User not found.' });
|
||||
return res.status(404).json({ message: 'User not found.' });
|
||||
}
|
||||
|
||||
if (user.id === 1) {
|
||||
return next({
|
||||
status: 400,
|
||||
return res.status(400).json({
|
||||
message:
|
||||
'Cannot unlink media server accounts for the primary administrator.',
|
||||
});
|
||||
@@ -391,8 +389,7 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
)?.password;
|
||||
|
||||
if (!user.email || !hasPassword) {
|
||||
return next({
|
||||
status: 400,
|
||||
return res.status(400).json({
|
||||
message: 'User does not have a local email or password set.',
|
||||
});
|
||||
}
|
||||
@@ -405,7 +402,7 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
|
||||
return res.status(204).send();
|
||||
} catch (e) {
|
||||
next({ status: 500, message: e.message });
|
||||
return res.status(500).json({ message: e.message });
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -413,19 +410,21 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
userSettingsRoutes.post<{ username: string; password: string }>(
|
||||
'/linked-accounts/jellyfin',
|
||||
isOwnProfile(),
|
||||
async (req, res, next) => {
|
||||
async (req, res) => {
|
||||
const settings = getSettings();
|
||||
const userRepository = getRepository(User);
|
||||
|
||||
if (!req.user) {
|
||||
return next({ status: 401, message: 'Unauthorized' });
|
||||
return res.status(401).json({ code: ApiErrorCode.Unauthorized });
|
||||
}
|
||||
// Make sure jellyfin login is enabled
|
||||
if (
|
||||
settings.main.mediaServerType !== MediaServerType.JELLYFIN &&
|
||||
settings.main.mediaServerType !== MediaServerType.EMBY
|
||||
) {
|
||||
return res.status(500).json({ error: 'Jellyfin/Emby login is disabled' });
|
||||
return res
|
||||
.status(500)
|
||||
.json({ message: 'Jellyfin/Emby login is disabled' });
|
||||
}
|
||||
|
||||
// Do not allow linking of an already linked account
|
||||
@@ -435,7 +434,7 @@ userSettingsRoutes.post<{ username: string; password: string }>(
|
||||
})
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: 'The specified account is already linked to a Jellyseerr user',
|
||||
message: 'The specified account is already linked to a Jellyseerr user',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -447,7 +446,7 @@ userSettingsRoutes.post<{ username: string; password: string }>(
|
||||
const jellyfinserver = new JellyfinAPI(hostname, undefined, deviceId);
|
||||
|
||||
const ip = req.ip;
|
||||
let clientIp;
|
||||
let clientIp: string | undefined;
|
||||
if (ip) {
|
||||
if (net.isIPv4(ip)) {
|
||||
clientIp = ip;
|
||||
@@ -470,7 +469,8 @@ userSettingsRoutes.post<{ username: string; password: string }>(
|
||||
})
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: 'The specified account is already linked to a Jellyseerr user',
|
||||
message:
|
||||
'The specified account is already linked to a Jellyseerr user',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -496,12 +496,12 @@ userSettingsRoutes.post<{ username: string; password: string }>(
|
||||
});
|
||||
if (
|
||||
e instanceof ApiError &&
|
||||
(e.errorCode == ApiErrorCode.InvalidCredentials ||
|
||||
e.errorCode == ApiErrorCode.NotAdmin)
|
||||
)
|
||||
return next({ status: 401, message: 'Unauthorized' });
|
||||
e.errorCode === ApiErrorCode.InvalidCredentials
|
||||
) {
|
||||
return res.status(401).json({ code: e.errorCode });
|
||||
}
|
||||
|
||||
return next({ status: 500 });
|
||||
return res.status(500).send();
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -509,7 +509,7 @@ userSettingsRoutes.post<{ username: string; password: string }>(
|
||||
userSettingsRoutes.delete<{ id: string }>(
|
||||
'/linked-accounts/jellyfin',
|
||||
isOwnProfileOrAdmin(),
|
||||
async (req, res, next) => {
|
||||
async (req, res) => {
|
||||
const settings = getSettings();
|
||||
const userRepository = getRepository(User);
|
||||
|
||||
@@ -518,7 +518,9 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
settings.main.mediaServerType !== MediaServerType.JELLYFIN &&
|
||||
settings.main.mediaServerType !== MediaServerType.EMBY
|
||||
) {
|
||||
return res.status(500).json({ error: 'Jellyfin/Emby login is disabled' });
|
||||
return res
|
||||
.status(500)
|
||||
.json({ message: 'Jellyfin/Emby login is disabled' });
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -527,12 +529,11 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return next({ status: 404, message: 'User not found.' });
|
||||
return res.status(404).json({ message: 'User not found.' });
|
||||
}
|
||||
|
||||
if (user.id === 1) {
|
||||
return next({
|
||||
status: 400,
|
||||
return res.status(400).json({
|
||||
message:
|
||||
'Cannot unlink media server accounts for the primary administrator.',
|
||||
});
|
||||
@@ -546,8 +547,7 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
)?.password;
|
||||
|
||||
if (!user.email || !hasPassword) {
|
||||
return next({
|
||||
status: 400,
|
||||
return res.status(400).json({
|
||||
message: 'User does not have a local email or password set.',
|
||||
});
|
||||
}
|
||||
@@ -561,7 +561,7 @@ userSettingsRoutes.delete<{ id: string }>(
|
||||
|
||||
return res.status(204).send();
|
||||
} catch (e) {
|
||||
next({ status: 500, message: e.message });
|
||||
return res.status(500).json({ message: e.message });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user