mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat(api): initial implementation of the auth system (#30)
Adds the auth system but does not add all required features. They will be handled in other tickets
This commit is contained in:
@@ -13,8 +13,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/ui": "^0.5.0",
|
"@tailwindcss/ui": "^0.5.0",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
|
"body-parser": "^1.19.0",
|
||||||
"bowser": "^2.10.0",
|
"bowser": "^2.10.0",
|
||||||
|
"connect-typeorm": "^1.1.4",
|
||||||
|
"cookie-parser": "^1.4.5",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
"express-session": "^1.17.1",
|
||||||
"next": "9.5.2",
|
"next": "9.5.2",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
"react-dom": "16.13.1",
|
"react-dom": "16.13.1",
|
||||||
@@ -26,7 +30,10 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^9.1.2",
|
"@commitlint/cli": "^9.1.2",
|
||||||
"@commitlint/config-conventional": "^9.1.2",
|
"@commitlint/config-conventional": "^9.1.2",
|
||||||
|
"@types/body-parser": "^1.19.0",
|
||||||
|
"@types/cookie-parser": "^1.4.2",
|
||||||
"@types/express": "^4.17.7",
|
"@types/express": "^4.17.7",
|
||||||
|
"@types/express-session": "^1.17.0",
|
||||||
"@types/node": "^14.0.27",
|
"@types/node": "^14.0.27",
|
||||||
"@types/react": "^16.9.46",
|
"@types/react": "^16.9.46",
|
||||||
"@types/react-transition-group": "^4.4.0",
|
"@types/react-transition-group": "^4.4.0",
|
||||||
|
62
server/api/plextv.ts
Normal file
62
server/api/plextv.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import axios, { AxiosInstance } from 'axios';
|
||||||
|
|
||||||
|
interface PlexAccountResponse {
|
||||||
|
user: PlexUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PlexUser {
|
||||||
|
id: number;
|
||||||
|
uuid: string;
|
||||||
|
email: string;
|
||||||
|
joined_at: string;
|
||||||
|
username: string;
|
||||||
|
title: string;
|
||||||
|
thumb: string;
|
||||||
|
hasPassword: boolean;
|
||||||
|
authToken: string;
|
||||||
|
subscription: {
|
||||||
|
active: boolean;
|
||||||
|
status: string;
|
||||||
|
plan: string;
|
||||||
|
features: string[];
|
||||||
|
};
|
||||||
|
roles: {
|
||||||
|
roles: string[];
|
||||||
|
};
|
||||||
|
entitlements: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlexTvAPI {
|
||||||
|
private authToken: string;
|
||||||
|
private axios: AxiosInstance;
|
||||||
|
|
||||||
|
constructor(authToken: string) {
|
||||||
|
this.authToken = authToken;
|
||||||
|
this.axios = axios.create({
|
||||||
|
baseURL: 'https://plex.tv',
|
||||||
|
headers: {
|
||||||
|
'X-Plex-Token': this.authToken,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getUser(): Promise<PlexUser> {
|
||||||
|
try {
|
||||||
|
const account = await this.axios.get<PlexAccountResponse>(
|
||||||
|
'/users/account.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
return account.data.user;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
'Something broke when getting account from plex.tv',
|
||||||
|
e.message
|
||||||
|
);
|
||||||
|
throw new Error('Invalid auth token');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlexTvAPI;
|
15
server/entity/Session.ts
Normal file
15
server/entity/Session.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { ISession } from 'connect-typeorm';
|
||||||
|
import { Index, Column, PrimaryColumn, Entity } from 'typeorm';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class Session implements ISession {
|
||||||
|
@Index()
|
||||||
|
@Column('bigint')
|
||||||
|
public expiredAt = Date.now();
|
||||||
|
|
||||||
|
@PrimaryColumn('varchar', { length: 255 })
|
||||||
|
public id = '';
|
||||||
|
|
||||||
|
@Column('text')
|
||||||
|
public json = '';
|
||||||
|
}
|
@@ -1,7 +1,12 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import next from 'next';
|
import next from 'next';
|
||||||
import { createConnection } from 'typeorm';
|
import { createConnection, getRepository } from 'typeorm';
|
||||||
import routes from './routes';
|
import routes from './routes';
|
||||||
|
import bodyParser from 'body-parser';
|
||||||
|
import cookieParser from 'cookie-parser';
|
||||||
|
import session from 'express-session';
|
||||||
|
import { TypeormStore } from 'connect-typeorm/out';
|
||||||
|
import { Session } from './entity/Session';
|
||||||
|
|
||||||
const dev = process.env.NODE_ENV !== 'production';
|
const dev = process.env.NODE_ENV !== 'production';
|
||||||
const app = next({ dev });
|
const app = next({ dev });
|
||||||
@@ -13,6 +18,23 @@ app
|
|||||||
.prepare()
|
.prepare()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const server = express();
|
const server = express();
|
||||||
|
server.use(cookieParser());
|
||||||
|
server.use(bodyParser.json());
|
||||||
|
server.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
// Setup sessions
|
||||||
|
const sessionRespository = getRepository(Session);
|
||||||
|
server.use(
|
||||||
|
session({
|
||||||
|
secret: 'verysecret',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
store: new TypeormStore({
|
||||||
|
cleanupLimit: 2,
|
||||||
|
ttl: 86400,
|
||||||
|
}).connect(sessionRespository),
|
||||||
|
})
|
||||||
|
);
|
||||||
server.use('/api', routes);
|
server.use('/api', routes);
|
||||||
server.get('*', (req, res) => handle(req, res));
|
server.get('*', (req, res) => handle(req, res));
|
||||||
|
|
||||||
|
29
server/middleware/auth.ts
Normal file
29
server/middleware/auth.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { getRepository } from 'typeorm';
|
||||||
|
import { User } from '../entity/User';
|
||||||
|
import { Middleware } from '../types/express';
|
||||||
|
|
||||||
|
export const checkUser: Middleware = async (req, _res, next) => {
|
||||||
|
if (req.session?.userId) {
|
||||||
|
const userRepository = getRepository(User);
|
||||||
|
|
||||||
|
const user = await userRepository.findOne({
|
||||||
|
where: { id: req.session.userId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
req.user = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isAuthenticated: Middleware = async (req, res, next) => {
|
||||||
|
if (!req.user) {
|
||||||
|
res.status(403).json({
|
||||||
|
status: 403,
|
||||||
|
error: 'You do not have permisson to access this endpoint',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
};
|
65
server/routes/auth.ts
Normal file
65
server/routes/auth.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { Router } from 'express';
|
||||||
|
import { getRepository } from 'typeorm';
|
||||||
|
import { User } from '../entity/User';
|
||||||
|
import PlexTvAPI from '../api/plextv';
|
||||||
|
|
||||||
|
const authRoutes = Router();
|
||||||
|
|
||||||
|
authRoutes.post('/login', async (req, res) => {
|
||||||
|
const userRepository = getRepository(User);
|
||||||
|
const body = req.body as { authToken?: string };
|
||||||
|
|
||||||
|
if (!body.authToken) {
|
||||||
|
return res.status(500).json({ error: 'You must provide an auth token' });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// First we need to use this auth token to get the users email from plex tv
|
||||||
|
const plextv = new PlexTvAPI(body.authToken);
|
||||||
|
const account = await plextv.getUser();
|
||||||
|
|
||||||
|
// Next let's see if the user already exists
|
||||||
|
let user = await userRepository.findOne({
|
||||||
|
where: { email: account.email },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
// Let's check if their plex token is up to date
|
||||||
|
if (user.plexToken !== body.authToken) {
|
||||||
|
user.plexToken = body.authToken;
|
||||||
|
await userRepository.save(user);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Here we check if it's the first user. If it is, we create the user with no check
|
||||||
|
// and give them admin permissions
|
||||||
|
const totalUsers = await userRepository.count();
|
||||||
|
|
||||||
|
if (totalUsers === 0) {
|
||||||
|
user = new User({
|
||||||
|
email: account.email,
|
||||||
|
plexToken: account.authToken,
|
||||||
|
// TODO: When we add permissions in #52, set admin here
|
||||||
|
});
|
||||||
|
await userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get to this point, the user does not already exist so we need to create the
|
||||||
|
// user _assuming_ they have access to the plex server
|
||||||
|
// (We cant do this until we finish the settings sytem and actually
|
||||||
|
// store the user token in ticket #55)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set logged in session
|
||||||
|
if (req.session && user) {
|
||||||
|
req.session.userId = user.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({ status: 'ok' });
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
res
|
||||||
|
.status(500)
|
||||||
|
.json({ error: 'Something went wrong. Is your auth token valid?' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default authRoutes;
|
@@ -1,9 +1,13 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import user from './user';
|
import user from './user';
|
||||||
|
import authRoutes from './auth';
|
||||||
|
import { checkUser, isAuthenticated } from '../middleware/auth';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.use('/user', user);
|
router.use(checkUser);
|
||||||
|
router.use('/user', isAuthenticated, user);
|
||||||
|
router.use('/auth', authRoutes);
|
||||||
|
|
||||||
router.get('/', (req, res) => {
|
router.get('/', (req, res) => {
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
@@ -12,4 +16,8 @@ router.get('/', (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.all('*', (req, res) =>
|
||||||
|
res.status(404).json({ status: 404, message: '404 Not Found' })
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@@ -6,7 +6,8 @@
|
|||||||
"noEmit": false,
|
"noEmit": false,
|
||||||
"strictPropertyInitialization": false,
|
"strictPropertyInitialization": false,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true
|
"emitDecoratorMetadata": true,
|
||||||
|
"typeRoots": ["types"]
|
||||||
},
|
},
|
||||||
"include": ["**/*.ts", "**/*.tsx"]
|
"include": ["**/*.ts", "**/*.tsx"]
|
||||||
}
|
}
|
||||||
|
21
server/types/express.d.ts
vendored
Normal file
21
server/types/express.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
import type { NextFunction, Request, Response } from 'express';
|
||||||
|
import type { User } from '../entity/User';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace Express {
|
||||||
|
export interface Session {
|
||||||
|
userId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Request {
|
||||||
|
user?: User;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Middleware = <ParamsDictionary, any, any>(
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
) => Promise<void | NextFunction> | void | NextFunction;
|
85
yarn.lock
85
yarn.lock
@@ -1242,7 +1242,7 @@
|
|||||||
hex-rgb "^4.1.0"
|
hex-rgb "^4.1.0"
|
||||||
postcss-selector-parser "^6.0.2"
|
postcss-selector-parser "^6.0.2"
|
||||||
|
|
||||||
"@types/body-parser@*":
|
"@types/body-parser@*", "@types/body-parser@^1.19.0":
|
||||||
version "1.19.0"
|
version "1.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
|
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
|
||||||
integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
|
integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
|
||||||
@@ -1262,6 +1262,18 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/cookie-parser@^1.4.2":
|
||||||
|
version "1.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.2.tgz#e4d5c5ffda82b80672a88a4281aaceefb1bd9df5"
|
||||||
|
integrity sha512-uwcY8m6SDQqciHsqcKDGbo10GdasYsPCYkH3hVegj9qAah6pX5HivOnOuI3WYmyQMnOATV39zv/Ybs0bC/6iVg==
|
||||||
|
dependencies:
|
||||||
|
"@types/express" "*"
|
||||||
|
|
||||||
|
"@types/debug@0.0.31":
|
||||||
|
version "0.0.31"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-0.0.31.tgz#bac8d8aab6a823e91deb7f79083b2a35fa638f33"
|
||||||
|
integrity sha512-LS1MCPaQKqspg7FvexuhmDbWUhE2yIJ+4AgVIyObfc06/UKZ8REgxGNjZc82wPLWmbeOm7S+gSsLgo75TanG4A==
|
||||||
|
|
||||||
"@types/eslint-visitor-keys@^1.0.0":
|
"@types/eslint-visitor-keys@^1.0.0":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||||
@@ -1276,7 +1288,15 @@
|
|||||||
"@types/qs" "*"
|
"@types/qs" "*"
|
||||||
"@types/range-parser" "*"
|
"@types/range-parser" "*"
|
||||||
|
|
||||||
"@types/express@^4.17.7":
|
"@types/express-session@^1.15.5", "@types/express-session@^1.17.0":
|
||||||
|
version "1.17.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/express-session/-/express-session-1.17.0.tgz#770daf81368f6278e3e40dd894e1e52abbdca0cd"
|
||||||
|
integrity sha512-OQEHeBFE1UhChVIBhRh9qElHUvTp4BzKKHxMDkGHT7WuYk5eL93hPG7D8YAIkoBSbhNEY0RjreF15zn+U0eLjA==
|
||||||
|
dependencies:
|
||||||
|
"@types/express" "*"
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/express@*", "@types/express@^4.17.7":
|
||||||
version "4.17.7"
|
version "4.17.7"
|
||||||
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59"
|
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59"
|
||||||
integrity sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==
|
integrity sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==
|
||||||
@@ -2092,7 +2112,7 @@ bn.js@^5.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
|
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
|
||||||
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
|
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
|
||||||
|
|
||||||
body-parser@1.19.0:
|
body-parser@1.19.0, body-parser@^1.19.0:
|
||||||
version "1.19.0"
|
version "1.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||||
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
|
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
|
||||||
@@ -2764,6 +2784,16 @@ configstore@^5.0.1:
|
|||||||
write-file-atomic "^3.0.0"
|
write-file-atomic "^3.0.0"
|
||||||
xdg-basedir "^4.0.0"
|
xdg-basedir "^4.0.0"
|
||||||
|
|
||||||
|
connect-typeorm@^1.1.4:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/connect-typeorm/-/connect-typeorm-1.1.4.tgz#80f4e60dc4eeb6c04de334c30bf3e4bb766a34e5"
|
||||||
|
integrity sha512-1/0b1aFzip0UBzuaSUkVZE4EW3n4UZzi3x2fmKeCaOb+sB4VZGj79txzLvtWIHLYY6kls/PKNcQHfEurdEjsUw==
|
||||||
|
dependencies:
|
||||||
|
"@types/debug" "0.0.31"
|
||||||
|
"@types/express-session" "^1.15.5"
|
||||||
|
debug "^4.1.1"
|
||||||
|
express-session "^1.15.6"
|
||||||
|
|
||||||
console-browserify@^1.1.0:
|
console-browserify@^1.1.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
|
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
|
||||||
@@ -2838,6 +2868,14 @@ convert-source-map@^0.3.3:
|
|||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
|
||||||
integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA=
|
integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA=
|
||||||
|
|
||||||
|
cookie-parser@^1.4.5:
|
||||||
|
version "1.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.5.tgz#3e572d4b7c0c80f9c61daf604e4336831b5d1d49"
|
||||||
|
integrity sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==
|
||||||
|
dependencies:
|
||||||
|
cookie "0.4.0"
|
||||||
|
cookie-signature "1.0.6"
|
||||||
|
|
||||||
cookie-signature@1.0.6:
|
cookie-signature@1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||||
@@ -3253,6 +3291,11 @@ depd@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||||
|
|
||||||
|
depd@~2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||||
|
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||||
|
|
||||||
des.js@^1.0.0:
|
des.js@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
|
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
|
||||||
@@ -3802,6 +3845,20 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
homedir-polyfill "^1.0.1"
|
homedir-polyfill "^1.0.1"
|
||||||
|
|
||||||
|
express-session@^1.15.6, express-session@^1.17.1:
|
||||||
|
version "1.17.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.1.tgz#36ecbc7034566d38c8509885c044d461c11bf357"
|
||||||
|
integrity sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==
|
||||||
|
dependencies:
|
||||||
|
cookie "0.4.0"
|
||||||
|
cookie-signature "1.0.6"
|
||||||
|
debug "2.6.9"
|
||||||
|
depd "~2.0.0"
|
||||||
|
on-headers "~1.0.2"
|
||||||
|
parseurl "~1.3.3"
|
||||||
|
safe-buffer "5.2.0"
|
||||||
|
uid-safe "~2.1.5"
|
||||||
|
|
||||||
express@^4.17.1:
|
express@^4.17.1:
|
||||||
version "4.17.1"
|
version "4.17.1"
|
||||||
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
||||||
@@ -6194,6 +6251,11 @@ on-finished@~2.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ee-first "1.1.1"
|
ee-first "1.1.1"
|
||||||
|
|
||||||
|
on-headers@~1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
|
||||||
|
integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
|
||||||
|
|
||||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
@@ -7095,6 +7157,11 @@ quick-lru@^4.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
|
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
|
||||||
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
|
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
|
||||||
|
|
||||||
|
random-bytes@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
|
||||||
|
integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=
|
||||||
|
|
||||||
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
|
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||||
@@ -7536,6 +7603,11 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
|
safe-buffer@5.2.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||||
|
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
|
||||||
|
|
||||||
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
|
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
@@ -8614,6 +8686,13 @@ typescript@^3.9.7:
|
|||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||||
|
|
||||||
|
uid-safe@~2.1.5:
|
||||||
|
version "2.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
|
||||||
|
integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==
|
||||||
|
dependencies:
|
||||||
|
random-bytes "~1.0.0"
|
||||||
|
|
||||||
undefsafe@^2.0.2:
|
undefsafe@^2.0.2:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae"
|
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae"
|
||||||
|
Reference in New Issue
Block a user