mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2025-12-24 10:49:30 -05:00
Compare commits
1 Commits
preview-wi
...
preview-fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dc00c8732 |
@@ -18,7 +18,7 @@ config/logs/*
|
||||
config/*.json
|
||||
dist
|
||||
Dockerfile*
|
||||
compose.yaml
|
||||
docker-compose.yml
|
||||
docs
|
||||
LICENSE
|
||||
node_modules
|
||||
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -40,7 +40,7 @@ docs export-ignore
|
||||
.all-contributorsrc export-ignore
|
||||
.editorconfig export-ignore
|
||||
Dockerfile.local export-ignore
|
||||
compose.yaml export-ignore
|
||||
docker-compose.yml export-ignore
|
||||
stylelint.config.js export-ignore
|
||||
|
||||
public/os_logo_filled.png export-ignore
|
||||
|
||||
@@ -52,7 +52,7 @@ All help is welcome and greatly appreciated! If you would like to contribute to
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
- Alternatively, you can use [Docker](https://www.docker.com/) with `docker compose up -d`. This method does not require installing NodeJS or Yarn on your machine directly.
|
||||
- Alternatively, you can use [Docker](https://www.docker.com/) with `docker-compose up -d`. This method does not require installing NodeJS or Yarn on your machine directly.
|
||||
|
||||
5. Create your patch and test your changes.
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
version: '3'
|
||||
services:
|
||||
jellyseerr:
|
||||
build:
|
||||
@@ -190,7 +190,7 @@ Caddy will automatically obtain and renew SSL certificates for your domain.
|
||||
|
||||
## Traefik (v2)
|
||||
|
||||
Add the following labels to the Jellyseerr service in your `compose.yaml` file:
|
||||
Add the following labels to the Jellyseerr service in your `docker-compose.yml` file:
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
|
||||
@@ -71,7 +71,7 @@ You could also use [diun](https://github.com/crazy-max/diun) to receive notifica
|
||||
For details on how to use Docker Compose, please [review the official Compose documentation](https://docs.docker.com/compose/reference/).
|
||||
|
||||
#### Installation:
|
||||
Define the `jellyseerr` service in your `compose.yaml` as follows:
|
||||
Define the `jellyseerr` service in your `docker-compose.yml` as follows:
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
@@ -94,17 +94,17 @@ If you are using emby, make sure to set the `JELLYFIN_TYPE` environment variable
|
||||
|
||||
Then, start all services defined in the Compose file:
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
#### Updating:
|
||||
Pull the latest image:
|
||||
```bash
|
||||
docker compose pull jellyseerr
|
||||
docker-compose pull jellyseerr
|
||||
```
|
||||
Then, restart all services defined in the Compose file:
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker-compose up -d
|
||||
```
|
||||
:::tip
|
||||
You may alternatively use a third-party mechanism like [dockge](https://github.com/louislam/dockge) to manage your docker compose files.
|
||||
|
||||
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { RateLimitOptions } from '@server/utils/rateLimit';
|
||||
// import rateLimit from '@server/utils/rateLimit';
|
||||
import rateLimit from '@server/utils/rateLimit';
|
||||
import type NodeCache from 'node-cache';
|
||||
|
||||
// 5 minute default TTL (in seconds)
|
||||
@@ -26,12 +26,11 @@ class ExternalAPI {
|
||||
params: Record<string, string> = {},
|
||||
options: ExternalAPIOptions = {}
|
||||
) {
|
||||
// if (options.rateLimit) {
|
||||
// this.fetch = rateLimit(fetch, options.rateLimit);
|
||||
// } else {
|
||||
// this.fetch = fetch;
|
||||
// }
|
||||
this.fetch = fetch;
|
||||
if (options.rateLimit) {
|
||||
this.fetch = rateLimit(fetch, options.rateLimit);
|
||||
} else {
|
||||
this.fetch = fetch;
|
||||
}
|
||||
|
||||
const url = new URL(baseUrl);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import logger from '@server/logger';
|
||||
import type { RateLimitOptions } from '@server/utils/rateLimit';
|
||||
// import rateLimit from '@server/utils/rateLimit';
|
||||
import rateLimit from '@server/utils/rateLimit';
|
||||
import { createHash } from 'crypto';
|
||||
import { promises } from 'fs';
|
||||
import mime from 'mime/lite';
|
||||
@@ -150,14 +150,13 @@ class ImageProxy {
|
||||
this.baseUrl = baseUrl;
|
||||
this.key = key;
|
||||
|
||||
// if (options.rateLimitOptions) {
|
||||
// this.fetch = rateLimit(fetch, {
|
||||
// ...options.rateLimitOptions,
|
||||
// });
|
||||
// } else {
|
||||
// this.fetch = fetch;
|
||||
// }
|
||||
this.fetch = fetch;
|
||||
if (options.rateLimitOptions) {
|
||||
this.fetch = rateLimit(fetch, {
|
||||
...options.rateLimitOptions,
|
||||
});
|
||||
} else {
|
||||
this.fetch = fetch;
|
||||
}
|
||||
this.headers = options.headers || null;
|
||||
}
|
||||
|
||||
|
||||
@@ -299,84 +299,54 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
|
||||
where: { jellyfinUserId: account.User.Id },
|
||||
});
|
||||
|
||||
const missingAdminUser = !user && !(await userRepository.count());
|
||||
if (
|
||||
missingAdminUser ||
|
||||
settings.main.mediaServerType === MediaServerType.NOT_CONFIGURED
|
||||
) {
|
||||
if (!user && !(await userRepository.count())) {
|
||||
// Check if user is admin on jellyfin
|
||||
if (account.User.Policy.IsAdministrator === false) {
|
||||
throw new ApiError(403, ApiErrorCode.NotAdmin);
|
||||
}
|
||||
|
||||
if (
|
||||
body.serverType !== MediaServerType.JELLYFIN &&
|
||||
body.serverType !== MediaServerType.EMBY
|
||||
) {
|
||||
throw new Error('select_server_type');
|
||||
}
|
||||
settings.main.mediaServerType = body.serverType;
|
||||
|
||||
if (missingAdminUser) {
|
||||
logger.info(
|
||||
'Sign-in attempt from Jellyfin user with access to the media server; creating initial admin user for Jellyseerr',
|
||||
{
|
||||
label: 'API',
|
||||
ip: req.ip,
|
||||
jellyfinUsername: account.User.Name,
|
||||
}
|
||||
);
|
||||
|
||||
// User doesn't exist, and there are no users in the database, we'll create the user
|
||||
// with admin permissions
|
||||
|
||||
user = new User({
|
||||
id: 1,
|
||||
email: body.email || account.User.Name,
|
||||
logger.info(
|
||||
'Sign-in attempt from Jellyfin user with access to the media server; creating initial admin user for Overseerr',
|
||||
{
|
||||
label: 'API',
|
||||
ip: req.ip,
|
||||
jellyfinUsername: account.User.Name,
|
||||
jellyfinUserId: account.User.Id,
|
||||
jellyfinDeviceId: deviceId,
|
||||
jellyfinAuthToken: account.AccessToken,
|
||||
permissions: Permission.ADMIN,
|
||||
avatar: `/avatarproxy/${account.User.Id}`,
|
||||
userType:
|
||||
body.serverType === MediaServerType.JELLYFIN
|
||||
? UserType.JELLYFIN
|
||||
: UserType.EMBY,
|
||||
});
|
||||
|
||||
await userRepository.save(user);
|
||||
} else {
|
||||
logger.info(
|
||||
'Sign-in attempt from Jellyfin user with access to the media server; editing admin user for Jellyseerr',
|
||||
{
|
||||
label: 'API',
|
||||
ip: req.ip,
|
||||
jellyfinUsername: account.User.Name,
|
||||
}
|
||||
);
|
||||
|
||||
// User alread exist but settings.json is not configured, we'll edit the admin user
|
||||
|
||||
user = await userRepository.findOne({
|
||||
where: { id: 1 },
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error('Unable to find admin user to edit');
|
||||
}
|
||||
user.email = body.email || account.User.Name;
|
||||
user.jellyfinUsername = account.User.Name;
|
||||
user.jellyfinUserId = account.User.Id;
|
||||
user.jellyfinDeviceId = deviceId;
|
||||
user.jellyfinAuthToken = account.AccessToken;
|
||||
user.permissions = Permission.ADMIN;
|
||||
user.avatar = `/avatarproxy/${account.User.Id}`;
|
||||
user.userType =
|
||||
body.serverType === MediaServerType.JELLYFIN
|
||||
? UserType.JELLYFIN
|
||||
: UserType.EMBY;
|
||||
);
|
||||
|
||||
await userRepository.save(user);
|
||||
// User doesn't exist, and there are no users in the database, we'll create the user
|
||||
// with admin permissions
|
||||
switch (body.serverType) {
|
||||
case MediaServerType.EMBY:
|
||||
settings.main.mediaServerType = MediaServerType.EMBY;
|
||||
user = new User({
|
||||
email: body.email || account.User.Name,
|
||||
jellyfinUsername: account.User.Name,
|
||||
jellyfinUserId: account.User.Id,
|
||||
jellyfinDeviceId: deviceId,
|
||||
jellyfinAuthToken: account.AccessToken,
|
||||
permissions: Permission.ADMIN,
|
||||
avatar: `/avatarproxy/${account.User.Id}`,
|
||||
userType: UserType.EMBY,
|
||||
});
|
||||
|
||||
break;
|
||||
case MediaServerType.JELLYFIN:
|
||||
settings.main.mediaServerType = MediaServerType.JELLYFIN;
|
||||
user = new User({
|
||||
email: body.email || account.User.Name,
|
||||
jellyfinUsername: account.User.Name,
|
||||
jellyfinUserId: account.User.Id,
|
||||
jellyfinDeviceId: deviceId,
|
||||
jellyfinAuthToken: account.AccessToken,
|
||||
permissions: Permission.ADMIN,
|
||||
avatar: `/avatarproxy/${account.User.Id}`,
|
||||
userType: UserType.JELLYFIN,
|
||||
});
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Error('select_server_type');
|
||||
}
|
||||
|
||||
// Create an API key on Jellyfin from this admin user
|
||||
@@ -398,6 +368,8 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
|
||||
settings.jellyfin.apiKey = apiKey;
|
||||
await settings.save();
|
||||
startJobs();
|
||||
|
||||
await userRepository.save(user);
|
||||
}
|
||||
// User already exists, let's update their information
|
||||
else if (account.User.Id === user?.jellyfinUserId) {
|
||||
|
||||
Reference in New Issue
Block a user