From 00cd6969e07ed92d9806262a607761a4d232379a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 20 Nov 2016 19:50:33 +0000 Subject: [PATCH] Implimented the features #218 --- .../Migrations/Version1100.cs | 34 +++- PlexRequests.Core/PlexRequests.Core.csproj | 3 + PlexRequests.Core/Users/IUserHelper.cs | 12 ++ PlexRequests.Core/Users/UserHelper.cs | 159 ++++++++++++++++++ PlexRequests.Core/Users/UserHelperModel.cs | 42 +++++ PlexRequests.Helpers/Permissions/Features.cs | 4 +- PlexRequests.Services/Jobs/RecentlyAdded.cs | 25 ++- .../Notification/NotificationEngine.cs | 14 +- PlexRequests.UI/Content/search.js | 41 ----- PlexRequests.UI/Modules/SearchModule.cs | 66 +------- PlexRequests.UI/Views/Search/Index.cshtml | 27 --- 11 files changed, 277 insertions(+), 150 deletions(-) create mode 100644 PlexRequests.Core/Users/IUserHelper.cs create mode 100644 PlexRequests.Core/Users/UserHelper.cs create mode 100644 PlexRequests.Core/Users/UserHelperModel.cs diff --git a/PlexRequests.Core.Migration/Migrations/Version1100.cs b/PlexRequests.Core.Migration/Migrations/Version1100.cs index 351ef723d..7797212be 100644 --- a/PlexRequests.Core.Migration/Migrations/Version1100.cs +++ b/PlexRequests.Core.Migration/Migrations/Version1100.cs @@ -32,6 +32,7 @@ using NLog; using System.Linq; using PlexRequests.Api.Interfaces; using PlexRequests.Core.SettingModels; +using PlexRequests.Core.Users; using PlexRequests.Helpers; using PlexRequests.Helpers.Permissions; using PlexRequests.Store; @@ -43,8 +44,9 @@ namespace PlexRequests.Core.Migration.Migrations [Migration(11000, "v1.10.0.0")] public class Version1100 : BaseMigration, IMigration { - public Version1100(IUserRepository userRepo, IRequestService requestService, ISettingsService log, IPlexApi plexApi, ISettingsService plexService, IPlexUserRepository plexusers, - ISettingsService prSettings, ISettingsService umSettings, ISettingsService sjs) + public Version1100(IUserRepository userRepo, IRequestService requestService, ISettingsService log, IPlexApi plexApi, ISettingsService plexService, + IPlexUserRepository plexusers, ISettingsService prSettings, ISettingsService umSettings, + ISettingsService sjs, IRepository usersToNotify) { UserRepo = userRepo; RequestService = requestService; @@ -55,6 +57,7 @@ namespace PlexRequests.Core.Migration.Migrations PlexRequestSettings = prSettings; UserManagementSettings = umSettings; ScheduledJobSettings = sjs; + UserNotifyRepo = usersToNotify; } public int Version => 11000; private IUserRepository UserRepo { get; } @@ -66,6 +69,7 @@ namespace PlexRequests.Core.Migration.Migrations private ISettingsService PlexRequestSettings { get; } private ISettingsService UserManagementSettings { get; } private ISettingsService ScheduledJobSettings { get; } + private IRepository UserNotifyRepo { get; } public void Start(IDbConnection con) { @@ -77,10 +81,36 @@ namespace PlexRequests.Core.Migration.Migrations UpdatePlexUsers(); PopulateDefaultUserManagementSettings(); UpdateScheduledJobs(); + MigrateUserNotifications(); UpdateSchema(con, Version); } + private void MigrateUserNotifications() + { + var usersToNotify = UserNotifyRepo.GetAll(); + var plexUsers = PlexUsers.GetAll().ToList(); + var users = UserRepo.GetAll().ToList(); + foreach (var u in usersToNotify) + { + var selectedPlexUser = plexUsers.FirstOrDefault(x => x.Username.Equals(u.Username, StringComparison.CurrentCultureIgnoreCase)); + if (selectedPlexUser != null) + { + selectedPlexUser.Features += (int)Features.RequestAddedNotification; + PlexUsers.Update(selectedPlexUser); + } + + var selectedLocalUser = + users.FirstOrDefault(x => x.UserName.Equals(u.Username, StringComparison.CurrentCultureIgnoreCase)); + if (selectedLocalUser != null) + { + selectedLocalUser.Features += (int) Features.RequestAddedNotification; + UserRepo.Update(selectedLocalUser); + } + + } + } + private void UpdateScheduledJobs() { var settings = ScheduledJobSettings.GetSettings(); diff --git a/PlexRequests.Core/PlexRequests.Core.csproj b/PlexRequests.Core/PlexRequests.Core.csproj index 75e2fb804..3753a4109 100644 --- a/PlexRequests.Core/PlexRequests.Core.csproj +++ b/PlexRequests.Core/PlexRequests.Core.csproj @@ -147,9 +147,12 @@ + + + diff --git a/PlexRequests.Core/Users/IUserHelper.cs b/PlexRequests.Core/Users/IUserHelper.cs new file mode 100644 index 000000000..492574d47 --- /dev/null +++ b/PlexRequests.Core/Users/IUserHelper.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using PlexRequests.Helpers.Permissions; + +namespace PlexRequests.Core.Users +{ + public interface IUserHelper + { + IEnumerable GetUsers(); + IEnumerable GetUsersWithPermission(Permissions permission); + IEnumerable GetUsersWithFeature(Features feature); + } +} \ No newline at end of file diff --git a/PlexRequests.Core/Users/UserHelper.cs b/PlexRequests.Core/Users/UserHelper.cs new file mode 100644 index 000000000..c42751a4d --- /dev/null +++ b/PlexRequests.Core/Users/UserHelper.cs @@ -0,0 +1,159 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: UserHelper.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System.Collections.Generic; +using System.Linq; +using PlexRequests.Core.Models; +using PlexRequests.Helpers; +using PlexRequests.Helpers.Permissions; +using PlexRequests.Store.Repository; + +namespace PlexRequests.Core.Users +{ + public class UserHelper : IUserHelper + { + public UserHelper(IUserRepository userRepository, IPlexUserRepository plexUsers, ISecurityExtensions security) + { + LocalUserRepository = userRepository; + PlexUserRepository = plexUsers; + Security = security; + } + + private IUserRepository LocalUserRepository { get; } + private IPlexUserRepository PlexUserRepository { get; } + private ISecurityExtensions Security { get; } + + + public IEnumerable GetUsers() + { + var model = new List(); + + var localUsers = LocalUserRepository.GetAll(); + var plexUsers = PlexUserRepository.GetAll(); + + foreach (var user in localUsers) + { + var props = ByteConverterHelper.ReturnObject(user.UserProperties); + model.Add(new UserHelperModel + { + Type = UserType.LocalUser, + Username = user.UserName, + UserAlias = props.UserAlias, + EmailAddress = props.EmailAddress, + Permissions = (Permissions)user.Permissions + }); + } + + model.AddRange(plexUsers.Select(user => new UserHelperModel + { + Type = UserType.LocalUser, + Username = user.Username, + UserAlias = user.UserAlias, + EmailAddress = user.EmailAddress, + Permissions = (Permissions)user.Permissions + })); + + return model; + } + + public IEnumerable GetUsersWithPermission(Permissions permission) + { + var model = new List(); + + var localUsers = LocalUserRepository.GetAll().ToList(); + var plexUsers = PlexUserRepository.GetAll().ToList(); + + var filteredLocal = localUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission)); + var filteredPlex = plexUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission)); + + + foreach (var user in filteredLocal) + { + var props = ByteConverterHelper.ReturnObject(user.UserProperties); + model.Add(new UserHelperModel + { + Type = UserType.LocalUser, + Username = user.UserName, + UserAlias = props.UserAlias, + EmailAddress = props.EmailAddress, + Permissions = (Permissions)user.Permissions, + Features = (Features)user.Features + }); + } + + model.AddRange(filteredPlex.Select(user => new UserHelperModel + { + Type = UserType.LocalUser, + Username = user.Username, + UserAlias = user.UserAlias, + EmailAddress = user.EmailAddress, + Permissions = (Permissions)user.Permissions, + Features = (Features)user.Features + })); + + return model; + } + + public IEnumerable GetUsersWithFeatures(Features features) + { + var model = new List(); + + var localUsers = LocalUserRepository.GetAll().ToList(); + var plexUsers = PlexUserRepository.GetAll().ToList(); + + var filteredLocal = localUsers.Where(x => ((Features)x.Features).HasFlag(features)); + var filteredPlex = plexUsers.Where(x => ((Features)x.Features).HasFlag(features)); + + + foreach (var user in filteredLocal) + { + var props = ByteConverterHelper.ReturnObject(user.UserProperties); + model.Add(new UserHelperModel + { + Type = UserType.LocalUser, + Username = user.UserName, + UserAlias = props.UserAlias, + EmailAddress = props.EmailAddress, + Permissions = (Permissions)user.Permissions, + Features = (Features)user.Features + }); + } + + model.AddRange(filteredPlex.Select(user => new UserHelperModel + { + Type = UserType.LocalUser, + Username = user.Username, + UserAlias = user.UserAlias, + EmailAddress = user.EmailAddress, + Permissions = (Permissions)user.Permissions, + Features = (Features)user.Features + })); + + return model; + } + } +} \ No newline at end of file diff --git a/PlexRequests.Core/Users/UserHelperModel.cs b/PlexRequests.Core/Users/UserHelperModel.cs new file mode 100644 index 000000000..5d66fc066 --- /dev/null +++ b/PlexRequests.Core/Users/UserHelperModel.cs @@ -0,0 +1,42 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: UserHelperModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using PlexRequests.Helpers; +using PlexRequests.Helpers.Permissions; + +namespace PlexRequests.Core.Users +{ + public class UserHelperModel + { + public string Username { get; set; } + public string UserAlias { get; set; } + public Permissions Permissions { get; set; } + public Features Features { get; set; } + public string EmailAddress { get; set; } + public UserType Type { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.Helpers/Permissions/Features.cs b/PlexRequests.Helpers/Permissions/Features.cs index a236a8d15..24a945ee3 100644 --- a/PlexRequests.Helpers/Permissions/Features.cs +++ b/PlexRequests.Helpers/Permissions/Features.cs @@ -35,8 +35,8 @@ namespace PlexRequests.Helpers.Permissions { [Display(Name = "Newsletter")] Newsletter = 1, - [Display(Name = "Recently Added Notification")] - RecentlyAddedNotification = 2, + [Display(Name = "Request Added Notification")] + RequestAddedNotification = 2, } } \ No newline at end of file diff --git a/PlexRequests.Services/Jobs/RecentlyAdded.cs b/PlexRequests.Services/Jobs/RecentlyAdded.cs index fb1d22c1b..8db8c4084 100644 --- a/PlexRequests.Services/Jobs/RecentlyAdded.cs +++ b/PlexRequests.Services/Jobs/RecentlyAdded.cs @@ -39,7 +39,9 @@ using PlexRequests.Api.Interfaces; using PlexRequests.Api.Models.Plex; using PlexRequests.Core; using PlexRequests.Core.SettingModels; +using PlexRequests.Core.Users; using PlexRequests.Helpers; +using PlexRequests.Helpers.Permissions; using PlexRequests.Services.Interfaces; using PlexRequests.Services.Jobs.Templates; using PlexRequests.Store.Models.Plex; @@ -52,8 +54,8 @@ namespace PlexRequests.Services.Jobs { public RecentlyAdded(IPlexApi api, ISettingsService plexSettings, ISettingsService email, IJobRecord rec, - ISettingsService newsletter, - IPlexReadOnlyDatabase db) + ISettingsService newsletter, + IPlexReadOnlyDatabase db, IUserHelper userHelper) { JobRecord = rec; Api = api; @@ -61,6 +63,7 @@ namespace PlexRequests.Services.Jobs EmailSettings = email; NewsletterSettings = newsletter; PlexDb = db; + UserHelper = userHelper; } private IPlexApi Api { get; } @@ -73,6 +76,7 @@ namespace PlexRequests.Services.Jobs private ISettingsService NewsletterSettings { get; } private IJobRecord JobRecord { get; } private IPlexReadOnlyDatabase PlexDb { get; } + private IUserHelper UserHelper { get; } private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -177,7 +181,7 @@ namespace PlexRequests.Services.Jobs } sb.Append("

"); } - + private void GenerateTvHtml(RecentlyAddedModel tv, PlexSettings plexSettings, StringBuilder sb) { // TV @@ -255,18 +259,21 @@ namespace PlexRequests.Services.Jobs if (!testEmail) { - if (newletterSettings.SendToPlexUsers) + //if (newletterSettings.SendToPlexUsers) + //{ + + var users = UserHelper.GetUsersWithFeature(Features.RequestAddedNotification); + if (users != null) { - var users = Api.GetUsers(plexSettings.PlexAuthToken); - if (users != null) + foreach (var user in users) { - foreach (var user in users.User) + if (!string.IsNullOrEmpty(user.EmailAddress)) { - if (user.Email != null) - message.Bcc.Add(new MailboxAddress(user.Username, user.Email)); + message.Bcc.Add(new MailboxAddress(user.Username, user.EmailAddress)); } } } + //} if (newletterSettings.CustomUsersEmailAddresses != null && newletterSettings.CustomUsersEmailAddresses.Any()) diff --git a/PlexRequests.Services/Notification/NotificationEngine.cs b/PlexRequests.Services/Notification/NotificationEngine.cs index f0ba5bec5..c849e378e 100644 --- a/PlexRequests.Services/Notification/NotificationEngine.cs +++ b/PlexRequests.Services/Notification/NotificationEngine.cs @@ -34,6 +34,8 @@ using NLog.Fluent; using PlexRequests.Api; using PlexRequests.Api.Interfaces; using PlexRequests.Core.Models; +using PlexRequests.Core.Users; +using PlexRequests.Helpers.Permissions; using PlexRequests.Services.Interfaces; using PlexRequests.Store; using PlexRequests.Store.Models; @@ -43,17 +45,19 @@ namespace PlexRequests.Services.Notification { public class NotificationEngine : INotificationEngine { - public NotificationEngine(IPlexApi p, IRepository repo, INotificationService service) + public NotificationEngine(IPlexApi p, IRepository repo, INotificationService service, IUserHelper userHelper) { PlexApi = p; UserNotifyRepo = repo; Notification = service; + UserHelper = userHelper; } private IPlexApi PlexApi { get; } private IRepository UserNotifyRepo { get; } private static Logger Log = LogManager.GetCurrentClassLogger(); private INotificationService Notification { get; } + private IUserHelper UserHelper { get; } public async Task NotifyUsers(IEnumerable modelChanged, string apiKey, NotificationType type) { @@ -63,8 +67,8 @@ namespace PlexRequests.Services.Notification var userAccount = PlexApi.GetAccount(apiKey); var adminUsername = userAccount.Username ?? string.Empty; - - var users = UserNotifyRepo.GetAll().ToList(); + + var users = UserHelper.GetUsersWithFeature(Features.RequestAddedNotification).ToList(); Log.Debug("Notifying Users Count {0}", users.Count); foreach (var model in modelChanged) { @@ -80,7 +84,7 @@ namespace PlexRequests.Services.Notification } var email = plexUser.User.FirstOrDefault(x => x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase)); - if (email == null) + if (string.IsNullOrEmpty(email?.Email)) { Log.Info("There is no email address for this Plex user, cannot send notification"); // We do not have a plex user that requested this! @@ -107,7 +111,7 @@ namespace PlexRequests.Services.Notification var adminUsername = userAccount.Username ?? string.Empty; - var users = UserNotifyRepo.GetAll().ToList(); + var users = UserHelper.GetUsersWithFeature(Features.RequestAddedNotification).ToList(); Log.Debug("Notifying Users Count {0}", users.Count); var selectedUsers = users.Select(x => x.Username).Intersect(model.RequestedUsers, StringComparer.CurrentCultureIgnoreCase); diff --git a/PlexRequests.UI/Content/search.js b/PlexRequests.UI/Content/search.js index e6772061f..d05f3b4e6 100644 --- a/PlexRequests.UI/Content/search.js +++ b/PlexRequests.UI/Content/search.js @@ -51,21 +51,6 @@ $(function () { }); focusSearch($('li.active a', '#nav-tabs').first().attr('href')); - // Get the user notification setting - var url = createBaseUrl(base, '/search/notifyuser/'); - $.ajax({ - type: "get", - url: url, - dataType: "json", - success: function (response) { - $('#notifyUser').prop("checked", response); - }, - error: function (e) { - console.log(e); - generateNotify("Something went wrong!", "danger"); - } - }); - // Type in movie search $("#movieSearchContent").on("input", function () { if (searchTimer) { @@ -184,32 +169,6 @@ $(function () { sendRequestAjax(data, type, url, buttonId); }); - // Enable/Disable user notifications - $('#saveNotificationSettings') - .click(function (e) { - e.preventDefault(); - var url = createBaseUrl(base, '/search/notifyuser/'); - var checked = $('#notifyUser').prop('checked'); - $.ajax({ - type: "post", - url: url, - data: { notify: checked }, - dataType: "json", - success: function (response) { - console.log(response); - if (response.result === true) { - generateNotify(response.message || "Success!", "success"); - } else { - generateNotify(response.message, "warning"); - } - }, - error: function (e) { - console.log(e); - generateNotify("Something went wrong!", "danger"); - } - }); - }); - // Report Issue $(document).on("click", ".dropdownIssue", function (e) { var issue = $(this).attr("issue-select"); diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index 01ac48e64..3e1ef1d9d 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -132,10 +132,7 @@ namespace PlexRequests.UI.Modules async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons); Post["request/tvEpisodes", true] = async (x, ct) => await RequestTvShow(0, "episode"); Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId); - - Post["/notifyuser", true] = async (x, ct) => await NotifyUser((bool)Request.Form.notify); - Get["/notifyuser", true] = async (x, ct) => await GetUserNotificationSettings(); - + Get["/seasons"] = x => GetSeasons(); Get["/episodes", true] = async (x, ct) => await GetEpisodes(); } @@ -1146,66 +1143,7 @@ namespace PlexRequests.UI.Modules return img; } - - private async Task NotifyUser(bool notify) - { - Analytics.TrackEventAsync(Category.Search, Action.Save, "NotifyUser", Username, CookieHelper.GetAnalyticClientId(Cookies), notify ? 1 : 0); - var authSettings = await Auth.GetSettingsAsync(); - var auth = authSettings.UserAuthentication; - var emailSettings = await EmailNotificationSettings.GetSettingsAsync(); - var email = emailSettings.EnableUserEmailNotifications; - if (!auth) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_ErrorPlexAccountOnly }); - } - if (!email) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_ErrorNotEnabled }); - } - var username = Username; - var originalList = await UsersToNotifyRepo.GetAllAsync(); - if (!notify) - { - if (originalList == null) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_NotificationError }); - } - var userToRemove = originalList.FirstOrDefault(x => x.Username == username); - if (userToRemove != null) - { - await UsersToNotifyRepo.DeleteAsync(userToRemove); - } - return Response.AsJson(new JsonResponseModel { Result = true }); - } - - - if (originalList == null) - { - var userModel = new UsersToNotify { Username = username }; - var insertResult = await UsersToNotifyRepo.InsertAsync(userModel); - return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = Resources.UI.Common_CouldNotSave }); - } - - var existingUser = originalList.FirstOrDefault(x => x.Username == username); - if (existingUser != null) - { - return Response.AsJson(new JsonResponseModel { Result = true }); // It's already enabled - } - else - { - var userModel = new UsersToNotify { Username = username }; - var insertResult = await UsersToNotifyRepo.InsertAsync(userModel); - return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = Resources.UI.Common_CouldNotSave }); - } - - } - private async Task GetUserNotificationSettings() - { - var all = await UsersToNotifyRepo.GetAllAsync(); - var retVal = all.FirstOrDefault(x => x.Username == Username); - return Response.AsJson(retVal != null); - } - + private Response GetSeasons() { var seriesId = (int)Request.Query.tvId; diff --git a/PlexRequests.UI/Views/Search/Index.cshtml b/PlexRequests.UI/Views/Search/Index.cshtml index 6ea284a4e..64446a264 100644 --- a/PlexRequests.UI/Views/Search/Index.cshtml +++ b/PlexRequests.UI/Views/Search/Index.cshtml @@ -111,33 +111,6 @@ } - -
-
-
-
-
- - -
-
-
-
- - -
-
-
-
- -
-
-
-
-
- - -