Added User Management support for Emby #435

This commit is contained in:
tidusjar 2017-01-30 21:58:13 +00:00
parent 4feb3cd462
commit 4193cb88fd
23 changed files with 354 additions and 118 deletions

View file

@ -51,5 +51,6 @@ namespace Ombi.Core.SettingModels
public int EmbyEpisodeCacher { get; set; } public int EmbyEpisodeCacher { get; set; }
public int EmbyContentCacher { get; set; } public int EmbyContentCacher { get; set; }
public int EmbyAvailabilityChecker { get; set; } public int EmbyAvailabilityChecker { get; set; }
public int EmbyUserChecker { get; set; }
} }
} }

View file

@ -0,0 +1,138 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: StoreCleanup.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Linq;
using NLog;
using Ombi.Api.Interfaces;
using Ombi.Core;
using Ombi.Core.SettingModels;
using Ombi.Core.Users;
using Ombi.Helpers.Permissions;
using Ombi.Services.Interfaces;
using Ombi.Store.Models.Emby;
using Ombi.Store.Repository;
using Quartz;
namespace Ombi.Services.Jobs
{
public class EmbyUserChecker : IJob, IEmbyUserChecker
{
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
public EmbyUserChecker(IExternalUserRepository<EmbyUsers> plexUsers, IEmbyApi embyApi, IJobRecord rec, ISettingsService<EmbySettings> embyS, ISettingsService<PlexRequestSettings> prSettings, ISettingsService<UserManagementSettings> umSettings,
IRequestService requestService, IUserRepository localUser)
{
Repo = plexUsers;
JobRecord = rec;
EmbyApi = embyApi;
EmbySettings = embyS;
PlexRequestSettings = prSettings;
UserManagementSettings = umSettings;
RequestService = requestService;
LocalUserRepository = localUser;
}
private IJobRecord JobRecord { get; }
private IEmbyApi EmbyApi { get; }
private IExternalUserRepository<EmbyUsers> Repo { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private ISettingsService<PlexRequestSettings> PlexRequestSettings { get; }
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
private IRequestService RequestService { get; }
private IUserRepository LocalUserRepository { get; }
public void Start()
{
JobRecord.SetRunning(true, JobNames.EmbyUserChecker);
try
{
var settings = EmbySettings.GetSettings();
if (string.IsNullOrEmpty(settings.ApiKey) || !settings.Enable)
{
return;
}
var embyUsers = EmbyApi.GetUsers(settings.FullUri, settings.ApiKey);
var userManagementSettings = UserManagementSettings.GetSettings();
var requests = RequestService.GetAll().ToList();
var dbUsers = Repo.GetAll().ToList();
var localUsers = LocalUserRepository.GetAll().ToList();
// Regular users
foreach (var user in embyUsers)
{
var dbUser = dbUsers.FirstOrDefault(x => x.EmbyUserId == user.Id);
if (dbUser != null)
{
// we already have a user
continue;
}
// Looks like it's a new user!
var m = new EmbyUsers
{
EmbyUserId = user.Id,
Permissions = UserManagementHelper.GetPermissions(userManagementSettings),
Features = UserManagementHelper.GetFeatures(userManagementSettings),
UserAlias = string.Empty,
Username = user.Name,
LoginId = Guid.NewGuid().ToString()
};
// If it's the admin, give them the admin permission
if (user.Policy.IsAdministrator)
{
if (!((Permissions) m.Permissions).HasFlag(Permissions.Administrator))
{
m.Permissions += (int)Permissions.Administrator;
}
}
Repo.Insert(m);
}
}
catch (Exception e)
{
Log.Error(e);
}
finally
{
JobRecord.SetRunning(false, JobNames.EmbyUserChecker);
JobRecord.Record(JobNames.EmbyUserChecker);
}
}
public void Execute(IJobExecutionContext context)
{
Start();
}
}
}

View file

@ -0,0 +1,10 @@
using Quartz;
namespace Ombi.Services.Jobs
{
public interface IEmbyUserChecker
{
void Execute(IJobExecutionContext context);
void Start();
}
}

View file

@ -45,6 +45,7 @@ namespace Ombi.Services.Jobs
public const string RecentlyAddedEmail = "Recently Added Email Notification"; public const string RecentlyAddedEmail = "Recently Added Email Notification";
public const string FaultQueueHandler = "Request Fault Queue Handler"; public const string FaultQueueHandler = "Request Fault Queue Handler";
public const string PlexUserChecker = "Plex User Checker"; public const string PlexUserChecker = "Plex User Checker";
public const string EmbyUserChecker = "Emby User Checker";
} }
} }

View file

@ -95,6 +95,7 @@
<Compile Include="Interfaces\IStoreBackup.cs" /> <Compile Include="Interfaces\IStoreBackup.cs" />
<Compile Include="Interfaces\IStoreCleanup.cs" /> <Compile Include="Interfaces\IStoreCleanup.cs" />
<Compile Include="Interfaces\IUserRequestLimitResetter.cs" /> <Compile Include="Interfaces\IUserRequestLimitResetter.cs" />
<Compile Include="Jobs\IEmbyUserChecker.cs" />
<Compile Include="Jobs\Interfaces\IEmbyEpisodeCacher.cs" /> <Compile Include="Jobs\Interfaces\IEmbyEpisodeCacher.cs" />
<Compile Include="Jobs\Interfaces\IEmbyContentCacher.cs" /> <Compile Include="Jobs\Interfaces\IEmbyContentCacher.cs" />
<Compile Include="Jobs\Interfaces\IEmbyAvailabilityChecker.cs" /> <Compile Include="Jobs\Interfaces\IEmbyAvailabilityChecker.cs" />
@ -104,6 +105,7 @@
<Compile Include="Jobs\EmbyAvailabilityChecker.cs" /> <Compile Include="Jobs\EmbyAvailabilityChecker.cs" />
<Compile Include="Jobs\EmbyContentCacher.cs" /> <Compile Include="Jobs\EmbyContentCacher.cs" />
<Compile Include="Jobs\EmbyEpisodeCacher.cs" /> <Compile Include="Jobs\EmbyEpisodeCacher.cs" />
<Compile Include="Jobs\EmbyUserChecker.cs" />
<Compile Include="Jobs\RadarrCacher.cs" /> <Compile Include="Jobs\RadarrCacher.cs" />
<Compile Include="Jobs\WatcherCacher.cs" /> <Compile Include="Jobs\WatcherCacher.cs" />
<Compile Include="Jobs\HtmlTemplateGenerator.cs" /> <Compile Include="Jobs\HtmlTemplateGenerator.cs" />

View file

@ -32,7 +32,7 @@ namespace Ombi.Store.Models.Emby
[Table(nameof(EmbyUsers))] [Table(nameof(EmbyUsers))]
public class EmbyUsers : Entity public class EmbyUsers : Entity
{ {
public string PlexUserId { get; set; } public string EmbyUserId { get; set; }
public string UserAlias { get; set; } public string UserAlias { get; set; }
public int Permissions { get; set; } public int Permissions { get; set; }
public int Features { get; set; } public int Features { get; set; }

View file

@ -33,7 +33,7 @@ using Ombi.Helpers;
namespace Ombi.Store.Repository namespace Ombi.Store.Repository
{ {
public class BaseExternalUserRepository<T> : BaseGenericRepository<T>, IExternalUserRepository<T> where T : class public class BaseExternalUserRepository<T> : BaseGenericRepository<T>, IExternalUserRepository<T> where T : Entity
{ {
public BaseExternalUserRepository(ISqliteConfiguration config, ICacheProvider cache) : base(config,cache) public BaseExternalUserRepository(ISqliteConfiguration config, ICacheProvider cache) : base(config,cache)
{ {

View file

@ -5,7 +5,7 @@ using System.Threading.Tasks;
namespace Ombi.Store.Repository namespace Ombi.Store.Repository
{ {
public interface IExternalUserRepository<T> where T : class public interface IExternalUserRepository<T> where T : Entity
{ {
T Get(string id); T Get(string id);
T Get(int id); T Get(int id);

View file

@ -128,7 +128,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS PlexUsers_Id ON PlexUsers (Id);
CREATE TABLE IF NOT EXISTS EmbyUsers CREATE TABLE IF NOT EXISTS EmbyUsers
( (
Id INTEGER PRIMARY KEY AUTOINCREMENT, Id INTEGER PRIMARY KEY AUTOINCREMENT,
PlexUserId varchar(100) NOT NULL, EmbyUserId varchar(100) NOT NULL,
UserAlias varchar(100) NOT NULL, UserAlias varchar(100) NOT NULL,
Permissions INTEGER, Permissions INTEGER,
Features INTEGER, Features INTEGER,

View file

@ -12,7 +12,10 @@
<strong>Email Address: </strong><span ng-bind="selectedUser.emailAddress"></span> <strong>Email Address: </strong><span ng-bind="selectedUser.emailAddress"></span>
</div> </div>
<div> <div>
<strong>User Type: </strong><span ng-bind="selectedUser.type === 1 ? 'Local User' : 'Plex User'"></span> <strong>User Type: </strong>
<span ng-if="selectedUser.type === 1">Local User</span>
<span ng-if="selectedUser.type === 2">Emby User</span>
<span ng-if="selectedUser.type === 3">Plex User</span>
</div> </div>
<br /> <br />
<br /> <br />

View file

@ -75,7 +75,9 @@
{{u.permissionsFormattedString}} {{u.permissionsFormattedString}}
</td> </td>
<td ng-hide="hideColumns"> <td ng-hide="hideColumns">
{{u.type === 1 ? 'Local User' : 'Plex User'}} <span ng-if="u.type === 1">Local User</span>
<span ng-if="u.type === 3">Plex User</span>
<span ng-if="u.type === 2">Emby User</span>
</td> </td>
<td ng-hide="hideColumns" ng-bind="u.lastLoggedIn === minDate ? 'Never' : formatDate(u.lastLoggedIn)"></td> <td ng-hide="hideColumns" ng-bind="u.lastLoggedIn === minDate ? 'Never' : formatDate(u.lastLoggedIn)"></td>
<td> <td>

View file

@ -25,12 +25,15 @@
$('#contentBody').on('click', '#embyApiKeySave', function (e) { $('#contentBody').on('click', '#embyApiKeySave', function (e) {
e.preventDefault(); e.preventDefault();
$('#spinner').attr("class", "fa fa-spinner fa-spin");
var $form = $("#embyAuthForm"); var $form = $("#embyAuthForm");
$.post($form.prop("action"), $form.serialize(), function (response) { $.post($form.prop("action"), $form.serialize(), function (response) {
if (response.result === true) { if (response.result === true) {
loadArea("authArea"); loadArea("authArea");
} else { } else {
$('#spinner').attr("class", "fa fa-times");
generateNotify(response.message, "warning"); generateNotify(response.message, "warning");
} }
}); });

View file

@ -78,6 +78,7 @@ namespace Ombi.UI.Jobs
JobBuilder.Create<EmbyEpisodeCacher>().WithIdentity("EmbyEpisodeCacher", "Emby").Build(), JobBuilder.Create<EmbyEpisodeCacher>().WithIdentity("EmbyEpisodeCacher", "Emby").Build(),
JobBuilder.Create<EmbyAvailabilityChecker>().WithIdentity("EmbyAvailabilityChecker", "Emby").Build(), JobBuilder.Create<EmbyAvailabilityChecker>().WithIdentity("EmbyAvailabilityChecker", "Emby").Build(),
JobBuilder.Create<EmbyContentCacher>().WithIdentity("EmbyContentCacher", "Emby").Build(), JobBuilder.Create<EmbyContentCacher>().WithIdentity("EmbyContentCacher", "Emby").Build(),
JobBuilder.Create<EmbyUserChecker>().WithIdentity("EmbyUserChecker", "Emby").Build(),
}; };
jobs.AddRange(jobList); jobs.AddRange(jobList);
@ -189,6 +190,10 @@ namespace Ombi.UI.Jobs
{ {
s.EmbyEpisodeCacher = 11; s.EmbyEpisodeCacher = 11;
} }
if (s.EmbyUserChecker == 0)
{
s.EmbyUserChecker = 24;
}
var triggers = new List<ITrigger>(); var triggers = new List<ITrigger>();
@ -311,11 +316,19 @@ namespace Ombi.UI.Jobs
.WithSimpleSchedule(x => x.WithIntervalInHours(s.EmbyContentCacher).RepeatForever()) .WithSimpleSchedule(x => x.WithIntervalInHours(s.EmbyContentCacher).RepeatForever())
.Build(); .Build();
var embyAvailabilityChecker = var embyAvailabilityChecker =
TriggerBuilder.Create()
.WithIdentity("EmbyAvailabilityChecker", "Emby")
.StartAt(DateBuilder.FutureDate(5, IntervalUnit.Minute))
.WithSimpleSchedule(x => x.WithIntervalInHours(s.EmbyAvailabilityChecker).RepeatForever())
.Build();
var embyUserChecker =
TriggerBuilder.Create() TriggerBuilder.Create()
.WithIdentity("EmbyAvailabilityChecker", "Emby") .WithIdentity("EmbyUserChecker", "Emby")
.StartAt(DateBuilder.FutureDate(5, IntervalUnit.Minute)) .StartNow()
.WithSimpleSchedule(x => x.WithIntervalInHours(s.EmbyAvailabilityChecker).RepeatForever()) //.StartAt(DateBuilder.FutureDate(1, IntervalUnit.Minute))
.WithSimpleSchedule(x => x.WithIntervalInHours(s.EmbyUserChecker).RepeatForever())
.Build(); .Build();
triggers.Add(rencentlyAdded); triggers.Add(rencentlyAdded);
@ -335,6 +348,7 @@ namespace Ombi.UI.Jobs
triggers.Add(embyEpisode); triggers.Add(embyEpisode);
triggers.Add(embyAvailabilityChecker); triggers.Add(embyAvailabilityChecker);
triggers.Add(embyContentCacher); triggers.Add(embyContentCacher);
triggers.Add(embyUserChecker);
return triggers; return triggers;
} }

View file

@ -33,6 +33,8 @@ namespace Ombi.UI.Models
{ {
public class ScheduledJobsViewModel : ScheduledJobsSettings public class ScheduledJobsViewModel : ScheduledJobsSettings
{ {
public bool Emby { get; set; }
public bool Plex { get; set; }
public Dictionary<string,DateTime> JobRecorder { get; set; } public Dictionary<string,DateTime> JobRecorder { get; set; }
} }
} }

View file

@ -1130,6 +1130,8 @@ namespace Ombi.UI.Modules.Admin
{ {
var s = await ScheduledJobSettings.GetSettingsAsync(); var s = await ScheduledJobSettings.GetSettingsAsync();
var allJobs = await JobRecorder.GetJobsAsync(); var allJobs = await JobRecorder.GetJobsAsync();
var emby = await EmbySettings.GetSettingsAsync();
var plex = await PlexService.GetSettingsAsync();
var dict = new Dictionary<string, DateTime>(); var dict = new Dictionary<string, DateTime>();
@ -1150,6 +1152,8 @@ namespace Ombi.UI.Modules.Admin
var model = new ScheduledJobsViewModel var model = new ScheduledJobsViewModel
{ {
Emby = emby.Enable,
Plex = plex.Enable,
CouchPotatoCacher = s.CouchPotatoCacher, CouchPotatoCacher = s.CouchPotatoCacher,
PlexAvailabilityChecker = s.PlexAvailabilityChecker, PlexAvailabilityChecker = s.PlexAvailabilityChecker,
SickRageCacher = s.SickRageCacher, SickRageCacher = s.SickRageCacher,

View file

@ -46,7 +46,7 @@ namespace Ombi.UI.Modules.Admin
IRadarrCacher radarrCacher, ICouchPotatoCacher cpCacher, IStoreBackup store, ISickRageCacher srCacher, IAvailabilityChecker plexChceker, IRadarrCacher radarrCacher, ICouchPotatoCacher cpCacher, IStoreBackup store, ISickRageCacher srCacher, IAvailabilityChecker plexChceker,
IStoreCleanup cleanup, IUserRequestLimitResetter requestLimit, IPlexEpisodeCacher episodeCacher, IRecentlyAdded recentlyAdded, IStoreCleanup cleanup, IUserRequestLimitResetter requestLimit, IPlexEpisodeCacher episodeCacher, IRecentlyAdded recentlyAdded,
IFaultQueueHandler faultQueueHandler, IPlexUserChecker plexUserChecker, IEmbyAvailabilityChecker embyAvailabilityChecker, IEmbyEpisodeCacher embyEpisode, IFaultQueueHandler faultQueueHandler, IPlexUserChecker plexUserChecker, IEmbyAvailabilityChecker embyAvailabilityChecker, IEmbyEpisodeCacher embyEpisode,
IEmbyContentCacher embyContentCacher) : base("admin", settingsService, security) IEmbyContentCacher embyContentCacher, IEmbyUserChecker embyUser) : base("admin", settingsService, security)
{ {
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx); Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
@ -67,6 +67,7 @@ namespace Ombi.UI.Modules.Admin
EmbyAvailabilityChecker = embyAvailabilityChecker; EmbyAvailabilityChecker = embyAvailabilityChecker;
EmbyContentCacher = embyContentCacher; EmbyContentCacher = embyContentCacher;
EmbyEpisodeCacher = embyEpisode; EmbyEpisodeCacher = embyEpisode;
EmbyUserChecker = embyUser;
Post["/schedulerun", true] = async (x, ct) => await ScheduleRun((string)Request.Form.key); Post["/schedulerun", true] = async (x, ct) => await ScheduleRun((string)Request.Form.key);
} }
@ -88,6 +89,7 @@ namespace Ombi.UI.Modules.Admin
private IEmbyAvailabilityChecker EmbyAvailabilityChecker { get; } private IEmbyAvailabilityChecker EmbyAvailabilityChecker { get; }
private IEmbyContentCacher EmbyContentCacher { get; } private IEmbyContentCacher EmbyContentCacher { get; }
private IEmbyEpisodeCacher EmbyEpisodeCacher { get; } private IEmbyEpisodeCacher EmbyEpisodeCacher { get; }
private IEmbyUserChecker EmbyUserChecker { get; }
private async Task<Response> ScheduleRun(string key) private async Task<Response> ScheduleRun(string key)
@ -162,6 +164,10 @@ namespace Ombi.UI.Modules.Admin
{ {
EmbyAvailabilityChecker.CheckAndUpdateAll(); EmbyAvailabilityChecker.CheckAndUpdateAll();
} }
if (key.Equals(JobNames.EmbyUserChecker, StringComparison.CurrentCultureIgnoreCase))
{
EmbyUserChecker.Start();
}
return Response.AsJson(new JsonResponseModel { Result = true }); return Response.AsJson(new JsonResponseModel { Result = true });

View file

@ -197,64 +197,95 @@ namespace Ombi.UI.Modules
} }
var plexSettings = await PlexSettings.GetSettingsAsync(); var plexSettings = await PlexSettings.GetSettingsAsync();
var plexDbUsers = await PlexUsersRepository.GetAllAsync(); if (plexSettings.Enable)
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
var plexDbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == model.Id);
var plexUser = plexUsers.User.FirstOrDefault(x => x.Id == model.Id);
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
if (plexDbUser != null && plexUser != null)
{ {
// We have a user in the DB for this Plex Account var plexDbUsers = await PlexUsersRepository.GetAllAsync();
plexDbUser.Permissions = permissionsValue; var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
plexDbUser.Features = featuresValue; var plexDbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == model.Id);
var plexUser = plexUsers.User.FirstOrDefault(x => x.Id == model.Id);
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias); var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
if (plexDbUser != null && plexUser != null)
plexDbUser.UserAlias = model.Alias;
plexDbUser.EmailAddress = model.EmailAddress;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexUser(plexUser, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// So it could actually be the admin
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
if (plexDbUser != null && account != null)
{
// We have a user in the DB for this Plex Account
plexDbUser.Permissions = permissionsValue;
plexDbUser.Features = featuresValue;
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
plexDbUser.UserAlias = model.Alias;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexAdmin(account, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// We have a Plex Account but he's not in the DB
if (plexUser != null)
{
var user = new PlexUsers
{ {
Permissions = permissionsValue, // We have a user in the DB for this Plex Account
Features = featuresValue, plexDbUser.Permissions = permissionsValue;
UserAlias = model.Alias, plexDbUser.Features = featuresValue;
PlexUserId = plexUser.Id,
EmailAddress = plexUser.Email,
Username = plexUser.Title,
LoginId = Guid.NewGuid().ToString()
};
await PlexUsersRepository.InsertAsync(user); await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
plexDbUser.UserAlias = model.Alias;
plexDbUser.EmailAddress = model.EmailAddress;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexUser(plexUser, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// So it could actually be the admin
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
if (plexDbUser != null && account != null)
{
// We have a user in the DB for this Plex Account
plexDbUser.Permissions = permissionsValue;
plexDbUser.Features = featuresValue;
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
plexDbUser.UserAlias = model.Alias;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexAdmin(account, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// We have a Plex Account but he's not in the DB
if (plexUser != null)
{
var user = new PlexUsers
{
Permissions = permissionsValue,
Features = featuresValue,
UserAlias = model.Alias,
PlexUserId = plexUser.Id,
EmailAddress = plexUser.Email,
Username = plexUser.Title,
LoginId = Guid.NewGuid().ToString()
};
await PlexUsersRepository.InsertAsync(user);
var retUser = MapPlexUser(plexUser, user, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
}
var embySettings = await EmbySettings.GetSettingsAsync();
if (embySettings.Enable)
{
var embyDbUsers = await EmbyRepository.GetAllAsync();
var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
var selectedDbUser = embyDbUsers.FirstOrDefault(x => x.EmbyUserId == model.Id);
var embyUser = embyUsers.FirstOrDefault(x => x.Id == model.Id);
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
if (selectedDbUser != null && embyUser != null)
{
// We have a user in the DB for this Plex Account
selectedDbUser.Permissions = permissionsValue;
selectedDbUser.Features = featuresValue;
await UpdateRequests(selectedDbUser.Username, selectedDbUser.UserAlias, model.Alias);
selectedDbUser.UserAlias = model.Alias;
selectedDbUser.EmailAddress = model.EmailAddress;
await EmbyRepository.UpdateAsync(selectedDbUser);
var retUser = MapEmbyUser(embyUser, selectedDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
var retUser = MapPlexUser(plexUser, user, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
} }
return null; // We should never end up here. return null; // We should never end up here.
} }
@ -535,7 +566,7 @@ namespace Ombi.UI.Modules
{ {
//Get Plex Users //Get Plex Users
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken); var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
if (plexUsers != null && plexUsers.User != null) if (plexUsers?.User != null)
{ {
foreach (var u in plexUsers.User) foreach (var u in plexUsers.User)
{ {
@ -585,12 +616,12 @@ namespace Ombi.UI.Modules
if (!string.IsNullOrEmpty(embySettings.ApiKey)) if (!string.IsNullOrEmpty(embySettings.ApiKey))
{ {
//Get Plex Users //Get Plex Users
var plexUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey); var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
if (plexUsers != null) if (embyUsers != null)
{ {
foreach (var u in plexUsers) foreach (var u in embyUsers)
{ {
var dbUser = embyDbUsers.FirstOrDefault(x => x.PlexUserId == u.Id); var dbUser = embyDbUsers.FirstOrDefault(x => x.EmbyUserId == u.Id);
var userDb = userLogins.FirstOrDefault(x => x.UserId == u.Id); var userDb = userLogins.FirstOrDefault(x => x.UserId == u.Id);
// We don't have the user in the database yet // We don't have the user in the database yet
@ -599,15 +630,6 @@ namespace Ombi.UI.Modules
: MapEmbyUser(u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue)); : MapEmbyUser(u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
} }
} }
// Also get the server admin
var account = PlexApi.GetAccount(embySettings.PlexAuthToken);
if (account != null)
{
var dbUser = embyDbUsers.FirstOrDefault(x => x.PlexUserId == account.Id);
var userDb = userLogins.FirstOrDefault(x => x.UserId == account.Id);
model.Add(MapPlexAdmin(account, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
} }
return Response.AsJson(model); return Response.AsJson(model);
} }

View file

@ -121,7 +121,7 @@ namespace Ombi.UI.Modules
if (model?.user == null) if (model?.user == null)
{ {
return return
Response.AsJson(new JsonResponseModel {Result = false, Message = "Incorrect username or password!"}); Response.AsJson(new JsonResponseModel { Result = false, Message = "Incorrect username or password!" });
} }
// Set the auth token in the session so we can use it in the next form // Set the auth token in the session so we can use it in the next form
@ -132,7 +132,7 @@ namespace Ombi.UI.Modules
return return
Response.AsJson( Response.AsJson(
new {Result = true, firstServer?.Port, Ip = firstServer?.LocalAddresses, firstServer?.Scheme}); new { Result = true, firstServer?.Port, Ip = firstServer?.LocalAddresses, firstServer?.Scheme });
} }
private async Task<Response> Plex() private async Task<Response> Plex()
@ -144,7 +144,7 @@ namespace Ombi.UI.Modules
return Response.AsJson(valid.SendJsonError()); return Response.AsJson(valid.SendJsonError());
} }
form.PlexAuthToken = Session[SessionKeys.UserWizardPlexAuth].ToString(); form.PlexAuthToken = Session[SessionKeys.UserWizardPlexAuth].ToString();
// Set the auth token from the previous form // Set the auth token from the previous form
// Get the machine ID from the settings (This could have changed) // Get the machine ID from the settings (This could have changed)
try try
@ -163,7 +163,7 @@ namespace Ombi.UI.Modules
var result = await PlexSettings.SaveSettingsAsync(form); var result = await PlexSettings.SaveSettingsAsync(form);
if (result) if (result)
{ {
return Response.AsJson(new JsonResponseModel {Result = true}); return Response.AsJson(new JsonResponseModel { Result = true });
} }
return return
Response.AsJson(new JsonResponseModel Response.AsJson(new JsonResponseModel
@ -189,7 +189,7 @@ namespace Ombi.UI.Modules
var result = await PlexRequestSettings.SaveSettingsAsync(currentSettings); var result = await PlexRequestSettings.SaveSettingsAsync(currentSettings);
if (result) if (result)
{ {
return Response.AsJson(new {Result = true}); return Response.AsJson(new { Result = true });
} }
return return
@ -207,7 +207,7 @@ namespace Ombi.UI.Modules
var result = await Auth.SaveSettingsAsync(form); var result = await Auth.SaveSettingsAsync(form);
if (result) if (result)
{ {
return Response.AsJson(new JsonResponseModel {Result = true}); return Response.AsJson(new JsonResponseModel { Result = true });
} }
return return
Response.AsJson(new JsonResponseModel Response.AsJson(new JsonResponseModel
@ -219,9 +219,9 @@ namespace Ombi.UI.Modules
private async Task<Response> CreateUser() private async Task<Response> CreateUser()
{ {
var username = (string) Request.Form.Username; var username = (string)Request.Form.Username;
var userId = Mapper.CreateUser(username, Request.Form.Password, var userId = Mapper.CreateUser(username, Request.Form.Password,
EnumHelper<Permissions>.All() - (int) Permissions.ReadOnlyUser, 0); EnumHelper<Permissions>.All() - (int)Permissions.ReadOnlyUser, 0);
Analytics.TrackEventAsync(Category.Wizard, Action.Finish, "Finished the wizard", username, Analytics.TrackEventAsync(Category.Wizard, Action.Finish, "Finished the wizard", username,
CookieHelper.GetAnalyticClientId(Cookies)); CookieHelper.GetAnalyticClientId(Cookies));
Session[SessionKeys.UsernameKey] = username; Session[SessionKeys.UsernameKey] = username;
@ -236,15 +236,15 @@ namespace Ombi.UI.Modules
var baseUrl = string.IsNullOrEmpty(settings.BaseUrl) ? string.Empty : $"/{settings.BaseUrl}"; var baseUrl = string.IsNullOrEmpty(settings.BaseUrl) ? string.Empty : $"/{settings.BaseUrl}";
return CustomModuleExtensions.LoginAndRedirect(this, (Guid) userId, fallbackRedirectUrl: $"{baseUrl}/search"); return CustomModuleExtensions.LoginAndRedirect(this, (Guid)userId, fallbackRedirectUrl: $"{baseUrl}/search");
} }
private async Task<Response> EmbyAuth() private async Task<Response> EmbyAuth()
{ {
var ip = (string) Request.Form.Ip; var ip = (string)Request.Form.Ip;
var port = (int) Request.Form.Port; var port = (int)Request.Form.Port;
var apiKey = (string) Request.Form.ApiKey; var apiKey = (string)Request.Form.ApiKey;
var ssl = (bool) Request.Form.Ssl; var ssl = (bool)Request.Form.Ssl;
var settings = new EmbySettings var settings = new EmbySettings
{ {
@ -262,7 +262,7 @@ namespace Ombi.UI.Modules
if (result != null && result.Any()) if (result != null && result.Any())
{ {
settings.AdministratorId = result.FirstOrDefault(x => x.Policy.IsAdministrator)?.Id ?? string.Empty;
await EmbySettings.SaveSettingsAsync(settings); await EmbySettings.SaveSettingsAsync(settings);
return Response.AsJson(new JsonResponseModel return Response.AsJson(new JsonResponseModel

View file

@ -63,6 +63,7 @@ namespace Ombi.UI.NinjectModules
Bind<IEmbyAvailabilityChecker>().To<EmbyAvailabilityChecker>(); Bind<IEmbyAvailabilityChecker>().To<EmbyAvailabilityChecker>();
Bind<IEmbyContentCacher>().To<EmbyContentCacher>(); Bind<IEmbyContentCacher>().To<EmbyContentCacher>();
Bind<IEmbyEpisodeCacher>().To<EmbyEpisodeCacher>(); Bind<IEmbyEpisodeCacher>().To<EmbyEpisodeCacher>();
Bind<IEmbyUserChecker>().To<EmbyUserChecker>();
Bind<IAnalytics>().To<Analytics>(); Bind<IAnalytics>().To<Analytics>();

View file

@ -36,21 +36,52 @@
<legend>Scheduler Settings</legend> <legend>Scheduler Settings</legend>
<small>Please note, you will need to restart for these settings to take effect</small> <small>Please note, you will need to restart for these settings to take effect</small>
<div class="form-group">
<label for="PlexAvailabilityChecker" class="control-label">Plex Availability Checker (min)</label>
<input type="text" class="form-control form-control-custom " id="PlexAvailabilityChecker" name="PlexAvailabilityChecker" value="@Model.PlexAvailabilityChecker">
</div>
<div class="form-group"> @if (Model.Plex)
<label for="PlexContentCacher" class="control-label">Plex Content Cacher (min)</label> {
<input type="text" class="form-control form-control-custom " id="PlexContentCacher" name="PlexContentCacher" value="@Model.PlexContentCacher"> <div class="form-group">
</div> <label for="PlexAvailabilityChecker" class="control-label">Plex Availability Checker (min)</label>
<input type="text" class="form-control form-control-custom " id="PlexAvailabilityChecker" name="PlexAvailabilityChecker" value="@Model.PlexAvailabilityChecker">
</div>
<div class="form-group"> <div class="form-group">
<label for="PlexUserChecker" class="control-label">Plex User Checker (hours)</label> <label for="PlexContentCacher" class="control-label">Plex Content Cacher (min)</label>
<input type="text" class="form-control form-control-custom " id="PlexUserChecker" name="PlexUserChecker" value="@Model.PlexUserChecker"> <input type="text" class="form-control form-control-custom " id="PlexContentCacher" name="PlexContentCacher" value="@Model.PlexContentCacher">
</div> </div>
<div class="form-group">
<label for="PlexUserChecker" class="control-label">Plex User Checker (hours)</label>
<input type="text" class="form-control form-control-custom " id="PlexUserChecker" name="PlexUserChecker" value="@Model.PlexUserChecker">
</div>
<small>Please note, the minimum time for this to run is 11 hours, if set below 11 then we will ignore that value. This is a very resource intensive job, the less we run it the better.</small>
<div class="form-group">
<label for="PlexEpisodeCacher" class="control-label">Plex Episode Cacher (hours)</label>
<input type="text" class="form-control form-control-custom " id="PlexEpisodeCacher" name="PlexEpisodeCacher" value="@Model.PlexEpisodeCacher">
</div>
}
@if (Model.Emby)
{
<div class="form-group">
<label for="EmbyAvailabilityChecker" class="control-label">Emby Availability Checker (min)</label>
<input type="text" class="form-control form-control-custom " id="EmbyAvailabilityChecker" name="EmbyAvailabilityChecker" value="@Model.EmbyAvailabilityChecker">
</div>
<div class="form-group">
<label for="EmbyContentCacher" class="control-label">Emby Content Cacher (min)</label>
<input type="text" class="form-control form-control-custom " id="EmbyContentCacher" name="EmbyContentCacher" value="@Model.EmbyContentCacher">
</div>
<div class="form-group">
<label for="EmbyUserChecker" class="control-label">Emby User Checker (hours)</label>
<input type="text" class="form-control form-control-custom " id="EmbyUserChecker" name="EmbyUserChecker" value="@Model.EmbyUserChecker">
</div>
<div class="form-group">
<label for="EmbyEpisodeCacher" class="control-label">Emby Episode Cacher (hours)</label>
<input type="text" class="form-control form-control-custom " id="EmbyEpisodeCacher" name="EmbyEpisodeCacher" value="@Model.EmbyEpisodeCacher">
</div>
}
<div class="form-group"> <div class="form-group">
<label for="CouchPotatoCacher" class="control-label">Couch Potato Cacher (min)</label> <label for="CouchPotatoCacher" class="control-label">Couch Potato Cacher (min)</label>
<input type="text" class="form-control form-control-custom " id="CouchPotatoCacher" name="CouchPotatoCacher" value="@Model.CouchPotatoCacher"> <input type="text" class="form-control form-control-custom " id="CouchPotatoCacher" name="CouchPotatoCacher" value="@Model.CouchPotatoCacher">
@ -64,11 +95,7 @@
<input type="text" class="form-control form-control-custom " id="RadarrCacher" name="RadarrCacher" value="@Model.RadarrCacher"> <input type="text" class="form-control form-control-custom " id="RadarrCacher" name="RadarrCacher" value="@Model.RadarrCacher">
</div> </div>
<small>Please note, the minimum time for this to run is 11 hours, if set below 11 then we will ignore that value. This is a very resource intensive job, the less we run it the better.</small>
<div class="form-group">
<label for="PlexEpisodeCacher" class="control-label">Plex Episode Cacher (hours)</label>
<input type="text" class="form-control form-control-custom " id="PlexEpisodeCacher" name="PlexEpisodeCacher" value="@Model.PlexEpisodeCacher">
</div>
<div class="form-group"> <div class="form-group">
<label for="SonarrCacher" class="control-label">Sonarr Cacher (min)</label> <label for="SonarrCacher" class="control-label">Sonarr Cacher (min)</label>

View file

@ -14,10 +14,10 @@
<input id="dateTimeOffset" name="DateTimeOffset" hidden="hidden" /> <input id="dateTimeOffset" name="DateTimeOffset" hidden="hidden" />
<div> <div>
<div> <div>
<label>@UI.UserLogin_Username</label> <label>Username</label>
</div> </div>
<div> <div>
<input id="username" class="form-control form-control-custom" type="text" name="Username" placeholder="@UI.UserLogin_Username_Placeholder" /> <input id="username" class="form-control form-control-custom" type="text" name="Username" placeholder="Username" />
</div> </div>
</div> </div>
<br /> <br />

View file

@ -64,7 +64,7 @@
<label for="portNumber" class="control-label">Port</label> <label for="portNumber" class="control-label">Port</label>
<div> <div>
<input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="8069"> <input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="8096">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -79,7 +79,7 @@
</div> </div>
</div> </div>
<div style="text-align: center; margin-top: 20px"> <div style="text-align: center; margin-top: 20px">
<a href="#" id="embyApiKeySave" class="btn btn-primary-outline">Next</a> <a href="#" id="embyApiKeySave" class="btn btn-primary-outline">Next <div id="spinner"></div></a>
</div> </div>
</form> </form>
</script> </script>