mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-24 06:55:23 -07:00
Provide a flag for missing users on Plex Server (#4688)
This commit is contained in:
parent
5446406cf2
commit
1792408b38
5 changed files with 128 additions and 11 deletions
|
@ -324,5 +324,84 @@ namespace Ombi.Schedule.Tests
|
||||||
|
|
||||||
_mocker.Verify<OmbiUserManager>(x => x.UpdateAsync(It.Is<OmbiUser>(x => x.ProviderUserId == "PLEX_ID" && x.Email == "email" && x.UserName == "user")), Times.Once);
|
_mocker.Verify<OmbiUserManager>(x => x.UpdateAsync(It.Is<OmbiUser>(x => x.ProviderUserId == "PLEX_ID" && x.Email == "email" && x.UserName == "user")), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Import_Cleanup_Missing_Plex_Users()
|
||||||
|
{
|
||||||
|
_mocker.Setup<ISettingsService<UserManagementSettings>, Task<UserManagementSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new UserManagementSettings
|
||||||
|
{
|
||||||
|
ImportPlexAdmin = true,
|
||||||
|
ImportPlexUsers = true,
|
||||||
|
DefaultRoles = new List<string>
|
||||||
|
{
|
||||||
|
OmbiRoles.RequestMovie
|
||||||
|
},
|
||||||
|
CleanupPlexUsers = true,
|
||||||
|
});
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexFriends>>(x => x.GetUsers(It.IsAny<string>())).ReturnsAsync(new PlexFriends
|
||||||
|
{
|
||||||
|
User = new UserFriends[]
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexAccount>>(x => x.GetAccount(It.IsAny<string>())).ReturnsAsync(new PlexAccount
|
||||||
|
{
|
||||||
|
user = new User
|
||||||
|
{
|
||||||
|
email = "email",
|
||||||
|
authentication_token = "user_token",
|
||||||
|
title = "user_title",
|
||||||
|
username = "user_username",
|
||||||
|
id = "user_id",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_mocker.Setup<OmbiUserManager, Task<IdentityResult>>(x => x.CreateAsync(It.Is<OmbiUser>(x => x.UserName == "user_username" && x.Email == "email" && x.ProviderUserId == "user_id" && x.UserType == UserType.PlexUser)))
|
||||||
|
.ReturnsAsync(IdentityResult.Success);
|
||||||
|
_mocker.Setup<OmbiUserManager, Task<IdentityResult>>(x => x.AddToRoleAsync(It.Is<OmbiUser>(x => x.UserName == "user_username"), It.Is<string>(x => x == OmbiRoles.Admin)))
|
||||||
|
.ReturnsAsync(IdentityResult.Success);
|
||||||
|
|
||||||
|
await _subject.Execute(null);
|
||||||
|
|
||||||
|
_mocker.Verify<OmbiUserManager>(x => x.DeleteAsync(It.Is<OmbiUser>(x => x.ProviderUserId == "PLEX_ID" && x.Email == "dupe" && x.UserName == "plex")), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Import_Cleanup_Missing_Plex_Admin()
|
||||||
|
{
|
||||||
|
_mocker.Setup<ISettingsService<UserManagementSettings>, Task<UserManagementSettings>>(x => x.GetSettingsAsync())
|
||||||
|
.ReturnsAsync(new UserManagementSettings
|
||||||
|
{
|
||||||
|
ImportPlexAdmin = true,
|
||||||
|
ImportPlexUsers = false,
|
||||||
|
DefaultRoles = new List<string>
|
||||||
|
{
|
||||||
|
OmbiRoles.RequestMovie
|
||||||
|
},
|
||||||
|
CleanupPlexUsers = true,
|
||||||
|
});
|
||||||
|
_mocker.Setup<IPlexApi, Task<PlexAccount>>(x => x.GetAccount(It.IsAny<string>())).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<OmbiUserManager, Task<IdentityResult>>(x => x.CreateAsync(It.Is<OmbiUser>(x => x.UserName == "diff_username" && x.Email == "diff_email" && x.ProviderUserId == "diff_user_id" && x.UserType == UserType.PlexUser)))
|
||||||
|
.ReturnsAsync(IdentityResult.Success);
|
||||||
|
_mocker.Setup<OmbiUserManager, Task<IdentityResult>>(x => x.AddToRoleAsync(It.Is<OmbiUser>(x => x.UserName == "diff_username"), It.Is<string>(x => x == OmbiRoles.Admin)))
|
||||||
|
.ReturnsAsync(IdentityResult.Success);
|
||||||
|
|
||||||
|
await _subject.Execute(null);
|
||||||
|
|
||||||
|
_mocker.Verify<OmbiUserManager>(x => x.DeleteAsync(It.Is<OmbiUser>(x => x.ProviderUserId == "PLEX_ID" && x.Email == "dupe" && x.UserName == "plex")), Times.Once);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,8 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
|
|
||||||
await _notification.SendNotificationToAdmins("Plex User Importer Started");
|
await _notification.SendNotificationToAdmins("Plex User Importer Started");
|
||||||
var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.PlexUser).ToListAsync();
|
var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.PlexUser).ToListAsync();
|
||||||
|
List<OmbiUser> newOrUpdatedUsers = new List<OmbiUser>();
|
||||||
|
|
||||||
foreach (var server in settings.Servers)
|
foreach (var server in settings.Servers)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(server.PlexAuthToken))
|
if (string.IsNullOrEmpty(server.PlexAuthToken))
|
||||||
|
@ -63,23 +65,46 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (userManagementSettings.ImportPlexAdmin)
|
if (userManagementSettings.ImportPlexAdmin)
|
||||||
{
|
{
|
||||||
await ImportAdmin(userManagementSettings, server, allUsers);
|
OmbiUser newOrUpdatedAdmin = await ImportAdmin(userManagementSettings, server, allUsers);
|
||||||
|
if (newOrUpdatedAdmin != null)
|
||||||
|
{
|
||||||
|
newOrUpdatedUsers.Add(newOrUpdatedAdmin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (userManagementSettings.ImportPlexUsers)
|
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");
|
await _notification.SendNotificationToAdmins("Plex User Importer Finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ImportPlexUsers(UserManagementSettings userManagementSettings, List<OmbiUser> allUsers, PlexServers server)
|
private async Task<List<OmbiUser>> ImportPlexUsers(UserManagementSettings userManagementSettings,
|
||||||
|
List<OmbiUser> allUsers, PlexServers server)
|
||||||
{
|
{
|
||||||
var users = await _api.GetUsers(server.PlexAuthToken);
|
var users = await _api.GetUsers(server.PlexAuthToken);
|
||||||
|
|
||||||
|
List<OmbiUser> newOrUpdatedUsers = new List<OmbiUser>();
|
||||||
|
|
||||||
foreach (var plexUser in users.User)
|
foreach (var plexUser in users.User)
|
||||||
{
|
{
|
||||||
// Check if we should import this user
|
// Check if we should import this user
|
||||||
|
@ -129,19 +154,21 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
{
|
{
|
||||||
continue;
|
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())
|
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)
|
foreach (var defaultRole in userManagementSettings.DefaultRoles)
|
||||||
{
|
{
|
||||||
await _userManager.AddToRoleAsync(dbUser, defaultRole);
|
await _userManager.AddToRoleAsync(dbUser, defaultRole);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newOrUpdatedUsers.Add(dbUser);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
newOrUpdatedUsers.Add(existingPlexUser);
|
||||||
// Do we need to update this user?
|
// Do we need to update this user?
|
||||||
existingPlexUser.Email = plexUser.Email;
|
existingPlexUser.Email = plexUser.Email;
|
||||||
existingPlexUser.UserName = plexUser.Username;
|
existingPlexUser.UserName = plexUser.Username;
|
||||||
|
@ -149,9 +176,12 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
await _userManager.UpdateAsync(existingPlexUser);
|
await _userManager.UpdateAsync(existingPlexUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newOrUpdatedUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ImportAdmin(UserManagementSettings settings, PlexServers server, List<OmbiUser> allUsers)
|
private async Task<OmbiUser> ImportAdmin(UserManagementSettings settings, PlexServers server,
|
||||||
|
List<OmbiUser> allUsers)
|
||||||
{
|
{
|
||||||
var plexAdmin = (await _api.GetAccount(server.PlexAuthToken)).user;
|
var plexAdmin = (await _api.GetAccount(server.PlexAuthToken)).user;
|
||||||
|
|
||||||
|
@ -166,7 +196,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
adminUserFromDb.UserName = plexAdmin.username;
|
adminUserFromDb.UserName = plexAdmin.username;
|
||||||
adminUserFromDb.ProviderUserId = plexAdmin.id;
|
adminUserFromDb.ProviderUserId = plexAdmin.id;
|
||||||
await _userManager.UpdateAsync(adminUserFromDb);
|
await _userManager.UpdateAsync(adminUserFromDb);
|
||||||
return;
|
return adminUserFromDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we don't have a user with the same username
|
// 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))
|
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");
|
_log.LogWarning($"Cannot add user {plexAdmin.username} because their username is already in Ombi, skipping this user");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newUser = new OmbiUser
|
var newUser = new OmbiUser
|
||||||
|
@ -190,11 +220,12 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
var result = await _userManager.CreateAsync(newUser);
|
var result = await _userManager.CreateAsync(newUser);
|
||||||
if (!LogResult(result))
|
if (!LogResult(result))
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var roleResult = await _userManager.AddToRoleAsync(newUser, OmbiRoles.Admin);
|
var roleResult = await _userManager.AddToRoleAsync(newUser, OmbiRoles.Admin);
|
||||||
LogResult(roleResult);
|
LogResult(roleResult);
|
||||||
|
return newUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool LogResult(IdentityResult result)
|
private bool LogResult(IdentityResult result)
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace Ombi.Settings.Settings.Models
|
||||||
{
|
{
|
||||||
public bool ImportPlexAdmin { get; set; }
|
public bool ImportPlexAdmin { get; set; }
|
||||||
public bool ImportPlexUsers { get; set; }
|
public bool ImportPlexUsers { get; set; }
|
||||||
|
public bool CleanupPlexUsers { get; set; }
|
||||||
public bool ImportEmbyUsers { get; set; }
|
public bool ImportEmbyUsers { get; set; }
|
||||||
public bool ImportJellyfinUsers { get; set; }
|
public bool ImportJellyfinUsers { get; set; }
|
||||||
public int MovieRequestLimit { get; set; }
|
public int MovieRequestLimit { get; set; }
|
||||||
|
|
|
@ -253,6 +253,7 @@ export interface ICustomPage extends ISettings {
|
||||||
|
|
||||||
export interface IUserManagementSettings extends ISettings {
|
export interface IUserManagementSettings extends ISettings {
|
||||||
importPlexUsers: boolean;
|
importPlexUsers: boolean;
|
||||||
|
cleanupPlexUsers: boolean;
|
||||||
importPlexAdmin: boolean;
|
importPlexAdmin: boolean;
|
||||||
importEmbyUsers: boolean;
|
importEmbyUsers: boolean;
|
||||||
importJellyfinUsers: boolean;
|
importJellyfinUsers: boolean;
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<mat-slide-toggle id="importAdmin" [(ngModel)]="settings.importPlexAdmin">Import Plex Admin</mat-slide-toggle>
|
<mat-slide-toggle id="importAdmin" [(ngModel)]="settings.importPlexAdmin">Import Plex Admin</mat-slide-toggle>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="settings.importPlexUsers || settings.importPlexAdmin">
|
||||||
|
<mat-slide-toggle id="cleanupPlexUsers" [(ngModel)]="settings.cleanupPlexUsers">
|
||||||
|
Cleanup Plex Users</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
<div *ngIf="plexUsers">
|
<div *ngIf="plexUsers">
|
||||||
<p>Plex Users excluded from Import</p>
|
<p>Plex Users excluded from Import</p>
|
||||||
|
|
||||||
|
@ -121,7 +126,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div><button type="button" [disabled]="!enableImportButton" (click)="runImporter()" class="mat-focus-indicator mat-stroked-button mat-raised-button mat-button-base">
|
<div><button type="button" [disabled]="!enableImportButton" (click)="runImporter()" class="mat-focus-indicator mat-stroked-button mat-raised-button mat-button-base">
|
||||||
Run Importer<div matripple class="mat-ripple mat-button-ripple" ng-reflect-disabled="false" ng-reflect-centered="false" ng-reflect-trigger="[object HTMLButtonElement]"></div><div class="mat-button-focus-overlay"></div></button>
|
Run Importer<div matripple class="mat-ripple mat-button-ripple" ng-reflect-disabled="false" ng-reflect-centered="false" ng-reflect-trigger="[object HTMLButtonElement]"></div><div class="mat-button-focus-overlay"></div></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-form-field" style="margin-top:1em;"></div>
|
<div class="md-form-field" style="margin-top:1em;"></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue