diff --git a/src/Ombi.Schedule.Tests/PlexUserImporterTests.cs b/src/Ombi.Schedule.Tests/PlexUserImporterTests.cs index ae29f1ddf..62d058d19 100644 --- a/src/Ombi.Schedule.Tests/PlexUserImporterTests.cs +++ b/src/Ombi.Schedule.Tests/PlexUserImporterTests.cs @@ -324,5 +324,84 @@ namespace Ombi.Schedule.Tests _mocker.Verify(x => x.UpdateAsync(It.Is(x => x.ProviderUserId == "PLEX_ID" && x.Email == "email" && x.UserName == "user")), Times.Once); } + + + [Test] + public async Task Import_Cleanup_Missing_Plex_Users() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()) + .ReturnsAsync(new UserManagementSettings + { + ImportPlexAdmin = true, + ImportPlexUsers = true, + DefaultRoles = new List + { + OmbiRoles.RequestMovie + }, + CleanupPlexUsers = true, + }); + _mocker.Setup>(x => x.GetUsers(It.IsAny())).ReturnsAsync(new PlexFriends + { + User = new UserFriends[] + { + } + }); + _mocker.Setup>(x => x.GetAccount(It.IsAny())).ReturnsAsync(new PlexAccount + { + user = new User + { + email = "email", + authentication_token = "user_token", + title = "user_title", + username = "user_username", + id = "user_id", + } + }); + + _mocker.Setup>(x => x.CreateAsync(It.Is(x => x.UserName == "user_username" && x.Email == "email" && x.ProviderUserId == "user_id" && x.UserType == UserType.PlexUser))) + .ReturnsAsync(IdentityResult.Success); + _mocker.Setup>(x => x.AddToRoleAsync(It.Is(x => x.UserName == "user_username"), It.Is(x => x == OmbiRoles.Admin))) + .ReturnsAsync(IdentityResult.Success); + + await _subject.Execute(null); + + _mocker.Verify(x => x.DeleteAsync(It.Is(x => x.ProviderUserId == "PLEX_ID" && x.Email == "dupe" && x.UserName == "plex")), Times.Once); + } + + [Test] + public async Task Import_Cleanup_Missing_Plex_Admin() + { + _mocker.Setup, Task>(x => x.GetSettingsAsync()) + .ReturnsAsync(new UserManagementSettings + { + ImportPlexAdmin = true, + ImportPlexUsers = false, + DefaultRoles = new List + { + OmbiRoles.RequestMovie + }, + CleanupPlexUsers = true, + }); + _mocker.Setup>(x => x.GetAccount(It.IsAny())).ReturnsAsync(new PlexAccount + { + user = new User + { + email = "diff_email", + authentication_token = "user_token", + title = "user_title", + username = "diff_username", + id = "diff_user_id", + } + }); + + _mocker.Setup>(x => x.CreateAsync(It.Is(x => x.UserName == "diff_username" && x.Email == "diff_email" && x.ProviderUserId == "diff_user_id" && x.UserType == UserType.PlexUser))) + .ReturnsAsync(IdentityResult.Success); + _mocker.Setup>(x => x.AddToRoleAsync(It.Is(x => x.UserName == "diff_username"), It.Is(x => x == OmbiRoles.Admin))) + .ReturnsAsync(IdentityResult.Success); + + await _subject.Execute(null); + + _mocker.Verify(x => x.DeleteAsync(It.Is(x => x.ProviderUserId == "PLEX_ID" && x.Email == "dupe" && x.UserName == "plex")), Times.Once); + } } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs index 4cbf73d60..3b931b586 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs @@ -56,6 +56,8 @@ namespace Ombi.Schedule.Jobs.Plex await _notification.SendNotificationToAdmins("Plex User Importer Started"); var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.PlexUser).ToListAsync(); + List newOrUpdatedUsers = new List(); + foreach (var server in settings.Servers) { if (string.IsNullOrEmpty(server.PlexAuthToken)) @@ -63,23 +65,46 @@ namespace Ombi.Schedule.Jobs.Plex continue; } + if (userManagementSettings.ImportPlexAdmin) { - await ImportAdmin(userManagementSettings, server, allUsers); + OmbiUser newOrUpdatedAdmin = await ImportAdmin(userManagementSettings, server, allUsers); + if (newOrUpdatedAdmin != null) + { + newOrUpdatedUsers.Add(newOrUpdatedAdmin); + } } if (userManagementSettings.ImportPlexUsers) { - await ImportPlexUsers(userManagementSettings, allUsers, server); + newOrUpdatedUsers.AddRange(await ImportPlexUsers(userManagementSettings, allUsers, server)); + } + } + + if (userManagementSettings.CleanupPlexUsers) + { + // Refresh users from updates + allUsers = await _userManager.Users.Where(x => x.UserType == UserType.PlexUser) + .ToListAsync(); + var missingUsers = allUsers + .Where(x => !newOrUpdatedUsers.Contains(x)); + foreach (var ombiUser in missingUsers) + { + _log.LogInformation("Deleting user {0} not found in Plex Server.", ombiUser.UserName); + await _userManager.DeleteAsync(ombiUser); } } + await _notification.SendNotificationToAdmins("Plex User Importer Finished"); } - private async Task ImportPlexUsers(UserManagementSettings userManagementSettings, List allUsers, PlexServers server) + private async Task> ImportPlexUsers(UserManagementSettings userManagementSettings, + List allUsers, PlexServers server) { var users = await _api.GetUsers(server.PlexAuthToken); + List newOrUpdatedUsers = new List(); + foreach (var plexUser in users.User) { // Check if we should import this user @@ -129,19 +154,21 @@ namespace Ombi.Schedule.Jobs.Plex { continue; } + // Get the new user object to avoid any concurrency failures + var dbUser = + await _userManager.Users.FirstOrDefaultAsync(x => x.UserName == newUser.UserName); if (userManagementSettings.DefaultRoles.Any()) { - // Get the new user object to avoid any concurrency failures - var dbUser = - await _userManager.Users.FirstOrDefaultAsync(x => x.UserName == newUser.UserName); foreach (var defaultRole in userManagementSettings.DefaultRoles) { await _userManager.AddToRoleAsync(dbUser, defaultRole); } } + newOrUpdatedUsers.Add(dbUser); } else { + newOrUpdatedUsers.Add(existingPlexUser); // Do we need to update this user? existingPlexUser.Email = plexUser.Email; existingPlexUser.UserName = plexUser.Username; @@ -149,9 +176,12 @@ namespace Ombi.Schedule.Jobs.Plex await _userManager.UpdateAsync(existingPlexUser); } } + + return newOrUpdatedUsers; } - private async Task ImportAdmin(UserManagementSettings settings, PlexServers server, List allUsers) + private async Task ImportAdmin(UserManagementSettings settings, PlexServers server, + List allUsers) { var plexAdmin = (await _api.GetAccount(server.PlexAuthToken)).user; @@ -166,7 +196,7 @@ namespace Ombi.Schedule.Jobs.Plex adminUserFromDb.UserName = plexAdmin.username; adminUserFromDb.ProviderUserId = plexAdmin.id; await _userManager.UpdateAsync(adminUserFromDb); - return; + return adminUserFromDb; } // Ensure we don't have a user with the same username @@ -174,7 +204,7 @@ namespace Ombi.Schedule.Jobs.Plex if (await _userManager.Users.AnyAsync(x => x.NormalizedUserName == normalUsername)) { _log.LogWarning($"Cannot add user {plexAdmin.username} because their username is already in Ombi, skipping this user"); - return; + return null; } var newUser = new OmbiUser @@ -190,11 +220,12 @@ namespace Ombi.Schedule.Jobs.Plex var result = await _userManager.CreateAsync(newUser); if (!LogResult(result)) { - return; + return null; } var roleResult = await _userManager.AddToRoleAsync(newUser, OmbiRoles.Admin); LogResult(roleResult); + return newUser; } private bool LogResult(IdentityResult result) diff --git a/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs b/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs index 3547812ee..8f04d67da 100644 --- a/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs +++ b/src/Ombi.Settings/Settings/Models/UserManagementSettings.cs @@ -7,6 +7,7 @@ namespace Ombi.Settings.Settings.Models { public bool ImportPlexAdmin { get; set; } public bool ImportPlexUsers { get; set; } + public bool CleanupPlexUsers { get; set; } public bool ImportEmbyUsers { get; set; } public bool ImportJellyfinUsers { get; set; } public int MovieRequestLimit { get; set; } diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index 91874d967..dd9156102 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -253,6 +253,7 @@ export interface ICustomPage extends ISettings { export interface IUserManagementSettings extends ISettings { importPlexUsers: boolean; + cleanupPlexUsers: boolean; importPlexAdmin: boolean; importEmbyUsers: boolean; importJellyfinUsers: boolean; diff --git a/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html index 266c725cb..7512294df 100644 --- a/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html @@ -17,6 +17,11 @@
Import Plex Admin
+ +
+ + Cleanup Plex Users +

Plex Users excluded from Import

@@ -121,7 +126,7 @@
-
+