Fixed #1583 you can now delete users.

Fixed the issue where the requested by was not showing.
Finally fixed the broken poster paths
pull/1614/head
tidusjar 7 years ago
parent c3b2ef2f31
commit 1dc8eac035

@ -13,5 +13,6 @@ namespace Ombi.Core.Engine.Interfaces
RequestCountModel RequestCount(); RequestCountModel RequestCount();
Task<IEnumerable<T>> GetRequests(int count, int position); Task<IEnumerable<T>> GetRequests(int count, int position);
Task<IEnumerable<T>> GetRequests(); Task<IEnumerable<T>> GetRequests();
Task<bool> UserHasRequest(string userId);
} }
} }

@ -120,7 +120,10 @@ namespace Ombi.Core.Engine
public async Task<IEnumerable<MovieRequests>> GetRequests(int count, int position) public async Task<IEnumerable<MovieRequests>> GetRequests(int count, int position)
{ {
var allRequests = await MovieRepository.GetWithUser().Skip(position).Take(count).ToListAsync(); var allRequests = await MovieRepository.GetWithUser().Skip(position).Take(count).ToListAsync();
allRequests.ForEach(x => PosterPathHelper.FixPosterPath(x.PosterPath)); allRequests.ForEach(x =>
{
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
});
return allRequests; return allRequests;
} }
@ -258,6 +261,11 @@ namespace Ombi.Core.Engine
await MovieRepository.Delete(request); await MovieRepository.Delete(request);
} }
public async Task<bool> UserHasRequest(string userId)
{
return await MovieRepository.GetAll().AnyAsync(x => x.RequestedUserId == userId);
}
private async Task<RequestEngineResult> AddMovieRequest(MovieRequests model, string movieName) private async Task<RequestEngineResult> AddMovieRequest(MovieRequests model, string movieName)
{ {
await MovieRepository.Add(model); await MovieRepository.Add(model);

@ -242,6 +242,11 @@ namespace Ombi.Core.Engine
await TvRepository.Delete(request); await TvRepository.Delete(request);
} }
public async Task<bool> UserHasRequest(string userId)
{
return await TvRepository.GetChild().AnyAsync(x => x.RequestedUserId == userId);
}
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest) private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest)
{ {
// Add the child // Add the child

@ -6,7 +6,7 @@ namespace Ombi.Core.Models.UI
public class UserViewModel public class UserViewModel
{ {
public string Id { get; set; } public string Id { get; set; }
public string Username { get; set; } public string UserName { get; set; }
public string Alias { get; set; } public string Alias { get; set; }
public List<ClaimCheckboxes> Claims { get; set; } public List<ClaimCheckboxes> Claims { get; set; }
public string EmailAddress { get; set; } public string EmailAddress { get; set; }

@ -4,6 +4,7 @@ using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
namespace Ombi.Core.Rule.Rules.Request namespace Ombi.Core.Rule.Rules.Request
{ {

@ -14,6 +14,8 @@ namespace Ombi.Store.Repository
IQueryable<T> GetAll(); IQueryable<T> GetAll();
Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate); Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate);
Task AddRange(IEnumerable<T> content); Task AddRange(IEnumerable<T> content);
Task DeleteRange(IEnumerable<T> req);
Task Delete(T request);
IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>( IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>(
IQueryable<TEntity> source, Expression<Func<TEntity, TProperty>> navigationPropertyPath) IQueryable<TEntity> source, Expression<Func<TEntity, TProperty>> navigationPropertyPath)

@ -48,6 +48,18 @@ namespace Ombi.Store.Repository
return content; return content;
} }
public async Task Delete(T request)
{
_db.Remove(request);
await _ctx.SaveChangesAsync();
}
public async Task DeleteRange(IEnumerable<T> req)
{
_db.RemoveRange(req);
await _ctx.SaveChangesAsync();
}
public IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>( public IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>(
IQueryable<TEntity> source, Expression<Func<TEntity, TProperty>> navigationPropertyPath) IQueryable<TEntity> source, Expression<Func<TEntity, TProperty>> navigationPropertyPath)
where TEntity : class where TEntity : class

@ -2,12 +2,11 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
namespace Ombi.Store.Repository namespace Ombi.Store.Repository.Requests
{ {
public interface IMovieRequestRepository : IRepository<MovieRequests> public interface IMovieRequestRepository : IRepository<MovieRequests>
{ {
Task<MovieRequests> Add(MovieRequests request); Task<MovieRequests> Add(MovieRequests request);
Task Delete(MovieRequests request);
Task<MovieRequests> GetRequestAsync(int theMovieDbId); Task<MovieRequests> GetRequestAsync(int theMovieDbId);
MovieRequests GetRequest(int theMovieDbId); MovieRequests GetRequest(int theMovieDbId);
Task Update(MovieRequests request); Task Update(MovieRequests request);

@ -1,4 +1,5 @@
using System.Linq; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Store.Context; using Ombi.Store.Context;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
@ -19,5 +20,6 @@ namespace Ombi.Store.Repository.Requests
Task UpdateChild(ChildRequests request); Task UpdateChild(ChildRequests request);
IQueryable<ChildRequests> GetChild(); IQueryable<ChildRequests> GetChild();
Task Save(); Task Save();
Task DeleteChildRange(IEnumerable<ChildRequests> request);
} }
} }

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -46,12 +47,6 @@ namespace Ombi.Store.Repository.Requests
.AsQueryable(); .AsQueryable();
} }
public async Task Delete(MovieRequests request)
{
Db.MovieRequests.Remove(request);
await Db.SaveChangesAsync();
}
public async Task Update(MovieRequests request) public async Task Update(MovieRequests request)
{ {
if (Db.Entry(request).State == EntityState.Detached) if (Db.Entry(request).State == EntityState.Detached)

@ -1,4 +1,5 @@
using System.Linq; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Store.Context; using Ombi.Store.Context;
@ -89,6 +90,12 @@ namespace Ombi.Store.Repository.Requests
await Db.SaveChangesAsync(); await Db.SaveChangesAsync();
} }
public async Task DeleteChildRange(IEnumerable<ChildRequests> request)
{
Db.ChildRequests.RemoveRange(request);
await Db.SaveChangesAsync();
}
public async Task Update(TvRequests request) public async Task Update(TvRequests request)
{ {
Db.Update(request); Db.Update(request);

@ -0,0 +1,5 @@
{
"cSpell.words": [
"usermanagement"
]
}

@ -10,7 +10,7 @@ import { RouterModule, Routes } from "@angular/router";
//import { DragulaModule, DragulaService } from 'ng2-dragula/ng2-dragula'; //import { DragulaModule, DragulaService } from 'ng2-dragula/ng2-dragula';
import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { GrowlModule } from "primeng/components/growl/growl"; import { GrowlModule } from "primeng/components/growl/growl";
import { ButtonModule, CaptchaModule, DataTableModule,DialogModule, SharedModule, TooltipModule } from "primeng/primeng"; import { ButtonModule, CaptchaModule,ConfirmationService, ConfirmDialogModule, DataTableModule,DialogModule, SharedModule, TooltipModule } from "primeng/primeng";
// Components // Components
import { AppComponent } from "./app.component"; import { AppComponent } from "./app.component";
@ -80,6 +80,7 @@ const routes: Routes = [
RequestsModule, RequestsModule,
CaptchaModule, CaptchaModule,
TooltipModule, TooltipModule,
ConfirmDialogModule,
], ],
declarations: [ declarations: [
AppComponent, AppComponent,
@ -98,6 +99,7 @@ const routes: Routes = [
IdentityService, IdentityService,
StatusService, StatusService,
LandingPageService, LandingPageService,
ConfirmationService,
ImageService, ImageService,
//DragulaService //DragulaService
], ],

@ -2,7 +2,7 @@
export interface IUser { export interface IUser {
id: string; id: string;
username: string; userName: string;
alias: string; alias: string;
claims: ICheckbox[]; claims: ICheckbox[];
emailAddress: string; emailAddress: string;

@ -30,9 +30,9 @@
<br /> <br />
<div> <div>
<span>Requested By: </span> <span>Requested By: </span>
<span *ngIf="!isAdmin">{{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.alias}}</span>
<span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.username}}</span> <span *ngIf="isAdmin && !request.requestedUser.alias">{{request.requestedUser.userName}}</span>
</div> </div>
<div> <div>
<span>Status: </span> <span>Status: </span>

@ -47,6 +47,10 @@ export class IdentityService extends ServiceAuthHelpers {
return this.http.delete(`${this.url}${user.id}`, { headers: this.headers }).map(this.extractData); return this.http.delete(`${this.url}${user.id}`, { headers: this.headers }).map(this.extractData);
} }
public hasUserRequested(userId: string): Observable<boolean> {
return this.http.get(`${this.url}userhasrequest/${userId}`).map(this.extractData);
}
public submitResetPassword(email: string): Observable<IIdentityResult> { public submitResetPassword(email: string): Observable<IIdentityResult> {
return this.regularHttp.post(this.url + "reset", JSON.stringify({email}), { headers: this.headers }).map(this.extractData); return this.regularHttp.post(this.url + "reset", JSON.stringify({email}), { headers: this.headers }).map(this.extractData);
} }

@ -20,7 +20,7 @@ export class UpdateDetailsComponent implements OnInit {
const localUser = x as IUpdateLocalUser; const localUser = x as IUpdateLocalUser;
this.form = this.fb.group({ this.form = this.fb.group({
id:[localUser.id], id:[localUser.id],
username: [localUser.username], username: [localUser.userName],
emailAddress: [localUser.emailAddress, [Validators.email]], emailAddress: [localUser.emailAddress, [Validators.email]],
confirmNewPassword: [localUser.confirmNewPassword], confirmNewPassword: [localUser.confirmNewPassword],
currentPassword: [localUser.currentPassword, [Validators.required]], currentPassword: [localUser.currentPassword, [Validators.required]],

@ -14,7 +14,7 @@
<div class="form-group"> <div class="form-group">
<label for="username" class="control-label">Username</label> <label for="username" class="control-label">Username</label>
<div> <div>
<input type="text" [(ngModel)]="user.username" class="form-control form-control-custom " id="username" name="username" value="{{user?.username}}"> <input type="text" [(ngModel)]="user.userName" class="form-control form-control-custom " id="username" name="username" value="{{user?.userName}}">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">

@ -24,7 +24,7 @@ export class UserManagementAddComponent implements OnInit {
emailAddress: "", emailAddress: "",
id: "", id: "",
password: "", password: "",
username: "", userName: "",
userType: UserType.LocalUser, userType: UserType.LocalUser,
checked:false, checked:false,
hasLoggedIn: false, hasLoggedIn: false,
@ -54,7 +54,7 @@ export class UserManagementAddComponent implements OnInit {
this.identityService.createUser(this.user).subscribe(x => { this.identityService.createUser(this.user).subscribe(x => {
if (x.successful) { if (x.successful) {
this.notificationSerivce.success("Updated", `The user ${this.user.username} has been created successfully`); this.notificationSerivce.success("Updated", `The user ${this.user.userName} has been created successfully`);
this.router.navigate(["usermanagement"]); this.router.navigate(["usermanagement"]);
} else { } else {
x.errors.forEach((val) => { x.errors.forEach((val) => {

@ -1,8 +1,10 @@
<div *ngIf="user"> <div *ngIf="user">
<h3>User: {{user.username}}</h3> <h3>User: {{user.userName}}</h3>
<button type="button" class="btn btn-primary-outline" style="float:right;" [routerLink]="['/usermanagement/']">Back</button> <button type="button" class="btn btn-primary-outline" style="float:right;" [routerLink]="['/usermanagement/']">Back</button>
<p-confirmDialog></p-confirmDialog>
<div class="modal-body" style="margin-top: 45px;"> <div class="modal-body" style="margin-top: 45px;">
<div class="col-md-6"> <div class="col-md-6">
<h4>User Details</h4> <h4>User Details</h4>
@ -14,7 +16,7 @@
<div class="form-group"> <div class="form-group">
<label for="username" class="control-label">Username</label> <label for="username" class="control-label">Username</label>
<div> <div>
<input type="text" [(ngModel)]="user.username" [readonly]="true" class="form-control form-control-custom " id="username" name="username" value="{{user?.username}}"> <input type="text" [(ngModel)]="user.userName" [readonly]="true" class="form-control form-control-custom " id="username" name="username" value="{{user?.userName}}">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">

@ -1,5 +1,6 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { Router } from "@angular/router"; import { Router } from "@angular/router";
import { ConfirmationService } from "primeng/primeng";
import { ActivatedRoute } from "@angular/router"; import { ActivatedRoute } from "@angular/router";
import { IUser } from "../interfaces"; import { IUser } from "../interfaces";
@ -15,8 +16,9 @@ export class UserManagementEditComponent {
constructor(private identityService: IdentityService, constructor(private identityService: IdentityService,
private route: ActivatedRoute, private route: ActivatedRoute,
private notificationSerivce: NotificationService, private notificationService: NotificationService,
private router: Router) { private router: Router,
private confirmationService: ConfirmationService) {
this.route.params this.route.params
.subscribe((params: any) => { .subscribe((params: any) => {
this.userId = params.id; this.userId = params.id;
@ -28,27 +30,38 @@ export class UserManagementEditComponent {
} }
public delete() { public delete() {
this.identityService.deleteUser(this.user).subscribe(x => {
if (x.successful) {
this.notificationSerivce.success("Deleted", `The user ${this.user.username} was deleted`);
this.router.navigate(["usermanagement"]);
} else {
x.errors.forEach((val) => {
this.notificationSerivce.error("Error", val);
});
}
this.confirmationService.confirm({
message: "Are you sure that you want to delete this user? If this user has any requests they will also be deleted.",
header: "Are you sure?",
icon: "fa fa-trash",
accept: () => {
this.identityService.deleteUser(this.user).subscribe(x => {
if (x.successful) {
this.notificationService.success("Deleted", `The user ${this.user.userName} was deleted`);
this.router.navigate(["usermanagement"]);
} else {
x.errors.forEach((val) => {
this.notificationService.error("Error", val);
});
}
});
},
reject: () => {
return;
},
}); });
} }
public resetPassword() { public resetPassword() {
this.identityService.submitResetPassword(this.user.emailAddress).subscribe(x => { this.identityService.submitResetPassword(this.user.emailAddress).subscribe(x => {
if (x.successful) { if (x.successful) {
this.notificationSerivce.success("Reset", `Sent reset password email to ${this.user.emailAddress}`); this.notificationService.success("Reset", `Sent reset password email to ${this.user.emailAddress}`);
this.router.navigate(["usermanagement"]); this.router.navigate(["usermanagement"]);
} else { } else {
x.errors.forEach((val) => { x.errors.forEach((val) => {
this.notificationSerivce.error("Error", val); this.notificationService.error("Error", val);
}); });
} }
@ -63,17 +76,17 @@ export class UserManagementEditComponent {
}); });
if (!hasClaims) { if (!hasClaims) {
this.notificationSerivce.error("Error", "Please assign a role"); this.notificationService.error("Error", "Please assign a role");
return; return;
} }
this.identityService.updateUser(this.user).subscribe(x => { this.identityService.updateUser(this.user).subscribe(x => {
if (x.successful) { if (x.successful) {
this.notificationSerivce.success("Updated", `The user ${this.user.username} has been updated successfully`); this.notificationService.success("Updated", `The user ${this.user.userName} has been updated successfully`);
this.router.navigate(["usermanagement"]); this.router.navigate(["usermanagement"]);
} else { } else {
x.errors.forEach((val) => { x.errors.forEach((val) => {
this.notificationSerivce.error("Error", val); this.notificationService.error("Error", val);
}); });
} }
}); });

@ -63,7 +63,7 @@
<input type="checkbox" [(ngModel)]="u.checked"> <input type="checkbox" [(ngModel)]="u.checked">
</td> </td>
<td> <td>
{{u.username}} {{u.userName}}
</td> </td>
<td> <td>
{{u.alias}} {{u.alias}}
@ -97,108 +97,4 @@
<div class="modal fade in" *ngIf="showEditDialog" style="display: block;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" (click)="showEditDialog=false">&times;</button>
<h4 class="modal-title">Editing User {{selectedUser?.username}}</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="username" class="control-label">Username</label>
<div>
<input type="text" [(ngModel)]="selectedUser.username" [readonly]="true" class="form-control form-control-custom " id="username" name="username" value="{{selectedUser?.username}}">
</div>
</div>
<div class="form-group">
<label for="alias" class="control-label">Alias</label>
<div>
<input type="text" [(ngModel)]="selectedUser.alias" class="form-control form-control-custom " id="alias" name="alias" value="{{selectedUser?.alias}}">
</div>
</div>
<div class="form-group">
<label for="alias" class="control-label">Email Address</label>
<div>
<input type="text" [(ngModel)]="selectedUser.emailAddress" class="form-control form-control-custom " id="emailAddress" name="emailAddress" value="{{selectedUser?.emailAddress}}">
</div>
</div>
<div *ngFor="let c of selectedUser.claims">
<div class="form-group">
<div class="checkbox">
<input type="checkbox" [(ngModel)]="c.enabled" [value]="c.value" id="create{{c.value}}" [attr.name]="'create' + c.value" ng-checked="c.enabled">
<label for="create{{c.value}}">{{c.value}}</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger-outline" (click)="showEditDialog=false">Close</button>
<button type="button" class="btn btn-primary-outline" (click)="updateUser()">Save changes</button>
</div>
</div>
</div>
</div>
<div>
<div class="modal fade in " *ngIf="showCreateDialogue" style="display: block;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" (click)="showCreateDialogue=false">&times;</button>
<h4 class="modal-title">Create User</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="username" class="control-label">Username</label>
<div>
<input type="text" [(ngModel)]="createdUser.username" class="form-control form-control-custom " id="username" name="username" value="{{createdUser?.username}}">
</div>
</div>
<div class="form-group">
<label for="alias" class="control-label">Alias</label>
<div>
<input type="text" [(ngModel)]="createdUser.alias" class="form-control form-control-custom " id="alias" name="alias" value="{{createdUser?.alias}}">
</div>
</div>
<div class="form-group">
<label for="emailAddress" class="control-label">Email Address</label>
<div>
<input type="text" [(ngModel)]="createdUser.emailAddress" class="form-control form-control-custom " id="emailAddress" name="emailAddress" value="{{createdUser?.emailAddress}}">
</div>
</div>
<div class="form-group">
<label for="password" class="control-label">Password</label>
<div>
<input type="password" [(ngModel)]="createdUser.password" class="form-control form-control-custom " id="password" name="password" value="{{createdUser?.password}}">
</div>
</div>
<div *ngFor="let c of availableClaims">
<div class="form-group">
<div class="checkbox">
<input type="checkbox" [(ngModel)]="c.enabled" [value]="c.value" id="create{{c.value}}" [attr.name]="'create' + c.value" ng-checked="c.enabled">
<label for="create{{c.value}}">{{c.value}}</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger-outline" (click)="showCreateDialogue=false">Close</button>
<button type="button" class="btn btn-primary-outline" (click)="create()">Add User</button>
</div>
</div>
</div>
</div>
</div>

@ -2,7 +2,7 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { RouterModule, Routes } from "@angular/router"; import { RouterModule, Routes } from "@angular/router";
import { MultiSelectModule, TooltipModule } from "primeng/primeng"; import { ConfirmationService, ConfirmDialogModule, MultiSelectModule, TooltipModule } from "primeng/primeng";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
@ -32,7 +32,7 @@ const routes: Routes = [
NgbModule.forRoot(), NgbModule.forRoot(),
MultiSelectModule, MultiSelectModule,
PipeModule, PipeModule,
ConfirmDialogModule,
TooltipModule, TooltipModule,
], ],
declarations: [ declarations: [
@ -46,6 +46,7 @@ const routes: Routes = [
], ],
providers: [ providers: [
IdentityService, IdentityService,
ConfirmationService,
], ],
}) })

@ -301,3 +301,13 @@ button.list-group-item:focus {
.ui-state-default { .ui-state-default {
border: 2px solid $bg-colour-disabled; border: 2px solid $bg-colour-disabled;
} }
.ui-button {
background: $primary-colour $i;
border: 1px solid $primary-colour-outline $i;
}
.ui-dialog-titlebar{
background:$bg-colour-disabled;
color:white;
}

@ -27,6 +27,8 @@ using Ombi.Schedule.Jobs.Ombi;
using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models;
using Ombi.Settings.Settings.Models.Notifications; using Ombi.Settings.Settings.Models.Notifications;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
using OmbiIdentityResult = Ombi.Models.Identity.IdentityResult; using OmbiIdentityResult = Ombi.Models.Identity.IdentityResult;
namespace Ombi.Controllers namespace Ombi.Controllers
@ -41,7 +43,9 @@ namespace Ombi.Controllers
public IdentityController(OmbiUserManager user, IMapper mapper, RoleManager<IdentityRole> rm, IEmailProvider prov, public IdentityController(OmbiUserManager user, IMapper mapper, RoleManager<IdentityRole> rm, IEmailProvider prov,
ISettingsService<EmailNotificationSettings> s, ISettingsService<EmailNotificationSettings> s,
ISettingsService<CustomizationSettings> c, ISettingsService<CustomizationSettings> c,
IWelcomeEmail welcome) IWelcomeEmail welcome,
IMovieRequestRepository m,
ITvRequestRepository t)
{ {
UserManager = user; UserManager = user;
Mapper = mapper; Mapper = mapper;
@ -50,6 +54,8 @@ namespace Ombi.Controllers
EmailSettings = s; EmailSettings = s;
CustomizationSettings = c; CustomizationSettings = c;
WelcomeEmail = welcome; WelcomeEmail = welcome;
MovieRepo = m;
TvRepo = t;
} }
private OmbiUserManager UserManager { get; } private OmbiUserManager UserManager { get; }
@ -59,6 +65,8 @@ namespace Ombi.Controllers
private ISettingsService<EmailNotificationSettings> EmailSettings { get; } private ISettingsService<EmailNotificationSettings> EmailSettings { get; }
private ISettingsService<CustomizationSettings> CustomizationSettings { get; } private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
private IWelcomeEmail WelcomeEmail { get; } private IWelcomeEmail WelcomeEmail { get; }
private IMovieRequestRepository MovieRepo { get; }
private ITvRequestRepository TvRepo { get; }
/// <summary> /// <summary>
/// This is what the Wizard will call when creating the user for the very first time. /// This is what the Wizard will call when creating the user for the very first time.
@ -134,7 +142,7 @@ namespace Ombi.Controllers
model.Add(await GetUserWithRoles(user)); model.Add(await GetUserWithRoles(user));
} }
return model.OrderBy(x => x.Username); return model.OrderBy(x => x.UserName);
} }
/// <summary> /// <summary>
@ -169,7 +177,7 @@ namespace Ombi.Controllers
var vm = new UserViewModel var vm = new UserViewModel
{ {
Alias = user.Alias, Alias = user.Alias,
Username = user.UserName, UserName = user.UserName,
Id = user.Id, Id = user.Id,
EmailAddress = user.Email, EmailAddress = user.Email,
UserType = (Core.Models.UserType)(int)user.UserType, UserType = (Core.Models.UserType)(int)user.UserType,
@ -223,7 +231,7 @@ namespace Ombi.Controllers
{ {
Alias = user.Alias, Alias = user.Alias,
Email = user.EmailAddress, Email = user.EmailAddress,
UserName = user.Username, UserName = user.UserName,
UserType = UserType.LocalUser, UserType = UserType.LocalUser,
}; };
var userResult = await UserManager.CreateAsync(ombiUser, user.Password); var userResult = await UserManager.CreateAsync(ombiUser, user.Password);
@ -423,6 +431,20 @@ namespace Ombi.Controllers
{ {
return Error("You do not have the correct permissions to delete this user"); return Error("You do not have the correct permissions to delete this user");
} }
// We need to delete all the requests first
var moviesUserRequested = MovieRepo.GetAll().Where(x => x.RequestedUserId == userId);
var tvUserRequested = TvRepo.GetChild().Where(x => x.RequestedUserId == userId);
if (moviesUserRequested.Any())
{
await MovieRepo.DeleteRange(moviesUserRequested);
}
if (tvUserRequested.Any())
{
await TvRepo.DeleteChildRange(tvUserRequested);
}
var result = await UserManager.DeleteAsync(userToDelete); var result = await UserManager.DeleteAsync(userToDelete);
if (result.Succeeded) if (result.Succeeded)
{ {
@ -559,7 +581,7 @@ namespace Ombi.Controllers
var ombiUser = new OmbiUser var ombiUser = new OmbiUser
{ {
Email = user.EmailAddress, Email = user.EmailAddress,
UserName = user.Username UserName = user.UserName
}; };
BackgroundJob.Enqueue(() => WelcomeEmail.SendEmail(ombiUser)); BackgroundJob.Enqueue(() => WelcomeEmail.SendEmail(ombiUser));
} }

@ -279,6 +279,21 @@ namespace Ombi.Controllers
return TvRequestEngine.RequestCount(); return TvRequestEngine.RequestCount();
} }
/// <summary>
/// Checks if the passed in user has a request
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[HttpGet("userhasrequest")]
public async Task<bool> UserHasRequest(string userId)
{
var movies = await MovieRequestEngine.UserHasRequest(userId);
var tv = await TvRequestEngine.UserHasRequest(userId);
return movies || tv;
}
///// <summary> ///// <summary>
///// Gets the specific grid model for the requests (for modelling the UI). ///// Gets the specific grid model for the requests (for modelling the UI).
///// </summary> ///// </summary>

@ -44,7 +44,7 @@ namespace Ombi.Controllers
public async Task<IActionResult> GetToken([FromBody] UserAuthModel model) public async Task<IActionResult> GetToken([FromBody] UserAuthModel model)
{ {
await _audit.Record(AuditType.None, AuditArea.Authentication, await _audit.Record(AuditType.None, AuditArea.Authentication,
$"Username {model.Username} attempting to authenticate"); $"UserName {model.Username} attempting to authenticate");
var user = await _userManager.FindByNameAsync(model.Username); var user = await _userManager.FindByNameAsync(model.Username);

Loading…
Cancel
Save