From bcb193f321177665c882fca5ae79fd9d34687a0f Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 29 Aug 2018 13:25:43 +0100 Subject: [PATCH 1/7] made a start !wip --- src/Ombi.Schedule.Tests/NewsletterTests.cs | 2 +- .../Entities/UserNotificationPreferences.cs | 20 +++++++++++++ src/Ombi/Controllers/IdentityController.cs | 29 ++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/Ombi.Store/Entities/UserNotificationPreferences.cs diff --git a/src/Ombi.Schedule.Tests/NewsletterTests.cs b/src/Ombi.Schedule.Tests/NewsletterTests.cs index fcbd35107..b3c2ce98a 100644 --- a/src/Ombi.Schedule.Tests/NewsletterTests.cs +++ b/src/Ombi.Schedule.Tests/NewsletterTests.cs @@ -18,7 +18,7 @@ namespace Ombi.Schedule.Tests var emailSettings = new Mock>(); var customziation = new Mock>(); var newsletterSettings = new Mock>(); - var newsletter = new NewsletterJob(null, null, null, null, null, null, customziation.Object, emailSettings.Object, null, null, newsletterSettings.Object, null); + var newsletter = new NewsletterJob(null, null, null, null, null, null, customziation.Object, emailSettings.Object, null, null, newsletterSettings.Object, null, null, null, null); var ep = new List(); foreach (var i in episodes) diff --git a/src/Ombi.Store/Entities/UserNotificationPreferences.cs b/src/Ombi.Store/Entities/UserNotificationPreferences.cs new file mode 100644 index 000000000..c779480c8 --- /dev/null +++ b/src/Ombi.Store/Entities/UserNotificationPreferences.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; +using Ombi.Helpers; + +namespace Ombi.Store.Entities +{ + [Table(nameof(UserNotificationPreferences))] + public class UserNotificationPreferences : Entity + { + public string UserId { get; set; } + public NotificationAgent Agent { get; set; } + public bool Enabled { get; set; } + public string Value { get; set; } + + [ForeignKey(nameof(UserId))] + public OmbiUser User { get; set; } + } +} diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 742d75b34..d7e556f26 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -60,7 +60,8 @@ namespace Ombi.Controllers IRepository issueComments, IRepository notificationRepository, IRepository subscriptionRepository, - ISettingsService umSettings) + ISettingsService umSettings, + IRepository notificationPreferences) { UserManager = user; Mapper = mapper; @@ -81,6 +82,7 @@ namespace Ombi.Controllers _requestSubscriptionRepository = subscriptionRepository; _notificationRepository = notificationRepository; _userManagementSettings = umSettings; + _userNotificationPreferences = notificationPreferences; } private OmbiUserManager UserManager { get; } @@ -102,6 +104,7 @@ namespace Ombi.Controllers private readonly IRepository _requestLogRepository; private readonly IRepository _notificationRepository; private readonly IRepository _requestSubscriptionRepository; + private readonly IRepository _userNotificationPreferences; /// @@ -787,6 +790,30 @@ namespace Ombi.Controllers return user.UserAccessToken; } + [HttpGet("notificationpreferences")] + public async Task> GetUserPreferences() + { + //TODO potentially use a view model + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + var userPreferences = await _userNotificationPreferences.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); + + var agents = Enum.GetValues(typeof(NotificationAgent)).Cast(); + foreach (var a in agents) + { + var hasAgent = userPreferences.Any(x => x.Agent == a); + if (!hasAgent) + { + // Create the default + userPreferences.Add(new UserNotificationPreferences + { + Agent = a, + }); + } + } + + return userPreferences; + } + private async Task> AddRoles(IEnumerable roles, OmbiUser ombiUser) { var roleResult = new List(); From 2886f6e6fa2f81bb2595b4228a7f6368448d71f2 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 13:05:41 +0100 Subject: [PATCH 2/7] Consolodated the usermanagement stuff, still a !wip but it's a start --- .../usermanagement-add.component.html | 79 --------- .../usermanagement-add.component.ts | 70 -------- .../usermanagement-edit.component.html | 70 -------- .../usermanagement-user.component.html | 154 ++++++++++++++++++ ...nt.ts => usermanagement-user.component.ts} | 92 +++++++++-- .../usermanagement.component.html | 4 +- .../usermanagement/usermanagement.module.ts | 4 +- 7 files changed, 235 insertions(+), 238 deletions(-) delete mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html delete mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts delete mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html create mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html rename src/Ombi/ClientApp/app/usermanagement/{usermanagement-edit.component.ts => usermanagement-user.component.ts} (51%) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html deleted file mode 100644 index 683bd5620..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html +++ /dev/null @@ -1,79 +0,0 @@ - -

Create User

- - - -
-
- - -
-
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts deleted file mode 100644 index 36b187e79..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Component, OnInit } from "@angular/core"; -import { Router } from "@angular/router"; - -import { ICheckbox, IUser, UserType } from "../interfaces"; -import { IdentityService, NotificationService } from "../services"; - -@Component({ - templateUrl: "./usermanagement-add.component.html", -}) -export class UserManagementAddComponent implements OnInit { - public user: IUser; - public availableClaims: ICheckbox[]; - public confirmPass: ""; - - constructor(private identityService: IdentityService, - private notificationSerivce: NotificationService, - private router: Router) { } - - public ngOnInit() { - this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); - this.user = { - alias: "", - claims: [], - emailAddress: "", - id: "", - password: "", - userName: "", - userType: UserType.LocalUser, - checked: false, - hasLoggedIn: false, - lastLoggedIn: new Date(), - episodeRequestLimit: 0, - movieRequestLimit: 0, - userAccessToken: "", - }; - } - - public create() { - this.user.claims = this.availableClaims; - - if (this.user.password) { - if (this.user.password !== this.confirmPass) { - this.notificationSerivce.error("Passwords do not match"); - return; - } - } - const hasClaims = this.availableClaims.some((item) => { - if (item.enabled) { return true; } - - return false; - }); - - if (!hasClaims) { - this.notificationSerivce.error("Please assign a role"); - return; - } - - this.identityService.createUser(this.user).subscribe(x => { - if (x.successful) { - this.notificationSerivce.success(`The user ${this.user.userName} has been created successfully`); - this.router.navigate(["usermanagement"]); - } else { - x.errors.forEach((val) => { - this.notificationSerivce.error(val); - }); - } - }); - } - -} diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html deleted file mode 100644 index 95a70cab0..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html +++ /dev/null @@ -1,70 +0,0 @@ -
-
-

User: {{user.userName}}

- - - - - - -
- - - - -
-
-
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html new file mode 100644 index 000000000..0dcb24cb4 --- /dev/null +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -0,0 +1,154 @@ +
+

Create User

+ + + +
+
+ + +
+
+
+ +
+ +
+
+

User: {{user.userName}}

+ + + + + + +
+ + + + +
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts similarity index 51% rename from src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.ts rename to src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index a83ef5a97..bca4f1058 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -1,32 +1,92 @@ -import { Component } from "@angular/core"; -import { Router } from "@angular/router"; +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { ICheckbox, IUser, UserType } from "../interfaces"; +import { IdentityService, NotificationService } from "../services"; + import { ConfirmationService } from "primeng/primeng"; -import { ActivatedRoute } from "@angular/router"; -import { IUser } from "../interfaces"; -import { IdentityService } from "../services"; -import { NotificationService } from "../services"; - @Component({ - templateUrl: "./usermanagement-edit.component.html", + templateUrl: "./usermanagement-user.component.html", }) -export class UserManagementEditComponent { +export class UserManagementUserComponent implements OnInit { + public user: IUser; public userId: string; + public availableClaims: ICheckbox[]; + public confirmPass: ""; + + public edit: boolean; constructor(private identityService: IdentityService, - private route: ActivatedRoute, private notificationService: NotificationService, private router: Router, + private route: ActivatedRoute, private confirmationService: ConfirmationService) { - this.route.params + this.route.params .subscribe((params: any) => { - this.userId = params.id; - - this.identityService.getUserById(this.userId).subscribe(x => { - this.user = x; - }); + if(params.id) { + this.userId = params.id; + this.edit = true; + this.identityService.getUserById(this.userId).subscribe(x => { + this.user = x; + }); + } }); + + } + + public ngOnInit() { + this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); + if(!this.edit) { + this.user = { + alias: "", + claims: [], + emailAddress: "", + id: "", + password: "", + userName: "", + userType: UserType.LocalUser, + checked: false, + hasLoggedIn: false, + lastLoggedIn: new Date(), + episodeRequestLimit: 0, + movieRequestLimit: 0, + userAccessToken: "", + }; + } + } + + public create() { + this.user.claims = this.availableClaims; + + if (this.user.password) { + if (this.user.password !== this.confirmPass) { + this.notificationService.error("Passwords do not match"); + return; + } + } + const hasClaims = this.availableClaims.some((item) => { + if (item.enabled) { return true; } + + return false; + }); + + if (!hasClaims) { + this.notificationService.error("Please assign a role"); + return; + } + + this.identityService.createUser(this.user).subscribe(x => { + if (x.successful) { + this.notificationService.success(`The user ${this.user.userName} has been created successfully`); + this.router.navigate(["usermanagement"]); + } else { + x.errors.forEach((val) => { + this.notificationService.error(val); + }); + } + }); } public delete() { diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 519db023f..de78f64f8 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -2,7 +2,7 @@ - +
@@ -94,7 +94,7 @@ Emby User - Details/Edit + Details/Edit diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index cf25446f5..7ff799729 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -10,6 +10,7 @@ import { UpdateDetailsComponent } from "./updatedetails.component"; import { UserManagementAddComponent } from "./usermanagement-add.component"; import { UserManagementEditComponent } from "./usermanagement-edit.component"; import { UserManagementComponent } from "./usermanagement.component"; +import { UserManagementUserComponent } from "./usermanagement-user.component"; import { PipeModule } from "../pipes/pipe.module"; import { IdentityService, PlexService } from "../services"; @@ -22,7 +23,7 @@ import { AddPlexUserComponent } from "./addplexuser.component"; const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "add", component: UserManagementAddComponent, canActivate: [AuthGuard] }, - { path: "edit/:id", component: UserManagementEditComponent, canActivate: [AuthGuard] }, + { path: "user", component: UserManagementUserComponent, canActivate: [AuthGuard] }, { path: "updatedetails", component: UpdateDetailsComponent, canActivate: [AuthGuard] }, ]; @@ -46,6 +47,7 @@ const routes: Routes = [ UserManagementEditComponent, UpdateDetailsComponent, AddPlexUserComponent, + UserManagementUserComponent, ], entryComponents:[ AddPlexUserComponent, From de2e3abfe02c70fbe1a61d51b2409ed189138f67 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 14:15:26 +0100 Subject: [PATCH 3/7] Added the API to add user notification preferences --- src/Ombi.Store/Entities/OmbiUser.cs | 1 + .../Entities/UserNotificationPreferences.cs | 7 ++- src/Ombi/Controllers/IdentityController.cs | 50 +++++++++++++++++-- .../Identity/AddNotificationPreference.cs | 12 +++++ 4 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 src/Ombi/Models/Identity/AddNotificationPreference.cs diff --git a/src/Ombi.Store/Entities/OmbiUser.cs b/src/Ombi.Store/Entities/OmbiUser.cs index 9513df818..801a50cb1 100644 --- a/src/Ombi.Store/Entities/OmbiUser.cs +++ b/src/Ombi.Store/Entities/OmbiUser.cs @@ -28,6 +28,7 @@ namespace Ombi.Store.Entities public string UserAccessToken { get; set; } public List NotificationUserIds { get; set; } + public List UserNotificationPreferences { get; set; } [NotMapped] public bool IsEmbyConnect => UserType == UserType.EmbyUser && EmbyConnectUserId.HasValue(); diff --git a/src/Ombi.Store/Entities/UserNotificationPreferences.cs b/src/Ombi.Store/Entities/UserNotificationPreferences.cs index c779480c8..7196d38ca 100644 --- a/src/Ombi.Store/Entities/UserNotificationPreferences.cs +++ b/src/Ombi.Store/Entities/UserNotificationPreferences.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Text; +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; using Ombi.Helpers; namespace Ombi.Store.Entities @@ -15,6 +13,7 @@ namespace Ombi.Store.Entities public string Value { get; set; } [ForeignKey(nameof(UserId))] + [JsonIgnore] public OmbiUser User { get; set; } } } diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index d7e556f26..71cac7a76 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -793,15 +793,14 @@ namespace Ombi.Controllers [HttpGet("notificationpreferences")] public async Task> GetUserPreferences() { - //TODO potentially use a view model var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); var userPreferences = await _userNotificationPreferences.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); var agents = Enum.GetValues(typeof(NotificationAgent)).Cast(); foreach (var a in agents) { - var hasAgent = userPreferences.Any(x => x.Agent == a); - if (!hasAgent) + var agent = userPreferences.FirstOrDefault(x => x.Agent == a); + if (agent == null) { // Create the default userPreferences.Add(new UserNotificationPreferences @@ -809,11 +808,56 @@ namespace Ombi.Controllers Agent = a, }); } + else + { + userPreferences.Add(agent); + } } return userPreferences; } + [HttpPost("NotificationPreferences")] + public async Task AddUserNotificationPreference([FromBody] AddNotificationPreference pref) + { + // Make sure the user exists + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == pref.UserId); + if (user == null) + { + return NotFound(); + } + // Check if we are editing a different user than ourself, if we are then we need to power user role + var me = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + if (!me.Id.Equals(user.Id, StringComparison.InvariantCultureIgnoreCase)) + { + var isPowerUser = await UserManager.IsInRoleAsync(me, OmbiRoles.PowerUser); + var isAdmin = await UserManager.IsInRoleAsync(me, OmbiRoles.Admin); + if (!isPowerUser && !isAdmin) + { + return Unauthorized(); + } + } + + // Make sure we don't already have a preference for this agent + var existingPreference = await _userNotificationPreferences.GetAll() + .FirstOrDefaultAsync(x => x.UserId == user.Id && x.Agent == pref.Agent); + if (existingPreference != null) + { + // Update it + existingPreference.Value = pref.Value; + existingPreference.Enabled = pref.Enabled; + } + await _userNotificationPreferences.Add(new UserNotificationPreferences + { + Agent = pref.Agent, + Enabled = pref.Enabled, + UserId = pref.UserId, + Value = pref.Value + }); + + return Json(true); + } + private async Task> AddRoles(IEnumerable roles, OmbiUser ombiUser) { var roleResult = new List(); diff --git a/src/Ombi/Models/Identity/AddNotificationPreference.cs b/src/Ombi/Models/Identity/AddNotificationPreference.cs new file mode 100644 index 000000000..51dc7f6fe --- /dev/null +++ b/src/Ombi/Models/Identity/AddNotificationPreference.cs @@ -0,0 +1,12 @@ +using Ombi.Helpers; + +namespace Ombi.Models.Identity +{ + public class AddNotificationPreference + { + public NotificationAgent Agent { get; set; } + public string UserId { get; set; } + public string Value { get; set; } + public bool Enabled { get; set; } + } +} \ No newline at end of file From 8573b7c729aba788bd575cdbf994d33ff8fed53e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 15:51:22 +0100 Subject: [PATCH 4/7] Did the notification side of things with the custom user defined preference !wip --- .../Agents/DiscordNotification.cs | 5 +++-- .../Agents/EmailNotification.cs | 3 ++- .../Agents/MattermostNotification.cs | 3 ++- .../Agents/MobileNotification.cs | 3 ++- .../Agents/PushbulletNotification.cs | 3 ++- .../Agents/PushoverNotification.cs | 3 ++- .../Agents/SlackNotification.cs | 3 ++- .../Agents/TelegramNotification.cs | 3 ++- src/Ombi.Notifications/BaseNotification.cs | 22 ++++++++++++++----- .../NotificationMessageCurlys.cs | 10 ++++++--- .../usermanagement/usermanagement.module.ts | 3 --- src/Ombi/Ombi.csproj | 2 +- 12 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs index d788b471c..84e907053 100644 --- a/src/Ombi.Notifications/Agents/DiscordNotification.cs +++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs @@ -20,8 +20,9 @@ namespace Ombi.Notifications.Agents { public DiscordNotification(IDiscordApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, - IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music) - : base(sn, r, m, t, s, log, sub, music) + IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) + : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index 3ab045e87..cff1f3b80 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -22,7 +22,8 @@ namespace Ombi.Notifications.Agents public class EmailNotification : BaseNotification, IEmailNotification { public EmailNotification(ISettingsService settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService c, - ILogger log, UserManager um, IRepository sub, IMusicRequestRepository music) : base(settings, r, m, t, c, log, sub, music) + ILogger log, UserManager um, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(settings, r, m, t, c, log, sub, music, userPref) { EmailProvider = prov; Logger = log; diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs index 9e8a34e3b..37e597854 100644 --- a/src/Ombi.Notifications/Agents/MattermostNotification.cs +++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs @@ -21,7 +21,8 @@ namespace Ombi.Notifications.Agents public class MattermostNotification : BaseNotification, IMattermostNotification { public MattermostNotification(IMattermostApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs index c521b99a4..a16785909 100644 --- a/src/Ombi.Notifications/Agents/MobileNotification.cs +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -22,7 +22,8 @@ namespace Ombi.Notifications.Agents { public MobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, - UserManager um, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + UserManager um, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { _api = api; _logger = log; diff --git a/src/Ombi.Notifications/Agents/PushbulletNotification.cs b/src/Ombi.Notifications/Agents/PushbulletNotification.cs index 0e488bf79..6c6b1f789 100644 --- a/src/Ombi.Notifications/Agents/PushbulletNotification.cs +++ b/src/Ombi.Notifications/Agents/PushbulletNotification.cs @@ -17,7 +17,8 @@ namespace Ombi.Notifications.Agents public class PushbulletNotification : BaseNotification, IPushbulletNotification { public PushbulletNotification(IPushbulletApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index b5d743cc2..86f91dbaa 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -18,7 +18,8 @@ namespace Ombi.Notifications.Agents public class PushoverNotification : BaseNotification, IPushoverNotification { public PushoverNotification(IPushoverApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/SlackNotification.cs b/src/Ombi.Notifications/Agents/SlackNotification.cs index 6c04f5ea6..ee81e9729 100644 --- a/src/Ombi.Notifications/Agents/SlackNotification.cs +++ b/src/Ombi.Notifications/Agents/SlackNotification.cs @@ -18,7 +18,8 @@ namespace Ombi.Notifications.Agents public class SlackNotification : BaseNotification, ISlackNotification { public SlackNotification(ISlackApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/TelegramNotification.cs b/src/Ombi.Notifications/Agents/TelegramNotification.cs index 7bcda7c7f..cf463bf99 100644 --- a/src/Ombi.Notifications/Agents/TelegramNotification.cs +++ b/src/Ombi.Notifications/Agents/TelegramNotification.cs @@ -19,7 +19,8 @@ namespace Ombi.Notifications.Agents public TelegramNotification(ITelegramApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s - , IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t,s,log, sub, music) + , IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t,s,log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index 287f86455..d351c8283 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -19,7 +19,8 @@ namespace Ombi.Notifications.Interfaces public abstract class BaseNotification : INotification where T : Settings.Settings.Models.Settings, new() { protected BaseNotification(ISettingsService settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv, - ISettingsService customization, ILogger> log, IRepository sub, IMusicRequestRepository album) + ISettingsService customization, ILogger> log, IRepository sub, IMusicRequestRepository album, + IRepository notificationUserPreferences) { Settings = settings; TemplateRepository = templateRepo; @@ -31,6 +32,7 @@ namespace Ombi.Notifications.Interfaces RequestSubscription = sub; _log = log; AlbumRepository = album; + UserNotificationPreferences = notificationUserPreferences; } protected ISettingsService Settings { get; } @@ -40,6 +42,7 @@ namespace Ombi.Notifications.Interfaces protected IMusicRequestRepository AlbumRepository { get; } protected CustomizationSettings Customization { get; set; } protected IRepository RequestSubscription { get; set; } + protected IRepository UserNotificationPreferences { get; set; } private ISettingsService CustomizationSettings { get; } private readonly ILogger> _log; @@ -167,7 +170,7 @@ namespace Ombi.Notifications.Interfaces { return new NotificationMessageContent { Disabled = true }; } - var parsed = Parse(model, template); + var parsed = Parse(model, template, agent); return parsed; } @@ -178,25 +181,32 @@ namespace Ombi.Notifications.Interfaces return subs.Select(x => x.User); } - private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template) + protected UserNotificationPreferences GetUserPreference(string userId, NotificationAgent agent) + { + return UserNotificationPreferences.GetAll() + .FirstOrDefault(x => x.Enabled && x.Agent == agent && x.UserId == userId); + } + + private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent) { var resolver = new NotificationMessageResolver(); var curlys = new NotificationMessageCurlys(); + var preference = GetUserPreference(model.UserId, agent); if (model.RequestType == RequestType.Movie) { _log.LogDebug("Notification options: {@model}, Req: {@MovieRequest}, Settings: {@Customization}", model, MovieRequest, Customization); - curlys.Setup(model, MovieRequest, Customization); + curlys.Setup(model, MovieRequest, Customization, preference); } else if (model.RequestType == RequestType.TvShow) { _log.LogDebug("Notification options: {@model}, Req: {@TvRequest}, Settings: {@Customization}", model, TvRequest, Customization); - curlys.Setup(model, TvRequest, Customization); + curlys.Setup(model, TvRequest, Customization, preference); } else if (model.RequestType == RequestType.Album) { _log.LogDebug("Notification options: {@model}, Req: {@AlbumRequest}, Settings: {@Customization}", model, AlbumRequest, Customization); - curlys.Setup(model, AlbumRequest, Customization); + curlys.Setup(model, AlbumRequest, Customization, preference); } var parsed = resolver.ParseMessage(template, curlys); diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 710f64619..5bc74f68e 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -14,9 +14,10 @@ namespace Ombi.Notifications { public class NotificationMessageCurlys { - public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s) + public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); + UserPreference = pref.Enabled ? pref.Value : string.Empty; string title; if (req == null) { @@ -58,9 +59,10 @@ namespace Ombi.Notifications AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; } - public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s) + public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); + UserPreference = pref.Enabled ? pref.Value : string.Empty; string title; if (req == null) { @@ -101,9 +103,10 @@ namespace Ombi.Notifications Alias = username.Alias.HasValue() ? username.Alias : username.UserName; } - public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s) + public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); + UserPreference = pref.Enabled ? pref.Value : string.Empty; string title; if (req == null) { @@ -221,6 +224,7 @@ namespace Ombi.Notifications public string IssueStatus { get; set; } public string IssueSubject { get; set; } public string NewIssueComment { get; set; } + public string UserPreference { get; set; } // System Defined private string LongDate => DateTime.Now.ToString("D"); diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index 7ff799729..81101978e 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -7,8 +7,6 @@ import { ConfirmationService, ConfirmDialogModule, MultiSelectModule, SidebarMod import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { UpdateDetailsComponent } from "./updatedetails.component"; -import { UserManagementAddComponent } from "./usermanagement-add.component"; -import { UserManagementEditComponent } from "./usermanagement-edit.component"; import { UserManagementComponent } from "./usermanagement.component"; import { UserManagementUserComponent } from "./usermanagement-user.component"; @@ -22,7 +20,6 @@ import { AddPlexUserComponent } from "./addplexuser.component"; const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, - { path: "add", component: UserManagementAddComponent, canActivate: [AuthGuard] }, { path: "user", component: UserManagementUserComponent, canActivate: [AuthGuard] }, { path: "updatedetails", component: UpdateDetailsComponent, canActivate: [AuthGuard] }, ]; diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 6640a8eb8..1ca47d306 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -8,7 +8,7 @@ $(SemVer) $(FullVer) - 2.8 + 3.0 false From 2204559b0aee9dfc1ca50ff9336d1e3fa9957001 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:38:41 +0100 Subject: [PATCH 5/7] Added the Notification Preferences to the user --- ...24_UserNotificationPreferences.Designer.cs | 1118 +++++++++++++++++ ...80919073124_UserNotificationPreferences.cs | 43 + .../Migrations/OmbiContextModelSnapshot.cs | 29 +- src/Ombi/ClientApp/app/interfaces/IUser.ts | 19 + .../app/services/identity.service.ts | 14 +- .../usermanagement-user.component.html | 285 +++-- .../usermanagement-user.component.ts | 12 +- .../usermanagement/usermanagement.module.ts | 3 +- src/Ombi/Controllers/IdentityController.cs | 98 +- 9 files changed, 1431 insertions(+), 190 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs diff --git a/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs new file mode 100644 index 000000000..d61ea31ba --- /dev/null +++ b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs @@ -0,0 +1,1118 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180919073124_UserNotificationPreferences")] + partial class UserNotificationPreferences + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs new file mode 100644 index 000000000..adb062af7 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class UserNotificationPreferences : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "UserNotificationPreferences", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + Agent = table.Column(nullable: false), + Enabled = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserNotificationPreferences", x => x.Id); + table.ForeignKey( + name: "FK_UserNotificationPreferences_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_UserNotificationPreferences_UserId", + table: "UserNotificationPreferences", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserNotificationPreferences"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 64400e58c..5e5aa23c6 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.1-rtm-30846"); + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -870,6 +870,26 @@ namespace Ombi.Store.Migrations b.ToTable("Tokens"); }); + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.Property("Id") @@ -1068,6 +1088,13 @@ namespace Ombi.Store.Migrations .HasForeignKey("UserId"); }); + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index cd96848fb..04546abf9 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -66,3 +66,22 @@ export interface IMassEmailModel { body: string; users: IUser[]; } + +export interface INotificationPreferences { + id: number; + userId: string; + agent: INotificationAgent; + enabled: boolean; + value: string; +} + +export enum INotificationAgent { + Email = 0, + Discord = 1, + Pushbullet = 2, + Pushover = 3, + Telegram = 4, + Slack = 5, + Mattermost = 6, + Mobile = 7, +} diff --git a/src/Ombi/ClientApp/app/services/identity.service.ts b/src/Ombi/ClientApp/app/services/identity.service.ts index e3dc1d8ad..bce159ebe 100644 --- a/src/Ombi/ClientApp/app/services/identity.service.ts +++ b/src/Ombi/ClientApp/app/services/identity.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { ICheckbox, ICreateWizardUser, IIdentityResult, IResetPasswordToken, IUpdateLocalUser, IUser, IWizardUserResult } from "../interfaces"; +import { ICheckbox, ICreateWizardUser, IIdentityResult, INotificationPreferences, IResetPasswordToken, IUpdateLocalUser, IUser, IWizardUserResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() @@ -43,6 +43,11 @@ export class IdentityService extends ServiceHelpers { public updateUser(user: IUser): Observable { return this.http.put(this.url, JSON.stringify(user), {headers: this.headers}); } + + public updateNotificationPreferences(pref: INotificationPreferences[]): Observable { + return this.http.post(`${this.url}NotificationPreferences`, JSON.stringify(pref), {headers: this.headers}); + } + public updateLocalUser(user: IUpdateLocalUser): Observable { return this.http.put(this.url + "local", JSON.stringify(user), {headers: this.headers}); } @@ -67,6 +72,13 @@ export class IdentityService extends ServiceHelpers { return this.http.post(`${this.url}welcomeEmail`, JSON.stringify(user), {headers: this.headers}); } + public getNotificationPreferences(): Observable { + return this.http.get(`${this.url}notificationpreferences`, {headers: this.headers}); + } + public getNotificationPreferencesForUser(userId: string): Observable { + return this.http.get(`${this.url}notificationpreferences/${userId}`, {headers: this.headers}); + } + public hasRole(role: string): boolean { const roles = localStorage.getItem("roles") as string[] | null; if (roles) { diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 0dcb24cb4..da1b4076e 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -1,153 +1,150 @@ -
-

Create User

+

Create User

+

User: {{user.userName}}

+
- - -
- -
-
-

User: {{user.userName}}

- - - - - - -
+
+ +
- - + +
diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index bca4f1058..e06c7c12b 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { ICheckbox, IUser, UserType } from "../interfaces"; +import { ICheckbox, INotificationAgent, INotificationPreferences, IUser, UserType } from "../interfaces"; import { IdentityService, NotificationService } from "../services"; import { ConfirmationService } from "primeng/primeng"; @@ -15,7 +15,9 @@ export class UserManagementUserComponent implements OnInit { public userId: string; public availableClaims: ICheckbox[]; public confirmPass: ""; - + public notificationPreferences: INotificationPreferences[]; + + public NotificationAgent = INotificationAgent; public edit: boolean; constructor(private identityService: IdentityService, @@ -38,6 +40,11 @@ export class UserManagementUserComponent implements OnInit { public ngOnInit() { this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); + if(this.edit) { + this.identityService.getNotificationPreferencesForUser(this.userId).subscribe(x => this.notificationPreferences = x); + } else { + this.identityService.getNotificationPreferences().subscribe(x => this.notificationPreferences = x); + } if(!this.edit) { this.user = { alias: "", @@ -142,6 +149,7 @@ export class UserManagementUserComponent implements OnInit { this.identityService.updateUser(this.user).subscribe(x => { if (x.successful) { + this.identityService.updateNotificationPreferences(this.notificationPreferences).subscribe(); this.notificationService.success(`The user ${this.user.userName} has been updated successfully`); this.router.navigate(["usermanagement"]); } else { diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index 81101978e..f12476677 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -21,6 +21,7 @@ import { AddPlexUserComponent } from "./addplexuser.component"; const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "user", component: UserManagementUserComponent, canActivate: [AuthGuard] }, + { path: "user/:id", component: UserManagementUserComponent, canActivate: [AuthGuard] }, { path: "updatedetails", component: UpdateDetailsComponent, canActivate: [AuthGuard] }, ]; @@ -40,8 +41,6 @@ const routes: Routes = [ ], declarations: [ UserManagementComponent, - UserManagementAddComponent, - UserManagementEditComponent, UpdateDetailsComponent, AddPlexUserComponent, UserManagementUserComponent, diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 71cac7a76..9e89a9506 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -125,7 +125,7 @@ namespace Ombi.Controllers if (users.Any(x => !x.UserName.Equals("api", StringComparison.InvariantCultureIgnoreCase))) { // No one should be calling this. Only the wizard - return new SaveWizardResult{ Result = false, Errors = new List {"Looks like there is an existing user!"} }; + return new SaveWizardResult { Result = false, Errors = new List { "Looks like there is an existing user!" } }; } if (user.UsePlexAdminAccount) @@ -562,7 +562,7 @@ namespace Ombi.Controllers // 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); @@ -588,9 +588,9 @@ namespace Ombi.Controllers { await _issueCommentsRepository.DeleteRange(issueComments); } - + // Delete the Subscriptions and mobile notification ids - var subs = _requestSubscriptionRepository.GetAll().Where(x => x.UserId == userId); + var subs = _requestSubscriptionRepository.GetAll().Where(x => x.UserId == userId); var mobileIds = _notificationRepository.GetAll().Where(x => x.UserId == userId); if (subs.Any()) { @@ -794,9 +794,26 @@ namespace Ombi.Controllers public async Task> GetUserPreferences() { var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + return await GetPreferences(user); + } + + [HttpGet("notificationpreferences/{userId}")] + public async Task> GetUserPreferences(string userId) + { + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == userId); + return await GetPreferences(user); + } + + private readonly List _excludedAgents = new List + { + NotificationAgent.Email, + NotificationAgent.Mobile + }; + private async Task> GetPreferences(OmbiUser user) + { var userPreferences = await _userNotificationPreferences.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); - var agents = Enum.GetValues(typeof(NotificationAgent)).Cast(); + var agents = Enum.GetValues(typeof(NotificationAgent)).Cast().Where(x => !_excludedAgents.Contains(x)); foreach (var a in agents) { var agent = userPreferences.FirstOrDefault(x => x.Agent == a); @@ -806,55 +823,56 @@ namespace Ombi.Controllers userPreferences.Add(new UserNotificationPreferences { Agent = a, + UserId = user.Id, }); } - else - { - userPreferences.Add(agent); - } } return userPreferences; } [HttpPost("NotificationPreferences")] - public async Task AddUserNotificationPreference([FromBody] AddNotificationPreference pref) + public async Task AddUserNotificationPreference([FromBody] List preferences) { - // Make sure the user exists - var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == pref.UserId); - if (user == null) + foreach (var pref in preferences) { - return NotFound(); - } - // Check if we are editing a different user than ourself, if we are then we need to power user role - var me = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); - if (!me.Id.Equals(user.Id, StringComparison.InvariantCultureIgnoreCase)) - { - var isPowerUser = await UserManager.IsInRoleAsync(me, OmbiRoles.PowerUser); - var isAdmin = await UserManager.IsInRoleAsync(me, OmbiRoles.Admin); - if (!isPowerUser && !isAdmin) + + // Make sure the user exists + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == pref.UserId); + if (user == null) { - return Unauthorized(); + return NotFound(); + } + // Check if we are editing a different user than ourself, if we are then we need to power user role + var me = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + if (!me.Id.Equals(user.Id, StringComparison.InvariantCultureIgnoreCase)) + { + var isPowerUser = await UserManager.IsInRoleAsync(me, OmbiRoles.PowerUser); + var isAdmin = await UserManager.IsInRoleAsync(me, OmbiRoles.Admin); + if (!isPowerUser && !isAdmin) + { + return Unauthorized(); + } } - } - // Make sure we don't already have a preference for this agent - var existingPreference = await _userNotificationPreferences.GetAll() - .FirstOrDefaultAsync(x => x.UserId == user.Id && x.Agent == pref.Agent); - if (existingPreference != null) - { - // Update it - existingPreference.Value = pref.Value; - existingPreference.Enabled = pref.Enabled; - } - await _userNotificationPreferences.Add(new UserNotificationPreferences - { - Agent = pref.Agent, - Enabled = pref.Enabled, - UserId = pref.UserId, - Value = pref.Value - }); + // Make sure we don't already have a preference for this agent + var existingPreference = await _userNotificationPreferences.GetAll() + .FirstOrDefaultAsync(x => x.UserId == user.Id && x.Agent == pref.Agent); + if (existingPreference != null) + { + // Update it + existingPreference.Value = pref.Value; + existingPreference.Enabled = pref.Enabled; + } + await _userNotificationPreferences.Add(new UserNotificationPreferences + { + Agent = pref.Agent, + Enabled = pref.Enabled, + UserId = pref.UserId, + Value = pref.Value + }); + } return Json(true); } From dbabb43537f767b4751e58f2bf12bf97043ee3aa Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:42:37 +0100 Subject: [PATCH 6/7] Added the music request limits --- src/Ombi.Core/Models/UI/UserViewModel.cs | 1 + src/Ombi/ClientApp/app/interfaces/IUser.ts | 1 + .../usermanagement-user.component.html | 17 ++++++++++++----- src/Ombi/Controllers/IdentityController.cs | 16 ++++++++++++++-- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Ombi.Core/Models/UI/UserViewModel.cs b/src/Ombi.Core/Models/UI/UserViewModel.cs index 1c1e6162b..62b296009 100644 --- a/src/Ombi.Core/Models/UI/UserViewModel.cs +++ b/src/Ombi.Core/Models/UI/UserViewModel.cs @@ -16,6 +16,7 @@ namespace Ombi.Core.Models.UI public UserType UserType { get; set; } public int MovieRequestLimit { get; set; } public int EpisodeRequestLimit { get; set; } + public int MusicRequestLimit { get; set; } } public class ClaimCheckboxes diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index 04546abf9..6cd1bc1d7 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -12,6 +12,7 @@ export interface IUser { hasLoggedIn: boolean; movieRequestLimit: number; episodeRequestLimit: number; + musicRequestLimit: number; userAccessToken: string; // FOR UI checked: boolean; diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index da1b4076e..f7bf702a0 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -102,12 +102,19 @@
- -
- + +
+ +
-
+
+ +
+ +
+
diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 9e89a9506..2acc1637f 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -61,7 +61,8 @@ namespace Ombi.Controllers IRepository notificationRepository, IRepository subscriptionRepository, ISettingsService umSettings, - IRepository notificationPreferences) + IRepository notificationPreferences, + IMusicRequestRepository musicRepo) { UserManager = user; Mapper = mapper; @@ -71,6 +72,7 @@ namespace Ombi.Controllers CustomizationSettings = c; WelcomeEmail = welcome; MovieRepo = m; + MusicRepo = musicRepo; TvRepo = t; _log = l; _plexApi = plexApi; @@ -96,6 +98,7 @@ namespace Ombi.Controllers private IWelcomeEmail WelcomeEmail { get; } private IMovieRequestRepository MovieRepo { get; } private ITvRequestRepository TvRepo { get; } + private IMusicRequestRepository MusicRepo { get; } private readonly ILogger _log; private readonly IPlexApi _plexApi; private readonly ISettingsService _plexSettings; @@ -295,7 +298,8 @@ namespace Ombi.Controllers LastLoggedIn = user.LastLoggedIn, HasLoggedIn = user.LastLoggedIn.HasValue, EpisodeRequestLimit = user.EpisodeRequestLimit ?? 0, - MovieRequestLimit = user.MovieRequestLimit ?? 0 + MovieRequestLimit = user.MovieRequestLimit ?? 0, + MusicRequestLimit = user.MusicRequestLimit ?? 0, }; foreach (var role in userRoles) @@ -347,6 +351,7 @@ namespace Ombi.Controllers UserType = UserType.LocalUser, MovieRequestLimit = user.MovieRequestLimit, EpisodeRequestLimit = user.EpisodeRequestLimit, + MusicRequestLimit = user.MusicRequestLimit, UserAccessToken = Guid.NewGuid().ToString("N"), }; var userResult = await UserManager.CreateAsync(ombiUser, user.Password); @@ -490,6 +495,7 @@ namespace Ombi.Controllers user.Email = ui.EmailAddress; user.MovieRequestLimit = ui.MovieRequestLimit; user.EpisodeRequestLimit = ui.EpisodeRequestLimit; + user.MusicRequestLimit = ui.MusicRequestLimit; var updateResult = await UserManager.UpdateAsync(user); if (!updateResult.Succeeded) { @@ -562,6 +568,7 @@ namespace Ombi.Controllers // 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); + var musicRequested = MusicRepo.GetAll().Where(x => x.RequestedUserId == userId); if (moviesUserRequested.Any()) { @@ -572,6 +579,11 @@ namespace Ombi.Controllers await TvRepo.DeleteChildRange(tvUserRequested); } + if (musicRequested.Any()) + { + await MusicRepo.DeleteRange(musicRequested); + } + // Delete any issues and request logs var issues = _issuesRepository.GetAll().Where(x => x.UserReportedId == userId); var issueComments = _issueCommentsRepository.GetAll().Where(x => x.UserId == userId); From 61a06905782a0d7a1be4a970d89fd342370f548c Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:43:55 +0100 Subject: [PATCH 7/7] !fixed lint --- .../app/usermanagement/usermanagement-user.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index e06c7c12b..fc79e0201 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -60,6 +60,7 @@ export class UserManagementUserComponent implements OnInit { episodeRequestLimit: 0, movieRequestLimit: 0, userAccessToken: "", + musicRequestLimit: 0, }; } }