Merge pull request #8 from tidusjar/develop

Bring develop branch up to date with source
pull/2197/head
Anojh Thayaparan 6 years ago committed by GitHub
commit e8acf79dc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
#tool "nuget:?package=GitVersion.CommandLine"
#addin "Cake.Gulp"
#addin "Cake.Npm"
#addin "nuget:?package=Cake.Npm&version=0.13.0"
#addin "SharpZipLib"
#addin nuget:?package=Cake.Compression&version=0.1.4
#addin "Cake.Incubator"

@ -55,15 +55,24 @@ namespace Ombi.Core.Authentication
return await _api.GetAccount(accessToken);
}
public async Task<Uri> GetOAuthUrl(int pinId, string code)
public async Task<Uri> GetOAuthUrl(int pinId, string code, string websiteAddress = null)
{
var settings = await _customizationSettingsService.GetSettingsAsync();
if (settings.ApplicationUrl.IsNullOrEmpty())
Uri url;
if (websiteAddress.IsNullOrEmpty())
{
return null;
var settings = await _customizationSettingsService.GetSettingsAsync();
if (settings.ApplicationUrl.IsNullOrEmpty())
{
return null;
}
url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false);
}
else
{
url = _api.GetOAuthUrl(pinId, code, websiteAddress, false);
}
var url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false);
return url;
}

@ -18,5 +18,6 @@ namespace Ombi.Core.Engine.Interfaces
Task<RequestEngineResult> ApproveMovieById(int requestId);
Task<RequestEngineResult> DenyMovieById(int modelId);
Task<IEnumerable<MovieRequests>> Filter(FilterViewModel vm);
}
}

@ -17,5 +17,6 @@ namespace Ombi.Core.Engine.Interfaces
Task<RequestEngineResult> MarkUnavailable(int modelId);
Task<RequestEngineResult> MarkAvailable(int modelId);
Task<int> GetTotal();
}
}

@ -144,6 +144,19 @@ namespace Ombi.Core.Engine
return allRequests;
}
public async Task<int> GetTotal()
{
var shouldHide = await HideFromOtherUsers();
if (shouldHide.Hide)
{
return await MovieRepository.GetWithUser(shouldHide.UserId).CountAsync();
}
else
{
return await MovieRepository.GetWithUser().CountAsync();
}
}
/// <summary>
/// Gets the requests.
/// </summary>

@ -130,7 +130,7 @@ namespace Ombi.Core.Engine
var newRequest = tvBuilder.CreateNewRequest(tv);
return await AddRequest(newRequest.NewRequest);
}
public async Task<IEnumerable<TvRequests>> GetRequests(int count, int position)
{
var shouldHide = await HideFromOtherUsers();
@ -280,7 +280,7 @@ namespace Ombi.Core.Engine
results.Background = PosterPathHelper.FixBackgroundPath(request.Background);
results.QualityOverride = request.QualityOverride;
results.RootFolder = request.RootFolder;
await TvRepository.Update(results);
return results;
}
@ -432,6 +432,19 @@ namespace Ombi.Core.Engine
};
}
public async Task<int> GetTotal()
{
var shouldHide = await HideFromOtherUsers();
if (shouldHide.Hide)
{
return await TvRepository.Get(shouldHide.UserId).CountAsync();
}
else
{
return await TvRepository.Get().CountAsync();
}
}
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest)
{
// Add the child

@ -9,7 +9,7 @@ namespace Ombi.Core.Authentication
{
Task<string> GetAccessTokenFromPin(int pinId);
Task<OAuthPin> RequestPin();
Task<Uri> GetOAuthUrl(int pinId, string code);
Task<Uri> GetOAuthUrl(int pinId, string code, string websiteAddress = null);
Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress);
Task<PlexAccount> GetAccount(string accessToken);
}

@ -65,5 +65,15 @@ namespace Ombi.Helpers
securePassword.MakeReadOnly();
return securePassword;
}
public static int IntParseLinq(string stringIn)
{
if (int.TryParse(stringIn, out var result))
{
return result;
}
return -1;
}
}
}

@ -112,6 +112,7 @@ namespace Ombi.Helpers
return uriBuilder.Uri;
}
}
public class ApplicationSettingsException : Exception

@ -98,8 +98,8 @@ namespace Ombi.Schedule.Jobs.Ombi
addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode);
// Filter out the ones that we haven't sent yet
var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(int.Parse(x.TheMovieDbId)));
var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(int.Parse(x.TheMovieDbId)));
var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId)));
var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId)));
_log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count());
_log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count());
@ -173,7 +173,7 @@ namespace Ombi.Schedule.Jobs.Ombi
AddedAt = DateTime.Now,
Type = RecentlyAddedType.Plex,
ContentType = ContentType.Parent,
ContentId = int.Parse(p.TheMovieDbId),
ContentId = StringHelper.IntParseLinq(p.TheMovieDbId),
});
}
@ -185,7 +185,7 @@ namespace Ombi.Schedule.Jobs.Ombi
AddedAt = DateTime.Now,
Type = RecentlyAddedType.Plex,
ContentType = ContentType.Episode,
ContentId = int.Parse(p.Series.TvDbId),
ContentId = StringHelper.IntParseLinq(p.Series.TvDbId),
EpisodeNumber = p.EpisodeNumber,
SeasonNumber = p.SeasonNumber
});
@ -199,7 +199,7 @@ namespace Ombi.Schedule.Jobs.Ombi
AddedAt = DateTime.Now,
Type = RecentlyAddedType.Emby,
ContentType = ContentType.Parent,
ContentId = int.Parse(e.TheMovieDbId),
ContentId = StringHelper.IntParseLinq(e.TheMovieDbId),
});
}
}
@ -211,7 +211,7 @@ namespace Ombi.Schedule.Jobs.Ombi
AddedAt = DateTime.Now,
Type = RecentlyAddedType.Emby,
ContentType = ContentType.Episode,
ContentId = int.Parse(p.Series.TvDbId),
ContentId = StringHelper.IntParseLinq(p.Series.TvDbId),
EpisodeNumber = p.EpisodeNumber,
SeasonNumber = p.SeasonNumber
});
@ -259,7 +259,7 @@ namespace Ombi.Schedule.Jobs.Ombi
var itemsToReturn = new HashSet<PlexEpisode>();
foreach (var ep in source)
{
var tvDbId = int.Parse(ep.Series.TvDbId);
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
{
continue;
@ -276,7 +276,7 @@ namespace Ombi.Schedule.Jobs.Ombi
var itemsToReturn = new HashSet<EmbyEpisode>();
foreach (var ep in source)
{
var tvDbId = int.Parse(ep.Series.TvDbId);
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
{
continue;
@ -374,7 +374,7 @@ namespace Ombi.Schedule.Jobs.Ombi
theMovieDbId = result.id.ToString();
}
var info = await _movieApi.GetMovieInformationWithExtraInfo(int.Parse(theMovieDbId));
var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId));
if (info == null)
{
continue;

@ -12,5 +12,6 @@ namespace Ombi.Settings.Settings.Models
public bool RequireLowercase { get; set; }
public bool RequireNonAlphanumeric { get; set; }
public bool RequireUppercase { get; set; }
public bool EnableOAuth { get; set; } // Plex OAuth
}
}

@ -145,6 +145,7 @@ export interface IAuthenticationSettings extends ISettings {
requiredLowercase: boolean;
requireNonAlphanumeric: boolean;
requireUppercase: boolean;
enableOAuth: boolean;
}
export interface IUserManagementSettings extends ISettings {

@ -17,7 +17,7 @@ include the remember me checkbox
</div>
<p id="profile-name" class="profile-name-card"></p>
<div *ngIf="!plexEnabled || !customizationSettings.applicationUrl || loginWithOmbi">
<div *ngIf="!authenticationSettings.enableOAuth || loginWithOmbi">
<form *ngIf="authenticationSettings" class="form-signin" novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
@ -41,15 +41,16 @@ include the remember me checkbox
<!-- /form -->
</div>
<!-- Main OAuth Flow -->
<div class="form-signin" *ngIf="plexEnabled && customizationSettings.applicationUrl && !loginWithOmbi">
<div *ngIf="authenticationSettings.enableOAuth && !loginWithOmbi">
<div class="form-signin">
<button class="btn btn-success" type="button" (click)="loginWithOmbi = true">
Sign In With {{appName}}</button>
</div>
<div class="form-signin" *ngIf="plexEnabled && customizationSettings.applicationUrl && !loginWithOmbi">
<div class="form-signin">
<button class="btn btn-primary" type="button" (click)="oauth()">
Sign In With Plex</button>
</div>
</div>
</div>
<!-- /card-container -->

@ -79,7 +79,6 @@ export class LoginComponent implements OnDestroy, OnInit {
public ngOnInit() {
this.settingsService.getAuthentication().subscribe(x => this.authenticationSettings = x);
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
this.settingsService.getStatusPlex().subscribe(x => this.plexEnabled = x);
this.images.getRandomBackground().subscribe(x => {
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")");
});
@ -125,7 +124,13 @@ export class LoginComponent implements OnDestroy, OnInit {
public oauth() {
this.authService.login({usePlexOAuth: true, password:"",rememberMe:true,username:""}).subscribe(x => {
window.location.href = x.url;
if (window.frameElement) {
// in frame
window.open(x.url, "_blank");
} else {
// not in frame
window.location.href = x.url;
}
});
}

@ -2,6 +2,7 @@
import { ActivatedRoute, Router } from "@angular/router";
import { AuthService } from "../auth/auth.service";
import { NotificationService } from "../services";
@Component({
templateUrl: "./loginoauth.component.html",
@ -11,7 +12,7 @@ export class LoginOAuthComponent implements OnInit {
public error: string;
constructor(private authService: AuthService, private router: Router,
private route: ActivatedRoute) {
private route: ActivatedRoute, private notify: NotificationService) {
this.route.params
.subscribe((params: any) => {
this.pin = params.pin;
@ -37,6 +38,10 @@ export class LoginOAuthComponent implements OnInit {
this.error = x.errorMessage;
}
}, err => {
this.notify.error(err.statusText);
this.router.navigate(["login"]);
});
}
}

@ -56,7 +56,7 @@
<br />
<div infinite-scroll [infiniteScrollDistance]="1" [infiniteScrollThrottle]="100" (scrolled)="loadMore()">
<div>
<div *ngFor="let request of movieRequests | orderBy: order : reverse : 'case-insensitive'">
@ -212,6 +212,8 @@
</div>
<p-paginator [rows]="10" [totalRecords]="totalMovies" (onPageChange)="paginate($event)"></p-paginator>
</div>

@ -8,7 +8,7 @@ import { Subject } from "rxjs/Subject";
import { AuthService } from "../auth/auth.service";
import { NotificationService, RadarrService, RequestService } from "../services";
import { FilterType, IFilter, IIssueCategory, IMovieRequests, IRadarrProfile, IRadarrRootFolder } from "../interfaces";
import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder } from "../interfaces";
@Component({
selector: "movie-requests",
@ -39,6 +39,7 @@ export class MovieRequestsComponent implements OnInit {
public order: string = "requestedDate";
public reverse = false;
public totalMovies: number = 100;
private currentlyLoaded: number;
private amountToLoad: number;
@ -65,8 +66,8 @@ export class MovieRequestsComponent implements OnInit {
}
public ngOnInit() {
this.amountToLoad = 100;
this.currentlyLoaded = 100;
this.amountToLoad = 10;
this.currentlyLoaded = 10;
this.loadInit();
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
this.filter = {
@ -74,8 +75,10 @@ export class MovieRequestsComponent implements OnInit {
statusFilter: FilterType.None};
}
public loadMore() {
this.loadRequests(this.amountToLoad, this.currentlyLoaded);
public paginate(event: IPagenator) {
const skipAmount = event.first;
this.loadRequests(this.amountToLoad, skipAmount);
}
public search(text: any) {
@ -226,7 +229,7 @@ export class MovieRequestsComponent implements OnInit {
if(!this.movieRequests) {
this.movieRequests = [];
}
this.movieRequests.push.apply(this.movieRequests, x);
this.movieRequests = x;
this.currentlyLoaded = currentlyLoaded + amountToLoad;
});
}
@ -267,6 +270,7 @@ export class MovieRequestsComponent implements OnInit {
}
private loadInit() {
this.requestService.getTotalMovies().subscribe(x => this.totalMovies = x);
this.requestService.getMovieRequests(this.amountToLoad, 0)
.subscribe(x => {
this.movieRequests = x;

@ -6,7 +6,7 @@ import { OrderModule } from "ngx-order-pipe";
import { InfiniteScrollModule } from "ngx-infinite-scroll";
import { ButtonModule, DialogModule } from "primeng/primeng";
import { ButtonModule, DialogModule, PaginatorModule } from "primeng/primeng";
import { MovieRequestsComponent } from "./movierequests.component";
// Request
import { RequestComponent } from "./request.component";
@ -36,6 +36,7 @@ const routes: Routes = [
SharedModule,
SidebarModule,
OrderModule,
PaginatorModule,
],
declarations: [
RequestComponent,

@ -120,6 +120,7 @@
</p-column>
</p-treeTable>
<p-paginator [rows]="10" [totalRecords]="totalTv" (onPageChange)="paginate($event)"></p-paginator>
</div>
<issue-report [movie]="false" [visible]="issuesBarVisible" [title]="issueRequest?.title"

@ -14,7 +14,7 @@ import { AuthService } from "../auth/auth.service";
import { NotificationService, RequestService, SonarrService } from "../services";
import { TreeNode } from "primeng/primeng";
import { IIssueCategory, ISonarrProfile, ISonarrRootFolder, ITvRequests } from "../interfaces";
import { IIssueCategory, IPagenator, ISonarrProfile, ISonarrRootFolder, ITvRequests } from "../interfaces";
@Component({
selector: "tv-requests",
@ -40,6 +40,7 @@ export class TvRequestsComponent implements OnInit {
public sonarrProfiles: ISonarrProfile[] = [];
public sonarrRootFolders: ISonarrRootFolder[] = [];
public totalTv: number = 100;
private currentlyLoaded: number;
private amountToLoad: number;
@ -105,25 +106,22 @@ export class TvRequestsComponent implements OnInit {
}
public ngOnInit() {
this.amountToLoad = 1000;
this.currentlyLoaded = 1000;
this.amountToLoad = 10;
this.currentlyLoaded = 10;
this.tvRequests = [];
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
this.loadInit();
}
public loadMore() {
//TODO: I believe this +1 is causing off by one error skipping loading of tv shows
//When removed and scrolling very slowly everything works as expected, however
//if you scroll really quickly then you start getting duplicates of movies
//since it's async and some subsequent results return first and then incrementer
//is increased so you see movies which had already been gotten show up...
this.requestService.getTvRequestsTree(this.amountToLoad, this.currentlyLoaded + 1)
.subscribe(x => {
this.tvRequests = x;
this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad;
});
public paginate(event: IPagenator) {
const skipAmount = event.first;
this.requestService.getTvRequestsTree(this.amountToLoad, skipAmount)
.subscribe(x => {
this.tvRequests = x;
this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad;
});
}
public search(text: any) {
@ -197,6 +195,7 @@ export class TvRequestsComponent implements OnInit {
}
private loadInit() {
this.requestService.getTotalTv().subscribe(x => this.totalTv = x);
this.requestService.getTvRequestsTree(this.amountToLoad, 0)
.subscribe(x => {
this.tvRequests = x;

@ -20,6 +20,14 @@ export class RequestService extends ServiceHelpers {
return this.http.post<IRequestEngineResult>(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers});
}
public getTotalMovies(): Observable<number> {
return this.http.get<number>(`${this.url}Movie/total`, {headers: this.headers});
}
public getTotalTv(): Observable<number> {
return this.http.get<number>(`${this.url}tv/total`, {headers: this.headers});
}
public requestTv(tv: ITvRequestViewModel): Observable<IRequestEngineResult> {
return this.http.post<IRequestEngineResult>(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers});
}

@ -71,10 +71,6 @@ export class SettingsService extends ServiceHelpers {
return this.http.get<IPlexSettings>(`${this.url}/Plex/`, {headers: this.headers});
}
public getStatusPlex(): Observable<boolean> {
return this.http.get<boolean>(`${this.url}/Plexstatus/`, {headers: this.headers});
}
public savePlex(settings: IPlexSettings): Observable<boolean> {
return this.http.post<boolean>(`${this.url}/Plex/`, JSON.stringify(settings), {headers: this.headers});
}

@ -14,6 +14,13 @@
</div>
</div>
<div class="form-group">
<div class="checkbox">
<input type="checkbox" id="enableOAuth" name="enableOAuth" formControlName="enableOAuth">
<label for="enableOAuth" >Enable Plex OAuth</label>
</div>
</div>
<!-- <hr/>
<div class="form-group">
<div class="checkbox">

@ -24,6 +24,7 @@ export class AuthenticationComponent implements OnInit {
requiredLowercase: [x.requiredLowercase],
requireNonAlphanumeric: [x.requireNonAlphanumeric],
requireUppercase: [x.requireUppercase],
enableOAuth: [x.enableOAuth],
});
});
}

@ -959,3 +959,7 @@ a > h4:hover {
width: 94%;
}
.ui-state-active {
background-color: $primary-colour-outline $i;
color: black $i;
}

@ -37,6 +37,15 @@ namespace Ombi.Controllers
return await MovieRequestEngine.GetRequests(count, position);
}
/// <summary>
/// Gets the total amount of movie requests.
/// </summary>
[HttpGet("movie/total")]
public async Task<int> GetTotalMovies()
{
return await MovieRequestEngine.GetTotal();
}
/// <summary>
/// Gets all movie requests.
/// </summary>
@ -146,6 +155,15 @@ namespace Ombi.Controllers
return await TvRequestEngine.GetRequestsTreeNode(count, position);
}
/// <summary>
/// Gets the total amount of TV requests.
/// </summary>
[HttpGet("tv/total")]
public async Task<int> GetTotalTV()
{
return await TvRequestEngine.GetTotal();
}
/// <summary>
/// Gets the tv requests.
/// </summary>

@ -147,16 +147,6 @@ namespace Ombi.Controllers
return s;
}
[HttpGet("plexstatus")]
[AllowAnonymous]
public async Task<bool> PlexStatusSettings()
{
var s = await Get<PlexSettings>();
return s.Enable;
}
/// <summary>
/// Save the Plex settings.
/// </summary>

@ -23,7 +23,7 @@ namespace Ombi.Controllers
{
[ApiV1]
[Produces("application/json")]
public class TokenController
public class TokenController : Controller
{
public TokenController(OmbiUserManager um, IOptions<TokenAuthentication> ta, IAuditRepository audit, ITokenRepository token,
IPlexOAuthManager oAuthManager)
@ -83,8 +83,9 @@ namespace Ombi.Controllers
// We need a PIN first
var pin = await _plexOAuthManager.RequestPin();
var websiteAddress = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}";
//https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd
var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code);
var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code, websiteAddress);
if (url == null)
{
return new JsonResult(new

@ -134,7 +134,7 @@ namespace Ombi
{
x.UseSQLiteStorage(sqliteStorage);
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
x.UseConsole();
//x.UseConsole();
});

Loading…
Cancel
Save