Compare commits

..

8 Commits

Author SHA1 Message Date
semantic-release-bot
4560c0f843 chore(release): 2.5.0 2025-03-11 02:42:37 +00:00
fallenbagel
2cd843535d chore: prepare for v2.4.1 2025-03-11 10:40:50 +08:00
Ludovic Ortega
077e355c77 feat(helm): upgrade jellyseerr to 2.4.0 (#1438)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-03-11 09:33:58 +08:00
fallenbagel
21ab20bba9 revert: reverts csrf-csrf back to csurf (#1442)
* revert: reverts csrf-csrf back to csurf

This reverts csrf-csrf change brought on by `9e3119` in #1393 back to `csurf` that is maintained

* fix: type declarations for csurf
2025-03-11 09:33:40 +08:00
Mihkel
cdfb30ea16 docs: update steps for service installation with NSSM (#1446) 2025-03-11 07:48:43 +08:00
Gauthier
771ecdf781 fix(ui): correct media action icon size (#1444)
This PR fixes an UI issue with inconsistent size for media action icons.

fix #1440
2025-03-11 00:08:49 +01:00
fallenbagel
863b675c77 ci(cypress): always run the upload video files step (#1445) 2025-03-11 07:06:56 +08:00
Gauthier
5b998bef82 fix(users): correct user list for Postgres (#1443)
PostgreSQL requires that the ORDER BY expression must appear in the SELECT list when using DISTINCT.
Since we were using a computed expression in the ORDER BY clause, we need to include it in the
SELECT list as well.

re #1333
2025-03-10 23:59:42 +01:00
13 changed files with 108 additions and 66 deletions

View File

@@ -37,6 +37,7 @@ jobs:
COMMIT_INFO_MESSAGE: ${{github.event.pull_request.title}}
COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha}}
- name: Upload video files
if: always()
uses: actions/upload-artifact@v4
with:
name: cypress-videos

View File

@@ -1,3 +1,21 @@
# [2.5.0](https://github.com/fallenbagel/jellyseerr/compare/v2.4.0...v2.5.0) (2025-03-11)
### Bug Fixes
* **ui:** correct media action icon size ([#1444](https://github.com/fallenbagel/jellyseerr/issues/1444)) ([771ecdf](https://github.com/fallenbagel/jellyseerr/commit/771ecdf7812004eec0f516cc424f9982936c8a2a)), closes [#1440](https://github.com/fallenbagel/jellyseerr/issues/1440)
* **users:** correct user list for Postgres ([#1443](https://github.com/fallenbagel/jellyseerr/issues/1443)) ([5b998be](https://github.com/fallenbagel/jellyseerr/commit/5b998bef82388dccaaa462ff2ff3a526dd03338c)), closes [#1333](https://github.com/fallenbagel/jellyseerr/issues/1333)
### Features
* **helm:** upgrade jellyseerr to 2.4.0 ([#1438](https://github.com/fallenbagel/jellyseerr/issues/1438)) ([077e355](https://github.com/fallenbagel/jellyseerr/commit/077e355c775af92ff4dd2341543555d473c1abbb))
### Reverts
* reverts csrf-csrf back to csurf ([#1442](https://github.com/fallenbagel/jellyseerr/issues/1442)) ([21ab20b](https://github.com/fallenbagel/jellyseerr/commit/21ab20bba97102fe9eb9d4af4213a604c05e0acc)), closes [#1393](https://github.com/fallenbagel/jellyseerr/issues/1393)
# [2.4.0](https://github.com/fallenbagel/jellyseerr/compare/v2.3.0...v2.4.0) (2025-03-10)

View File

@@ -3,8 +3,8 @@ kubeVersion: ">=1.23.0-0"
name: jellyseerr-chart
description: Jellyseerr helm chart for Kubernetes
type: application
version: 2.1.1
appVersion: "2.3.0"
version: 2.2.0
appVersion: "2.4.0"
maintainers:
- name: Jellyseerr
url: https://github.com/Fallenbagel/jellyseerr

View File

@@ -1,6 +1,6 @@
# jellyseerr-chart
![Version: 2.1.1](https://img.shields.io/badge/Version-2.1.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.3.0](https://img.shields.io/badge/AppVersion-2.3.0-informational?style=flat-square)
![Version: 2.2.0](https://img.shields.io/badge/Version-2.2.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.4.0](https://img.shields.io/badge/AppVersion-2.4.0-informational?style=flat-square)
Jellyseerr helm chart for Kubernetes

View File

@@ -255,7 +255,8 @@ To run jellyseerr as a service:
1. Download the [Non-Sucking Service Manager](https://nssm.cc/download)
2. Install NSSM:
```powershell
nssm install Jellyseerr "C:\Program Files\nodejs\node.exe" ["C:\jellyseerr\dist\index.js"]
nssm install Jellyseerr "C:\Program Files\nodejs\node.exe" "C:\jellyseerr\dist\index.js"
nssm set Jellyseerr AppDirectory "C:\jellyseerr"
nssm set Jellyseerr AppEnvironmentExtra NODE_ENV=production
```
3. Start the service:

View File

@@ -1,6 +1,6 @@
{
"name": "jellyseerr",
"version": "2.4.0",
"version": "2.5.0",
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
@@ -32,6 +32,7 @@
},
"license": "MIT",
"dependencies": {
"@dr.pogodin/csurf": "^1.14.1",
"@formatjs/intl-displaynames": "6.2.6",
"@formatjs/intl-locale": "3.1.1",
"@formatjs/intl-pluralrules": "5.1.10",
@@ -51,7 +52,6 @@
"copy-to-clipboard": "3.3.3",
"country-flag-icons": "1.5.5",
"cronstrue": "2.23.0",
"csrf-csrf": "^3.1.0",
"date-fns": "2.29.3",
"dayjs": "1.11.7",
"email-templates": "12.0.1",

49
pnpm-lock.yaml generated
View File

@@ -8,6 +8,9 @@ importers:
.:
dependencies:
'@dr.pogodin/csurf':
specifier: ^1.14.1
version: 1.14.1
'@formatjs/intl-displaynames':
specifier: 6.2.6
version: 6.2.6
@@ -65,9 +68,6 @@ importers:
cronstrue:
specifier: 2.23.0
version: 2.23.0
csrf-csrf:
specifier: ^3.1.0
version: 3.1.0
date-fns:
specifier: 2.29.3
version: 2.29.3
@@ -1549,6 +1549,10 @@ packages:
'@dabh/diagnostics@2.0.3':
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
'@dr.pogodin/csurf@1.14.1':
resolution: {integrity: sha512-ijqJsKSDlepDYbprkEEcqbiYero2y4DeL4X5ivnkbKonliLtH8SfHCEtdUwoRZLPTUy2WeFPHI+gveU+Z8ZxLA==}
engines: {node: '>= 18'}
'@emnapi/runtime@1.2.0':
resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==}
@@ -4405,6 +4409,10 @@ packages:
cookie-signature@1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
cookie-signature@1.2.2:
resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
engines: {node: '>=6.6.0'}
cookie@0.4.2:
resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==}
engines: {node: '>= 0.6'}
@@ -4417,6 +4425,10 @@ packages:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'}
cookie@1.0.2:
resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==}
engines: {node: '>=18'}
copy-to-clipboard@3.3.3:
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
@@ -4509,9 +4521,6 @@ packages:
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
engines: {node: '>=8'}
csrf-csrf@3.1.0:
resolution: {integrity: sha512-kZacFfFbdYFxNnFdigRHCzVAq019vJyUUtgPLjCtzh6jMXcWmf8bGUx/hsqtSEMXaNcPm8iXpjC+hW5aeOsRMg==}
css-select@4.3.0:
resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
@@ -8317,6 +8326,9 @@ packages:
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
rndm@1.2.0:
resolution: {integrity: sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==}
run-applescript@3.2.0:
resolution: {integrity: sha512-Ep0RsvAjnRcBX1p5vogbaBdAGu/8j/ewpvGqnQYunnLd9SM0vWcPJewPKNnWFggf0hF0pwIgwV5XK7qQ7UZ8Qg==}
engines: {node: '>=4'}
@@ -9064,6 +9076,10 @@ packages:
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
tsscmp@1.0.6:
resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==}
engines: {node: '>=0.6.x'}
tsutils@3.21.0:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'}
@@ -11290,6 +11306,15 @@ snapshots:
enabled: 2.0.0
kuler: 2.0.0
'@dr.pogodin/csurf@1.14.1':
dependencies:
cookie: 1.0.2
cookie-signature: 1.2.2
http-errors: 2.0.0
rndm: 1.2.0
tsscmp: 1.0.6
uid-safe: 2.1.5
'@emnapi/runtime@1.2.0':
dependencies:
tslib: 2.6.3
@@ -14928,12 +14953,16 @@ snapshots:
cookie-signature@1.0.6: {}
cookie-signature@1.2.2: {}
cookie@0.4.2: {}
cookie@0.7.1: {}
cookie@0.7.2: {}
cookie@1.0.2: {}
copy-to-clipboard@3.3.3:
dependencies:
toggle-selection: 1.0.6
@@ -15044,10 +15073,6 @@ snapshots:
crypto-random-string@2.0.0: {}
csrf-csrf@3.1.0:
dependencies:
http-errors: 2.0.0
css-select@4.3.0:
dependencies:
boolbase: 1.0.0
@@ -19665,6 +19690,8 @@ snapshots:
dependencies:
glob: 7.2.3
rndm@1.2.0: {}
run-applescript@3.2.0:
dependencies:
execa: 0.10.0
@@ -20534,6 +20561,8 @@ snapshots:
tslib@2.8.1: {}
tsscmp@1.0.6: {}
tsutils@3.21.0(typescript@4.9.5):
dependencies:
tslib: 1.14.1

View File

@@ -1,3 +1,4 @@
import csurf from '@dr.pogodin/csurf';
import PlexAPI from '@server/api/plexapi';
import dataSource, { getRepository, isPgsql } from '@server/datasource';
import DiscoverSlider from '@server/entity/DiscoverSlider';
@@ -28,7 +29,6 @@ import restartFlag from '@server/utils/restartFlag';
import { getClientIp } from '@supercharge/request-ip';
import { TypeormStore } from 'connect-typeorm/out';
import cookieParser from 'cookie-parser';
import { doubleCsrf } from 'csrf-csrf';
import type { NextFunction, Request, Response } from 'express';
import express from 'express';
import * as OpenApiValidator from 'express-openapi-validator';
@@ -162,23 +162,18 @@ app
}
});
if (settings.network.csrfProtection) {
const { doubleCsrfProtection, generateToken } = doubleCsrf({
getSecret: () => settings.clientId,
cookieName: 'XSRF-TOKEN',
cookieOptions: {
httpOnly: true,
sameSite: 'strict',
secure: !dev,
},
size: 64,
ignoredMethods: ['GET', 'HEAD', 'OPTIONS'],
});
server.use(doubleCsrfProtection);
server.use(
csurf({
cookie: {
httpOnly: true,
sameSite: true,
secure: !dev,
},
})
);
server.use((req, res, next) => {
res.cookie('XSRF-TOKEN', generateToken(req, res), {
sameSite: 'strict',
res.cookie('XSRF-TOKEN', req.csrfToken(), {
sameSite: true,
secure: !dev,
});
next();

View File

@@ -60,22 +60,24 @@ router.get('/', async (req, res, next) => {
query = query.orderBy('user.updatedAt', 'DESC');
break;
case 'displayname':
query = query.orderBy(
`CASE WHEN (user.username IS NULL OR user.username = '') THEN (
CASE WHEN (user.plexUsername IS NULL OR user.plexUsername = '') THEN (
CASE WHEN (user.jellyfinUsername IS NULL OR user.jellyfinUsername = '') THEN
"user"."email"
ELSE
LOWER(user.jellyfinUsername)
END)
ELSE
LOWER(user.jellyfinUsername)
END)
ELSE
LOWER(user.username)
END`,
'ASC'
);
query = query
.addSelect(
`CASE WHEN (user.username IS NULL OR user.username = '') THEN (
CASE WHEN (user.plexUsername IS NULL OR user.plexUsername = '') THEN (
CASE WHEN (user.jellyfinUsername IS NULL OR user.jellyfinUsername = '') THEN
"user"."email"
ELSE
LOWER(user.jellyfinUsername)
END)
ELSE
LOWER(user.jellyfinUsername)
END)
ELSE
LOWER(user.username)
END`,
'displayname_sort_key'
)
.orderBy('displayname_sort_key', 'ASC');
break;
case 'requests':
query = query

4
server/types/custom.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
declare module '@dr.pogodin/csurf' {
import csrf = require('csurf');
export = csrf;
}

View File

@@ -590,7 +590,7 @@ const MovieDetails = ({ movie }: MovieDetailsProps) => {
buttonSize={'md'}
onClick={() => setShowBlacklistModal(true)}
>
<EyeSlashIcon className={'h-3'} />
<EyeSlashIcon />
</Button>
</Tooltip>
)}
@@ -608,9 +608,9 @@ const MovieDetails = ({ movie }: MovieDetailsProps) => {
onClick={onClickWatchlistBtn}
>
{isUpdating ? (
<Spinner className="h-3" />
<Spinner />
) : (
<StarIcon className={'h-3 text-amber-300'} />
<StarIcon className={'text-amber-300'} />
)}
</Button>
</Tooltip>
@@ -623,11 +623,7 @@ const MovieDetails = ({ movie }: MovieDetailsProps) => {
buttonSize={'md'}
onClick={onClickDeleteWatchlistBtn}
>
{isUpdating ? (
<Spinner className="h-3" />
) : (
<MinusCircleIcon className={'h-3'} />
)}
{isUpdating ? <Spinner /> : <MinusCircleIcon />}
</Button>
</Tooltip>
)}

View File

@@ -632,7 +632,7 @@ const TvDetails = ({ tv }: TvDetailsProps) => {
buttonSize={'md'}
onClick={() => setShowBlacklistModal(true)}
>
<EyeSlashIcon className={'h-3'} />
<EyeSlashIcon />
</Button>
</Tooltip>
)}
@@ -650,9 +650,9 @@ const TvDetails = ({ tv }: TvDetailsProps) => {
onClick={onClickWatchlistBtn}
>
{isUpdating ? (
<Spinner className="h-3" />
<Spinner />
) : (
<StarIcon className={'h-3 text-amber-300'} />
<StarIcon className={'text-amber-300'} />
)}
</Button>
</Tooltip>
@@ -665,11 +665,7 @@ const TvDetails = ({ tv }: TvDetailsProps) => {
buttonSize={'md'}
onClick={onClickDeleteWatchlistBtn}
>
{isUpdating ? (
<Spinner className="h-3" />
) : (
<MinusCircleIcon className={'h-3'} />
)}
{isUpdating ? <Spinner /> : <MinusCircleIcon />}
</Button>
</Tooltip>
)}

View File

@@ -31,7 +31,7 @@ if (typeof window !== 'undefined') {
const headers = {
...(init?.headers || {}),
...(csrfToken ? { 'X-CSRF-TOKEN': csrfToken } : {}),
...(csrfToken ? { 'XSRF-TOKEN': csrfToken } : {}),
};
const newInit: RequestInit = {