Skip to content

Commit

Permalink
refactor: checks if the default avatar is cached to avoid creating du…
Browse files Browse the repository at this point in the history
…plicates for different users
  • Loading branch information
JoaquinOlivero committed Aug 26, 2024
1 parent c9ff802 commit b46d247
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 152 deletions.
33 changes: 32 additions & 1 deletion server/routes/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,14 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
}),
userType: UserType.EMBY,
});

if (
user.avatar.includes('https://gravatar.com') &&

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
https://gravatar.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
user.avatar.includes('default=mm&size=200')
) {
user.avatar = 'https://gravatar.com/avatar/?default=mm&size=200';
}

break;
case MediaServerType.JELLYFIN:
settings.main.mediaServerType = MediaServerType.JELLYFIN;
Expand All @@ -361,6 +369,14 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
}),
userType: UserType.JELLYFIN,
});

if (
user.avatar.includes('https://gravatar.com') &&

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
https://gravatar.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
user.avatar.includes('default=mm&size=200')
) {
user.avatar = 'https://gravatar.com/avatar/?default=mm&size=200';
}

break;
default:
throw new Error('select_server_type');
Expand Down Expand Up @@ -415,15 +431,23 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
}
user.avatar = avatar;
} else {
const avatar = gravatarUrl(user.email || account.User.Name, {
let avatar = gravatarUrl(user.email || account.User.Name, {
default: 'mm',
size: 200,
});

if (
avatar.includes('https://gravatar.com') &&

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
https://gravatar.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
avatar.includes('default=mm&size=200')
) {
avatar = 'https://gravatar.com/avatar/?default=mm&size=200';
}

if (avatar !== user.avatar) {
const avatarProxy = new ImageProxy('avatar', '');
avatarProxy.clearCachedImage(user.avatar);
}

user.avatar = avatar;
}
user.jellyfinUsername = account.User.Name;
Expand Down Expand Up @@ -474,6 +498,13 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
? UserType.JELLYFIN
: UserType.EMBY,
});

if (
user.avatar.includes('https://gravatar.com') &&

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
https://gravatar.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
user.avatar.includes('default=mm&size=200')
) {
user.avatar = 'https://gravatar.com/avatar/?default=mm&size=200';
}
//initialize Jellyfin/Emby users with local login
const passedExplicitPassword = body.password && body.password.length > 0;
if (passedExplicitPassword) {
Expand Down
10 changes: 9 additions & 1 deletion server/routes/avatarproxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ const router = Router();
const avatarImageProxy = new ImageProxy('avatar', '');
// Proxy avatar images
router.get('/*', async (req, res) => {
const imagePath = req.url.startsWith('/') ? req.url.slice(1) : req.url;
let imagePath = req.url.startsWith('/') ? req.url.slice(1) : req.url;

try {
if (
imagePath.includes('https://gravatar.com') &&

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
https://gravatar.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
imagePath.includes('default=mm&size=200')
) {
imagePath = 'https://gravatar.com/avatar/?default=mm&size=200';
}

const imageData = await avatarImageProxy.getImage(imagePath);

res.writeHead(200, {
Expand Down
16 changes: 15 additions & 1 deletion server/routes/user/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,14 @@ router.post(
}

const passedExplicitPassword = body.password && body.password.length > 0;
const avatar = gravatarUrl(email, { default: 'mm', size: 200 });
let avatar = gravatarUrl(email, { default: 'mm', size: 200 });

if (
avatar.includes('https://gravatar.com') &&

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
https://gravatar.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
avatar.includes('default=mm&size=200')
) {
avatar = 'https://gravatar.com/avatar/?default=mm&size=200';
}

if (
!passedExplicitPassword &&
Expand Down Expand Up @@ -553,6 +560,13 @@ router.post(
userType: UserType.JELLYFIN,
});

if (
newUser.avatar.includes('https://gravatar.com') &&

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
https://gravatar.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
newUser.avatar.includes('default=mm&size=200')
) {
newUser.avatar = 'https://gravatar.com/avatar/?default=mm&size=200';
}

await userRepository.save(newUser);
createdUsers.push(newUser);
}
Expand Down
140 changes: 70 additions & 70 deletions src/components/IssueDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import type Issue from '@server/entity/Issue';
import type { MovieDetails } from '@server/models/Movie';
import type { TvDetails } from '@server/models/Tv';
import { Field, Form, Formik } from 'formik';
import Image from 'next/image';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useState } from 'react';
Expand Down Expand Up @@ -264,8 +263,9 @@ const IssueDetails = () => {
</div>
<h1>
<Link
href={`/${issueData.media.mediaType === MediaType.MOVIE ? 'movie' : 'tv'
}/${data.id}`}
href={`/${
issueData.media.mediaType === MediaType.MOVIE ? 'movie' : 'tv'
}/${data.id}`}
className="hover:underline"
>
{title}
Expand Down Expand Up @@ -302,7 +302,7 @@ const IssueDetails = () => {
<FormattedRelativeTime
value={Math.floor(
(new Date(issueData.createdAt).getTime() - Date.now()) /
1000
1000
)}
updateIntervalInSeconds={1}
numeric="auto"
Expand Down Expand Up @@ -367,7 +367,7 @@ const IssueDetails = () => {
<FormattedRelativeTime
value={Math.floor(
(new Date(issueData.updatedAt).getTime() - Date.now()) /
1000
1000
)}
updateIntervalInSeconds={1}
numeric="auto"
Expand All @@ -388,16 +388,16 @@ const IssueDetails = () => {
<PlayIcon />
<span>
{settings.currentSettings.mediaServerType ===
MediaServerType.EMBY
MediaServerType.EMBY
? intl.formatMessage(messages.playonplex, {
mediaServerName: 'Emby',
})
mediaServerName: 'Emby',
})
: settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? intl.formatMessage(messages.playonplex, {
? intl.formatMessage(messages.playonplex, {
mediaServerName: 'Plex',
})
: intl.formatMessage(messages.playonplex, {
: intl.formatMessage(messages.playonplex, {
mediaServerName: 'Jellyfin',
})}
</span>
Expand Down Expand Up @@ -436,16 +436,16 @@ const IssueDetails = () => {
<PlayIcon />
<span>
{settings.currentSettings.mediaServerType ===
MediaServerType.EMBY
MediaServerType.EMBY
? intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Emby',
})
mediaServerName: 'Emby',
})
: settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? intl.formatMessage(messages.play4konplex, {
? intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Plex',
})
: intl.formatMessage(messages.play4konplex, {
: intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Jellyfin',
})}
</span>
Expand Down Expand Up @@ -530,52 +530,52 @@ const IssueDetails = () => {
<div className="mt-4 flex items-center justify-end space-x-2">
{(hasPermission(Permission.MANAGE_ISSUES) ||
belongsToUser) && (
<>
{issueData.status === IssueStatus.OPEN ? (
<Button
type="button"
buttonType="danger"
onClick={async () => {
await updateIssueStatus('resolved');
<>
{issueData.status === IssueStatus.OPEN ? (
<Button
type="button"
buttonType="danger"
onClick={async () => {
await updateIssueStatus('resolved');

if (values.message) {
handleSubmit();
}
}}
>
<CheckCircleIcon />
<span>
{intl.formatMessage(
values.message
? messages.closeissueandcomment
: messages.closeissue
)}
</span>
</Button>
) : (
<Button
type="button"
buttonType="default"
onClick={async () => {
await updateIssueStatus('open');
if (values.message) {
handleSubmit();
}
}}
>
<CheckCircleIcon />
<span>
{intl.formatMessage(
values.message
? messages.closeissueandcomment
: messages.closeissue
)}
</span>
</Button>
) : (
<Button
type="button"
buttonType="default"
onClick={async () => {
await updateIssueStatus('open');

if (values.message) {
handleSubmit();
}
}}
>
<ArrowPathIcon />
<span>
{intl.formatMessage(
values.message
? messages.reopenissueandcomment
: messages.reopenissue
)}
</span>
</Button>
)}
</>
)}
if (values.message) {
handleSubmit();
}
}}
>
<ArrowPathIcon />
<span>
{intl.formatMessage(
values.message
? messages.reopenissueandcomment
: messages.reopenissue
)}
</span>
</Button>
)}
</>
)}
<Button
type="submit"
buttonType="primary"
Expand Down Expand Up @@ -641,7 +641,7 @@ const IssueDetails = () => {
<FormattedRelativeTime
value={Math.floor(
(new Date(issueData.updatedAt).getTime() - Date.now()) /
1000
1000
)}
updateIntervalInSeconds={1}
numeric="auto"
Expand All @@ -662,16 +662,16 @@ const IssueDetails = () => {
<PlayIcon />
<span>
{settings.currentSettings.mediaServerType ===
MediaServerType.EMBY
MediaServerType.EMBY
? intl.formatMessage(messages.playonplex, {
mediaServerName: 'Emby',
})
mediaServerName: 'Emby',
})
: settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? intl.formatMessage(messages.playonplex, {
? intl.formatMessage(messages.playonplex, {
mediaServerName: 'Plex',
})
: intl.formatMessage(messages.playonplex, {
: intl.formatMessage(messages.playonplex, {
mediaServerName: 'Jellyfin',
})}
</span>
Expand Down Expand Up @@ -709,16 +709,16 @@ const IssueDetails = () => {
<PlayIcon />
<span>
{settings.currentSettings.mediaServerType ===
MediaServerType.EMBY
MediaServerType.EMBY
? intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Emby',
})
mediaServerName: 'Emby',
})
: settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? intl.formatMessage(messages.play4konplex, {
? intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Plex',
})
: intl.formatMessage(messages.play4konplex, {
: intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Jellyfin',
})}
</span>
Expand Down
Loading

0 comments on commit b46d247

Please sign in to comment.