Added the ability to invite Plex Friends from the user management screen.

pull/2452/head
Jamie 6 years ago
parent 9c10e98a23
commit 505929737c

@ -11,6 +11,7 @@ namespace Ombi.Api.Plex
public interface IPlexApi public interface IPlexApi
{ {
Task<PlexStatus> GetStatus(string authToken, string uri); Task<PlexStatus> GetStatus(string authToken, string uri);
Task<PlexLibrariesForMachineId> GetLibrariesForMachineId(string authToken, string machineId);
Task<PlexAuthentication> SignIn(UserRequest user); Task<PlexAuthentication> SignIn(UserRequest user);
Task<PlexServer> GetServer(string authToken); Task<PlexServer> GetServer(string authToken);
Task<PlexContainer> GetLibrarySections(string authToken, string plexFullHost); Task<PlexContainer> GetLibrarySections(string authToken, string plexFullHost);

@ -0,0 +1,66 @@
namespace Ombi.Api.Plex.Models
{
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
[XmlRoot(ElementName = "Section")]
public class SectionLite
{
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "key")]
public string Key { get; set; }
[XmlAttribute(AttributeName = "type")]
public string Type { get; set; }
[XmlAttribute(AttributeName = "title")]
public string Title { get; set; }
}
[XmlRoot(ElementName = "Server")]
public class ServerLib
{
[XmlElement(ElementName = "Section")]
public List<SectionLite> Section { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "address")]
public string Address { get; set; }
[XmlAttribute(AttributeName = "port")]
public string Port { get; set; }
[XmlAttribute(AttributeName = "version")]
public string Version { get; set; }
[XmlAttribute(AttributeName = "scheme")]
public string Scheme { get; set; }
[XmlAttribute(AttributeName = "host")]
public string Host { get; set; }
[XmlAttribute(AttributeName = "localAddresses")]
public string LocalAddresses { get; set; }
[XmlAttribute(AttributeName = "machineIdentifier")]
public string MachineIdentifier { get; set; }
[XmlAttribute(AttributeName = "createdAt")]
public string CreatedAt { get; set; }
[XmlAttribute(AttributeName = "updatedAt")]
public string UpdatedAt { get; set; }
[XmlAttribute(AttributeName = "owned")]
public string Owned { get; set; }
[XmlAttribute(AttributeName = "synced")]
public string Synced { get; set; }
}
[XmlRoot(ElementName = "MediaContainer")]
public class PlexLibrariesForMachineId
{
[XmlElement(ElementName = "Server")]
public ServerLib Server { get; set; }
[XmlAttribute(AttributeName = "friendlyName")]
public string FriendlyName { get; set; }
[XmlAttribute(AttributeName = "identifier")]
public string Identifier { get; set; }
[XmlAttribute(AttributeName = "machineIdentifier")]
public string MachineIdentifier { get; set; }
[XmlAttribute(AttributeName = "size")]
public string Size { get; set; }
}
}

@ -127,6 +127,13 @@ namespace Ombi.Api.Plex
return await Api.Request<PlexContainer>(request); return await Api.Request<PlexContainer>(request);
} }
public async Task<PlexLibrariesForMachineId> GetLibrariesForMachineId(string authToken, string machineId)
{
var request = new Request("", $"https://plex.tv/api/servers/{machineId}", HttpMethod.Get, ContentType.Xml);
await AddHeaders(request, authToken);
return await Api.Request<PlexLibrariesForMachineId>(request);
}
/// <summary> /// <summary>
// 192.168.1.69:32400/library/metadata/3662/allLeaves // 192.168.1.69:32400/library/metadata/3662/allLeaves
// The metadata ratingkey should be in the Cache // The metadata ratingkey should be in the Cache

@ -34,6 +34,19 @@ export interface IPlexLibResponse {
data: IPlexLibraries; data: IPlexLibraries;
} }
export interface IPlexLibSimpleResponse {
successful: boolean;
message: string;
data: IPlexSection[];
}
export interface IPlexSection {
id: string;
key: string;
type: string;
title: string;
}
export interface IMediaContainer { export interface IMediaContainer {
directory: IDirectory[]; directory: IDirectory[];
} }

@ -6,7 +6,7 @@ import { Observable } from "rxjs";
import { ServiceHelpers } from "../service.helpers"; import { ServiceHelpers } from "../service.helpers";
import { IPlexAuthentication, IPlexLibResponse, IPlexOAuthViewModel, IPlexServer, IPlexServerAddViewModel, IPlexServerViewModel, IPlexUserAddResponse, IPlexUserViewModel, IUsersModel } from "../../interfaces"; import { IPlexAuthentication, IPlexLibResponse, IPlexLibSimpleResponse, IPlexOAuthViewModel, IPlexServer, IPlexServerAddViewModel, IPlexServerViewModel, IPlexUserAddResponse, IPlexUserViewModel, IUsersModel } from "../../interfaces";
@Injectable() @Injectable()
export class PlexService extends ServiceHelpers { export class PlexService extends ServiceHelpers {
@ -30,8 +30,8 @@ export class PlexService extends ServiceHelpers {
return this.http.post<IPlexLibResponse>(`${this.url}Libraries`, JSON.stringify(plexSettings), {headers: this.headers}); return this.http.post<IPlexLibResponse>(`${this.url}Libraries`, JSON.stringify(plexSettings), {headers: this.headers});
} }
public getLibrariesFromSettings(machineId: string): Observable<IPlexLibResponse> { public getLibrariesFromSettings(machineId: string): Observable<IPlexLibSimpleResponse> {
return this.http.get<IPlexLibResponse>(`${this.url}Libraries/${machineId}`, {headers: this.headers}); return this.http.get<IPlexLibSimpleResponse>(`${this.url}Libraries/${machineId}`, {headers: this.headers});
} }
public addUserToServer(user: IPlexUserViewModel): Observable<IPlexUserAddResponse> { public addUserToServer(user: IPlexUserViewModel): Observable<IPlexUserAddResponse> {

@ -3,6 +3,9 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>You can invite a user to share your Plex Library here. The invited user will be asked to confirm friendship.</p> <p>You can invite a user to share your Plex Library here. The invited user will be asked to confirm friendship.</p>
<p>Please note that this user will not appear in your Ombi Users since they have not accepted the Plex Invite, as soon as they accept
the Plex invite then the User Importer job will run (if enabled) and add the user into Ombi.
</p>
<div *ngIf="plexServers"> <div *ngIf="plexServers">
@ -39,21 +42,25 @@
<div *ngIf="!form.value.allLibsSelected"> <div *ngIf="!form.value.allLibsSelected">
<div *ngFor="let lib of plexLibs.mediaContainer.directory"> <div *ngFor="let lib of plexLibs">
<div class="form-group"> <div class="col-md-4">
<div class="checkbox"> <div class="checkbox">
<input type="checkbox" id="{{lib.key}}" value={{lib.key}} (change)="checkedLib($event.target.checked, $event.target.value)"> <input type="checkbox" id="{{lib.id}}" value={{lib.id}} (change)="checkedLib($event.target.checked, $event.target.value)">
<label for="{{lib.key}}">{{lib.title}}</label> <label for="{{lib.id}}">{{lib.title}}</label>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
<br>
<br>
<br>
</form> </form>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="submit" class="btn btn-primary-outline" (click)="onSubmit(form)" [disabled]="form.invalid">Add</button> <button type="button" class="btn btn-primary-outline" (click)="onSubmit(form)" [disabled]="form.invalid">Add</button>
<button type="button" class="btn btn-danger-outline" (click)="activeModal.close('Close click')">Close</button> <button type="button" class="btn btn-danger-outline" (click)="activeModal.close('Close click')">Close</button>
</div> </div>

@ -4,7 +4,7 @@ import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap";
import { NotificationService, PlexService } from "../services"; import { NotificationService, PlexService } from "../services";
import { IPlexLibraries, IPlexServersAdd } from "../interfaces"; import { IPlexSection, IPlexServersAdd } from "../interfaces";
@Component({ @Component({
selector: "ngbd-modal-content", selector: "ngbd-modal-content",
@ -15,7 +15,7 @@ export class AddPlexUserComponent implements OnInit {
@Input() public name: string; @Input() public name: string;
public plexServers: IPlexServersAdd[]; public plexServers: IPlexServersAdd[];
public plexLibs: IPlexLibraries; public plexLibs: IPlexSection[];
public libsSelected: number[] = []; public libsSelected: number[] = [];
@ -65,12 +65,11 @@ export class AddPlexUserComponent implements OnInit {
} }
public onSubmit(form: FormGroup) { public onSubmit(form: FormGroup) {
debugger;
if (form.invalid) { if (form.invalid) {
this.notificationService.error("Please check your entered values"); this.notificationService.error("Please check your entered values");
return; return;
} }
const libs = form.value.allLibsSelected ? this.plexLibs.mediaContainer.directory.map(x => +x.key) : this.libsSelected; const libs = form.value.allLibsSelected ? [] : this.libsSelected;
this.plexService.addUserToServer({ username: form.value.username, machineIdentifier: form.value.selectedServer, libsSelected: libs }).subscribe(x => { this.plexService.addUserToServer({ username: form.value.username, machineIdentifier: form.value.selectedServer, libsSelected: libs }).subscribe(x => {
if (x.success) { if (x.success) {
@ -78,6 +77,7 @@ export class AddPlexUserComponent implements OnInit {
} else { } else {
this.notificationService.error(x.error); this.notificationService.error(x.error);
} }
this.activeModal.close();
}); });
} }

@ -1,12 +1,13 @@
<h1>User Management</h1> <h1>User Management</h1>
<div *ngIf="plexEnabled">
<button type="button" style="float:right;" class="btn btn-success-outline" (click)="open()">Add Plex Friend</button>
<hr>
</div>
<button type="button" class="btn btn-success-outline" [routerLink]="['/usermanagement/add']">Add User To Ombi</button> <button type="button" class="btn btn-success-outline" [routerLink]="['/usermanagement/add']">Add User To Ombi</button>
<button type="button" style="float:right;" class="btn btn-primary-outline"(click)="showBulkEdit = !showBulkEdit" [disabled]="!hasChecked()">Bulk Edit</button> <button type="button" style="float:right;" class="btn btn-primary-outline"(click)="showBulkEdit = !showBulkEdit" [disabled]="!hasChecked()">Bulk Edit</button>
<div *ngIf="plexEnabled">
<button type="button" style="float:right;" class="btn btn-success-outline" (click)="open()">Add Plex Friend</button>
</div>
<!-- Table --> <!-- Table -->
<table class="table table-striped table-hover table-responsive table-condensed table-usermanagement"> <table class="table table-striped table-hover table-responsive table-condensed table-usermanagement">
<thead> <thead>

@ -977,7 +977,17 @@ a > h4:hover {
top: 7%; top: 7%;
} }
.modal-header { .modal.fade .modal-dialog {
background-color: #282828; -webkit-transform: translate(0, 0%);
padding-top:75px; -ms-transform: translate(0, 0%);
-o-transform: translate(0, 0%);
transform: translate(0, 0%);
-webkit-transition: -webkit-transform .3s ease-out;
-o-transition: -o-transform .3s ease-out;
transition: transform .3s ease-out;
}
.modal-footer .btn+.btn {
margin-left: 5px;
margin-bottom: 10px;
} }

@ -130,18 +130,18 @@ namespace Ombi.Controllers.External
[HttpGet("Libraries/{machineId}")] [HttpGet("Libraries/{machineId}")]
[PowerUser] [PowerUser]
public async Task<PlexLibrariesResponse> GetPlexLibraries(string machineId) public async Task<PlexLibrariesLiteResponse> GetPlexLibraries(string machineId)
{ {
try try
{ {
var s = await PlexSettings.GetSettingsAsync(); var s = await PlexSettings.GetSettingsAsync();
var settings = s.Servers.FirstOrDefault(x => x.MachineIdentifier == machineId); var settings = s.Servers.FirstOrDefault(x => x.MachineIdentifier == machineId);
var libs = await PlexApi.GetLibrarySections(settings.PlexAuthToken, settings.FullUri); var libs = await PlexApi.GetLibrariesForMachineId(settings.PlexAuthToken, machineId);
return new PlexLibrariesResponse return new PlexLibrariesLiteResponse
{ {
Successful = true, Successful = true,
Data = libs Data = libs.Server.Section
}; };
} }
catch (Exception e) catch (Exception e)
@ -149,7 +149,7 @@ namespace Ombi.Controllers.External
_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; var message = e.InnerException != null ? $"{e.Message} - {e.InnerException.Message}" : e.Message;
return new PlexLibrariesResponse return new PlexLibrariesLiteResponse
{ {
Successful = false, Successful = false,
Message = message Message = message

@ -25,6 +25,7 @@
// ************************************************************************/ // ************************************************************************/
#endregion #endregion
using System.Collections.Generic;
using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models;
namespace Ombi.Models.External namespace Ombi.Models.External
@ -35,4 +36,11 @@ namespace Ombi.Models.External
public bool Successful { get; set; } public bool Successful { get; set; }
public string Message { get; set; } public string Message { get; set; }
} }
public class PlexLibrariesLiteResponse
{
public List<SectionLite> Data { get; set; }
public bool Successful { get; set; }
public string Message { get; set; }
}
} }
Loading…
Cancel
Save