feat(plex): selective user import (#2188)
* feat(api): allow importing of only selected Plex users * feat(frontend): modal for importing Plex users * feat: add alert if 'Enable New Plex Sign-In' setting is enabled * refactor: fetch all existing Plex users in a single DB query Co-authored-by: Ryan Cohen <ryan@sct.dev>
This commit is contained in:
@@ -224,7 +224,7 @@ class PlexTvAPI {
|
||||
|
||||
const users = friends.MediaContainer.User;
|
||||
|
||||
const user = users.find((u) => Number(u.$.id) === userId);
|
||||
const user = users.find((u) => parseInt(u.$.id) === userId);
|
||||
|
||||
if (!user) {
|
||||
throw new Error(
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface PublicSettingsResponse {
|
||||
enablePushRegistration: boolean;
|
||||
locale: string;
|
||||
emailEnabled: boolean;
|
||||
newPlexLogin: boolean;
|
||||
}
|
||||
|
||||
export interface CacheItem {
|
||||
|
||||
@@ -113,6 +113,7 @@ interface FullPublicSettings extends PublicSettings {
|
||||
enablePushRegistration: boolean;
|
||||
locale: string;
|
||||
emailEnabled: boolean;
|
||||
newPlexLogin: boolean;
|
||||
}
|
||||
|
||||
export interface NotificationAgentConfig {
|
||||
@@ -469,6 +470,7 @@ class Settings {
|
||||
enablePushRegistration: this.data.notifications.agents.webpush.enabled,
|
||||
locale: this.data.main.locale,
|
||||
emailEnabled: this.data.notifications.agents.email.enabled,
|
||||
newPlexLogin: this.data.main.newPlexLogin,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Router } from 'express';
|
||||
import rateLimit from 'express-rate-limit';
|
||||
import fs from 'fs';
|
||||
import { merge, omit } from 'lodash';
|
||||
import { merge, omit, sortBy } from 'lodash';
|
||||
import { rescheduleJob } from 'node-schedule';
|
||||
import path from 'path';
|
||||
import { getRepository } from 'typeorm';
|
||||
@@ -225,6 +225,58 @@ settingsRoutes.post('/plex/sync', (req, res) => {
|
||||
return res.status(200).json(plexFullScanner.status());
|
||||
});
|
||||
|
||||
settingsRoutes.get(
|
||||
'/plex/users',
|
||||
isAuthenticated(Permission.MANAGE_USERS),
|
||||
async (req, res) => {
|
||||
const userRepository = getRepository(User);
|
||||
const qb = userRepository.createQueryBuilder('user');
|
||||
|
||||
const admin = await userRepository.findOneOrFail({
|
||||
select: ['id', 'plexToken'],
|
||||
order: { id: 'ASC' },
|
||||
});
|
||||
const plexApi = new PlexTvAPI(admin.plexToken ?? '');
|
||||
const plexUsers = (await plexApi.getUsers()).MediaContainer.User.map(
|
||||
(user) => user.$
|
||||
);
|
||||
|
||||
const unimportedPlexUsers: {
|
||||
id: string;
|
||||
title: string;
|
||||
username: string;
|
||||
email: string;
|
||||
thumb: string;
|
||||
}[] = [];
|
||||
|
||||
const existingUsers = await qb
|
||||
.where('user.plexId IN (:...plexIds)', {
|
||||
plexIds: plexUsers.map((plexUser) => plexUser.id),
|
||||
})
|
||||
.orWhere('user.email IN (:...plexEmails)', {
|
||||
plexEmails: plexUsers.map((plexUser) => plexUser.email.toLowerCase()),
|
||||
})
|
||||
.getMany();
|
||||
|
||||
await Promise.all(
|
||||
plexUsers.map(async (plexUser) => {
|
||||
if (
|
||||
!existingUsers.find(
|
||||
(user) =>
|
||||
user.plexId === parseInt(plexUser.id) ||
|
||||
user.email === plexUser.email.toLowerCase()
|
||||
) &&
|
||||
(await plexApi.checkUserAccess(parseInt(plexUser.id)))
|
||||
) {
|
||||
unimportedPlexUsers.push(plexUser);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return res.status(200).json(sortBy(unimportedPlexUsers, 'username'));
|
||||
}
|
||||
);
|
||||
|
||||
settingsRoutes.get(
|
||||
'/logs',
|
||||
rateLimit({ windowMs: 60 * 1000, max: 50 }),
|
||||
|
||||
@@ -400,6 +400,7 @@ router.post(
|
||||
try {
|
||||
const settings = getSettings();
|
||||
const userRepository = getRepository(User);
|
||||
const body = req.body as { plexIds: string[] } | undefined;
|
||||
|
||||
// taken from auth.ts
|
||||
const mainUser = await userRepository.findOneOrFail({
|
||||
@@ -434,7 +435,7 @@ router.post(
|
||||
user.plexId = parseInt(account.id);
|
||||
}
|
||||
await userRepository.save(user);
|
||||
} else {
|
||||
} else if (!body || body.plexIds.includes(account.id)) {
|
||||
if (await mainPlexTv.checkUserAccess(parseInt(account.id))) {
|
||||
const newUser = new User({
|
||||
plexUsername: account.username,
|
||||
|
||||
Reference in New Issue
Block a user