#2363 Added the ability to pass any username into the API using the ApiAlias header

This commit is contained in:
tidusjar 2019-01-16 21:33:15 +00:00
parent 359d191fc3
commit 3b91392323
18 changed files with 1455 additions and 116 deletions

View file

@ -83,7 +83,8 @@ namespace Ombi.Core.Engine
Approved = false, Approved = false,
RequestedUserId = userDetails.Id, RequestedUserId = userDetails.Id,
Background = movieInfo.BackdropPath, Background = movieInfo.BackdropPath,
LangCode = model.LanguageCode LangCode = model.LanguageCode,
RequestedByAlias = model.RequestedByAlias
}; };
var usDates = movieInfo.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US"); var usDates = movieInfo.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US");

View file

@ -83,7 +83,8 @@ namespace Ombi.Core.Engine
Title = album.title, Title = album.title,
Disk = album.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url, Disk = album.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url,
Cover = album.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url, Cover = album.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url,
ForeignArtistId = album?.artist?.foreignArtistId ?? string.Empty ForeignArtistId = album?.artist?.foreignArtistId ?? string.Empty,
RequestedByAlias = model.RequestedByAlias
}; };
if (requestModel.Cover.IsNullOrEmpty()) if (requestModel.Cover.IsNullOrEmpty())
{ {

View file

@ -72,6 +72,7 @@ namespace Ombi.Core.Helpers
SeasonRequests = new List<SeasonRequests>(), SeasonRequests = new List<SeasonRequests>(),
Title = ShowInfo.name, Title = ShowInfo.name,
ReleaseYear = FirstAir, ReleaseYear = FirstAir,
RequestedByAlias = model.RequestedByAlias,
SeriesType = ShowInfo.genres.Any( s => s.Equals("Anime", StringComparison.InvariantCultureIgnoreCase)) ? SeriesType.Anime : SeriesType.Standard SeriesType = ShowInfo.genres.Any( s => s.Equals("Anime", StringComparison.InvariantCultureIgnoreCase)) ? SeriesType.Anime : SeriesType.Standard
}; };

View file

@ -24,11 +24,20 @@
// 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 Newtonsoft.Json;
namespace Ombi.Core.Models.Requests namespace Ombi.Core.Models.Requests
{ {
public class MovieRequestViewModel public class MovieRequestViewModel
{ {
public int TheMovieDbId { get; set; } public int TheMovieDbId { get; set; }
public string LanguageCode { get; set; } = "en"; public string LanguageCode { get; set; } = "en";
/// <summary>
/// This is only set from a HTTP Header
/// </summary>
[JsonIgnore]
public string RequestedByAlias { get; set; }
} }
} }

View file

@ -3,5 +3,6 @@
public class MusicAlbumRequestViewModel public class MusicAlbumRequestViewModel
{ {
public string ForeignAlbumId { get; set; } public string ForeignAlbumId { get; set; }
public string RequestedByAlias { get; set; }
} }
} }

View file

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace Ombi.Core.Models.Requests namespace Ombi.Core.Models.Requests
{ {
@ -9,6 +10,8 @@ namespace Ombi.Core.Models.Requests
public bool FirstSeason { get; set; } public bool FirstSeason { get; set; }
public int TvDbId { get; set; } public int TvDbId { get; set; }
public List<SeasonsViewModel> Seasons { get; set; } = new List<SeasonsViewModel>(); public List<SeasonsViewModel> Seasons { get; set; } = new List<SeasonsViewModel>();
[JsonIgnore]
public string RequestedByAlias { get; set; }
} }
public class SeasonsViewModel public class SeasonsViewModel

View file

@ -34,7 +34,7 @@ namespace Ombi.Store.Entities
public bool IsEmbyConnect => UserType == UserType.EmbyUser && EmbyConnectUserId.HasValue(); public bool IsEmbyConnect => UserType == UserType.EmbyUser && EmbyConnectUserId.HasValue();
[NotMapped] [NotMapped]
public string UserAlias => string.IsNullOrEmpty(Alias) ? UserName : Alias; public virtual string UserAlias => string.IsNullOrEmpty(Alias) ? UserName : Alias;
[NotMapped] [NotMapped]
public bool EmailLogin { get; set; } public bool EmailLogin { get; set; }

View file

@ -17,6 +17,7 @@ namespace Ombi.Store.Entities.Requests
public DateTime MarkedAsDenied { get; set; } public DateTime MarkedAsDenied { get; set; }
public string DeniedReason { get; set; } public string DeniedReason { get; set; }
public RequestType RequestType { get; set; } public RequestType RequestType { get; set; }
public string RequestedByAlias { get; set; }
[ForeignKey(nameof(RequestedUserId))] [ForeignKey(nameof(RequestedUserId))]
public OmbiUser RequestedUser { get; set; } public OmbiUser RequestedUser { get; set; }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ombi.Store.Migrations
{
public partial class RequestedByAlias : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "RequestedByAlias",
table: "MovieRequests",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "RequestedByAlias",
table: "ChildRequests",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "RequestedByAlias",
table: "AlbumRequests",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "RequestedByAlias",
table: "MovieRequests");
migrationBuilder.DropColumn(
name: "RequestedByAlias",
table: "ChildRequests");
migrationBuilder.DropColumn(
name: "RequestedByAlias",
table: "AlbumRequests");
}
}
}

View file

@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-rtm-35687"); .HasAnnotation("ProductVersion", "2.2.1-servicing-10028");
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{ {
@ -583,6 +583,8 @@ namespace Ombi.Store.Migrations
b.Property<int>("RequestType"); b.Property<int>("RequestType");
b.Property<string>("RequestedByAlias");
b.Property<DateTime>("RequestedDate"); b.Property<DateTime>("RequestedDate");
b.Property<string>("RequestedUserId"); b.Property<string>("RequestedUserId");
@ -621,6 +623,8 @@ namespace Ombi.Store.Migrations
b.Property<int>("RequestType"); b.Property<int>("RequestType");
b.Property<string>("RequestedByAlias");
b.Property<DateTime>("RequestedDate"); b.Property<DateTime>("RequestedDate");
b.Property<string>("RequestedUserId"); b.Property<string>("RequestedUserId");
@ -749,6 +753,8 @@ namespace Ombi.Store.Migrations
b.Property<int>("RequestType"); b.Property<int>("RequestType");
b.Property<string>("RequestedByAlias");
b.Property<DateTime>("RequestedDate"); b.Property<DateTime>("RequestedDate");
b.Property<string>("RequestedUserId"); b.Property<string>("RequestedUserId");

View file

@ -87,6 +87,7 @@ export interface IBaseRequest {
requestedUser: IUser; requestedUser: IUser;
canApprove: boolean; canApprove: boolean;
title: string; title: string;
requestedByAlias: string;
} }
export interface ITvRequests { export interface ITvRequests {

View file

@ -1,23 +1,26 @@
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<input type="text" id="search" class="form-control form-control-custom searchwidth" placeholder="Search" (keyup)="search($event)"> <input type="text" id="search" class="form-control form-control-custom searchwidth" placeholder="Search"
(keyup)="search($event)">
<span class="input-group-btn"> <span class="input-group-btn">
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay"> <button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
<i class="fa fa-filter"></i> {{ 'Requests.Filter' | translate }} <i class="fa fa-filter"></i> {{ 'Requests.Filter' | translate }}
</button> </button>
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" <button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
aria-expanded="true"> aria-haspopup="true" aria-expanded="true">
<i class="fa fa-sort"></i> {{ 'Requests.Sort' | translate }} <i class="fa fa-sort"></i> {{ 'Requests.Sort' | translate }}
<span class="caret"></span> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2"> <ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
<li> <li>
<a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' | translate }} <a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' |
translate }}
</a> </a>
<a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{ 'Requests.SortRequestDateDesc' | translate }} <a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{
'Requests.SortRequestDateDesc' | translate }}
</a> </a>
<a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate}} <a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate}}
@ -58,16 +61,20 @@
<div class="col-sm-5 small-padding"> <div class="col-sm-5 small-padding">
<div> <div>
<a href="http://www.imdb.com/title/{{request.imdbId}}/" target="_blank"> <a href="http://www.imdb.com/title/{{request.imdbId}}/" target="_blank">
<h4 class="request-title">{{request.title}} ({{request.releaseDate | amLocal | amDateFormat: 'YYYY'}})</h4> <h4 class="request-title">{{request.title}} ({{request.releaseDate | amLocal | amDateFormat:
'YYYY'}})</h4>
</a> </a>
</div> </div>
<br /> <br />
<div class="request-info"> <div class="request-info">
<div class="request-by"> <div class="request-by">
<span>{{ 'Requests.RequestedBy' | translate }} </span> <span>{{ 'Requests.RequestedBy' | translate }} </span>
<span *ngIf="!isAdmin">{{request.requestedUser.userName}}</span> <span *ngIf="request.requestedByAlias">{{request.requestedByAlias}}</span>
<span *ngIf="isAdmin && request.requestedUser.alias">{{request.requestedUser.alias}}</span> <span *ngIf="!request.requestedByAlias">
<span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.userName}}</span> <span *ngIf="!isAdmin">{{request.requestedUser.userName}}</span>
<span *ngIf="isAdmin && request.requestedUser.alias">{{request.requestedUser.alias}}</span>
<span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.userName}}</span>
</span>
</div> </div>
<div class="request-status"> <div class="request-status">
<span>{{ 'Requests.Status' | translate }} </span> <span>{{ 'Requests.Status' | translate }} </span>
@ -77,13 +84,14 @@
<div class="requested-status"> <div class="requested-status">
<span>{{ 'Requests.RequestStatus' | translate }} </span> <span>{{ 'Requests.RequestStatus' | translate }} </span>
<span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span> <span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
<span *ngIf="request.approved && !request.available" id="processingRequestLabel" class="label label-info" [translate]="'Common.ProcessingRequest'"></span> <span *ngIf="request.approved && !request.available" id="processingRequestLabel" class="label label-info"
[translate]="'Common.ProcessingRequest'"></span>
<span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span> <span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span>
<span *ngIf="request.deniedReason" title="{{request.deniedReason}}"> <span *ngIf="request.deniedReason" title="{{request.deniedReason}}">
<i class="fa fa-info-circle"></i> <i class="fa fa-info-circle"></i>
</span> </span>
<span *ngIf="!request.approved && !request.availble && !request.denied" id="pendingApprovalLabel" class="label label-warning" <span *ngIf="!request.approved && !request.availble && !request.denied" id="pendingApprovalLabel"
[translate]="'Common.PendingApproval'"></span> class="label label-warning" [translate]="'Common.PendingApproval'"></span>
</div> </div>
<div *ngIf="request.denied" id="requestDenied"> <div *ngIf="request.denied" id="requestDenied">
@ -93,16 +101,21 @@
</div> </div>
<div id="releaseDate">{{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate | amLocal | amDateFormat: 'LL'} }}</div> <div id="releaseDate">{{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate |
<div *ngIf="request.digitalReleaseDate" id="digitalReleaseDate">{{ 'Requests.DigitalRelease' | translate: {date: request.digitalReleaseDate | amLocal | amDateFormat: 'LL'} }}</div> amLocal | amDateFormat: 'LL'} }}</div>
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal | amDateFormat: 'LL'}}</div> <div *ngIf="request.digitalReleaseDate" id="digitalReleaseDate">{{ 'Requests.DigitalRelease' |
translate: {date: request.digitalReleaseDate | amLocal | amDateFormat: 'LL'} }}</div>
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal
| amDateFormat: 'LL'}}</div>
<br /> <br />
</div> </div>
<div *ngIf="isAdmin"> <div *ngIf="isAdmin">
<div *ngIf="request.qualityOverrideTitle" class="quality-override">{{ 'Requests.QualityOverride' | translate }} <div *ngIf="request.qualityOverrideTitle" class="quality-override">{{ 'Requests.QualityOverride' |
translate }}
<span>{{request.qualityOverrideTitle}} </span> <span>{{request.qualityOverrideTitle}} </span>
</div> </div>
<div *ngIf="request.rootPathOverrideTitle" class="root-override">{{ 'Requests.RootFolderOverride' | translate }} <div *ngIf="request.rootPathOverrideTitle" class="root-override">{{ 'Requests.RootFolderOverride' |
translate }}
<span>{{request.rootPathOverrideTitle}} </span> <span>{{request.rootPathOverrideTitle}} </span>
</div> </div>
</div> </div>
@ -112,10 +125,12 @@
<div class="row"> <div class="row">
<div class="col-md-2 col-md-push-6"> <div class="col-md-2 col-md-push-6">
<a *ngIf="request.showSubscribe && !request.subscribed" style="color:white" (click)="subscribe(request)" pTooltip="Subscribe for notifications"> <a *ngIf="request.showSubscribe && !request.subscribed" style="color:white" (click)="subscribe(request)"
pTooltip="Subscribe for notifications">
<i class="fa fa-rss"></i> <i class="fa fa-rss"></i>
</a> </a>
<a *ngIf="request.showSubscribe && request.subscribed" style="color:red" (click)="unSubscribe(request)" pTooltip="Unsubscribe notification"> <a *ngIf="request.showSubscribe && request.subscribed" style="color:red" (click)="unSubscribe(request)"
pTooltip="Unsubscribe notification">
<i class="fa fa-rss"></i> <i class="fa fa-rss"></i>
</a> </a>
</div> </div>
@ -123,7 +138,8 @@
<div *ngIf="isAdmin"> <div *ngIf="isAdmin">
<div *ngIf="!request.approved" id="approveBtn"> <div *ngIf="!request.approved" id="approveBtn">
<form> <form>
<button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve" type="submit"> <button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve"
type="submit">
<i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }} <i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}
</button> </button>
</form> </form>
@ -133,7 +149,8 @@
<button type="button" class="btn btn-sm btn-warning-outline"> <button type="button" class="btn btn-sm btn-warning-outline">
<i class="fa fa-plus"></i> {{ 'Requests.ChangeRootFolder' | translate }} <i class="fa fa-plus"></i> {{ 'Requests.ChangeRootFolder' | translate }}
</button> </button>
<button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<span class="caret"></span> <span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span> <span class="sr-only">Toggle Dropdown</span>
</button> </button>
@ -149,7 +166,8 @@
<button type="button" class="btn btn-sm btn-warning-outline"> <button type="button" class="btn btn-sm btn-warning-outline">
<i class="fa fa-plus"></i> {{ 'Requests.ChangeQualityProfile' | translate }} <i class="fa fa-plus"></i> {{ 'Requests.ChangeQualityProfile' | translate }}
</button> </button>
<button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button type="button" class="btn btn-warning-outline dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<span class="caret"></span> <span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span> <span class="sr-only">Toggle Dropdown</span>
</button> </button>
@ -169,12 +187,12 @@
<form id="markBtnGroup"> <form id="markBtnGroup">
<button id="unavailableBtn" *ngIf="request.available" (click)="changeAvailability(request, false)" style="text-align: right" <button id="unavailableBtn" *ngIf="request.available" (click)="changeAvailability(request, false)"
value="false" class="btn btn-sm btn-info-outline change"> style="text-align: right" value="false" class="btn btn-sm btn-info-outline change">
<i class="fa fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }} <i class="fa fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}
</button> </button>
<button id="availableBtn" *ngIf="!request.available" (click)="changeAvailability(request, true)" style="text-align: right" <button id="availableBtn" *ngIf="!request.available" (click)="changeAvailability(request, true)"
value="true" class="btn btn-sm btn-success-outline change"> style="text-align: right" value="true" class="btn btn-sm btn-success-outline change">
<i class="fa fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }} <i class="fa fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}
</button> </button>
</form> </form>
@ -190,8 +208,8 @@
</form> </form>
</div> </div>
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn"> <div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" <button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
aria-expanded="true"> aria-haspopup="true" aria-expanded="true">
<i class="fa fa-plus"></i> {{ 'Requests.ReportIssue' | translate }} <i class="fa fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
<span class="caret"></span> <span class="caret"></span>
</button> </button>
@ -204,8 +222,8 @@
</div> </div>
</div> </div>
<br/> <br />
<br/> <br />
@ -216,11 +234,11 @@
</div> </div>
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false"> <p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false">
<span>Please enter a rejection reason, the user will be notified of this:</span> <span>Please enter a rejection reason, the user will be notified of this:</span>
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea> <textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
<p-footer> <p-footer>
<button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button> <button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button>
<button type="button"(click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button> <button type="button" (click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button>
</p-footer> </p-footer>
</p-dialog> </p-dialog>

View file

@ -1,23 +1,26 @@
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<input type="text" id="search" class="form-control form-control-custom searchwidth" placeholder="Search" (keyup)="search($event)"> <input type="text" id="search" class="form-control form-control-custom searchwidth" placeholder="Search"
(keyup)="search($event)">
<span class="input-group-btn"> <span class="input-group-btn">
<button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay"> <button id="filterBtn" class="btn btn-sm btn-info-outline" (click)="filterDisplay = !filterDisplay">
<i class="fa fa-filter"></i> {{ 'Requests.Filter' | translate }} <i class="fa fa-filter"></i> {{ 'Requests.Filter' | translate }}
</button> </button>
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" <button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
aria-expanded="true"> aria-haspopup="true" aria-expanded="true">
<i class="fa fa-sort"></i> {{ 'Requests.Sort' | translate }} <i class="fa fa-sort"></i> {{ 'Requests.Sort' | translate }}
<span class="caret"></span> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2"> <ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
<li> <li>
<a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' | translate }} <a (click)="setOrder(OrderType.RequestedDateAsc, $event)">{{ 'Requests.SortRequestDateAsc' |
translate }}
</a> </a>
<a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{ 'Requests.SortRequestDateDesc' | translate }} <a class="active" (click)="setOrder(OrderType.RequestedDateDesc, $event)">{{
'Requests.SortRequestDateDesc' | translate }}
</a> </a>
<a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate}} <a (click)="setOrder(OrderType.TitleAsc, $event)">{{ 'Requests.SortTitleAsc' | translate}}
@ -45,7 +48,7 @@
<div class="col-md-12"> <div class="col-md-12">
<div *ngFor="let request of albumRequests" class="col-md-4"> <div *ngFor="let request of albumRequests" class="col-md-4">
<div class="row"> <div class="row">
<div class="album-bg backdrop" [style.background-image]="request.background"></div> <div class="album-bg backdrop" [style.background-image]="request.background"></div>
<div class="album-tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div> <div class="album-tint" style="background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%);"></div>
@ -59,7 +62,7 @@
<div> <div>
<h4> <h4>
<a href="" target="_blank"> <a href="" target="_blank">
{{request.title | truncate: 36}} {{request.title | truncate: 36}}
</a> </a>
</h4> </h4>
@ -73,21 +76,25 @@
<div class="request-info"> <div class="request-info">
<div class="request-by"> <div class="request-by">
<span>{{ 'Requests.RequestedBy' | translate }} </span> <span>{{ 'Requests.RequestedBy' | translate }} </span>
<span *ngIf="!isAdmin">{{request.requestedUser.userName}}</span> <span *ngIf="request.requestedByAlias">{{request.requestedByAlias}}</span>
<span *ngIf="isAdmin && request.requestedUser.alias">{{request.requestedUser.alias}}</span> <span *ngIf="!request.requestedByAlias">
<span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.userName}}</span> <span *ngIf="!isAdmin">{{request.requestedUser.userName}}</span>
<span *ngIf="isAdmin && request.requestedUser.alias">{{request.requestedUser.alias}}</span>
<span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.userName}}</span>
</span>
</div> </div>
<div class="requested-status"> <div class="requested-status">
<span>{{ 'Requests.RequestStatus' | translate }} </span> <span>{{ 'Requests.RequestStatus' | translate }} </span>
<span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span> <span *ngIf="request.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span>
<span *ngIf="request.approved && !request.available" id="processingRequestLabel" class="label label-info" [translate]="'Common.ProcessingRequest'"></span> <span *ngIf="request.approved && !request.available" id="processingRequestLabel" class="label label-info"
[translate]="'Common.ProcessingRequest'"></span>
<span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span> <span *ngIf="request.denied" class="label label-danger" id="requestDeclinedLabel" [translate]="'Common.RequestDenied'"></span>
<span *ngIf="request.deniedReason" title="{{request.deniedReason}}"> <span *ngIf="request.deniedReason" title="{{request.deniedReason}}">
<i class="fa fa-info-circle"></i> <i class="fa fa-info-circle"></i>
</span> </span>
<span *ngIf="!request.approved && !request.availble && !request.denied" id="pendingApprovalLabel" class="label label-warning" <span *ngIf="!request.approved && !request.availble && !request.denied" id="pendingApprovalLabel"
[translate]="'Common.PendingApproval'"></span> class="label label-warning" [translate]="'Common.PendingApproval'"></span>
</div> </div>
<div *ngIf="request.denied" id="requestDenied"> <div *ngIf="request.denied" id="requestDenied">
@ -97,8 +104,10 @@
</div> </div>
<div id="releaseDate">{{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | amLocal | amDateFormat: 'LL'} }}</div> <div id="releaseDate">{{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | amLocal |
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal | amDateFormat: 'LL'}}</div> amDateFormat: 'LL'} }}</div>
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal
| amDateFormat: 'LL'}}</div>
<br /> <br />
</div> </div>
<!-- <div *ngIf="isAdmin"> <!-- <div *ngIf="isAdmin">
@ -126,7 +135,8 @@
<div *ngIf="isAdmin"> <div *ngIf="isAdmin">
<div *ngIf="!request.approved" id="approveBtn"> <div *ngIf="!request.approved" id="approveBtn">
<form class="col-md-6"> <form class="col-md-6">
<button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve" type="submit"> <button (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve"
type="submit">
<i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }} <i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}
</button> </button>
</form> </form>
@ -172,12 +182,12 @@
<form id="markBtnGroup"> <form id="markBtnGroup">
<button id="unavailableBtn" *ngIf="request.available" (click)="changeAvailability(request, false)" style="text-align: right" <button id="unavailableBtn" *ngIf="request.available" (click)="changeAvailability(request, false)"
value="false" class="btn btn-sm btn-info-outline change"> style="text-align: right" value="false" class="btn btn-sm btn-info-outline change">
<i class="fa fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }} <i class="fa fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}
</button> </button>
<button id="availableBtn" *ngIf="!request.available" (click)="changeAvailability(request, true)" style="text-align: right" <button id="availableBtn" *ngIf="!request.available" (click)="changeAvailability(request, true)"
value="true" class="btn btn-sm btn-success-outline change"> style="text-align: right" value="true" class="btn btn-sm btn-success-outline change">
<i class="fa fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }} <i class="fa fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}
</button> </button>
</form> </form>
@ -193,8 +203,8 @@
</form> </form>
</div> </div>
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn"> <div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" <button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown"
aria-expanded="true"> aria-haspopup="true" aria-expanded="true">
<i class="fa fa-plus"></i> {{ 'Requests.ReportIssue' | translate }} <i class="fa fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
<span class="caret"></span> <span class="caret"></span>
</button> </button>
@ -207,8 +217,8 @@
</div> </div>
</div> </div>
<br/> <br />
<br/> <br />
@ -272,8 +282,8 @@
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false"> <p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false">
<span>Please enter a rejection reason, the user will be notified of this:</span> <span>Please enter a rejection reason, the user will be notified of this:</span>
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea> <textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
<p-footer> <p-footer>
<button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button> <button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button>
<button type="button"(click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button> <button type="button" (click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button>
</p-footer> </p-footer>
</p-dialog> </p-dialog>

View file

@ -5,29 +5,41 @@
<div class="col-md-2"> <div class="col-md-2">
<span [translate]="'Requests.RequestedBy'"></span> <span [translate]="'Requests.RequestedBy'"></span>
<span *ngIf="child.requestedByAlias">{{child.requestedByAlias}}</span>
<span *ngIf="!isAdmin">{{child.requestedUser.userName}}</span> <span *ngIf="!child.requestedByAlias">
<span *ngIf="isAdmin && child.requestedUser.alias">{{child.requestedUser.alias}}</span> <span *ngIf="!isAdmin">{{child.requestedUser.userName}}</span>
<span *ngIf="isAdmin && !child.requestedUser.alias">{{child.requestedUser.userName}}</span> <span *ngIf="isAdmin && child.requestedUser.alias">{{child.requestedUser.alias}}</span>
<span *ngIf="isAdmin && !child.requestedUser.alias">{{child.requestedUser.userName}}</span>
</span>
</div> </div>
<div class="col-md-1 col-md-push-9"> <div class="col-md-1 col-md-push-9">
<button id="subscribeBtn" *ngIf="child.showSubscribe && !child.subscribed" (click)="subscribe(child)" class="btn btn-sm btn-primary-outline" pTooltip="Subscribe for notifications" type="submit"><i class="fa fa-rss"></i> Subscribe</button> <button id="subscribeBtn" *ngIf="child.showSubscribe && !child.subscribed" (click)="subscribe(child)"
<button id="subscribeBtn" *ngIf="child.showSubscribe && child.subscribed" (click)="unSubscribe(child)" class="btn btn-sm btn-danger-outline" pTooltip="UnSubscribe for notifications" type="submit"><i class="fa fa-rss"></i> UnSubscribe</button> class="btn btn-sm btn-primary-outline" pTooltip="Subscribe for notifications" type="submit"><i
class="fa fa-rss"></i> Subscribe</button>
<button id="subscribeBtn" *ngIf="child.showSubscribe && child.subscribed" (click)="unSubscribe(child)"
class="btn btn-sm btn-danger-outline" pTooltip="UnSubscribe for notifications" type="submit"><i
class="fa fa-rss"></i> UnSubscribe</button>
<div *ngIf="isAdmin"> <div *ngIf="isAdmin">
<button id="approveBtn" *ngIf="child.canApprove && !child.approved" (click)="approve(child)" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}</button> <button id="approveBtn" *ngIf="child.canApprove && !child.approved" (click)="approve(child)" class="btn btn-sm btn-success-outline"
<button id="unavailableBtn" *ngIf="child.available" (click)="changeAvailability(child, false)" style="text-align: right" value="false" class="btn btn-sm btn-info-outline change"><i class="fa fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}</button> type="submit"><i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}</button>
<button id="availableBtn" *ngIf="!child.available" (click)="changeAvailability(child, true)" style="text-align: right" value="true" class="btn btn-sm btn-success-outline change"><i class="fa fa-plus"></i> {{ 'Requests.MarkAvailable' | translate }}</button> <button id="unavailableBtn" *ngIf="child.available" (click)="changeAvailability(child, false)"
style="text-align: right" value="false" class="btn btn-sm btn-info-outline change"><i class="fa fa-minus"></i>
{{ 'Requests.MarkUnavailable' | translate }}</button>
<button id="availableBtn" *ngIf="!child.available" (click)="changeAvailability(child, true)" style="text-align: right"
value="true" class="btn btn-sm btn-success-outline change"><i class="fa fa-plus"></i> {{
'Requests.MarkAvailable' | translate }}</button>
<button id="denyBtn" *ngIf="!child.denied" type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny"> <button id="denyBtn" *ngIf="!child.denied" type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny">
<i class="fa fa-times"></i> {{ 'Requests.Deny' | translate }}</button> <i class="fa fa-times"></i> {{ 'Requests.Deny' | translate }}</button>
</div> </div>
<div *ngIf="isAdmin || isRequestUser(child)"> <div *ngIf="isAdmin || isRequestUser(child)">
<button id="removeBtn" type="button" (click)="removeRequest(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> {{ 'Requests.Remove' | translate }}</button> <button id="removeBtn" type="button" (click)="removeRequest(child)" class="btn btn-sm btn-danger-outline deny"><i
</div> class="fa fa-times"></i> {{ 'Requests.Remove' | translate }}</button>
</div>
</div> </div>
@ -77,13 +89,17 @@
{{ep.airDate | amLocal | amDateFormat: 'L' }} {{ep.airDate | amLocal | amDateFormat: 'L' }}
</td> </td>
<td> <td>
<span *ngIf="child.denied" class="label label-danger" id="deniedLabel" [translate]="'Common.Denied'"> <span *ngIf="child.denied" class="label label-danger" id="deniedLabel"
<i style="color:red;" class="fa fa-check" pTooltip="{{child.deniedReason}}"></i> [translate]="'Common.Denied'">
<i style="color:red;" class="fa fa-check" pTooltip="{{child.deniedReason}}"></i>
</span> </span>
<span *ngIf="!child.denied && ep.available" class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span> <span *ngIf="!child.denied && ep.available" class="label label-success" id="availableLabel"
<span *ngIf="!child.denied &&ep.approved && !ep.available" class="label label-info" id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span> [translate]="'Common.Available'"></span>
<span *ngIf="!child.denied &&ep.approved && !ep.available" class="label label-info"
id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span>
<div *ngIf="!child.denied && !ep.approved"> <div *ngIf="!child.denied && !ep.approved">
<div *ngIf="!ep.available"><span class="label label-warning" id="pendingApprovalLabel" [translate]="'Common.PendingApproval'"></span></div> <div *ngIf="!ep.available"><span class="label label-warning" id="pendingApprovalLabel"
[translate]="'Common.PendingApproval'"></span></div>
</div> </div>
</td> </td>
@ -105,8 +121,8 @@
<p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false"> <p-dialog *ngIf="requestToDeny" header="Deny Request '{{requestToDeny.title}}''" [(visible)]="denyDisplay" [draggable]="false">
<span>Please enter a rejection reason, the user will be notified of this:</span> <span>Please enter a rejection reason, the user will be notified of this:</span>
<textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea> <textarea [(ngModel)]="rejectionReason" class="form-control-custom form-control"></textarea>
<p-footer> <p-footer>
<button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button> <button type="button" (click)="denyRequest();" label="Reject" class="btn btn-success">Deny</button>
<button type="button"(click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button> <button type="button" (click)="denyDisplay=false" label="Close" class="btn btn-danger">Close</button>
</p-footer> </p-footer>
</p-dialog> </p-dialog>

View file

@ -16,7 +16,6 @@ import { IdentityService, PlexService, RadarrService, SonarrService } from "../s
import { AuthGuard } from "../auth/auth.guard"; import { AuthGuard } from "../auth/auth.guard";
import { OrderModule } from "ngx-order-pipe"; import { OrderModule } from "ngx-order-pipe";
import { AddPlexUserComponent } from "./addplexuser.component";
import { SharedModule } from "../shared/shared.module"; import { SharedModule } from "../shared/shared.module";
@ -45,12 +44,8 @@ const routes: Routes = [
declarations: [ declarations: [
UserManagementComponent, UserManagementComponent,
UpdateDetailsComponent, UpdateDetailsComponent,
AddPlexUserComponent,
UserManagementUserComponent, UserManagementUserComponent,
], ],
entryComponents:[
AddPlexUserComponent,
],
exports: [ exports: [
RouterModule, RouterModule,
], ],

View file

@ -76,6 +76,7 @@ namespace Ombi.Controllers
[HttpPost] [HttpPost]
public async Task<RequestEngineResult> RequestAlbum([FromBody] MusicAlbumRequestViewModel album) public async Task<RequestEngineResult> RequestAlbum([FromBody] MusicAlbumRequestViewModel album)
{ {
album.RequestedByAlias = GetApiAlias();
var result = await _engine.RequestAlbum(album); var result = await _engine.RequestAlbum(album);
if (result.Result) if (result.Result)
{ {
@ -168,5 +169,14 @@ namespace Ombi.Controllers
{ {
return await _engine.GetRemainingRequests(); return await _engine.GetRemainingRequests();
} }
private string GetApiAlias()
{
if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias))
{
return apiAlias;
}
return null;
}
} }
} }

View file

@ -8,12 +8,14 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Attributes; using Ombi.Attributes;
using Ombi.Core.Models.UI; using Ombi.Core.Models.UI;
using Ombi.Models; using Ombi.Models;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Helpers;
namespace Ombi.Controllers namespace Ombi.Controllers
{ {
@ -82,6 +84,7 @@ namespace Ombi.Controllers
[HttpPost("movie")] [HttpPost("movie")]
public async Task<RequestEngineResult> RequestMovie([FromBody] MovieRequestViewModel movie) public async Task<RequestEngineResult> RequestMovie([FromBody] MovieRequestViewModel movie)
{ {
movie.RequestedByAlias = GetApiAlias();
var result = await MovieRequestEngine.RequestMovie(movie); var result = await MovieRequestEngine.RequestMovie(movie);
if (result.Result) if (result.Result)
{ {
@ -277,6 +280,7 @@ namespace Ombi.Controllers
[HttpPost("tv")] [HttpPost("tv")]
public async Task<RequestEngineResult> RequestTv([FromBody] TvRequestViewModel tv) public async Task<RequestEngineResult> RequestTv([FromBody] TvRequestViewModel tv)
{ {
tv.RequestedByAlias = GetApiAlias();
var result = await TvRequestEngine.RequestTvShow(tv); var result = await TvRequestEngine.RequestTvShow(tv);
if (result.Result) if (result.Result)
{ {
@ -521,5 +525,15 @@ namespace Ombi.Controllers
{ {
return await TvRequestEngine.GetRemainingRequests(); return await TvRequestEngine.GetRemainingRequests();
} }
private string GetApiAlias()
{
if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias))
{
return apiAlias;
}
return null;
}
} }
} }