Merge pull request #4365 from Ombi-app/feature/request-limits-missing

Feature/request limits missing
pull/4367/head^2
Jamie 3 years ago committed by GitHub
commit b2dfdfdb79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -117,7 +117,11 @@ namespace Ombi.Schedule.Jobs.Emby
ProviderUserId = embyUser.Id, ProviderUserId = embyUser.Id,
Alias = isConnectUser ? embyUser.Name : string.Empty, Alias = isConnectUser ? embyUser.Name : string.Empty,
MovieRequestLimit = userManagementSettings.MovieRequestLimit, MovieRequestLimit = userManagementSettings.MovieRequestLimit,
MovieRequestLimitType = userManagementSettings.MovieRequestLimitType,
EpisodeRequestLimit = userManagementSettings.EpisodeRequestLimit, EpisodeRequestLimit = userManagementSettings.EpisodeRequestLimit,
EpisodeRequestLimitType = userManagementSettings.EpisodeRequestLimitType,
MusicRequestLimit = userManagementSettings.MusicRequestLimit,
MusicRequestLimitType = userManagementSettings.MusicRequestLimitType,
StreamingCountry = userManagementSettings.DefaultStreamingCountry StreamingCountry = userManagementSettings.DefaultStreamingCountry
}; };
var result = await _userManager.CreateAsync(newUser); var result = await _userManager.CreateAsync(newUser);

@ -104,7 +104,11 @@ namespace Ombi.Schedule.Jobs.Plex
Email = plexUser?.Email ?? string.Empty, Email = plexUser?.Email ?? string.Empty,
Alias = string.Empty, Alias = string.Empty,
MovieRequestLimit = userManagementSettings.MovieRequestLimit, MovieRequestLimit = userManagementSettings.MovieRequestLimit,
MovieRequestLimitType = userManagementSettings.MovieRequestLimitType,
EpisodeRequestLimit = userManagementSettings.EpisodeRequestLimit, EpisodeRequestLimit = userManagementSettings.EpisodeRequestLimit,
EpisodeRequestLimitType = userManagementSettings.EpisodeRequestLimitType,
MusicRequestLimit = userManagementSettings.MusicRequestLimit,
MusicRequestLimitType = userManagementSettings.MusicRequestLimitType,
StreamingCountry = userManagementSettings.DefaultStreamingCountry StreamingCountry = userManagementSettings.DefaultStreamingCountry
}; };
_log.LogInformation("Creating Plex user {0}", newUser.UserName); _log.LogInformation("Creating Plex user {0}", newUser.UserName);

@ -1,4 +1,5 @@
using System.Collections.Generic; using Ombi.Store.Entities;
using System.Collections.Generic;
namespace Ombi.Settings.Settings.Models namespace Ombi.Settings.Settings.Models
{ {
@ -9,7 +10,11 @@ namespace Ombi.Settings.Settings.Models
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; }
public RequestLimitType MovieRequestLimitType { get; set; } = RequestLimitType.Week;
public int EpisodeRequestLimit { get; set; } public int EpisodeRequestLimit { get; set; }
public RequestLimitType EpisodeRequestLimitType { get; set; } = RequestLimitType.Week;
public int MusicRequestLimit { get; set; }
public RequestLimitType MusicRequestLimitType { get; set; } = RequestLimitType.Week;
public string DefaultStreamingCountry { get; set; } = "US"; public string DefaultStreamingCountry { get; set; } = "US";
public List<string> DefaultRoles { get; set; } = new List<string>(); public List<string> DefaultRoles { get; set; } = new List<string>();
public List<string> BannedPlexUserIds { get; set; } = new List<string>(); public List<string> BannedPlexUserIds { get; set; } = new List<string>();

@ -1,4 +1,5 @@
import { ISettings } from "./ICommon"; import { ISettings } from "./ICommon";
import { RequestLimitType } from ".";
export interface IExternalSettings extends ISettings { export interface IExternalSettings extends ISettings {
ssl: boolean; ssl: boolean;
@ -247,10 +248,14 @@ export interface IUserManagementSettings extends ISettings {
defaultRoles: string[]; defaultRoles: string[];
movieRequestLimit: number; movieRequestLimit: number;
episodeRequestLimit: number; episodeRequestLimit: number;
musicRequestLimit: number;
bannedPlexUserIds: string[]; bannedPlexUserIds: string[];
bannedEmbyUserIds: string[]; bannedEmbyUserIds: string[];
bannedJellyfinUserIds: string[]; bannedJellyfinUserIds: string[];
defaultStreamingCountry: string; defaultStreamingCountry: string;
movieRequestLimitType: RequestLimitType;
episodeRequestLimitType: RequestLimitType;
musicRequestLimitType: RequestLimitType;
} }
export interface IAbout { export interface IAbout {

@ -39,18 +39,18 @@
<div class="form-group"> <div class="form-group">
<mat-slide-toggle id="importJellyfinUsers" [(ngModel)]="settings.importJellyfinUsers">Import Jellyfin Users</mat-slide-toggle> <mat-slide-toggle id="importJellyfinUsers" [(ngModel)]="settings.importJellyfinUsers">Import Jellyfin Users</mat-slide-toggle>
</div> </div>
<div *ngIf="jellyfinUsers"> <div *ngIf="jellyfinUsers">
<p>Jellyfin Users excluded from Import</p> <p>Jellyfin Users excluded from Import</p>
<p-autoComplete [(ngModel)]="bannedJellyfinUsers" [suggestions]="filteredJellyfinUsers" [multiple]="true" field="username" (completeMethod)="filterJellyfinList($event)"></p-autoComplete> <p-autoComplete [(ngModel)]="bannedJellyfinUsers" [suggestions]="filteredJellyfinUsers" [multiple]="true" field="username" (completeMethod)="filterJellyfinList($event)"></p-autoComplete>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<h4>Default Roles</h4> <h3>Default Roles</h3>
<hr>
<div *ngFor="let c of claims"> <div *ngFor="let c of claims">
<div class="form-group"> <div class="form-group">
<div> <div>
@ -60,7 +60,10 @@
</div> </div>
</div> </div>
<h4>Default Request Limits</h4> <h3>Default Request Limits</h3>
<hr>
<div class="form-group"> <div class="form-group">
<label for="movieRequestLimit" class="control-label">Movie Request Limit</label> <label for="movieRequestLimit" class="control-label">Movie Request Limit</label>
<div> <div>
@ -68,12 +71,38 @@
</div> </div>
</div> </div>
<mat-label>Movie Request Limit Type</mat-label>
<mat-select id="movieRequestLimitType" [(value)]="settings.movieRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}}
</mat-option>
</mat-select>
<div class="form-group"> <div class="form-group">
<label for="episodeRequestLimit" class="control-label">Episode Request Limit</label> <label for="episodeRequestLimit" class="control-label">Episode Request Limit</label>
<div> <div>
<input type="text" [(ngModel)]="settings.episodeRequestLimit" class="form-control form-small form-control-custom" id="episodeRequestLimit" name="episodeRequestLimit" value="{{settings?.episodeRequestLimit}}"> <input type="text" [(ngModel)]="settings.episodeRequestLimit" class="form-control form-small form-control-custom" id="episodeRequestLimit" name="episodeRequestLimit" value="{{settings?.episodeRequestLimit}}">
</div> </div>
</div>
<mat-label>Episode Request Limit Type</mat-label>
<mat-select id="episodeRequestLimitType" [(value)]="settings.episodeRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}}
</mat-option>
</mat-select>
<div class="form-group">
<label for="episodeRequestLimit" class="control-label">Music Request Limit</label>
<div>
<input type="text" [(ngModel)]="settings.musicRequestLimit" class="form-control form-small form-control-custom" id="musicRequestLimit" name="musicRequestLimit" value="{{settings?.musicRequestLimit}}">
</div>
</div> </div>
<mat-label>Music Request Limit Type</mat-label>
<mat-select id="musicRequestLimitType" [(value)]="settings.musicRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}}
</mat-option>
</mat-select>
<mat-form-field> <mat-form-field>
<mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label> <mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label>

@ -1,8 +1,8 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { EmbyService, IdentityService, JellyfinService, JobService, NotificationService, PlexService, SettingsService } from "../../services";
import { ICheckbox, IUserManagementSettings, RequestLimitType } from "../../interfaces";
import { ICheckbox, IUserManagementSettings } from "../../interfaces";
import { IUsersModel } from "../../interfaces"; import { IUsersModel } from "../../interfaces";
import { EmbyService, JellyfinService, IdentityService, JobService, NotificationService, PlexService, SettingsService } from "../../services";
@Component({ @Component({
templateUrl: "./usermanagement.component.html", templateUrl: "./usermanagement.component.html",
@ -31,6 +31,9 @@ export class UserManagementComponent implements OnInit {
public enableImportButton = false; public enableImportButton = false;
public countries: string[]; public countries: string[];
public requestLimitTypes: RequestLimitType[] = [RequestLimitType.Day, RequestLimitType.Week, RequestLimitType.Month];
public RequestLimitType = RequestLimitType;
constructor(private readonly settingsService: SettingsService, constructor(private readonly settingsService: SettingsService,
private readonly notificationService: NotificationService, private readonly notificationService: NotificationService,
private readonly identityService: IdentityService, private readonly identityService: IdentityService,
@ -120,7 +123,7 @@ export class UserManagementComponent implements OnInit {
if (x === true) { if (x === true) {
this.notificationService.success("Successfully saved the User Management Settings"); this.notificationService.success("Successfully saved the User Management Settings");
} else { } else {
this.notificationService.success( "There was an error when saving the Ombi settings"); this.notificationService.success( "There was an error when saving the settings");
} }
}); });
} }

@ -50,7 +50,7 @@
</div> </div>
<div class="col-6"> <div class="col-6">
<mat-label>Movie Request Limit Type</mat-label> <mat-label>Movie Request Limit Type</mat-label>
<mat-select [(value)]="user.movieRequestLimitType"> <mat-select id="movieRequestLimitType" [(value)]="user.movieRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value"> <mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}} {{RequestLimitType[value]}}
</mat-option> </mat-option>
@ -65,7 +65,7 @@
</div> </div>
<div class="col-6"> <div class="col-6">
<mat-label>Episode Request Limit Type</mat-label> <mat-label>Episode Request Limit Type</mat-label>
<mat-select [(value)]="user.episodeRequestLimitType"> <mat-select id="episodeRequestLimitType" [(value)]="user.episodeRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value"> <mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}} {{RequestLimitType[value]}}
</mat-option> </mat-option>
@ -80,7 +80,7 @@
</div> </div>
<div class="col-6"> <div class="col-6">
<mat-label>Music Request Limit Type</mat-label> <mat-label>Music Request Limit Type</mat-label>
<mat-select [(value)]="user.musicRequestLimitType"> <mat-select id="musicRequestLimitType" [(value)]="user.musicRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value"> <mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}} {{RequestLimitType[value]}}
</mat-option> </mat-option>

@ -118,7 +118,7 @@
<p-sidebar [(visible)]="showBulkEdit" position="right" [modal]="false"> <p-sidebar [(visible)]="showBulkEdit" position="right" [modal]="false" [style]="{width:'40em'}">
<div> <div>
<div *ngFor="let c of availableClaims"> <div *ngFor="let c of availableClaims">
<div class="form-group"> <div class="form-group">
@ -129,19 +129,52 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col-6">
<mat-form-field appearance="outline" class="full"> <mat-form-field appearance="outline" class="full">
<mat-label>Movie Request Limit</mat-label> <mat-label>Movie Request Limit</mat-label>
<input matInput id="movieRequestLimit" name="movieRequestLimit" [(ngModel)]="bulkMovieLimit"> <input matInput id="movieRequestLimit" name="movieRequestLimit" [(ngModel)]="bulkMovieLimit">
</mat-form-field> </mat-form-field></div>
<div class="col-6">
<mat-label>Movie Request Limit Type</mat-label>
<mat-select id="movieRequestLimitType" [(value)]="movieRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}}
</mat-option>
</mat-select>
</div></div>
<div class="row">
<div class="col-6">
<mat-form-field appearance="outline" class="full"> <mat-form-field appearance="outline" class="full">
<mat-label>Episode Request Limit</mat-label> <mat-label>Episode Request Limit</mat-label>
<input matInput id="episodeRequestLimit" name="episodeRequestLimit" [(ngModel)]="bulkEpisodeLimit"> <input matInput id="episodeRequestLimit" name="episodeRequestLimit" [(ngModel)]="bulkEpisodeLimit">
</mat-form-field> </mat-form-field>
</div>
<div class="col-6">
<mat-label>Episode Request Limit Type</mat-label>
<mat-select id="episodeRequestLimitType" [(value)]="episodeRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}}
</mat-option>
</mat-select>
</div>
</div>
<div class="row">
<div class="col-6">
<mat-form-field appearance="outline" class="full"> <mat-form-field appearance="outline" class="full">
<mat-label>Music Request Limit</mat-label> <mat-label>Music Request Limit</mat-label>
<input matInput id="musicRequestLimit" name="musicRequestLimit" [(ngModel)]="bulkMusicLimit"> <input matInput id="musicRequestLimit" name="musicRequestLimit" [(ngModel)]="bulkMusicLimit">
</mat-form-field> </mat-form-field>
</div>
<div class="col-6">
<mat-label>Music Request Limit Type</mat-label>
<mat-select id="musicRequestLimitType" [(value)]="musicRequestLimitType">
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
{{RequestLimitType[value]}}
</mat-option>
</mat-select>
</div>
</div>
<mat-form-field appearance="outline" class="full"> <mat-form-field appearance="outline" class="full">
<mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label> <mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label>
<mat-select [(value)]="bulkStreaming"> <mat-select [(value)]="bulkStreaming">
@ -152,7 +185,7 @@
</mat-form-field> </mat-form-field>
<button type="button" mat-raised-button (click)="bulkUpdate()">Update Users</button> <button type="button" mat-raised-button color="primary" (click)="bulkUpdate()">Update Users</button>
</p-sidebar> </p-sidebar>
</div> </div>
</div> </div>

@ -87,4 +87,8 @@
table { table {
width: 100%; width: 100%;
}
::ng-deep .p-sidebar {
background: $background-dark !important;
} }

@ -1,5 +1,5 @@
import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core"; import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core";
import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IUser } from "../interfaces"; import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IUser, RequestLimitType } from "../interfaces";
import { IdentityService, NotificationService, SettingsService } from "../services"; import { IdentityService, NotificationService, SettingsService } from "../services";
import { CustomizationFacade } from "../state/customization"; import { CustomizationFacade } from "../state/customization";
@ -32,6 +32,12 @@ export class UserManagementComponent implements OnInit {
public plexEnabled: boolean; public plexEnabled: boolean;
public countries: string[]; public countries: string[];
public requestLimitTypes: RequestLimitType[] = [RequestLimitType.Day, RequestLimitType.Week, RequestLimitType.Month];
public RequestLimitType = RequestLimitType;
public musicRequestLimitType: RequestLimitType;
public episodeRequestLimitType: RequestLimitType;
public movieRequestLimitType: RequestLimitType;
constructor(private identityService: IdentityService, constructor(private identityService: IdentityService,
private settingsService: SettingsService, private settingsService: SettingsService,
@ -95,6 +101,15 @@ export class UserManagementComponent implements OnInit {
if (this.bulkStreaming) { if (this.bulkStreaming) {
x.streamingCountry = this.bulkStreaming; x.streamingCountry = this.bulkStreaming;
} }
if (this.musicRequestLimitType) {
x.musicRequestLimitType = this.musicRequestLimitType;
}
if (this.episodeRequestLimitType) {
x.episodeRequestLimitType = this.episodeRequestLimitType;
}
if (this.movieRequestLimitType) {
x.movieRequestLimitType = this.movieRequestLimitType;
}
this.identityService.updateUser(x).subscribe(y => { this.identityService.updateUser(x).subscribe(y => {
if (!y.successful) { if (!y.successful) {
this.notificationService.error(`Could not update user ${x.userName}. Reason ${y.errors[0]}`); this.notificationService.error(`Could not update user ${x.userName}. Reason ${y.errors[0]}`);
@ -108,6 +123,9 @@ export class UserManagementComponent implements OnInit {
this.bulkEpisodeLimit = undefined; this.bulkEpisodeLimit = undefined;
this.bulkMusicLimit = undefined; this.bulkMusicLimit = undefined;
this.bulkStreaming = undefined; this.bulkStreaming = undefined;
this.movieRequestLimitType = undefined;
this.episodeRequestLimitType = undefined;
this.musicRequestLimitType = undefined;
} }
public isAllSelected() { public isAllSelected() {

@ -23,6 +23,7 @@
// //
// -- This will overwrite an existing command -- // -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
import 'cypress-wait-until'; import 'cypress-wait-until';
Cypress.Commands.add("landingSettings", (enabled) => { Cypress.Commands.add("landingSettings", (enabled) => {
@ -66,7 +67,7 @@ Cypress.Commands.add('removeLogin', () => {
}); });
Cypress.Commands.add('verifyNotification', (text) => { Cypress.Commands.add('verifyNotification', (text) => {
cy.contains(text); cy.contains(text, {timeout: 10000});
}); });
Cypress.Commands.add('createUser', (username, password, claims) => { Cypress.Commands.add('createUser', (username, password, claims) => {

@ -10,7 +10,7 @@ describe("Movie Details Buttons", () => {
Page.adminOptionsDialog.requestButton.click(); Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification("Tom & Jerry (2021) has been successfully added"); cy.verifyNotification("Request for Tom & Jerry has been added successfully");
Page.requestedButton.should("be.visible"); Page.requestedButton.should("be.visible");
}); });
@ -26,7 +26,7 @@ describe("Movie Details Buttons", () => {
Page.visit("651571"); Page.visit("651571");
Page.requestButton.click(); Page.requestButton.click();
cy.verifyNotification("Breach (2020) has been successfully added"); cy.verifyNotification("Request for Breach has been added successfully");
Page.requestedButton.should("be.visible"); Page.requestedButton.should("be.visible");
}); });
@ -62,7 +62,7 @@ describe("Movie Details Buttons", () => {
Page.visit("793723"); Page.visit("793723");
Page.requestButton.click(); Page.requestButton.click();
cy.verifyNotification("Sentinelle (2021) has been successfully added"); cy.verifyNotification("Request for Sentinelle has been added successfully");
Page.requestedButton.should("be.visible"); Page.requestedButton.should("be.visible");
@ -90,7 +90,7 @@ describe("Movie Details Buttons", () => {
Page.adminOptionsDialog.isOpen(); Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click(); Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification( cy.verifyNotification(
"Harry Potter and the Deathly Hallows: Part 1 (2010) has been successfully added" "Request for Harry Potter and the Deathly Hallows: Part 1 has been added successfully"
); );
cy.reload(); cy.reload();
@ -98,6 +98,10 @@ describe("Movie Details Buttons", () => {
Page.markAvailableButton.should("exist"); Page.markAvailableButton.should("exist");
Page.markAvailableButton.click(); Page.markAvailableButton.click();
cy.waitUntil(() => {
return Page.availableButton.should("be.visible");
})
cy.verifyNotification("Request is now available"); cy.verifyNotification("Request is now available");
Page.availableButton.should("exist"); Page.availableButton.should("exist");
}); });
@ -111,7 +115,7 @@ describe("Movie Details Buttons", () => {
Page.adminOptionsDialog.isOpen(); Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click(); Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification( cy.verifyNotification(
"Harry Potter and the Philosopher's Stone (2001) has been successfully added" "Request for Harry Potter and the Philosopher's Stone has been added successfully"
); );
cy.reload(); cy.reload();

@ -42,7 +42,7 @@ describe("Discover Cards Requests Tests", () => {
Page.adminOptionsDialog.isOpen(); Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click(); Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification("has been successfully added!"); cy.verifyNotification("has been added successfully");
card.requestButton.should("not.exist"); card.requestButton.should("not.exist");
card.availabilityText.should("have.text", "Pending"); card.availabilityText.should("have.text", "Pending");
@ -91,7 +91,7 @@ describe("Discover Cards Requests Tests", () => {
card.requestButton.should("be.visible"); card.requestButton.should("be.visible");
card.requestButton.click(); card.requestButton.click();
cy.verifyNotification("has been successfully added!"); cy.verifyNotification("has been added successfully");
card.requestButton.should("not.exist"); card.requestButton.should("not.exist");
card.availabilityText.should("have.text", "Pending"); card.availabilityText.should("have.text", "Pending");

Loading…
Cancel
Save