mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-11 15:56:05 -07:00
Added the user login for emby users #435
This commit is contained in:
parent
4193cb88fd
commit
643676e7ea
15 changed files with 296 additions and 137 deletions
|
@ -12,5 +12,6 @@ namespace Ombi.Api.Interfaces
|
||||||
List<EmbyUser> GetUsers(Uri baseUri, string apiKey);
|
List<EmbyUser> GetUsers(Uri baseUri, string apiKey);
|
||||||
EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri);
|
EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri);
|
||||||
EmbyInformation GetInformation(string mediaId, EmbyMediaType type, string apiKey, string userId, Uri baseUri);
|
EmbyInformation GetInformation(string mediaId, EmbyMediaType type, string apiKey, string userId, Uri baseUri);
|
||||||
|
EmbyUser LogIn(string username, string password, string apiKey, Uri baseUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -45,4 +45,9 @@ namespace Ombi.Api.Models.Emby
|
||||||
public EmbyConfiguration Configuration { get; set; }
|
public EmbyConfiguration Configuration { get; set; }
|
||||||
public EmbyPolicy Policy { get; set; }
|
public EmbyPolicy Policy { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class EmbyUserLogin
|
||||||
|
{
|
||||||
|
public EmbyUser User { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -27,9 +27,12 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Ombi.Api.Interfaces;
|
using Ombi.Api.Interfaces;
|
||||||
using Ombi.Api.Models.Emby;
|
using Ombi.Api.Models.Emby;
|
||||||
|
using Ombi.Helpers;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
|
|
||||||
namespace Ombi.Api
|
namespace Ombi.Api
|
||||||
|
@ -152,6 +155,43 @@ namespace Ombi.Api
|
||||||
return GetAll<EmbySeriesItem>("Series", apiKey, userId, baseUri);
|
return GetAll<EmbySeriesItem>("Series", apiKey, userId, baseUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EmbyUser LogIn(string username, string password, string apiKey, Uri baseUri)
|
||||||
|
{
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Resource = "emby/users/authenticatebyname",
|
||||||
|
Method = Method.POST
|
||||||
|
};
|
||||||
|
|
||||||
|
var body = new
|
||||||
|
{
|
||||||
|
username,
|
||||||
|
password = StringHasher.GetSha1Hash(password).ToLower(),
|
||||||
|
passwordMd5 = StringHasher.CalcuateMd5Hash(password)
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddJsonBody(body);
|
||||||
|
|
||||||
|
request.AddHeader("X-Emby-Authorization",
|
||||||
|
$"MediaBrowser Client=\"Ombi\", Device=\"Ombi\", DeviceId=\"{AssemblyHelper.GetProductVersion()}\", Version=\"{AssemblyHelper.GetAssemblyVersion()}\"");
|
||||||
|
AddHeaders(request, apiKey);
|
||||||
|
|
||||||
|
|
||||||
|
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling LogInfor Emby, Retrying {0}", timespan), new[] {
|
||||||
|
TimeSpan.FromSeconds (1),
|
||||||
|
TimeSpan.FromSeconds(5)
|
||||||
|
});
|
||||||
|
|
||||||
|
var obj = policy.Execute(() => Api.Execute(request, baseUri));
|
||||||
|
|
||||||
|
if (obj.StatusCode == HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonConvert.DeserializeObject<EmbyUserLogin>(obj.Content)?.User;
|
||||||
|
}
|
||||||
|
|
||||||
private EmbyItemContainer<T> GetAll<T>(string type, string apiKey, string userId, Uri baseUri)
|
private EmbyItemContainer<T> GetAll<T>(string type, string apiKey, string userId, Uri baseUri)
|
||||||
{
|
{
|
||||||
var request = new RestRequest
|
var request = new RestRequest
|
||||||
|
@ -180,9 +220,13 @@ namespace Ombi.Api
|
||||||
|
|
||||||
private static void AddHeaders(IRestRequest req, string apiKey)
|
private static void AddHeaders(IRestRequest req, string apiKey)
|
||||||
{
|
{
|
||||||
req.AddHeader("X-MediaBrowser-Token", apiKey);
|
if (!string.IsNullOrEmpty(apiKey))
|
||||||
|
{
|
||||||
|
req.AddHeader("X-MediaBrowser-Token", apiKey);
|
||||||
|
}
|
||||||
req.AddHeader("Accept", "application/json");
|
req.AddHeader("Accept", "application/json");
|
||||||
req.AddHeader("Content-Type", "application/json");
|
req.AddHeader("Content-Type", "application/json");
|
||||||
|
req.AddHeader("Device", "Ombi");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ namespace Ombi.Core
|
||||||
Func<NancyContext, Response> HttpStatusCodeIfNot(HttpStatusCode statusCode, Func<NancyContext, bool> test);
|
Func<NancyContext, Response> HttpStatusCodeIfNot(HttpStatusCode statusCode, Func<NancyContext, bool> test);
|
||||||
bool IsLoggedIn(NancyContext context);
|
bool IsLoggedIn(NancyContext context);
|
||||||
bool IsNormalUser(IUserIdentity user);
|
bool IsNormalUser(IUserIdentity user);
|
||||||
bool IsPlexUser(IUserIdentity user);
|
bool IsExternalUser(IUserIdentity user);
|
||||||
bool HasPermissions(string userName, Permissions perm);
|
bool HasPermissions(string userName, Permissions perm);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -36,6 +36,7 @@ using Ombi.Core.SettingModels;
|
||||||
using Ombi.Core.Users;
|
using Ombi.Core.Users;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Helpers.Permissions;
|
using Ombi.Helpers.Permissions;
|
||||||
|
using Ombi.Store.Models.Emby;
|
||||||
using Ombi.Store.Models.Plex;
|
using Ombi.Store.Models.Plex;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
|
@ -43,17 +44,20 @@ namespace Ombi.Core
|
||||||
{
|
{
|
||||||
public class SecurityExtensions : ISecurityExtensions
|
public class SecurityExtensions : ISecurityExtensions
|
||||||
{
|
{
|
||||||
public SecurityExtensions(IUserRepository userRepository, IResourceLinker linker, IExternalUserRepository<PlexUsers> plexUsers, ISettingsService<UserManagementSettings> umSettings)
|
public SecurityExtensions(IUserRepository userRepository, IResourceLinker linker, IExternalUserRepository<PlexUsers> plexUsers, ISettingsService<UserManagementSettings> umSettings,
|
||||||
|
IExternalUserRepository<EmbyUsers> embyUsers)
|
||||||
{
|
{
|
||||||
UserRepository = userRepository;
|
UserRepository = userRepository;
|
||||||
Linker = linker;
|
Linker = linker;
|
||||||
PlexUsers = plexUsers;
|
PlexUsers = plexUsers;
|
||||||
UserManagementSettings = umSettings;
|
UserManagementSettings = umSettings;
|
||||||
|
EmbyUsers = embyUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IUserRepository UserRepository { get; }
|
private IUserRepository UserRepository { get; }
|
||||||
private IResourceLinker Linker { get; }
|
private IResourceLinker Linker { get; }
|
||||||
private IExternalUserRepository<PlexUsers> PlexUsers { get; }
|
private IExternalUserRepository<PlexUsers> PlexUsers { get; }
|
||||||
|
private IExternalUserRepository<EmbyUsers> EmbyUsers { get; }
|
||||||
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
|
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
|
||||||
|
|
||||||
public bool IsLoggedIn(NancyContext context)
|
public bool IsLoggedIn(NancyContext context)
|
||||||
|
@ -70,16 +74,18 @@ namespace Ombi.Core
|
||||||
return realUser || plexUser;
|
return realUser || plexUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPlexUser(IUserIdentity user)
|
public bool IsExternalUser(IUserIdentity user)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var plexUser = PlexUsers.GetUserByUsername(user.UserName);
|
var plexUser = PlexUsers.GetUserByUsername(user.UserName);
|
||||||
return plexUser != null;
|
var embyUser = EmbyUsers.GetUserByUsername(user.UserName);
|
||||||
}
|
|
||||||
|
|
||||||
|
return plexUser != null || embyUser != null;
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsNormalUser(IUserIdentity user)
|
public bool IsNormalUser(IUserIdentity user)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
|
@ -107,6 +113,12 @@ namespace Ombi.Core
|
||||||
return !string.IsNullOrEmpty(plexUser.UserAlias) ? plexUser.UserAlias : plexUser.Username;
|
return !string.IsNullOrEmpty(plexUser.UserAlias) ? plexUser.UserAlias : plexUser.Username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var embyUser = EmbyUsers.GetUserByUsername(username);
|
||||||
|
if (embyUser != null)
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(embyUser.UserAlias) ? embyUser.UserAlias : embyUser.Username;
|
||||||
|
}
|
||||||
|
|
||||||
var dbUser = UserRepository.GetUserByUsername(username);
|
var dbUser = UserRepository.GetUserByUsername(username);
|
||||||
if (dbUser != null)
|
if (dbUser != null)
|
||||||
{
|
{
|
||||||
|
@ -303,6 +315,12 @@ namespace Ombi.Core
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var embyUsers = EmbyUsers.GetUserByUsername(userName);
|
||||||
|
if (embyUsers != null)
|
||||||
|
{
|
||||||
|
return (Permissions) embyUsers.Permissions;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
@ -49,5 +50,10 @@ namespace Ombi.Helpers
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetSha1Hash(string input)
|
||||||
|
{
|
||||||
|
return string.Join("", (new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input))).Select(x => x.ToString("x2")).ToArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -81,10 +81,8 @@ namespace Ombi.Services.Jobs
|
||||||
}
|
}
|
||||||
var embyUsers = EmbyApi.GetUsers(settings.FullUri, settings.ApiKey);
|
var embyUsers = EmbyApi.GetUsers(settings.FullUri, settings.ApiKey);
|
||||||
var userManagementSettings = UserManagementSettings.GetSettings();
|
var userManagementSettings = UserManagementSettings.GetSettings();
|
||||||
var requests = RequestService.GetAll().ToList();
|
|
||||||
|
|
||||||
var dbUsers = Repo.GetAll().ToList();
|
var dbUsers = Repo.GetAll().ToList();
|
||||||
var localUsers = LocalUserRepository.GetAll().ToList();
|
|
||||||
|
|
||||||
// Regular users
|
// Regular users
|
||||||
foreach (var user in embyUsers)
|
foreach (var user in embyUsers)
|
||||||
|
|
|
@ -30,6 +30,8 @@ using System.Data;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Models.Emby;
|
||||||
|
using Ombi.Store.Models.Plex;
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
|
@ -43,9 +45,25 @@ namespace Ombi.Store.Repository
|
||||||
private ISqliteConfiguration DbConfig { get; }
|
private ISqliteConfiguration DbConfig { get; }
|
||||||
private IDbConnection Db => DbConfig.DbConnection();
|
private IDbConnection Db => DbConfig.DbConnection();
|
||||||
|
|
||||||
|
private string TableName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (typeof(T) == typeof(PlexUsers))
|
||||||
|
{
|
||||||
|
return "PlexUsers";
|
||||||
|
}
|
||||||
|
if (typeof(T) == typeof(EmbyUsers))
|
||||||
|
{
|
||||||
|
return "EmbyUsers";
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public T GetUser(string userGuid)
|
public T GetUser(string userGuid)
|
||||||
{
|
{
|
||||||
var sql = @"SELECT * FROM PlexUsers
|
var sql = $@"SELECT * FROM {TableName}
|
||||||
WHERE PlexUserId = @UserGuid
|
WHERE PlexUserId = @UserGuid
|
||||||
COLLATE NOCASE";
|
COLLATE NOCASE";
|
||||||
return Db.QueryFirstOrDefault<T>(sql, new {UserGuid = userGuid});
|
return Db.QueryFirstOrDefault<T>(sql, new {UserGuid = userGuid});
|
||||||
|
@ -53,7 +71,7 @@ namespace Ombi.Store.Repository
|
||||||
|
|
||||||
public T GetUserByUsername(string username)
|
public T GetUserByUsername(string username)
|
||||||
{
|
{
|
||||||
var sql = @"SELECT * FROM PlexUsers
|
var sql = $@"SELECT * FROM {TableName}
|
||||||
WHERE Username = @UserName
|
WHERE Username = @UserName
|
||||||
COLLATE NOCASE";
|
COLLATE NOCASE";
|
||||||
return Db.QueryFirstOrDefault<T>(sql, new {UserName = username});
|
return Db.QueryFirstOrDefault<T>(sql, new {UserName = username});
|
||||||
|
@ -61,7 +79,7 @@ namespace Ombi.Store.Repository
|
||||||
|
|
||||||
public async Task<T> GetUserAsync(string userguid)
|
public async Task<T> GetUserAsync(string userguid)
|
||||||
{
|
{
|
||||||
var sql = @"SELECT * FROM PlexUsers
|
var sql = $@"SELECT * FROM {TableName}
|
||||||
WHERE PlexUserId = @UserGuid
|
WHERE PlexUserId = @UserGuid
|
||||||
COLLATE NOCASE";
|
COLLATE NOCASE";
|
||||||
return await Db.QueryFirstOrDefaultAsync<T>(sql, new {UserGuid = userguid});
|
return await Db.QueryFirstOrDefaultAsync<T>(sql, new {UserGuid = userguid});
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using Nancy.Cryptography;
|
using Nancy.Cryptography;
|
||||||
|
using Ombi.Store.Models.Emby;
|
||||||
using Ombi.Store.Models.Plex;
|
using Ombi.Store.Models.Plex;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ namespace Ombi.UI.Authentication
|
||||||
public IUserRepository LocalUserRepository { get; set; }
|
public IUserRepository LocalUserRepository { get; set; }
|
||||||
|
|
||||||
public IExternalUserRepository<PlexUsers> PlexUserRepository { get; set; }
|
public IExternalUserRepository<PlexUsers> PlexUserRepository { get; set; }
|
||||||
|
public IExternalUserRepository<EmbyUsers> EmbyUserRepository { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets RequiresSSL property</summary>
|
/// <summary>Gets or sets RequiresSSL property</summary>
|
||||||
/// <value>The flag that indicates whether SSL is required</value>
|
/// <value>The flag that indicates whether SSL is required</value>
|
||||||
|
|
|
@ -42,6 +42,7 @@ using Ombi.Core;
|
||||||
using Ombi.Core.SettingModels;
|
using Ombi.Core.SettingModels;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Store;
|
using Ombi.Store;
|
||||||
|
using Ombi.Store.Models.Emby;
|
||||||
using Ombi.Store.Models.Plex;
|
using Ombi.Store.Models.Plex;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
using Ombi.UI.Authentication;
|
using Ombi.UI.Authentication;
|
||||||
|
@ -89,7 +90,8 @@ namespace Ombi.UI
|
||||||
var config = new CustomAuthenticationConfiguration
|
var config = new CustomAuthenticationConfiguration
|
||||||
{
|
{
|
||||||
RedirectUrl = redirect,
|
RedirectUrl = redirect,
|
||||||
PlexUserRepository = container.Get<IExternalUserRepository<PlexUsers>>(), // TODO emby
|
PlexUserRepository = container.Get<IExternalUserRepository<PlexUsers>>(),
|
||||||
|
EmbyUserRepository = container.Get<IExternalUserRepository<EmbyUsers>>(),
|
||||||
LocalUserRepository = container.Get<IUserRepository>()
|
LocalUserRepository = container.Get<IUserRepository>()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,9 @@ namespace Ombi.UI.Helpers
|
||||||
return Security.IsLoggedIn(context);
|
return Security.IsLoggedIn(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsPlexUser(this HtmlHelpers helper)
|
public static bool IsExternalUser(this HtmlHelpers helper)
|
||||||
{
|
{
|
||||||
return Security.IsPlexUser(helper.CurrentUser);
|
return Security.IsExternalUser(helper.CurrentUser);
|
||||||
}
|
}
|
||||||
public static bool IsNormalUser(this HtmlHelpers helper)
|
public static bool IsNormalUser(this HtmlHelpers helper)
|
||||||
{
|
{
|
||||||
|
|
|
@ -326,8 +326,8 @@ namespace Ombi.UI.Jobs
|
||||||
var embyUserChecker =
|
var embyUserChecker =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("EmbyUserChecker", "Emby")
|
.WithIdentity("EmbyUserChecker", "Emby")
|
||||||
.StartNow()
|
//.StartNow()
|
||||||
//.StartAt(DateBuilder.FutureDate(1, IntervalUnit.Minute))
|
.StartAt(DateBuilder.FutureDate(1, IntervalUnit.Minute))
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInHours(s.EmbyUserChecker).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInHours(s.EmbyUserChecker).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ using Nancy.Linker;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Ombi.Api;
|
using Ombi.Api;
|
||||||
using Ombi.Api.Interfaces;
|
using Ombi.Api.Interfaces;
|
||||||
|
using Ombi.Api.Models.Emby;
|
||||||
using Ombi.Api.Models.Plex;
|
using Ombi.Api.Models.Plex;
|
||||||
using Ombi.Core;
|
using Ombi.Core;
|
||||||
using Ombi.Core.SettingModels;
|
using Ombi.Core.SettingModels;
|
||||||
|
@ -45,6 +46,7 @@ using Ombi.Helpers.Analytics;
|
||||||
using Ombi.Helpers.Permissions;
|
using Ombi.Helpers.Permissions;
|
||||||
using Ombi.Store;
|
using Ombi.Store;
|
||||||
using Ombi.Store.Models;
|
using Ombi.Store.Models;
|
||||||
|
using Ombi.Store.Models.Emby;
|
||||||
using Ombi.Store.Models.Plex;
|
using Ombi.Store.Models.Plex;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
using Ombi.UI.Authentication;
|
using Ombi.UI.Authentication;
|
||||||
|
@ -57,7 +59,7 @@ namespace Ombi.UI.Modules
|
||||||
{
|
{
|
||||||
public UserLoginModule(ISettingsService<AuthenticationSettings> auth, IPlexApi api, ISettingsService<PlexSettings> plexSettings, ISettingsService<PlexRequestSettings> pr,
|
public UserLoginModule(ISettingsService<AuthenticationSettings> auth, IPlexApi api, ISettingsService<PlexSettings> plexSettings, ISettingsService<PlexRequestSettings> pr,
|
||||||
ISettingsService<LandingPageSettings> lp, IAnalytics a, IResourceLinker linker, IRepository<UserLogins> userLogins, IExternalUserRepository<PlexUsers> plexUsers, ICustomUserMapper custom,
|
ISettingsService<LandingPageSettings> lp, IAnalytics a, IResourceLinker linker, IRepository<UserLogins> userLogins, IExternalUserRepository<PlexUsers> plexUsers, ICustomUserMapper custom,
|
||||||
ISecurityExtensions security, ISettingsService<UserManagementSettings> userManagementSettings)
|
ISecurityExtensions security, ISettingsService<UserManagementSettings> userManagementSettings, IEmbyApi embyApi, ISettingsService<EmbySettings> emby, IExternalUserRepository<EmbyUsers> embyU)
|
||||||
: base("userlogin", pr, security)
|
: base("userlogin", pr, security)
|
||||||
{
|
{
|
||||||
AuthService = auth;
|
AuthService = auth;
|
||||||
|
@ -70,45 +72,9 @@ namespace Ombi.UI.Modules
|
||||||
PlexUserRepository = plexUsers;
|
PlexUserRepository = plexUsers;
|
||||||
CustomUserMapper = custom;
|
CustomUserMapper = custom;
|
||||||
UserManagementSettings = userManagementSettings;
|
UserManagementSettings = userManagementSettings;
|
||||||
|
EmbySettings = emby;
|
||||||
//Get["UserLoginIndex", "/", true] = async (x, ct) =>
|
EmbyApi = embyApi;
|
||||||
//{
|
EmbyUserRepository = embyU;
|
||||||
// if (Request.Query["landing"] == null)
|
|
||||||
// {
|
|
||||||
// var s = await LandingPageSettings.GetSettingsAsync();
|
|
||||||
// if (s.Enabled)
|
|
||||||
// {
|
|
||||||
// if (s.BeforeLogin) // Before login
|
|
||||||
// {
|
|
||||||
// if (string.IsNullOrEmpty(Username))
|
|
||||||
// {
|
|
||||||
// // They are not logged in
|
|
||||||
// return
|
|
||||||
// Context.GetRedirect(Linker.BuildRelativeUri(Context, "LandingPageIndex").ToString());
|
|
||||||
// }
|
|
||||||
// return Context.GetRedirect(Linker.BuildRelativeUri(Context, "SearchIndex").ToString());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // After login
|
|
||||||
// if (string.IsNullOrEmpty(Username))
|
|
||||||
// {
|
|
||||||
// // Not logged in yet
|
|
||||||
// return Context.GetRedirect(Linker.BuildRelativeUri(Context, "UserLoginIndex").ToString() + "?landing");
|
|
||||||
// }
|
|
||||||
// // Send them to landing
|
|
||||||
// var landingUrl = Linker.BuildRelativeUri(Context, "LandingPageIndex").ToString();
|
|
||||||
// return Context.GetRedirect(landingUrl);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!string.IsNullOrEmpty(Username) || IsAdmin)
|
|
||||||
// {
|
|
||||||
// var url = Linker.BuildRelativeUri(Context, "SearchIndex").ToString();
|
|
||||||
// return Response.AsRedirect(url);
|
|
||||||
// }
|
|
||||||
// var settings = await AuthService.GetSettingsAsync();
|
|
||||||
// return View["Index", settings];
|
|
||||||
//};
|
|
||||||
|
|
||||||
Post["/", true] = async (x, ct) => await LoginUser();
|
Post["/", true] = async (x, ct) => await LoginUser();
|
||||||
Get["/logout"] = x => Logout();
|
Get["/logout"] = x => Logout();
|
||||||
|
@ -159,11 +125,14 @@ namespace Ombi.UI.Modules
|
||||||
private ISettingsService<AuthenticationSettings> AuthService { get; }
|
private ISettingsService<AuthenticationSettings> AuthService { get; }
|
||||||
private ISettingsService<LandingPageSettings> LandingPageSettings { get; }
|
private ISettingsService<LandingPageSettings> LandingPageSettings { get; }
|
||||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||||
|
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||||
private IPlexApi Api { get; }
|
private IPlexApi Api { get; }
|
||||||
|
private IEmbyApi EmbyApi { get; }
|
||||||
private IResourceLinker Linker { get; }
|
private IResourceLinker Linker { get; }
|
||||||
private IAnalytics Analytics { get; }
|
private IAnalytics Analytics { get; }
|
||||||
private IRepository<UserLogins> UserLogins { get; }
|
private IRepository<UserLogins> UserLogins { get; }
|
||||||
private IExternalUserRepository<PlexUsers> PlexUserRepository { get; }
|
private IExternalUserRepository<PlexUsers> PlexUserRepository { get; }
|
||||||
|
private IExternalUserRepository<EmbyUsers> EmbyUserRepository { get; }
|
||||||
private ICustomUserMapper CustomUserMapper { get; }
|
private ICustomUserMapper CustomUserMapper { get; }
|
||||||
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
|
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
|
||||||
|
|
||||||
|
@ -182,41 +151,77 @@ namespace Ombi.UI.Modules
|
||||||
}
|
}
|
||||||
|
|
||||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||||
|
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||||
|
|
||||||
var authenticated = false;
|
var authenticated = false;
|
||||||
var isOwner = false;
|
var isOwner = false;
|
||||||
var userId = string.Empty;
|
var userId = string.Empty;
|
||||||
|
EmbyUser embyUser = null;
|
||||||
|
|
||||||
if (settings.UserAuthentication) // Check against the users in Plex
|
if (plexSettings.Enable)
|
||||||
{
|
{
|
||||||
Log.Debug("Need to auth");
|
if (settings.UserAuthentication) // Check against the users in Plex
|
||||||
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
|
||||||
if (authenticated)
|
|
||||||
{
|
{
|
||||||
userId = GetUserIdIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
Log.Debug("Need to auth");
|
||||||
|
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||||
|
if (authenticated)
|
||||||
|
{
|
||||||
|
userId = GetUserIdIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||||
|
}
|
||||||
|
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, username))
|
||||||
|
{
|
||||||
|
Log.Debug("User is the account owner");
|
||||||
|
authenticated = true;
|
||||||
|
isOwner = true;
|
||||||
|
userId = GetOwnerId(plexSettings.PlexAuthToken, username);
|
||||||
|
}
|
||||||
|
UsersModel dbUser = await IsDbuser(username);
|
||||||
|
if (dbUser != null) // in the db?
|
||||||
|
{
|
||||||
|
var perms = (Permissions) dbUser.Permissions;
|
||||||
|
authenticated = true;
|
||||||
|
isOwner = perms.HasFlag(Permissions.Administrator);
|
||||||
|
userId = dbUser.UserGuid;
|
||||||
|
}
|
||||||
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
}
|
}
|
||||||
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, username))
|
else if (!settings.UserAuthentication) // No auth, let them pass!
|
||||||
{
|
{
|
||||||
Log.Debug("User is the account owner");
|
|
||||||
authenticated = true;
|
authenticated = true;
|
||||||
isOwner = true;
|
|
||||||
userId = GetOwnerId(plexSettings.PlexAuthToken, username);
|
|
||||||
}
|
}
|
||||||
UsersModel dbUser = await IsDbuser(username);
|
|
||||||
if (dbUser != null) // in the db?
|
|
||||||
{
|
|
||||||
var perms = (Permissions)dbUser.Permissions;
|
|
||||||
authenticated = true;
|
|
||||||
isOwner = perms.HasFlag(Permissions.Administrator);
|
|
||||||
userId = dbUser.UserGuid;
|
|
||||||
}
|
|
||||||
Log.Debug("Friends list result = {0}", authenticated);
|
|
||||||
}
|
}
|
||||||
else if (!settings.UserAuthentication) // No auth, let them pass!
|
if (embySettings.Enable)
|
||||||
{
|
{
|
||||||
authenticated = true;
|
if (settings.UserAuthentication) // Check against the users in Plex
|
||||||
|
{
|
||||||
|
Log.Debug("Need to auth");
|
||||||
|
authenticated = CheckIfEmbyUser(username, embySettings);
|
||||||
|
if (authenticated)
|
||||||
|
{
|
||||||
|
embyUser = GetEmbyUser(username, embySettings);
|
||||||
|
userId = embyUser?.Id;
|
||||||
|
}
|
||||||
|
if (embyUser?.Policy?.IsAdministrator ?? false)
|
||||||
|
{
|
||||||
|
Log.Debug("User is the account owner");
|
||||||
|
authenticated = true;
|
||||||
|
isOwner = true;
|
||||||
|
}
|
||||||
|
UsersModel dbUser = await IsDbuser(username);
|
||||||
|
if (dbUser != null) // in the db?
|
||||||
|
{
|
||||||
|
var perms = (Permissions)dbUser.Permissions;
|
||||||
|
authenticated = true;
|
||||||
|
isOwner = perms.HasFlag(Permissions.Administrator);
|
||||||
|
userId = dbUser.UserGuid;
|
||||||
|
}
|
||||||
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
|
}
|
||||||
|
else if (!settings.UserAuthentication) // No auth, let them pass!
|
||||||
|
{
|
||||||
|
authenticated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.UsePassword || isOwner || Security.HasPermissions(username, Permissions.Administrator))
|
if (settings.UsePassword || isOwner || Security.HasPermissions(username, Permissions.Administrator))
|
||||||
{
|
{
|
||||||
Session[SessionKeys.UserLoginName] = username;
|
Session[SessionKeys.UserLoginName] = username;
|
||||||
|
@ -232,7 +237,7 @@ namespace Ombi.UI.Modules
|
||||||
{
|
{
|
||||||
return Response.AsJson(new { result = false, message = Resources.UI.UserLogin_IncorrectUserPass });
|
return Response.AsJson(new { result = false, message = Resources.UI.UserLogin_IncorrectUserPass });
|
||||||
}
|
}
|
||||||
var result = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner);
|
var result = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner, plexSettings.Enable, embySettings.Enable);
|
||||||
|
|
||||||
|
|
||||||
var landingSettings = await LandingPageSettings.GetSettingsAsync();
|
var landingSettings = await LandingPageSettings.GetSettingsAsync();
|
||||||
|
@ -294,26 +299,54 @@ namespace Ombi.UI.Modules
|
||||||
var userId = string.Empty;
|
var userId = string.Empty;
|
||||||
|
|
||||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||||
|
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||||
|
|
||||||
if (settings.UserAuthentication) // Authenticate with Plex
|
if (plexSettings.Enable)
|
||||||
{
|
{
|
||||||
Log.Debug("Need to auth and also provide pass");
|
if (settings.UserAuthentication) // Authenticate with Plex
|
||||||
var signedIn = (PlexAuthentication)Api.SignIn(username, password);
|
|
||||||
if (signedIn.user?.authentication_token != null)
|
|
||||||
{
|
{
|
||||||
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
Log.Debug("Need to auth and also provide pass");
|
||||||
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, signedIn.user?.username))
|
var signedIn = (PlexAuthentication) Api.SignIn(username, password);
|
||||||
|
if (signedIn.user?.authentication_token != null)
|
||||||
{
|
{
|
||||||
Log.Debug("User is the account owner");
|
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
||||||
authenticated = true;
|
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, signedIn.user?.username))
|
||||||
isOwner = true;
|
{
|
||||||
|
Log.Debug("User is the account owner");
|
||||||
|
authenticated = true;
|
||||||
|
isOwner = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||||
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
|
}
|
||||||
|
userId = signedIn.user.uuid;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
}
|
||||||
|
if (embySettings.Enable)
|
||||||
|
{
|
||||||
|
if (settings.UserAuthentication) // Authenticate with Plex
|
||||||
|
{
|
||||||
|
Log.Debug("Need to auth and also provide pass");
|
||||||
|
var signedIn = (EmbyUser)EmbyApi.LogIn(username, password, embySettings.ApiKey, embySettings.FullUri);
|
||||||
|
if (signedIn != null)
|
||||||
{
|
{
|
||||||
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
||||||
Log.Debug("Friends list result = {0}", authenticated);
|
if (signedIn?.Policy?.IsAdministrator ?? false)
|
||||||
|
{
|
||||||
|
Log.Debug("User is the account owner");
|
||||||
|
authenticated = true;
|
||||||
|
isOwner = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
authenticated = CheckIfEmbyUser(username, embySettings);
|
||||||
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
|
}
|
||||||
|
userId = signedIn?.Id;
|
||||||
}
|
}
|
||||||
userId = signedIn.user.uuid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +366,7 @@ namespace Ombi.UI.Modules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var m = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner);
|
var m = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner, plexSettings.Enable, embySettings.Enable);
|
||||||
|
|
||||||
var landingSettings = await LandingPageSettings.GetSettingsAsync();
|
var landingSettings = await LandingPageSettings.GetSettingsAsync();
|
||||||
|
|
||||||
|
@ -555,59 +588,47 @@ namespace Ombi.UI.Modules
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<LoginModel> AuthenticationSetup(string userId, string username, int dateTimeOffset, Guid loginGuid, bool isOwner)
|
private async Task<LoginModel> AuthenticationSetup(string userId, string username, int dateTimeOffset, Guid loginGuid, bool isOwner, bool plex, bool emby)
|
||||||
{
|
{
|
||||||
var m = new LoginModel();
|
var m = new LoginModel();
|
||||||
var settings = await AuthService.GetSettingsAsync();
|
var settings = await AuthService.GetSettingsAsync();
|
||||||
|
|
||||||
var localUsers = await CustomUserMapper.GetUsersAsync();
|
var localUsers = await CustomUserMapper.GetUsersAsync();
|
||||||
var plexLocalUsers = await PlexUserRepository.GetAllAsync();
|
var plexLocalUsers = await PlexUserRepository.GetAllAsync();
|
||||||
|
var embyLocalUsers = await EmbyUserRepository.GetAllAsync();
|
||||||
|
|
||||||
|
var localUser = false;
|
||||||
|
|
||||||
|
|
||||||
UserLogins.Insert(new UserLogins { UserId = userId, Type = UserType.PlexUser, LastLoggedIn = DateTime.UtcNow });
|
|
||||||
Log.Debug("We are authenticated! Setting session.");
|
Log.Debug("We are authenticated! Setting session.");
|
||||||
// Add to the session (Used in the BaseModules)
|
// Add to the session (Used in the BaseModules)
|
||||||
Session[SessionKeys.UsernameKey] = username;
|
Session[SessionKeys.UsernameKey] = username;
|
||||||
Session[SessionKeys.ClientDateTimeOffsetKey] = dateTimeOffset;
|
Session[SessionKeys.ClientDateTimeOffsetKey] = dateTimeOffset;
|
||||||
|
|
||||||
var plexLocal = plexLocalUsers.FirstOrDefault(x => x.Username == username);
|
if (plex)
|
||||||
if (plexLocal != null)
|
|
||||||
{
|
{
|
||||||
loginGuid = Guid.Parse(plexLocal.LoginId);
|
var plexLocal = plexLocalUsers.FirstOrDefault(x => x.Username == username);
|
||||||
|
if (plexLocal != null)
|
||||||
|
{
|
||||||
|
loginGuid = Guid.Parse(plexLocal.LoginId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (emby)
|
||||||
|
{
|
||||||
|
var embyLocal = embyLocalUsers.FirstOrDefault(x => x.Username == username);
|
||||||
|
if (embyLocal != null)
|
||||||
|
{
|
||||||
|
loginGuid = Guid.Parse(embyLocal.LoginId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var dbUser = localUsers.FirstOrDefault(x => x.UserName == username);
|
var dbUser = localUsers.FirstOrDefault(x => x.UserName == username);
|
||||||
if (dbUser != null)
|
if (dbUser != null)
|
||||||
{
|
{
|
||||||
loginGuid = Guid.Parse(dbUser.UserGuid);
|
loginGuid = Guid.Parse(dbUser.UserGuid);
|
||||||
|
localUser = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (loginGuid != Guid.Empty)
|
|
||||||
//{
|
|
||||||
// if (!settings.UserAuthentication)// Do not need to auth make admin use login screen for now TODO remove this
|
|
||||||
// {
|
|
||||||
// if (dbUser != null)
|
|
||||||
// {
|
|
||||||
// var perms = (Permissions)dbUser.Permissions;
|
|
||||||
// if (perms.HasFlag(Permissions.Administrator))
|
|
||||||
// {
|
|
||||||
// var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
|
||||||
// Session["TempMessage"] = Resources.UI.UserLogin_AdminUsePassword;
|
|
||||||
// //return Response.AsRedirect(uri.ToString());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (plexLocal != null)
|
|
||||||
// {
|
|
||||||
// var perms = (Permissions)plexLocal.Permissions;
|
|
||||||
// if (perms.HasFlag(Permissions.Administrator))
|
|
||||||
// {
|
|
||||||
// var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
|
||||||
// Session["TempMessage"] = Resources.UI.UserLogin_AdminUsePassword;
|
|
||||||
// //return Response.AsRedirect(uri.ToString());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (loginGuid == Guid.Empty && settings.UserAuthentication)
|
if (loginGuid == Guid.Empty && settings.UserAuthentication)
|
||||||
{
|
{
|
||||||
var defaultSettings = UserManagementSettings.GetSettings();
|
var defaultSettings = UserManagementSettings.GetSettings();
|
||||||
|
@ -622,21 +643,52 @@ namespace Ombi.UI.Modules
|
||||||
defaultPermissions += (int)Permissions.Administrator;
|
defaultPermissions += (int)Permissions.Administrator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (plex)
|
||||||
// Looks like we still don't have an entry, so this user does not exist
|
|
||||||
await PlexUserRepository.InsertAsync(new PlexUsers
|
|
||||||
{
|
{
|
||||||
PlexUserId = userId,
|
// Looks like we still don't have an entry, so this user does not exist
|
||||||
UserAlias = string.Empty,
|
await PlexUserRepository.InsertAsync(new PlexUsers
|
||||||
Permissions = (int)defaultPermissions,
|
{
|
||||||
Features = UserManagementHelper.GetPermissions(defaultSettings),
|
PlexUserId = userId,
|
||||||
Username = username,
|
UserAlias = string.Empty,
|
||||||
EmailAddress = string.Empty, // We don't have it, we will get it on the next scheduled job run (in 30 mins)
|
Permissions = (int) defaultPermissions,
|
||||||
LoginId = loginGuid.ToString()
|
Features = UserManagementHelper.GetPermissions(defaultSettings),
|
||||||
});
|
Username = username,
|
||||||
|
EmailAddress = string.Empty,
|
||||||
|
// We don't have it, we will get it on the next scheduled job run (in 30 mins)
|
||||||
|
LoginId = loginGuid.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (emby)
|
||||||
|
{
|
||||||
|
await EmbyUserRepository.InsertAsync(new EmbyUsers
|
||||||
|
{
|
||||||
|
EmbyUserId = userId,
|
||||||
|
UserAlias = string.Empty,
|
||||||
|
Permissions = (int)defaultPermissions,
|
||||||
|
Features = UserManagementHelper.GetPermissions(defaultSettings),
|
||||||
|
Username = username,
|
||||||
|
EmailAddress = string.Empty,
|
||||||
|
LoginId = loginGuid.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m.LoginGuid = loginGuid;
|
m.LoginGuid = loginGuid;
|
||||||
m.UserId = userId;
|
m.UserId = userId;
|
||||||
|
var type = UserType.LocalUser;
|
||||||
|
if (localUser)
|
||||||
|
{
|
||||||
|
type = UserType.LocalUser;
|
||||||
|
}
|
||||||
|
else if (plex)
|
||||||
|
{
|
||||||
|
type = UserType.PlexUser;
|
||||||
|
}
|
||||||
|
else if (emby)
|
||||||
|
{
|
||||||
|
type = UserType.EmbyUser;;
|
||||||
|
}
|
||||||
|
UserLogins.Insert(new UserLogins { UserId = userId, Type = type, LastLoggedIn = DateTime.UtcNow });
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,6 +730,19 @@ namespace Ombi.UI.Modules
|
||||||
return allUsers != null && allUsers.Any(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
return allUsers != null && allUsers.Any(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckIfEmbyUser(string username, EmbySettings s)
|
||||||
|
{
|
||||||
|
var users = EmbyApi.GetUsers(s.FullUri, s.ApiKey);
|
||||||
|
var allUsers = users?.Where(x => !string.IsNullOrEmpty(x.Name));
|
||||||
|
return allUsers != null && allUsers.Any(x => x.Name.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
}
|
||||||
|
private EmbyUser GetEmbyUser(string username, EmbySettings s)
|
||||||
|
{
|
||||||
|
var users = EmbyApi.GetUsers(s.FullUri, s.ApiKey);
|
||||||
|
var allUsers = users?.Where(x => !string.IsNullOrEmpty(x.Name));
|
||||||
|
return allUsers?.FirstOrDefault(x => x.Name.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private string GetUserIdIsInPlexFriends(string username, string authToken)
|
private string GetUserIdIsInPlexFriends(string username, string authToken)
|
||||||
{
|
{
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace Ombi.UI
|
||||||
{
|
{
|
||||||
Log.Info("This is not Mono");
|
Log.Info("This is not Mono");
|
||||||
Console.WriteLine("Press any key to exit");
|
Console.WriteLine("Press any key to exit");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (Html.IsPlexUser()) // Logged in but not admin
|
else if (Html.IsExternalUser()) // Logged in but not admin
|
||||||
{
|
{
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-user"></i> @UI.Layout_Welcome @Context.CurrentUser.UserName <span class="caret"></span></a>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-user"></i> @UI.Layout_Welcome @Context.CurrentUser.UserName <span class="caret"></span></a>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue