mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-15 01:32:55 -07:00
parent
1813b45fb3
commit
560072eba4
33 changed files with 279 additions and 91 deletions
|
@ -18,5 +18,6 @@ namespace Ombi.Api.Plex
|
|||
Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, int ratingKey);
|
||||
Task<PlexContainer> GetAllEpisodes(string authToken, string host, string section, int start, int retCount);
|
||||
Task<PlexFriends> GetUsers(string authToken);
|
||||
Task<PlexAccount> GetAccount(string authToken);
|
||||
}
|
||||
}
|
|
@ -2,13 +2,21 @@
|
|||
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class PlexAccount
|
||||
{
|
||||
public User user { get; set; }
|
||||
}
|
||||
|
||||
public class User
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string email { get; set; }
|
||||
public string uuid { get; set; }
|
||||
public string joined_at { get; set; }
|
||||
public string username { get; set; }
|
||||
public string title { get; set; }
|
||||
public string thumb { get; set; }
|
||||
public string hasPassword { get; set; }
|
||||
public string authentication_token { get; set; }
|
||||
public Subscription subscription { get; set; }
|
||||
public Roles roles { get; set; }
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Ombi.Api.Plex
|
|||
|
||||
private const string SignInUri = "https://plex.tv/users/sign_in.json";
|
||||
private const string FriendsUri = "https://plex.tv/pms/friends/all";
|
||||
private const string GetAccountUri = "https://plex.tv/users/account";
|
||||
private const string GetAccountUri = "https://plex.tv/users/account.json";
|
||||
private const string ServerUri = "https://plex.tv/pms/servers.xml";
|
||||
|
||||
/// <summary>
|
||||
|
@ -52,6 +52,13 @@ namespace Ombi.Api.Plex
|
|||
return await Api.Request<PlexStatus>(request);
|
||||
}
|
||||
|
||||
public async Task<PlexAccount> GetAccount(string authToken)
|
||||
{
|
||||
var request = new Request(GetAccountUri, string.Empty, HttpMethod.Get);
|
||||
AddHeaders(request, authToken);
|
||||
return await Api.Request<PlexAccount>(request);
|
||||
}
|
||||
|
||||
public async Task<PlexServer> GetServer(string authToken)
|
||||
{
|
||||
var request = new Request(ServerUri, string.Empty, HttpMethod.Get, ContentType.Xml);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.Rule.Rules.Request;
|
||||
using Ombi.Store.Entities.Requests;
|
||||
using NUnit.Framework;
|
||||
using Ombi.Helpers;
|
||||
|
||||
namespace Ombi.Core.Tests.Rule.Request
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@ using System.Security.Principal;
|
|||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.Rule.Rules;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Store.Entities.Requests;
|
||||
|
||||
namespace Ombi.Core.Tests.Rule.Request
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Rule.Interfaces;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Store.Entities;
|
||||
using Ombi.Store.Entities.Requests;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using Ombi.Core.Claims;
|
||||
using Ombi.Store.Entities;
|
||||
using Ombi.Store.Entities;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Rule.Interfaces;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Store.Entities.Requests;
|
||||
|
||||
namespace Ombi.Core.Rule.Rules
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.Rule.Interfaces;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Store.Entities.Requests;
|
||||
|
||||
namespace Ombi.Core.Rule.Rules.Specific
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace Ombi.Core.Senders
|
|||
// Get the root path from the rootfolder selected.
|
||||
// For some reason, if we haven't got one use the first root folder in Sonarr
|
||||
// TODO make this overrideable via the UI
|
||||
var rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? 0, s);
|
||||
var rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? int.Parse(s.RootPath), s);
|
||||
try
|
||||
{
|
||||
// Does the series actually exist?
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace Ombi.Core.Claims
|
||||
namespace Ombi.Helpers
|
||||
{
|
||||
public static class OmbiRoles
|
||||
{
|
|
@ -39,7 +39,7 @@ namespace Ombi.Notifications.Interfaces
|
|||
|
||||
public async Task NotifyAsync(NotificationOptions model)
|
||||
{
|
||||
var configuration = GetConfiguration();
|
||||
var configuration = await GetConfiguration();
|
||||
await NotifyAsync(model, configuration);
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,12 @@ namespace Ombi.Notifications.Interfaces
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the TV or Movie Request
|
||||
/// </summary>
|
||||
/// <param name="requestId"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual async Task LoadRequest(int requestId, RequestType type)
|
||||
{
|
||||
if (type == RequestType.Movie)
|
||||
|
@ -112,12 +118,19 @@ namespace Ombi.Notifications.Interfaces
|
|||
}
|
||||
}
|
||||
|
||||
private T GetConfiguration()
|
||||
private async Task<T> GetConfiguration()
|
||||
{
|
||||
var settings = Settings.GetSettings();
|
||||
var settings = await Settings.GetSettingsAsync();
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the correct template from the DB
|
||||
/// </summary>
|
||||
/// <param name="agent"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual async Task<NotificationMessageContent> LoadTemplate(NotificationAgent agent, NotificationType type, NotificationOptions model)
|
||||
{
|
||||
var template = await TemplateRepository.GetTemplate(agent, type);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
@ -44,6 +45,8 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.PlexUser).ToListAsync();
|
||||
foreach (var server in settings.Servers)
|
||||
{
|
||||
|
@ -52,6 +55,8 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
continue;
|
||||
}
|
||||
|
||||
await ImportAdmin(userManagementSettings, server, allUsers);
|
||||
|
||||
var users = await _api.GetUsers(server.PlexAuthToken);
|
||||
|
||||
foreach (var plexUser in users.User)
|
||||
|
@ -80,12 +85,8 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
};
|
||||
_log.LogInformation("Creating Plex user {0}", newUser.UserName);
|
||||
var result = await _userManager.CreateAsync(newUser);
|
||||
if (!result.Succeeded)
|
||||
if (!LogResult(result))
|
||||
{
|
||||
foreach (var identityError in result.Errors)
|
||||
{
|
||||
_log.LogError(LoggingEvents.PlexUserImporter, identityError.Description);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (userManagementSettings.DefaultRoles.Any())
|
||||
|
@ -107,5 +108,59 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ImportAdmin(UserManagementSettings settings, PlexServers server, List<OmbiUser> allUsers)
|
||||
{
|
||||
if (!settings.ImportPlexAdmin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var plexAdmin = (await _api.GetAccount(server.PlexAuthToken)).user;
|
||||
|
||||
// Check if the admin is already in the DB
|
||||
var adminUserFromDb = allUsers.FirstOrDefault(x =>
|
||||
x.ProviderUserId.Equals(plexAdmin.id, StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
if (adminUserFromDb != null)
|
||||
{
|
||||
// Let's update the user
|
||||
adminUserFromDb.Email = plexAdmin.email;
|
||||
adminUserFromDb.UserName = plexAdmin.username;
|
||||
adminUserFromDb.ProviderUserId = plexAdmin.id;
|
||||
await _userManager.UpdateAsync(adminUserFromDb);
|
||||
return;
|
||||
}
|
||||
|
||||
var newUser = new OmbiUser
|
||||
{
|
||||
UserType = UserType.PlexUser,
|
||||
UserName = plexAdmin.username ?? plexAdmin.id,
|
||||
ProviderUserId = plexAdmin.id,
|
||||
Email = plexAdmin.email ?? string.Empty,
|
||||
Alias = string.Empty
|
||||
};
|
||||
|
||||
var result = await _userManager.CreateAsync(newUser);
|
||||
if (!LogResult(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var roleResult = await _userManager.AddToRoleAsync(newUser, OmbiRoles.Admin);
|
||||
LogResult(roleResult);
|
||||
}
|
||||
|
||||
private bool LogResult(IdentityResult result)
|
||||
{
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
foreach (var identityError in result.Errors)
|
||||
{
|
||||
_log.LogError(LoggingEvents.PlexUserImporter, identityError.Description);
|
||||
}
|
||||
}
|
||||
return result.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,8 +13,6 @@ namespace Ombi.Core.Settings.Models.External
|
|||
public class PlexServers : ExternalSettings
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool EnableEpisodeSearching { get; set; }
|
||||
|
||||
public string PlexAuthToken { get; set; }
|
||||
public string MachineIdentifier { get; set; }
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Ombi.Settings.Settings.Models
|
|||
{
|
||||
public class UserManagementSettings : Settings
|
||||
{
|
||||
public bool ImportPlexAdmin { get; set; }
|
||||
public bool ImportPlexUsers { get; set; }
|
||||
public bool ImportEmbyUsers { get; set; }
|
||||
public List<string> DefaultRoles { get; set; } = new List<string>();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Helpers;
|
||||
|
||||
namespace Ombi.Attributes
|
||||
{
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<p-growl [value]="notificationService.messages" [life]="3000"></p-growl>
|
||||
|
||||
<div *ngIf="user.name">
|
||||
<div *ngIf="hasRole('Admin') || hasRole('PowerUser')" class="adminUser"></div>
|
||||
</div>
|
||||
<nav *ngIf="showNav" class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
|
|
|
@ -122,6 +122,7 @@ export interface IAuthenticationSettings extends ISettings {
|
|||
|
||||
export interface IUserManagementSettings extends ISettings {
|
||||
importPlexUsers: boolean;
|
||||
importPlexAdmin: boolean;
|
||||
importEmbyUsers: boolean;
|
||||
defaultRoles: string[];
|
||||
bannedPlexUserIds: string[];
|
||||
|
|
|
@ -14,6 +14,12 @@ export interface IUser {
|
|||
checked: boolean;
|
||||
}
|
||||
|
||||
export interface ICreateWizardUser {
|
||||
username: string;
|
||||
password: string;
|
||||
usePlexAdminAccount: boolean;
|
||||
}
|
||||
|
||||
export enum UserType {
|
||||
LocalUser = 1,
|
||||
PlexUser = 2,
|
||||
|
|
|
@ -28,7 +28,7 @@ export class MovieSearchComponent implements OnInit {
|
|||
private readonly translate: TranslateService, private sanitizer: DomSanitizer) {
|
||||
|
||||
this.searchChanged
|
||||
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||
.distinctUntilChanged() // only emit if value is different from previous value
|
||||
.subscribe(x => {
|
||||
this.searchText = x as string;
|
||||
|
@ -40,9 +40,9 @@ export class MovieSearchComponent implements OnInit {
|
|||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.searchApplied = true;
|
||||
// Now let's load some exta info including IMDBId
|
||||
// Now let's load some extra info including IMDB Id
|
||||
// This way the search is fast at displaying results.
|
||||
this.getExtaInfo();
|
||||
this.getExtraInfo();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ export class MovieSearchComponent implements OnInit {
|
|||
this.searchService.popularMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
public nowPlayingMovies() {
|
||||
|
@ -111,7 +111,7 @@ export class MovieSearchComponent implements OnInit {
|
|||
this.searchService.nowPlayingMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
public topRatedMovies() {
|
||||
|
@ -119,19 +119,19 @@ export class MovieSearchComponent implements OnInit {
|
|||
this.searchService.topRatedMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
public upcomingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.upcomignMovies()
|
||||
this.searchService.upcomingMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
this.getExtraInfo();
|
||||
});
|
||||
}
|
||||
|
||||
private getExtaInfo() {
|
||||
private getExtraInfo() {
|
||||
|
||||
this.movieResults.forEach((val, index) => {
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ export class MovieSearchGridComponent implements OnInit {
|
|||
}
|
||||
public upcomingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.upcomignMovies()
|
||||
this.searchService.upcomingMovies()
|
||||
.subscribe(x => {
|
||||
this.movieResults = x;
|
||||
this.getExtaInfo();
|
||||
|
@ -130,7 +130,7 @@ export class MovieSearchGridComponent implements OnInit {
|
|||
}
|
||||
|
||||
private getExtaInfo() {
|
||||
this.movieResults.forEach((val, index) => {
|
||||
this.movieResults.forEach((val) => {
|
||||
this.searchService.getMovieInformation(val.id)
|
||||
.subscribe(m => this.updateItem(val, m));
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Http } from "@angular/http";
|
|||
import { AuthHttp } from "angular2-jwt";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
|
||||
import { ICheckbox, IIdentityResult, IResetPasswordToken, IUpdateLocalUser, IUser } from "../interfaces";
|
||||
import { ICheckbox, ICreateWizardUser, IIdentityResult, IResetPasswordToken, IUpdateLocalUser, IUser } from "../interfaces";
|
||||
import { ServiceAuthHelpers } from "./service.helpers";
|
||||
|
||||
@Injectable()
|
||||
|
@ -12,8 +12,8 @@ export class IdentityService extends ServiceAuthHelpers {
|
|||
constructor(http: AuthHttp, private regularHttp: Http, public platformLocation: PlatformLocation) {
|
||||
super(http, "/api/v1/Identity/", platformLocation);
|
||||
}
|
||||
public createWizardUser(username: string, password: string): Observable<boolean> {
|
||||
return this.regularHttp.post(`${this.url}Wizard/`, JSON.stringify({ username, password }), { headers: this.headers }).map(this.extractData);
|
||||
public createWizardUser(user: ICreateWizardUser): Observable<boolean> {
|
||||
return this.regularHttp.post(`${this.url}Wizard/`, JSON.stringify(user), { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
|
||||
public getUser(): Observable<IUser> {
|
||||
|
|
|
@ -22,7 +22,7 @@ export class SearchService extends ServiceAuthHelpers {
|
|||
public popularMovies(): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get(`${this.url}/Movie/Popular`).map(this.extractData);
|
||||
}
|
||||
public upcomignMovies(): Observable<ISearchMovieResult[]> {
|
||||
public upcomingMovies(): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get(`${this.url}/Movie/upcoming`).map(this.extractData);
|
||||
}
|
||||
public nowPlayingMovies(): Observable<ISearchMovieResult[]> {
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
<label for="importPlex">Import Plex Users</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="importAdmin" [(ngModel)]="settings.importPlexAdmin">
|
||||
<label for="importAdmin">Import Plex Admin</label>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="plexUsers">
|
||||
<p>Plex Users exclude from Import</p>
|
||||
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
<h1>User Management</h1>
|
||||
|
||||
|
||||
<!--Search-->
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon left-radius">
|
||||
<i class="fa fa-search"></i>
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control" id="search" placeholder="Search" [(ngModel)]="searchTerm">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<button type="button" class="btn btn-success-outline" [routerLink]="['/usermanagement/add']">Add User</button>
|
||||
<!-- Table -->
|
||||
|
|
|
@ -18,7 +18,7 @@ export class CreateAdminComponent {
|
|||
private router: Router, private auth: AuthService, private settings: SettingsService) { }
|
||||
|
||||
public createUser() {
|
||||
this.identityService.createWizardUser(this.username, this.password).subscribe(x => {
|
||||
this.identityService.createWizardUser({username: this.username, password: this.password, usePlexAdminAccount: false}).subscribe(x => {
|
||||
if (x) {
|
||||
// Log me in.
|
||||
this.auth.login({ username: this.username, password: this.password, rememberMe:false }).subscribe(c => {
|
||||
|
|
|
@ -23,3 +23,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p-confirmDialog></p-confirmDialog>
|
|
@ -1,8 +1,11 @@
|
|||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { ConfirmationService } from "primeng/primeng";
|
||||
|
||||
import { PlexService } from "../../services";
|
||||
import { NotificationService } from "../../services";
|
||||
import { IdentityService, NotificationService, SettingsService } from "../../services";
|
||||
import { AuthService } from "./../../auth/auth.service";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./plex.component.html",
|
||||
|
@ -12,7 +15,12 @@ export class PlexComponent {
|
|||
public login: string;
|
||||
public password: string;
|
||||
|
||||
constructor(private plexService: PlexService, private router: Router, private notificationService: NotificationService) { }
|
||||
constructor(private plexService: PlexService, private router: Router,
|
||||
private notificationService: NotificationService,
|
||||
private confirmationService: ConfirmationService,
|
||||
private identityService: IdentityService,
|
||||
private settings: SettingsService,
|
||||
private auth: AuthService) { }
|
||||
|
||||
public requestAuthToken() {
|
||||
this.plexService.logIn(this.login, this.password).subscribe(x => {
|
||||
|
@ -20,7 +28,46 @@ export class PlexComponent {
|
|||
this.notificationService.error("Username or password was incorrect. Could not authenticate with Plex.");
|
||||
return;
|
||||
}
|
||||
this.router.navigate(["Wizard/CreateAdmin"]);
|
||||
this.confirmationService.confirm({
|
||||
message: "Do you want your Plex user to be the main admin account on Ombi?",
|
||||
header: "Use Plex Account",
|
||||
icon: "fa fa-check",
|
||||
accept: () => {
|
||||
this.identityService.createWizardUser({
|
||||
username: "",
|
||||
password: "",
|
||||
usePlexAdminAccount: true,
|
||||
}).subscribe(x => {
|
||||
if (x) {
|
||||
this.auth.login({ username: this.login, password: this.password, rememberMe:false }).subscribe(c => {
|
||||
localStorage.setItem("id_token", c.access_token);
|
||||
|
||||
// Mark that we have done the settings now
|
||||
this.settings.getOmbi().subscribe(ombi => {
|
||||
ombi.wizard = true;
|
||||
|
||||
this.settings.saveOmbi(ombi).subscribe(x => {
|
||||
this.settings.getUserManagementSettings().subscribe(usr => {
|
||||
|
||||
usr.importPlexAdmin = true;
|
||||
this.settings.saveUserManagementSettings(usr).subscribe(saved => {
|
||||
this.router.navigate(["login"]);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.notificationService.error("Could not get the Plex Admin Information");
|
||||
return;
|
||||
}
|
||||
});
|
||||
},
|
||||
reject: () => {
|
||||
this.router.navigate(["Wizard/CreateAdmin"]);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ import { NgModule } from "@angular/core";
|
|||
import { FormsModule } from "@angular/forms";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import {ConfirmationService, ConfirmDialogModule } from "primeng/primeng";
|
||||
|
||||
import { CreateAdminComponent } from "./createadmin/createadmin.component";
|
||||
import { EmbyComponent } from "./emby/emby.component";
|
||||
import { MediaServerComponent } from "./mediaserver/mediaserver.component";
|
||||
|
@ -25,6 +27,7 @@ const routes: Routes = [
|
|||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ConfirmDialogModule,
|
||||
RouterModule.forChild(routes),
|
||||
],
|
||||
declarations: [
|
||||
|
@ -41,6 +44,7 @@ const routes: Routes = [
|
|||
PlexService,
|
||||
IdentityService,
|
||||
EmbyService,
|
||||
ConfirmationService,
|
||||
],
|
||||
|
||||
})
|
||||
|
|
48
src/Ombi/Controllers/External/PlexController.cs
vendored
48
src/Ombi/Controllers/External/PlexController.cs
vendored
|
@ -43,32 +43,30 @@ namespace Ombi.Controllers.External
|
|||
{
|
||||
try
|
||||
{
|
||||
// Do we already have settings?
|
||||
_log.LogDebug("OK, signing into Plex");
|
||||
var settings = await PlexSettings.GetSettingsAsync();
|
||||
if (!settings.Servers?.Any() ?? false) return null;
|
||||
|
||||
_log.LogDebug("This is our first time, good to go!");
|
||||
|
||||
// Do we already have settings?
|
||||
_log.LogDebug("OK, signing into Plex");
|
||||
var settings = await PlexSettings.GetSettingsAsync();
|
||||
if (!settings.Servers?.Any() ?? false) return null;
|
||||
var result = await PlexApi.SignIn(request);
|
||||
|
||||
_log.LogDebug("This is our first time, good to go!");
|
||||
|
||||
var result = await PlexApi.SignIn(request);
|
||||
|
||||
_log.LogDebug("Attempting to sign in to Plex.Tv");
|
||||
if (!string.IsNullOrEmpty(result.user?.authentication_token))
|
||||
{
|
||||
_log.LogDebug("Sign in successful");
|
||||
_log.LogDebug("Getting servers");
|
||||
var server = await PlexApi.GetServer(result.user.authentication_token);
|
||||
var servers = server.Server.FirstOrDefault();
|
||||
if (servers == null)
|
||||
_log.LogDebug("Attempting to sign in to Plex.Tv");
|
||||
if (!string.IsNullOrEmpty(result.user?.authentication_token))
|
||||
{
|
||||
_log.LogWarning("Looks like we can't find any Plex Servers");
|
||||
}
|
||||
_log.LogDebug("Adding first server");
|
||||
_log.LogDebug("Sign in successful");
|
||||
_log.LogDebug("Getting servers");
|
||||
var server = await PlexApi.GetServer(result.user.authentication_token);
|
||||
var servers = server.Server.FirstOrDefault();
|
||||
if (servers == null)
|
||||
{
|
||||
_log.LogWarning("Looks like we can't find any Plex Servers");
|
||||
}
|
||||
_log.LogDebug("Adding first server");
|
||||
|
||||
settings.Enable = true;
|
||||
settings.Servers = new List<PlexServers> {
|
||||
settings.Enable = true;
|
||||
settings.Servers = new List<PlexServers> {
|
||||
new PlexServers
|
||||
{
|
||||
PlexAuthToken = result.user.authentication_token,
|
||||
|
@ -81,11 +79,11 @@ namespace Ombi.Controllers.External
|
|||
}
|
||||
};
|
||||
|
||||
await PlexSettings.SaveSettingsAsync(settings);
|
||||
}
|
||||
await PlexSettings.SaveSettingsAsync(settings);
|
||||
}
|
||||
|
||||
_log.LogDebug("Finished");
|
||||
return result;
|
||||
_log.LogDebug("Finished");
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -12,14 +12,15 @@ using Microsoft.AspNetCore.Mvc;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using Ombi.Api.Plex;
|
||||
using Ombi.Attributes;
|
||||
using Ombi.Config;
|
||||
using Ombi.Core.Authentication;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.Helpers;
|
||||
using Ombi.Core.Models.UI;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Models;
|
||||
using Ombi.Models.Identity;
|
||||
using Ombi.Notifications;
|
||||
|
@ -35,6 +36,7 @@ using OmbiIdentityResult = Ombi.Models.Identity.IdentityResult;
|
|||
|
||||
namespace Ombi.Controllers
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// The Identity Controller, the API for everything Identity/User related
|
||||
/// </summary>
|
||||
|
@ -48,7 +50,9 @@ namespace Ombi.Controllers
|
|||
IWelcomeEmail welcome,
|
||||
IMovieRequestRepository m,
|
||||
ITvRequestRepository t,
|
||||
ILogger<IdentityController> l)
|
||||
ILogger<IdentityController> l,
|
||||
IPlexApi plexApi,
|
||||
ISettingsService<PlexSettings> settings)
|
||||
{
|
||||
UserManager = user;
|
||||
Mapper = mapper;
|
||||
|
@ -60,6 +64,8 @@ namespace Ombi.Controllers
|
|||
MovieRepo = m;
|
||||
TvRepo = t;
|
||||
_log = l;
|
||||
_plexApi = plexApi;
|
||||
_plexSettings = settings;
|
||||
}
|
||||
|
||||
private OmbiUserManager UserManager { get; }
|
||||
|
@ -71,7 +77,9 @@ namespace Ombi.Controllers
|
|||
private IWelcomeEmail WelcomeEmail { get; }
|
||||
private IMovieRequestRepository MovieRepo { get; }
|
||||
private ITvRequestRepository TvRepo { get; }
|
||||
private ILogger<IdentityController> _log;
|
||||
private readonly ILogger<IdentityController> _log;
|
||||
private readonly IPlexApi _plexApi;
|
||||
private readonly ISettingsService<PlexSettings> _plexSettings;
|
||||
|
||||
/// <summary>
|
||||
/// This is what the Wizard will call when creating the user for the very first time.
|
||||
|
@ -85,7 +93,7 @@ namespace Ombi.Controllers
|
|||
[HttpPost("Wizard")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
[AllowAnonymous]
|
||||
public async Task<bool> CreateWizardUser([FromBody] UserAuthModel user)
|
||||
public async Task<bool> CreateWizardUser([FromBody] CreateUserWizardModel user)
|
||||
{
|
||||
var users = UserManager.Users;
|
||||
if (users.Any())
|
||||
|
@ -94,13 +102,48 @@ namespace Ombi.Controllers
|
|||
return false;
|
||||
}
|
||||
|
||||
if (user.UsePlexAdminAccount)
|
||||
{
|
||||
var settings = await _plexSettings.GetSettingsAsync();
|
||||
var authToken = settings.Servers.FirstOrDefault()?.PlexAuthToken ?? string.Empty;
|
||||
if (authToken.IsNullOrEmpty())
|
||||
{
|
||||
_log.LogWarning("Could not find an auth token to create the plex user with");
|
||||
return false;
|
||||
}
|
||||
var plexUser = await _plexApi.GetAccount(authToken);
|
||||
var adminUser = new OmbiUser
|
||||
{
|
||||
UserName = plexUser.user.username,
|
||||
UserType = UserType.PlexUser,
|
||||
Email = plexUser.user.email,
|
||||
ProviderUserId = plexUser.user.id
|
||||
};
|
||||
|
||||
return await SaveWizardUser(user, adminUser);
|
||||
}
|
||||
|
||||
var userToCreate = new OmbiUser
|
||||
{
|
||||
UserName = user.Username,
|
||||
UserType = UserType.LocalUser
|
||||
};
|
||||
|
||||
var result = await UserManager.CreateAsync(userToCreate, user.Password);
|
||||
return await SaveWizardUser(user, userToCreate);
|
||||
}
|
||||
|
||||
private async Task<bool> SaveWizardUser(CreateUserWizardModel user, OmbiUser userToCreate)
|
||||
{
|
||||
IdentityResult result;
|
||||
// When creating the admin as the plex user, we do not pass in the password.
|
||||
if (user.Password.HasValue())
|
||||
{
|
||||
result = await UserManager.CreateAsync(userToCreate, user.Password);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await UserManager.CreateAsync(userToCreate);
|
||||
}
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_log.LogInformation("Created User {0}", userToCreate.UserName);
|
||||
|
|
|
@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Ombi.Core.Authentication;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Models;
|
||||
using Ombi.Models.Identity;
|
||||
using Ombi.Store.Entities;
|
||||
|
|
9
src/Ombi/Models/CreateUserWizardModel.cs
Normal file
9
src/Ombi/Models/CreateUserWizardModel.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Models
|
||||
{
|
||||
public class CreateUserWizardModel
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public bool UsePlexAdminAccount { get; set; }
|
||||
}
|
||||
}
|
|
@ -5,5 +5,6 @@
|
|||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public bool RememberMe { get; set; }
|
||||
public bool UsePlexAdminAccount { get; set; }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue