mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-10 15:32:37 -07:00
User management stuff
This commit is contained in:
parent
0828756171
commit
b851d77364
17 changed files with 232 additions and 94 deletions
|
@ -1,63 +1,64 @@
|
||||||
#region Copyright
|
#region Copyright
|
||||||
// /************************************************************************
|
// /************************************************************************
|
||||||
// Copyright (c) 2016 Jamie Rees
|
// Copyright (c) 2016 Jamie Rees
|
||||||
// File: PlexAuthentication.cs
|
// File: PlexAuthentication.cs
|
||||||
// Created By: Jamie Rees
|
// Created By: Jamie Rees
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
// a copy of this software and associated documentation files (the
|
// a copy of this software and associated documentation files (the
|
||||||
// "Software"), to deal in the Software without restriction, including
|
// "Software"), to deal in the Software without restriction, including
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
// permit persons to whom the Software is furnished to do so, subject to
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
// the following conditions:
|
// the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be
|
// The above copyright notice and this permission notice shall be
|
||||||
// included in all copies or substantial portions of the Software.
|
// included in all copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PlexRequests.Api.Models.Plex
|
namespace PlexRequests.Api.Models.Plex
|
||||||
{
|
{
|
||||||
public class PlexAuthentication
|
public class PlexAuthentication
|
||||||
{
|
{
|
||||||
public User user { get; set; }
|
public User user { get; set; }
|
||||||
}
|
}
|
||||||
public class Subscription
|
public class Subscription
|
||||||
{
|
{
|
||||||
public bool active { get; set; }
|
public bool active { get; set; }
|
||||||
public string status { get; set; }
|
public string status { get; set; }
|
||||||
public object plan { get; set; }
|
public object plan { get; set; }
|
||||||
public object features { get; set; }
|
public object features { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Roles
|
public class Roles
|
||||||
{
|
{
|
||||||
public List<object> roles { get; set; }
|
public List<object> roles { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class User
|
public class User
|
||||||
{
|
{
|
||||||
public string email { get; set; }
|
public string email { get; set; }
|
||||||
public string joined_at { get; set; }
|
public string uuid { get; set; }
|
||||||
public string username { get; set; }
|
public string joined_at { get; set; }
|
||||||
public string title { get; set; }
|
public string username { get; set; }
|
||||||
public string authentication_token { get; set; }
|
public string title { get; set; }
|
||||||
public Subscription subscription { get; set; }
|
public string authentication_token { get; set; }
|
||||||
public Roles roles { get; set; }
|
public Subscription subscription { get; set; }
|
||||||
public List<string> entitlements { get; set; }
|
public Roles roles { get; set; }
|
||||||
public object confirmed_at { get; set; }
|
public List<string> entitlements { get; set; }
|
||||||
public int forum_id { get; set; }
|
public object confirmed_at { get; set; }
|
||||||
}
|
public int forum_id { get; set; }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,12 +53,11 @@ namespace PlexRequests.Core.Migration.Migrations
|
||||||
UpdateApplicationSettings();
|
UpdateApplicationSettings();
|
||||||
UpdateDb(con);
|
UpdateDb(con);
|
||||||
|
|
||||||
UpdateSchema(con, Version);
|
UpdateSchema(con, Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateDb(IDbConnection con)
|
private void UpdateDb(IDbConnection con)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateApplicationSettings()
|
private void UpdateApplicationSettings()
|
||||||
|
|
|
@ -139,7 +139,6 @@ namespace PlexRequests.Core
|
||||||
return CreateUser(username, password, new[] { UserClaims.User }, properties);
|
return CreateUser(username, password, new[] { UserClaims.User }, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IEnumerable<string> GetAllClaims()
|
public IEnumerable<string> GetAllClaims()
|
||||||
{
|
{
|
||||||
var properties = typeof(UserClaims).GetConstantsValues<string>();
|
var properties = typeof(UserClaims).GetConstantsValues<string>();
|
||||||
|
@ -200,6 +199,5 @@ namespace PlexRequests.Core
|
||||||
Guid? CreatePowerUser(string username, string password, UserProperties properties = null);
|
Guid? CreatePowerUser(string username, string password, UserProperties properties = null);
|
||||||
Guid? CreateRegularUser(string username, string password, UserProperties properties = null);
|
Guid? CreateRegularUser(string username, string password, UserProperties properties = null);
|
||||||
void DeleteUser(string userId);
|
void DeleteUser(string userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@
|
||||||
<Compile Include="TypeHelper.cs" />
|
<Compile Include="TypeHelper.cs" />
|
||||||
<Compile Include="UriHelper.cs" />
|
<Compile Include="UriHelper.cs" />
|
||||||
<Compile Include="UserClaims.cs" />
|
<Compile Include="UserClaims.cs" />
|
||||||
|
<Compile Include="UserType.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
|
35
PlexRequests.Helpers/UserType.cs
Normal file
35
PlexRequests.Helpers/UserType.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: UserType.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
|
||||||
|
namespace PlexRequests.Helpers
|
||||||
|
{
|
||||||
|
|
||||||
|
public enum UserType
|
||||||
|
{
|
||||||
|
PlexUser,
|
||||||
|
LocalUser
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,6 +87,7 @@
|
||||||
<Compile Include="Repository\GenericRepository.cs" />
|
<Compile Include="Repository\GenericRepository.cs" />
|
||||||
<Compile Include="RequestedModel.cs" />
|
<Compile Include="RequestedModel.cs" />
|
||||||
<Compile Include="UserEntity.cs" />
|
<Compile Include="UserEntity.cs" />
|
||||||
|
<Compile Include="UserLogins.cs" />
|
||||||
<Compile Include="UsersModel.cs" />
|
<Compile Include="UsersModel.cs" />
|
||||||
<Compile Include="UserRepository.cs" />
|
<Compile Include="UserRepository.cs" />
|
||||||
<Compile Include="Sql.Designer.cs">
|
<Compile Include="Sql.Designer.cs">
|
||||||
|
|
|
@ -11,6 +11,15 @@ CREATE TABLE IF NOT EXISTS Users
|
||||||
UserProperties BLOB
|
UserProperties BLOB
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS UserLogins
|
||||||
|
(
|
||||||
|
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
UserId varchar(50) NOT NULL ,
|
||||||
|
Type INTEGER NOT NULL,
|
||||||
|
LastLoggedIn varchar(100) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS UserLogins_UserId ON UserLogins (UserId);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS GlobalSettings
|
CREATE TABLE IF NOT EXISTS GlobalSettings
|
||||||
(
|
(
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace PlexRequests.Store
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddColumn(this IDbConnection connection, string tableName, string alterType, string newColumn, bool isNullable, string dataType)
|
public static void AddColumn(this IDbConnection connection, string tableName, string alterType, string newColumn, bool allowNulls, string dataType)
|
||||||
{
|
{
|
||||||
connection.Open();
|
connection.Open();
|
||||||
var result = connection.Query<TableInfo>($"PRAGMA table_info({tableName});");
|
var result = connection.Query<TableInfo>($"PRAGMA table_info({tableName});");
|
||||||
|
@ -67,7 +67,7 @@ namespace PlexRequests.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
var query = $"ALTER TABLE {tableName} {alterType} {newColumn} {dataType}";
|
var query = $"ALTER TABLE {tableName} {alterType} {newColumn} {dataType}";
|
||||||
if (isNullable)
|
if (!allowNulls)
|
||||||
{
|
{
|
||||||
query = query + " NOT NULL";
|
query = query + " NOT NULL";
|
||||||
}
|
}
|
||||||
|
|
41
PlexRequests.Store/UserLogins.cs
Normal file
41
PlexRequests.Store/UserLogins.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: UserLogins.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 Dapper.Contrib.Extensions;
|
||||||
|
using PlexRequests.Helpers;
|
||||||
|
|
||||||
|
namespace PlexRequests.Store
|
||||||
|
{
|
||||||
|
[Table("UserLogins")]
|
||||||
|
public class UserLogins : Entity
|
||||||
|
{
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public UserType Type { get; set; }
|
||||||
|
public DateTime LastLoggedIn { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,8 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using Dapper.Contrib.Extensions;
|
using Dapper.Contrib.Extensions;
|
||||||
|
|
||||||
namespace PlexRequests.Store
|
namespace PlexRequests.Store
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using PlexRequests.Helpers;
|
||||||
|
|
||||||
namespace PlexRequests.UI.Models
|
namespace PlexRequests.UI.Models
|
||||||
{
|
{
|
||||||
|
@ -18,6 +20,7 @@ namespace PlexRequests.UI.Models
|
||||||
public UserManagementPlexInformation PlexInfo { get; set; }
|
public UserManagementPlexInformation PlexInfo { get; set; }
|
||||||
public string[] ClaimsArray { get; set; }
|
public string[] ClaimsArray { get; set; }
|
||||||
public List<UserManagementUpdateModel.ClaimsModel> ClaimsItem { get; set; }
|
public List<UserManagementUpdateModel.ClaimsModel> ClaimsItem { get; set; }
|
||||||
|
public DateTime LastLoggedIn { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserManagementPlexInformation
|
public class UserManagementPlexInformation
|
||||||
|
@ -40,11 +43,6 @@ namespace PlexRequests.UI.Models
|
||||||
public string NumLibraries { get; set; }
|
public string NumLibraries { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum UserType
|
|
||||||
{
|
|
||||||
PlexUser,
|
|
||||||
LocalUser
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UserManagementCreateModel
|
public class UserManagementCreateModel
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,13 +40,15 @@ using Nancy.Security;
|
||||||
using PlexRequests.Core;
|
using PlexRequests.Core;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Helpers;
|
using PlexRequests.Helpers;
|
||||||
|
using PlexRequests.Store;
|
||||||
|
using PlexRequests.Store.Repository;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
namespace PlexRequests.UI.Modules
|
namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
public class LoginModule : BaseModule
|
public class LoginModule : BaseModule
|
||||||
{
|
{
|
||||||
public LoginModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IResourceLinker linker)
|
public LoginModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IResourceLinker linker, IRepository<UserLogins> userLoginRepo)
|
||||||
: base(pr)
|
: base(pr)
|
||||||
{
|
{
|
||||||
UserMapper = m;
|
UserMapper = m;
|
||||||
|
@ -101,6 +103,14 @@ namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
redirect = !string.IsNullOrEmpty(BaseUrl) ? $"/{BaseUrl}/search" : "/search";
|
redirect = !string.IsNullOrEmpty(BaseUrl) ? $"/{BaseUrl}/search" : "/search";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userLoginRepo.Insert(new UserLogins
|
||||||
|
{
|
||||||
|
LastLoggedIn = DateTime.UtcNow,
|
||||||
|
Type = UserType.LocalUser,
|
||||||
|
UserId = userId.ToString()
|
||||||
|
});
|
||||||
|
|
||||||
return this.LoginAndRedirect(userId.Value, expiry, redirect);
|
return this.LoginAndRedirect(userId.Value, expiry, redirect);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -232,10 +232,18 @@ namespace PlexRequests.UI.Modules
|
||||||
var plexMovies = Checker.GetPlexMovies();
|
var plexMovies = Checker.GetPlexMovies();
|
||||||
var settings = await PrService.GetSettingsAsync();
|
var settings = await PrService.GetSettingsAsync();
|
||||||
var viewMovies = new List<SearchMovieViewModel>();
|
var viewMovies = new List<SearchMovieViewModel>();
|
||||||
|
var counter = 0;
|
||||||
foreach (var movie in apiMovies)
|
foreach (var movie in apiMovies)
|
||||||
{
|
{
|
||||||
var movieInfoTask = MovieApi.GetMovieInformation(movie.Id).ConfigureAwait(false); // TODO needs to be careful about this, it's adding extra time to search...
|
var imdbId = string.Empty;
|
||||||
// https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
|
if (counter <= 5) // Let's only do it for the first 5 items
|
||||||
|
{
|
||||||
|
var movieInfoTask = await MovieApi.GetMovieInformation(movie.Id).ConfigureAwait(false); // TODO needs to be careful about this, it's adding extra time to search...
|
||||||
|
// https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
|
||||||
|
imdbId = movieInfoTask.ImdbId;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
var viewMovie = new SearchMovieViewModel
|
var viewMovie = new SearchMovieViewModel
|
||||||
{
|
{
|
||||||
Adult = movie.Adult,
|
Adult = movie.Adult,
|
||||||
|
@ -254,8 +262,7 @@ namespace PlexRequests.UI.Modules
|
||||||
VoteCount = movie.VoteCount
|
VoteCount = movie.VoteCount
|
||||||
};
|
};
|
||||||
var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies);
|
var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies);
|
||||||
var movieInfo = await movieInfoTask;
|
var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString(), imdbId);
|
||||||
var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString(), movieInfo.ImdbId);
|
|
||||||
if (plexMovie != null)
|
if (plexMovie != null)
|
||||||
{
|
{
|
||||||
viewMovie.Available = true;
|
viewMovie.Available = true;
|
||||||
|
|
|
@ -42,6 +42,8 @@ using PlexRequests.Core;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Helpers;
|
using PlexRequests.Helpers;
|
||||||
using PlexRequests.Helpers.Analytics;
|
using PlexRequests.Helpers.Analytics;
|
||||||
|
using PlexRequests.Store;
|
||||||
|
using PlexRequests.Store.Repository;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +54,7 @@ namespace PlexRequests.UI.Modules
|
||||||
public class UserLoginModule : BaseModule
|
public class UserLoginModule : BaseModule
|
||||||
{
|
{
|
||||||
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) : base("userlogin", pr)
|
ISettingsService<LandingPageSettings> lp, IAnalytics a, IResourceLinker linker, IRepository<UserLogins> userLogins) : base("userlogin", pr)
|
||||||
{
|
{
|
||||||
AuthService = auth;
|
AuthService = auth;
|
||||||
LandingPageSettings = lp;
|
LandingPageSettings = lp;
|
||||||
|
@ -60,13 +62,14 @@ namespace PlexRequests.UI.Modules
|
||||||
Api = api;
|
Api = api;
|
||||||
PlexSettings = plexSettings;
|
PlexSettings = plexSettings;
|
||||||
Linker = linker;
|
Linker = linker;
|
||||||
|
UserLogins = userLogins;
|
||||||
|
|
||||||
Get["UserLoginIndex", "/", true] = async (x, ct) =>
|
Get["UserLoginIndex", "/", true] = async (x, ct) =>
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(Username) || IsAdmin)
|
if (!string.IsNullOrEmpty(Username) || IsAdmin)
|
||||||
{
|
{
|
||||||
var url = Linker.BuildRelativeUri(Context, "SearchIndex").ToString();
|
var url = Linker.BuildRelativeUri(Context, "SearchIndex").ToString();
|
||||||
return Response.AsRedirect(url);
|
return Response.AsRedirect(url);
|
||||||
}
|
}
|
||||||
var settings = await AuthService.GetSettingsAsync();
|
var settings = await AuthService.GetSettingsAsync();
|
||||||
return View["Index", settings];
|
return View["Index", settings];
|
||||||
|
@ -82,11 +85,13 @@ namespace PlexRequests.UI.Modules
|
||||||
private IPlexApi Api { get; }
|
private IPlexApi Api { get; }
|
||||||
private IResourceLinker Linker { get; }
|
private IResourceLinker Linker { get; }
|
||||||
private IAnalytics Analytics { get; }
|
private IAnalytics Analytics { get; }
|
||||||
|
private IRepository<UserLogins> UserLogins { get; }
|
||||||
|
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
private async Task<Response> LoginUser()
|
private async Task<Response> LoginUser()
|
||||||
{
|
{
|
||||||
|
var userId = string.Empty;
|
||||||
var dateTimeOffset = Request.Form.DateTimeOffset;
|
var dateTimeOffset = Request.Form.DateTimeOffset;
|
||||||
var username = Request.Form.username.Value;
|
var username = Request.Form.username.Value;
|
||||||
Log.Debug("Username \"{0}\" attempting to login", username);
|
Log.Debug("Username \"{0}\" attempting to login", username);
|
||||||
|
@ -135,6 +140,7 @@ namespace PlexRequests.UI.Modules
|
||||||
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||||
Log.Debug("Friends list result = {0}", authenticated);
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
}
|
}
|
||||||
|
userId = signedIn.user.uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (settings.UserAuthentication) // Check against the users in Plex
|
else if (settings.UserAuthentication) // Check against the users in Plex
|
||||||
|
@ -147,6 +153,11 @@ namespace PlexRequests.UI.Modules
|
||||||
authenticated = true;
|
authenticated = true;
|
||||||
}
|
}
|
||||||
Log.Debug("Friends list result = {0}", authenticated);
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
|
if (authenticated)
|
||||||
|
{
|
||||||
|
// Get the user that is authenticated to store in the UserLogins
|
||||||
|
userId = GetUserIdIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!settings.UserAuthentication) // No auth, let them pass!
|
else if (!settings.UserAuthentication) // No auth, let them pass!
|
||||||
{
|
{
|
||||||
|
@ -156,13 +167,13 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
if (authenticated)
|
if (authenticated)
|
||||||
{
|
{
|
||||||
|
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] = (string)username;
|
Session[SessionKeys.UsernameKey] = (string)username;
|
||||||
|
Session[SessionKeys.ClientDateTimeOffsetKey] = (int)dateTimeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Session[SessionKeys.ClientDateTimeOffsetKey] = (int)dateTimeOffset;
|
|
||||||
|
|
||||||
if (!authenticated)
|
if (!authenticated)
|
||||||
{
|
{
|
||||||
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
||||||
|
@ -214,6 +225,14 @@ namespace PlexRequests.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 string GetUserIdIsInPlexFriends(string username, string authToken)
|
||||||
|
{
|
||||||
|
var users = Api.GetUsers(authToken);
|
||||||
|
var allUsers = users?.User?.Where(x => !string.IsNullOrEmpty(x.Title));
|
||||||
|
return allUsers?.Where(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase)).Select(x => x.Id).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsUserInDeniedList(string username, AuthenticationSettings settings)
|
private bool IsUserInDeniedList(string username, AuthenticationSettings settings)
|
||||||
{
|
{
|
||||||
return settings.DeniedUserList.Any(x => x.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
return settings.DeniedUserList.Any(x => x.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
|
@ -14,13 +14,14 @@ using PlexRequests.Core.Models;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Helpers;
|
using PlexRequests.Helpers;
|
||||||
using PlexRequests.Store;
|
using PlexRequests.Store;
|
||||||
|
using PlexRequests.Store.Repository;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
namespace PlexRequests.UI.Modules
|
namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
public class UserManagementModule : BaseModule
|
public class UserManagementModule : BaseModule
|
||||||
{
|
{
|
||||||
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService<PlexSettings> plex) : base("usermanagement", pr)
|
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService<PlexSettings> plex, IRepository<UserLogins> userLogins) : base("usermanagement", pr)
|
||||||
{
|
{
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
this.RequiresClaims(UserClaims.Admin);
|
this.RequiresClaims(UserClaims.Admin);
|
||||||
|
@ -28,6 +29,7 @@ namespace PlexRequests.UI.Modules
|
||||||
UserMapper = m;
|
UserMapper = m;
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
PlexSettings = plex;
|
PlexSettings = plex;
|
||||||
|
UserLoginsRepo = userLogins;
|
||||||
|
|
||||||
Get["/"] = x => Load();
|
Get["/"] = x => Load();
|
||||||
|
|
||||||
|
@ -43,6 +45,7 @@ namespace PlexRequests.UI.Modules
|
||||||
private ICustomUserMapper UserMapper { get; }
|
private ICustomUserMapper UserMapper { get; }
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||||
|
private IRepository<UserLogins> UserLoginsRepo { get; }
|
||||||
|
|
||||||
private Negotiator Load()
|
private Negotiator Load()
|
||||||
{
|
{
|
||||||
|
@ -55,7 +58,8 @@ namespace PlexRequests.UI.Modules
|
||||||
var model = new List<UserManagementUsersViewModel>();
|
var model = new List<UserManagementUsersViewModel>();
|
||||||
foreach (var user in localUsers)
|
foreach (var user in localUsers)
|
||||||
{
|
{
|
||||||
model.Add(MapLocalUser(user));
|
var userDb = UserLoginsRepo.Get(user.UserGuid);
|
||||||
|
model.Add(MapLocalUser(user, userDb.LastLoggedIn));
|
||||||
}
|
}
|
||||||
|
|
||||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||||
|
@ -66,7 +70,7 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
foreach (var u in plexUsers.User)
|
foreach (var u in plexUsers.User)
|
||||||
{
|
{
|
||||||
|
var userDb = UserLoginsRepo.Get(u.Id);
|
||||||
model.Add(new UserManagementUsersViewModel
|
model.Add(new UserManagementUsersViewModel
|
||||||
{
|
{
|
||||||
Username = u.Username,
|
Username = u.Username,
|
||||||
|
@ -77,7 +81,8 @@ namespace PlexRequests.UI.Modules
|
||||||
PlexInfo = new UserManagementPlexInformation
|
PlexInfo = new UserManagementPlexInformation
|
||||||
{
|
{
|
||||||
Thumb = u.Thumb
|
Thumb = u.Thumb
|
||||||
}
|
},
|
||||||
|
LastLoggedIn = userDb.LastLoggedIn,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +110,7 @@ namespace PlexRequests.UI.Modules
|
||||||
var user = UserMapper.CreateUser(model.Username, model.Password, model.Claims, new UserProperties { EmailAddress = model.EmailAddress });
|
var user = UserMapper.CreateUser(model.Username, model.Password, model.Claims, new UserProperties { EmailAddress = model.EmailAddress });
|
||||||
if (user.HasValue)
|
if (user.HasValue)
|
||||||
{
|
{
|
||||||
return Response.AsJson(MapLocalUser(UserMapper.GetUser(user.Value)));
|
return Response.AsJson(MapLocalUser(UserMapper.GetUser(user.Value), DateTime.MinValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save user" });
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save user" });
|
||||||
|
@ -150,8 +155,8 @@ namespace PlexRequests.UI.Modules
|
||||||
userFound.UserProperties = ByteConverterHelper.ReturnBytes(currentProps);
|
userFound.UserProperties = ByteConverterHelper.ReturnBytes(currentProps);
|
||||||
|
|
||||||
var user = UserMapper.EditUser(userFound);
|
var user = UserMapper.EditUser(userFound);
|
||||||
|
var dbUser = UserLoginsRepo.Get(user.UserGuid);
|
||||||
var retUser = MapLocalUser(user);
|
var retUser = MapLocalUser(user, dbUser.LastLoggedIn);
|
||||||
return Response.AsJson(retUser);
|
return Response.AsJson(retUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +229,7 @@ namespace PlexRequests.UI.Modules
|
||||||
return Response.AsJson(retVal);
|
return Response.AsJson(retVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserManagementUsersViewModel MapLocalUser(UsersModel user)
|
private UserManagementUsersViewModel MapLocalUser(UsersModel user, DateTime lastLoggedIn)
|
||||||
{
|
{
|
||||||
var claims = ByteConverterHelper.ReturnObject<string[]>(user.Claims);
|
var claims = ByteConverterHelper.ReturnObject<string[]>(user.Claims);
|
||||||
var claimsString = string.Join(", ", claims);
|
var claimsString = string.Join(", ", claims);
|
||||||
|
@ -240,7 +245,8 @@ namespace PlexRequests.UI.Modules
|
||||||
EmailAddress = userProps.EmailAddress,
|
EmailAddress = userProps.EmailAddress,
|
||||||
Alias = userProps.UserAlias,
|
Alias = userProps.UserAlias,
|
||||||
ClaimsArray = claims,
|
ClaimsArray = claims,
|
||||||
ClaimsItem = new List<UserManagementUpdateModel.ClaimsModel>()
|
ClaimsItem = new List<UserManagementUpdateModel.ClaimsModel>(),
|
||||||
|
LastLoggedIn = lastLoggedIn
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add all of the current claims
|
// Add all of the current claims
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
{
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">@record.Key</div>
|
<div class="col-md-4">@record.Key</div>
|
||||||
<div class="col-md-5 col-md-push-3 date">@record.Value.ToString("O")</div>
|
<div class="col-md-5 col-md-push-3 date">@record.Value.ToString("R")</div>
|
||||||
</div>
|
</div>
|
||||||
<hr style="margin-top: 4px; margin-bottom: 4px"/>
|
<hr style="margin-top: 4px; margin-bottom: 4px"/>
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,14 @@
|
||||||
<span ng-show="sortType == 'type' && sortReverse" class="fa fa-caret-up"></span>
|
<span ng-show="sortType == 'type' && sortReverse" class="fa fa-caret-up"></span>
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<a href="#" ng-click="sortType = 'lastLoggedIn'; sortReverse = !sortReverse">
|
||||||
|
Last Logged In
|
||||||
|
<span ng-show="sortType == 'lastLoggedIn' && !sortReverse" class="fa fa-caret-down"></span>
|
||||||
|
<span ng-show="sortType == 'lastLoggedIn' && sortReverse" class="fa fa-caret-up"></span>
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -97,6 +105,9 @@
|
||||||
<td>
|
<td>
|
||||||
{{u.type === 1 ? 'Local User' : 'Plex User'}}
|
{{u.type === 1 ? 'Local User' : 'Plex User'}}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{u.lastLoggedIn}}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" ng-click="selectUser(u.id)" class="btn btn-sm btn-info-outline">Details/Edit</a>
|
<a href="#" ng-click="selectUser(u.id)" class="btn btn-sm btn-info-outline">Details/Edit</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue