From 97d63f13d38bb4378b59fb76f3e1cb29efe659ac Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 26 Sep 2017 22:51:46 +0100 Subject: [PATCH] Added the ability to enable Plex User importing. We also allow you to exclude users #1456 --- .../Jobs/Plex/PlexUserImporter.cs | 8 ++- .../Settings/Models/UserManagementSettings.cs | 4 +- src/Ombi/ClientApp/app/app.component.html | 2 +- src/Ombi/ClientApp/app/app.module.ts | 3 +- src/Ombi/ClientApp/app/interfaces/IPlex.ts | 5 ++ .../ClientApp/app/interfaces/ISettings.ts | 5 +- .../app/search/search.component.html | 2 +- .../app/services/applications/plex.service.ts | 6 +- .../usermanagement.component.html | 64 +++++++++++-------- .../usermanagement.component.ts | 55 ++++++++++++++-- src/Ombi/ClientApp/styles/Themes/plex.scss | 13 ++++ src/Ombi/ClientApp/styles/base.scss | 12 ++++ .../Controllers/External/PlexController.cs | 29 ++++++++- ...enViewModel.cs => PlexServersViewModel.cs} | 0 .../Models/External/PlexUsersViewModel.cs | 8 +++ 15 files changed, 171 insertions(+), 45 deletions(-) rename src/Ombi/Models/External/{PlexRequestTokenViewModel.cs => PlexServersViewModel.cs} (100%) create mode 100644 src/Ombi/Models/External/PlexUsersViewModel.cs diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs index 85e6e053e..52f79332f 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs @@ -55,6 +55,13 @@ namespace Ombi.Schedule.Jobs.Plex foreach (var plexUsers in users.User) { + // Check if we should import this user + if (userManagementSettings.BannedPlexUserIds.Contains(plexUsers.Id)) + { + // Do not import these, they are not allowed into the country. + continue; + } + // Check if this Plex User already exists // We are using the Plex USERNAME and Not the TITLE, the Title is for HOME USERS var existingPlexUser = allUsers.FirstOrDefault(x => x.ProviderUserId == plexUsers.Id); @@ -79,7 +86,6 @@ namespace Ombi.Schedule.Jobs.Plex } continue; } - // TODO Set default permissions/roles if (userManagementSettings.DefaultRoles.Any()) { foreach (var defaultRole in userManagementSettings.DefaultRoles) diff --git a/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs b/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs index 32aa3c5c1..f0c984353 100644 --- a/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs +++ b/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs @@ -6,6 +6,8 @@ namespace Ombi.Settings.Settings.Models { public bool ImportPlexUsers { get; set; } public bool ImportEmbyUsers { get; set; } - public List DefaultRoles { get; set; } + public List DefaultRoles { get; set; } = new List(); + public List BannedPlexUserIds { get; set; } = new List(); + public List BannedEmbyUserIds { get; set; } = new List(); } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index 8ae646b33..d0c947352 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -28,7 +28,7 @@
  • User Management
  • diff --git a/src/Ombi/ClientApp/app/app.module.ts b/src/Ombi/ClientApp/app/app.module.ts index 2945e9647..2a8dea9d5 100644 --- a/src/Ombi/ClientApp/app/app.module.ts +++ b/src/Ombi/ClientApp/app/app.module.ts @@ -10,7 +10,7 @@ import { RouterModule, Routes } from "@angular/router"; //import { DragulaModule, DragulaService } from 'ng2-dragula/ng2-dragula'; import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { GrowlModule } from "primeng/components/growl/growl"; -import { ButtonModule, CaptchaModule, DataTableModule,DialogModule, SharedModule } from "primeng/primeng"; +import { ButtonModule, CaptchaModule, DataTableModule,DialogModule, SharedModule, TooltipModule } from "primeng/primeng"; // Components import { AppComponent } from "./app.component"; @@ -79,6 +79,7 @@ const routes: Routes = [ UserManagementModule, RequestsModule, CaptchaModule, + TooltipModule, ], declarations: [ AppComponent, diff --git a/src/Ombi/ClientApp/app/interfaces/IPlex.ts b/src/Ombi/ClientApp/app/interfaces/IPlex.ts index d8ce4ed06..44bfc83d3 100644 --- a/src/Ombi/ClientApp/app/interfaces/IPlex.ts +++ b/src/Ombi/ClientApp/app/interfaces/IPlex.ts @@ -20,6 +20,11 @@ export interface IPlexLibResponse { data: IPlexLibraries; } +export interface IPlexFriends { + id: string; + username: string; +} + export interface IMediaContainer { directory: IDirectory[]; } diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 9a10e5388..1f952b70e 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -1,5 +1,4 @@ import { ISettings } from "./ICommon"; -import { ICheckbox } from "./index"; export interface IExternalSettings extends ISettings { ssl: boolean; @@ -106,7 +105,9 @@ export interface IAuthenticationSettings extends ISettings { export interface IUserManagementSettings extends ISettings { importPlexUsers: boolean; importEmbyUsers: boolean; - defaultClaims: ICheckbox[]; + defaultRoles: string[]; + bannedPlexUserIds: string[]; + bannedEmbyUserIds: string[]; } export interface IAbout { diff --git a/src/Ombi/ClientApp/app/search/search.component.html b/src/Ombi/ClientApp/app/search/search.component.html index 3226360bc..1969bde8c 100644 --- a/src/Ombi/ClientApp/app/search/search.component.html +++ b/src/Ombi/ClientApp/app/search/search.component.html @@ -1,5 +1,5 @@ 

    Search

    -

    Want to watch something that is not currently available?! No problem! Just search for it below and request it!

    +

    Want to watch something that is not currently available? No problem, just search for it below and request it!


    diff --git a/src/Ombi/ClientApp/app/services/applications/plex.service.ts b/src/Ombi/ClientApp/app/services/applications/plex.service.ts index 75e2d8148..6711646f0 100644 --- a/src/Ombi/ClientApp/app/services/applications/plex.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/plex.service.ts @@ -6,8 +6,7 @@ import { Observable } from "rxjs/Rx"; import { ServiceAuthHelpers } from "../service.helpers"; -import { IPlexAuthentication, IPlexLibResponse, IPlexServerViewModel } from "../../interfaces"; -import { IPlexServer } from "../../interfaces"; +import { IPlexAuthentication, IPlexFriends, IPlexLibResponse, IPlexServer, IPlexServerViewModel } from "../../interfaces"; @Injectable() export class PlexService extends ServiceAuthHelpers { @@ -27,4 +26,7 @@ export class PlexService extends ServiceAuthHelpers { return this.http.post(`${this.url}Libraries`, JSON.stringify(plexSettings), { headers: this.headers }).map(this.extractData).catch(this.handleError); } + public getFriends(): Observable { + return this.http.get(`${this.url}Friends`, { headers: this.headers }).map(this.extractData).catch(this.handleError); + } } diff --git a/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html index c66e6f428..a639bef1e 100644 --- a/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.html @@ -2,42 +2,50 @@
    User Management Settings -
    -
    - -
    -
    - - -
    -
    +
    +
    +
    +
    + + +
    - -
    +
    +

    Plex Users exclude from Import

    - -
    -
    - - -
    -
    - +
    -
    -

    Default Roles

    - -
    -
    -
    - - -
    +
    + + +
    +
    + +
    +
    +
    +

    Default Roles

    + +
    +
    +
    + + +
    +
    +
    + +
    +
    +
    + +
    +
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.ts b/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.ts index b0cd5fff0..4f362a342 100644 --- a/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.ts +++ b/src/Ombi/ClientApp/app/settings/usermanagement/usermanagement.component.ts @@ -1,7 +1,8 @@ import { Component, OnInit } from "@angular/core"; import { ICheckbox, IUserManagementSettings } from "../../interfaces"; -import { IdentityService, SettingsService } from "../../services"; +import { IPlexFriends } from "../../interfaces/IPlex"; +import { IdentityService, NotificationService, PlexService, SettingsService } from "../../services"; @Component({ templateUrl: "./usermanagement.component.html", @@ -13,22 +14,40 @@ export class UserManagementComponent implements OnInit { public settings: IUserManagementSettings; public claims: ICheckbox[]; + public plexUsers: IPlexFriends[]; + public filteredPlexUsers: IPlexFriends[]; + public bannedPlexUsers: IPlexFriends[] = []; + constructor(private settingsService: SettingsService, - //private notificationService: NotificationService, - private identityService: IdentityService) { + private notificationService: NotificationService, + private identityService: IdentityService, + private plexService: PlexService) { } public ngOnInit(): void { this.settingsService.getUserManagementSettings().subscribe(x => { this.settings = x; + + this.plexService.getFriends().subscribe(f => { + this.plexUsers = f; + this.plexUsers.forEach((plex) => { + const isExcluded = this.settings.bannedPlexUserIds.some((val) => { + return plex.id === val; + }); + if (isExcluded) { + this.bannedPlexUsers.push(plex); + } + }); + }); + this.identityService.getAllAvailableClaims().subscribe(c => { this.claims = c; this.claims.forEach((claim) => { - if (this.settings.defaultClaims) { - const hasClaim = this.settings.defaultClaims.some((item) => { - return item.value === claim.value && item.enabled; + if (this.settings.defaultRoles) { + const hasClaim = this.settings.defaultRoles.some((item) => { + return item === claim.value; }); claim.enabled = hasClaim; } @@ -37,6 +56,30 @@ export class UserManagementComponent implements OnInit { }); this.settingsService.getPlex().subscribe(x => this.plexEnabled = x.enable); this.settingsService.getEmby().subscribe(x => this.embyEnabled = x.enable); + } + public submit(): void { + const enabledClaims = this.claims.filter((claim) => { + return claim.enabled; + }); + this.settings.defaultRoles = enabledClaims.map((claim) => claim.value); + this.settings.bannedPlexUserIds = this.bannedPlexUsers.map((u) => u.id); + this.settingsService.saveUserManagementSettings(this.settings).subscribe(x => { + if (x === true) { + this.notificationService.success("Saved", "Successfully saved the User Management Settings"); + } else { + this.notificationService.success("Settings Saved", "There was an error when saving the Ombi settings"); + } + }); + } + + public filterCountryMultiple(event: any) { + this.filteredPlexUsers = this.filter(event.query, this.plexUsers); + } + + private filter(query: string, users: IPlexFriends[]): IPlexFriends[] { + return users.filter((val) => { + return val.username.toLowerCase().indexOf(query.toLowerCase()) === 0; + }); } } diff --git a/src/Ombi/ClientApp/styles/Themes/plex.scss b/src/Ombi/ClientApp/styles/Themes/plex.scss index a894152cd..79b1e6ab2 100644 --- a/src/Ombi/ClientApp/styles/Themes/plex.scss +++ b/src/Ombi/ClientApp/styles/Themes/plex.scss @@ -278,4 +278,17 @@ button.list-group-item:focus { } .ui-widget-content { color: #ffffff; +} + + +.ui-inputtext { + background: $bg-colour; + color:white; +} +.ui-autocomplete-input-token input{ + color:white; +} + +.ui-state-default { + border: 2px solid $bg-colour-disabled; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index d19e51c41..b584cb128 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -782,4 +782,16 @@ textarea { .ui-treetable-toggler.fa.fa-fw.ui-clickable.fa-caret-right, .ui-treetable-toggler.fa.fa-fw.ui-clickable.fa-caret-down { display: none; +} + +.ui-state-highlight { + background: $primary-colour; +} + +.ui-inputtext { + background: $form-color; +} + +.ui-state-default { + border: 1px solid $form-color-lighter; } \ No newline at end of file diff --git a/src/Ombi/Controllers/External/PlexController.cs b/src/Ombi/Controllers/External/PlexController.cs index b04e08650..f5b5ee706 100644 --- a/src/Ombi/Controllers/External/PlexController.cs +++ b/src/Ombi/Controllers/External/PlexController.cs @@ -10,6 +10,7 @@ using Ombi.Api.Plex.Models; using Ombi.Attributes; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; using Ombi.Models.External; namespace Ombi.Controllers.External @@ -104,9 +105,9 @@ namespace Ombi.Controllers.External Data = libs }; } - catch (Exception e) + catch (Exception e) { - _log.LogWarning(e,"Error thrown when attempting to obtain the plex libs"); + _log.LogWarning(e, "Error thrown when attempting to obtain the plex libs"); var message = e.InnerException != null ? $"{e.Message} - {e.InnerException.Message}" : e.Message; return new PlexLibrariesResponse @@ -142,6 +143,30 @@ namespace Ombi.Controllers.External } } + /// + /// Gets the plex friends. + /// + /// + [HttpGet("friends")] + public async Task> GetFriends() + { + var vm = new List(); + var s = await PlexSettings.GetSettingsAsync(); + foreach (var server in s.Servers) + { + var users = await PlexApi.GetUsers(server.PlexAuthToken); + if (users?.User != null && users.User.Any()) + { + vm.AddRange(users.User.Select(u => new PlexUsersViewModel + { + Username = u.Username, + Id = u.Id + })); + } + } + // Filter out any dupes + return vm.DistinctBy(x => x.Id); + } } } diff --git a/src/Ombi/Models/External/PlexRequestTokenViewModel.cs b/src/Ombi/Models/External/PlexServersViewModel.cs similarity index 100% rename from src/Ombi/Models/External/PlexRequestTokenViewModel.cs rename to src/Ombi/Models/External/PlexServersViewModel.cs diff --git a/src/Ombi/Models/External/PlexUsersViewModel.cs b/src/Ombi/Models/External/PlexUsersViewModel.cs new file mode 100644 index 000000000..c2c5f1c77 --- /dev/null +++ b/src/Ombi/Models/External/PlexUsersViewModel.cs @@ -0,0 +1,8 @@ +namespace Ombi.Models.External +{ + public class PlexUsersViewModel + { + public string Username { get; set; } + public string Id { get; set; } + } +}