mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-15 01:32:55 -07:00
Emby user importer is now therer! #1456
This commit is contained in:
parent
28abc214b7
commit
143c619db0
15 changed files with 248 additions and 41 deletions
|
@ -144,6 +144,7 @@ namespace Ombi.DependencyInjection
|
|||
services.AddTransient<IRadarrCacher, RadarrCacher>();
|
||||
services.AddTransient<IOmbiAutomaticUpdater, OmbiAutomaticUpdater>();
|
||||
services.AddTransient<IPlexUserImporter, PlexUserImporter>();
|
||||
services.AddTransient<IEmbyUserImporter, EmbyUserImporter>();
|
||||
services.AddTransient<IWelcomeEmail, WelcomeEmail>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Ombi.Helpers
|
|||
public static EventId PlexEpisodeCacher => new EventId(2001);
|
||||
public static EventId EmbyContentCacher => new EventId(2002);
|
||||
public static EventId PlexUserImporter => new EventId(2003);
|
||||
public static EventId EmbyUserImporter => new EventId(2004);
|
||||
|
||||
public static EventId MovieSender => new EventId(3000);
|
||||
|
||||
|
|
|
@ -10,13 +10,15 @@ namespace Ombi.Schedule
|
|||
public class JobSetup : IJobSetup
|
||||
{
|
||||
public JobSetup(IPlexContentCacher plexContentCacher, IRadarrCacher radarrCacher,
|
||||
IOmbiAutomaticUpdater updater, IEmbyContentCacher embyCacher, IPlexUserImporter userImporter)
|
||||
IOmbiAutomaticUpdater updater, IEmbyContentCacher embyCacher, IPlexUserImporter userImporter,
|
||||
IEmbyUserImporter embyUserImporter)
|
||||
{
|
||||
PlexContentCacher = plexContentCacher;
|
||||
RadarrCacher = radarrCacher;
|
||||
Updater = updater;
|
||||
EmbyContentCacher = embyCacher;
|
||||
PlexUserImporter = userImporter;
|
||||
EmbyUserImporter = embyUserImporter;
|
||||
}
|
||||
|
||||
private IPlexContentCacher PlexContentCacher { get; }
|
||||
|
@ -24,14 +26,16 @@ namespace Ombi.Schedule
|
|||
private IOmbiAutomaticUpdater Updater { get; }
|
||||
private IPlexUserImporter PlexUserImporter { get; }
|
||||
private IEmbyContentCacher EmbyContentCacher { get; }
|
||||
private IEmbyUserImporter EmbyUserImporter { get; }
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
RecurringJob.AddOrUpdate(() => PlexContentCacher.CacheContent(), Cron.Hourly);
|
||||
RecurringJob.AddOrUpdate(() => EmbyContentCacher.Start(), Cron.Hourly);
|
||||
RecurringJob.AddOrUpdate(() => RadarrCacher.CacheContent(), Cron.Hourly);
|
||||
RecurringJob.AddOrUpdate(() => PlexUserImporter.Start(), Cron.Daily);
|
||||
RecurringJob.AddOrUpdate(() => Updater.Update(null), Cron.Daily);
|
||||
RecurringJob.AddOrUpdate(() => PlexContentCacher.CacheContent(), Cron.Hourly(20));
|
||||
RecurringJob.AddOrUpdate(() => EmbyContentCacher.Start(), Cron.Hourly(5));
|
||||
RecurringJob.AddOrUpdate(() => RadarrCacher.CacheContent(), Cron.Hourly(10));
|
||||
RecurringJob.AddOrUpdate(() => PlexUserImporter.Start(), Cron.Daily(1));
|
||||
RecurringJob.AddOrUpdate(() => EmbyUserImporter.Start(), Cron.Daily);
|
||||
RecurringJob.AddOrUpdate(() => Updater.Update(null), Cron.Daily(3));
|
||||
|
||||
//BackgroundJob.Enqueue(() => PlexUserImporter.Start());
|
||||
}
|
||||
|
|
131
src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs
Normal file
131
src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs
Normal file
|
@ -0,0 +1,131 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: EmbyUserImporter.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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Emby;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Settings.Settings.Models;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Schedule.Jobs.Emby
|
||||
{
|
||||
public class EmbyUserImporter : IEmbyUserImporter
|
||||
{
|
||||
public EmbyUserImporter(IEmbyApi api, UserManager<OmbiUser> um, ILogger<EmbyUserImporter> log,
|
||||
ISettingsService<EmbySettings> embySettings, ISettingsService<UserManagementSettings> ums)
|
||||
{
|
||||
_api = api;
|
||||
_userManager = um;
|
||||
_log = log;
|
||||
_embySettings = embySettings;
|
||||
_userManagementSettings = ums;
|
||||
}
|
||||
|
||||
private readonly IEmbyApi _api;
|
||||
private readonly UserManager<OmbiUser> _userManager;
|
||||
private readonly ILogger<EmbyUserImporter> _log;
|
||||
private readonly ISettingsService<EmbySettings> _embySettings;
|
||||
private readonly ISettingsService<UserManagementSettings> _userManagementSettings;
|
||||
|
||||
public async Task Start()
|
||||
{
|
||||
var userManagementSettings = await _userManagementSettings.GetSettingsAsync();
|
||||
if (!userManagementSettings.ImportEmbyUsers)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var settings = await _embySettings.GetSettingsAsync();
|
||||
if (!settings.Enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.EmbyUser).ToListAsync();
|
||||
foreach (var server in settings.Servers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(server.ApiKey))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var embyUsers = await _api.GetUsers(server.FullUri, server.ApiKey);
|
||||
foreach (var embyUser in embyUsers)
|
||||
{
|
||||
// Check if we should import this user
|
||||
if (userManagementSettings.BannedEmbyUserIds.Contains(embyUser.Id))
|
||||
{
|
||||
// Do not import these, they are not allowed into the country.
|
||||
continue;
|
||||
}
|
||||
// Check if this Plex User already exists
|
||||
// We are using the Plex USERNAME and Not the TITLE, the Title is for HOME USERS
|
||||
var existingEmbyUser = allUsers.FirstOrDefault(x => x.ProviderUserId == embyUser.Id);
|
||||
if (existingEmbyUser == null)
|
||||
{
|
||||
// Create this users
|
||||
// We do not store a password against the user since they will authenticate via Plex
|
||||
var newUser = new OmbiUser
|
||||
{
|
||||
UserType = UserType.EmbyUser,
|
||||
UserName = embyUser.Name,
|
||||
ProviderUserId = embyUser.Id,
|
||||
Alias = string.Empty
|
||||
};
|
||||
var result = await _userManager.CreateAsync(newUser);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
foreach (var identityError in result.Errors)
|
||||
{
|
||||
_log.LogError(LoggingEvents.EmbyUserImporter, identityError.Description);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (userManagementSettings.DefaultRoles.Any())
|
||||
{
|
||||
foreach (var defaultRole in userManagementSettings.DefaultRoles)
|
||||
{
|
||||
await _userManager.AddToRoleAsync(newUser, defaultRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do we need to update this user?
|
||||
existingEmbyUser.UserName = embyUser.Name;
|
||||
|
||||
await _userManager.UpdateAsync(existingEmbyUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
src/Ombi.Schedule/Jobs/Emby/IEmbyUserImporter.cs
Normal file
9
src/Ombi.Schedule/Jobs/Emby/IEmbyUserImporter.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.Schedule.Jobs.Emby
|
||||
{
|
||||
public interface IEmbyUserImporter
|
||||
{
|
||||
Task Start();
|
||||
}
|
||||
}
|
|
@ -21,3 +21,8 @@ export interface ICheckbox {
|
|||
value: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface IUsersModel {
|
||||
id: string;
|
||||
username: string;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,6 @@ export interface IPlexLibResponse {
|
|||
data: IPlexLibraries;
|
||||
}
|
||||
|
||||
export interface IPlexFriends {
|
||||
id: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface IMediaContainer {
|
||||
directory: IDirectory[];
|
||||
}
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
import { Injectable } from "@angular/core";
|
||||
import { Http } from "@angular/http";
|
||||
import { AuthHttp } from "angular2-jwt";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
import { ServiceAuthHelpers } from "../service.helpers";
|
||||
|
||||
import { IEmbySettings } from "../../interfaces";
|
||||
import { IEmbySettings, IUsersModel } from "../../interfaces";
|
||||
|
||||
@Injectable()
|
||||
export class EmbyService extends ServiceHelpers {
|
||||
constructor(http: Http) {
|
||||
export class EmbyService extends ServiceAuthHelpers {
|
||||
constructor(http: AuthHttp, private regularHttp: Http) {
|
||||
super(http, "/api/v1/Emby/");
|
||||
}
|
||||
|
||||
public logIn(settings: IEmbySettings): Observable<IEmbySettings> {
|
||||
return this.http.post(`${this.url}`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||
return this.regularHttp.post(`${this.url}`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
public getUsers(): Observable<IUsersModel[]> {
|
||||
return this.http.get(`${this.url}users`, { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Observable } from "rxjs/Rx";
|
|||
|
||||
import { ServiceAuthHelpers } from "../service.helpers";
|
||||
|
||||
import { IPlexAuthentication, IPlexFriends, IPlexLibResponse, IPlexServer, IPlexServerViewModel } from "../../interfaces";
|
||||
import { IPlexAuthentication, IPlexLibResponse, IPlexServer, IPlexServerViewModel, IUsersModel } from "../../interfaces";
|
||||
|
||||
@Injectable()
|
||||
export class PlexService extends ServiceAuthHelpers {
|
||||
|
@ -26,7 +26,7 @@ export class PlexService extends ServiceAuthHelpers {
|
|||
return this.http.post(`${this.url}Libraries`, JSON.stringify(plexSettings), { headers: this.headers }).map(this.extractData).catch(this.handleError);
|
||||
}
|
||||
|
||||
public getFriends(): Observable<IPlexFriends[]> {
|
||||
public getFriends(): Observable<IUsersModel[]> {
|
||||
return this.http.get(`${this.url}Friends`, { headers: this.headers }).map(this.extractData).catch(this.handleError);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button id="testEmby" type="submit" (click)="test()" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
|
||||
<button id="testEmby" type="submit" (click)="test(server)" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<div *ngIf="plexUsers">
|
||||
<p>Plex Users exclude from Import</p>
|
||||
|
||||
<p-autoComplete [(ngModel)]="bannedPlexUsers" [suggestions]="filteredPlexUsers" [multiple]="true" field="username" (completeMethod)="filterUserList($event)"></p-autoComplete>
|
||||
<p-autoComplete [(ngModel)]="bannedPlexUsers" [suggestions]="filteredPlexUsers" [multiple]="true" field="username" (completeMethod)="filterPlexList($event)"></p-autoComplete>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -28,6 +28,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="embyUsers">
|
||||
<p>Emby Users exclude from Import</p>
|
||||
|
||||
<p-autoComplete [(ngModel)]="bannedEmbyUsers" [suggestions]="filteredEmbyUsers" [multiple]="true" field="username" (completeMethod)="filterEmbyList($event)"></p-autoComplete>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { ICheckbox, IUserManagementSettings } from "../../interfaces";
|
||||
import { IPlexFriends } from "../../interfaces/IPlex";
|
||||
import { IdentityService, JobService, NotificationService, PlexService, SettingsService } from "../../services";
|
||||
import { IUsersModel } from "../../interfaces";
|
||||
import { EmbyService, IdentityService, JobService, NotificationService, PlexService, SettingsService } from "../../services";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./usermanagement.component.html",
|
||||
|
@ -14,16 +14,20 @@ export class UserManagementComponent implements OnInit {
|
|||
public settings: IUserManagementSettings;
|
||||
public claims: ICheckbox[];
|
||||
|
||||
public plexUsers: IPlexFriends[];
|
||||
public filteredPlexUsers: IPlexFriends[];
|
||||
public bannedPlexUsers: IPlexFriends[] = [];
|
||||
public plexUsers: IUsersModel[];
|
||||
public filteredPlexUsers: IUsersModel[];
|
||||
public bannedPlexUsers: IUsersModel[] = [];
|
||||
|
||||
constructor(private settingsService: SettingsService,
|
||||
private notificationService: NotificationService,
|
||||
private identityService: IdentityService,
|
||||
private plexService: PlexService,
|
||||
private jobService: JobService) {
|
||||
public embyUsers: IUsersModel[];
|
||||
public filteredEmbyUsers: IUsersModel[];
|
||||
public bannedEmbyUsers: IUsersModel[] = [];
|
||||
|
||||
constructor(private readonly settingsService: SettingsService,
|
||||
private readonly notificationService: NotificationService,
|
||||
private readonly identityService: IdentityService,
|
||||
private readonly plexService: PlexService,
|
||||
private readonly jobService: JobService,
|
||||
private readonly embyService: EmbyService) {
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
|
@ -42,6 +46,18 @@ export class UserManagementComponent implements OnInit {
|
|||
});
|
||||
});
|
||||
|
||||
this.embyService.getUsers().subscribe(f => {
|
||||
this.embyUsers = f;
|
||||
this.embyUsers.forEach((emby) => {
|
||||
const isExcluded = this.settings.bannedPlexUserIds.some((val) => {
|
||||
return emby.id === val;
|
||||
});
|
||||
if (isExcluded) {
|
||||
this.bannedEmbyUsers.push(emby);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.identityService.getAllAvailableClaims().subscribe(c => {
|
||||
|
||||
this.claims = c;
|
||||
|
@ -65,6 +81,7 @@ export class UserManagementComponent implements OnInit {
|
|||
});
|
||||
this.settings.defaultRoles = enabledClaims.map((claim) => claim.value);
|
||||
this.settings.bannedPlexUserIds = this.bannedPlexUsers.map((u) => u.id);
|
||||
this.settings.bannedEmbyUserIds = this.bannedEmbyUsers.map((u) => u.id);
|
||||
|
||||
this.settingsService.saveUserManagementSettings(this.settings).subscribe(x => {
|
||||
if (x === true) {
|
||||
|
@ -75,15 +92,19 @@ export class UserManagementComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
public filterUserList(event: any) {
|
||||
public filterPlexList(event: any) {
|
||||
this.filteredPlexUsers = this.filter(event.query, this.plexUsers);
|
||||
}
|
||||
|
||||
public filterEmbyList(event: any) {
|
||||
this.filteredEmbyUsers = this.filter(event.query, this.embyUsers);
|
||||
}
|
||||
|
||||
public runImporter(): void {
|
||||
this.jobService.runPlexImporter().subscribe();
|
||||
}
|
||||
|
||||
private filter(query: string, users: IPlexFriends[]): IPlexFriends[] {
|
||||
private filter(query: string, users: IUsersModel[]): IUsersModel[] {
|
||||
return users.filter((val) => {
|
||||
return val.username.toLowerCase().indexOf(query.toLowerCase()) === 0;
|
||||
});
|
||||
|
|
32
src/Ombi/Controllers/External/EmbyController.cs
vendored
32
src/Ombi/Controllers/External/EmbyController.cs
vendored
|
@ -1,11 +1,15 @@
|
|||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Ombi.Api.Emby;
|
||||
using Ombi.Api.Plex;
|
||||
using Ombi.Attributes;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Models.External;
|
||||
|
||||
namespace Ombi.Controllers.External
|
||||
{
|
||||
|
@ -58,5 +62,31 @@ namespace Ombi.Controllers.External
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the emby users.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("users")]
|
||||
public async Task<IEnumerable<UsersViewModel>> EmbyUsers()
|
||||
{
|
||||
var vm = new List<UsersViewModel>();
|
||||
var s = await EmbySettings.GetSettingsAsync();
|
||||
foreach (var server in s.Servers)
|
||||
{
|
||||
var users = await EmbyApi.GetUsers(server.FullUri, server.ApiKey);
|
||||
if (users != null && users.Any())
|
||||
{
|
||||
vm.AddRange(users.Select(u => new UsersViewModel
|
||||
{
|
||||
Username = u.Name,
|
||||
Id = u.Id
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out any dupes
|
||||
return vm.DistinctBy(x => x.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,16 +148,16 @@ namespace Ombi.Controllers.External
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("friends")]
|
||||
public async Task<IEnumerable<PlexUsersViewModel>> GetFriends()
|
||||
public async Task<IEnumerable<UsersViewModel>> GetFriends()
|
||||
{
|
||||
var vm = new List<PlexUsersViewModel>();
|
||||
var vm = new List<UsersViewModel>();
|
||||
var s = await PlexSettings.GetSettingsAsync();
|
||||
foreach (var server in s.Servers)
|
||||
{
|
||||
var users = await PlexApi.GetUsers(server.PlexAuthToken);
|
||||
if (users?.User != null && users.User.Any())
|
||||
{
|
||||
vm.AddRange(users.User.Select(u => new PlexUsersViewModel
|
||||
vm.AddRange(users.User.Select(u => new UsersViewModel
|
||||
{
|
||||
Username = u.Username,
|
||||
Id = u.Id
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace Ombi.Models.External
|
||||
{
|
||||
public class PlexUsersViewModel
|
||||
public class UsersViewModel
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string Id { get; set; }
|
Loading…
Add table
Add a link
Reference in a new issue