Implimented the features #218

pull/733/head
tidusjar 8 years ago
parent 4cf01fb9c4
commit 00cd6969e0

@ -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<LogSettings> log, IPlexApi plexApi, ISettingsService<PlexSettings> plexService, IPlexUserRepository plexusers,
ISettingsService<PlexRequestSettings> prSettings, ISettingsService<UserManagementSettings> umSettings, ISettingsService<ScheduledJobsSettings> sjs)
public Version1100(IUserRepository userRepo, IRequestService requestService, ISettingsService<LogSettings> log, IPlexApi plexApi, ISettingsService<PlexSettings> plexService,
IPlexUserRepository plexusers, ISettingsService<PlexRequestSettings> prSettings, ISettingsService<UserManagementSettings> umSettings,
ISettingsService<ScheduledJobsSettings> sjs, IRepository<UsersToNotify> 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> PlexRequestSettings { get; }
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
private ISettingsService<ScheduledJobsSettings> ScheduledJobSettings { get; }
private IRepository<UsersToNotify> 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();

@ -147,9 +147,12 @@
<Compile Include="StatusChecker\AppveyorBranchResult.cs" />
<Compile Include="TvSender.cs" />
<Compile Include="TvSenderOld.cs" />
<Compile Include="Users\IUserHelper.cs" />
<Compile Include="Users\UserHelper.cs" />
<Compile Include="UserIdentity.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UserMapper.cs" />
<Compile Include="Users\UserHelperModel.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />

@ -0,0 +1,12 @@
using System.Collections.Generic;
using PlexRequests.Helpers.Permissions;
namespace PlexRequests.Core.Users
{
public interface IUserHelper
{
IEnumerable<UserHelperModel> GetUsers();
IEnumerable<UserHelperModel> GetUsersWithPermission(Permissions permission);
IEnumerable<UserHelperModel> GetUsersWithFeature(Features feature);
}
}

@ -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<UserHelperModel> GetUsers()
{
var model = new List<UserHelperModel>();
var localUsers = LocalUserRepository.GetAll();
var plexUsers = PlexUserRepository.GetAll();
foreach (var user in localUsers)
{
var props = ByteConverterHelper.ReturnObject<UserProperties>(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<UserHelperModel> GetUsersWithPermission(Permissions permission)
{
var model = new List<UserHelperModel>();
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<UserProperties>(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<UserHelperModel> GetUsersWithFeatures(Features features)
{
var model = new List<UserHelperModel>();
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<UserProperties>(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;
}
}
}

@ -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; }
}
}

@ -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,
}
}

@ -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> plexSettings,
ISettingsService<EmailNotificationSettings> email, IJobRecord rec,
ISettingsService<NewletterSettings> newsletter,
IPlexReadOnlyDatabase db)
ISettingsService<NewletterSettings> 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<NewletterSettings> 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("</table><br/><br/>");
}
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())

@ -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<UsersToNotify> repo, INotificationService service)
public NotificationEngine(IPlexApi p, IRepository<UsersToNotify> repo, INotificationService service, IUserHelper userHelper)
{
PlexApi = p;
UserNotifyRepo = repo;
Notification = service;
UserHelper = userHelper;
}
private IPlexApi PlexApi { get; }
private IRepository<UsersToNotify> UserNotifyRepo { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
private INotificationService Notification { get; }
private IUserHelper UserHelper { get; }
public async Task NotifyUsers(IEnumerable<RequestedModel> 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);

@ -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");

@ -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<Response> 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<Response> 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;

@ -111,33 +111,6 @@
</div>
}
<!-- Notification tab -->
<div role="tabpanel" class="tab-pane" id="NotificationsTab">
<div class="input-group">
<div class="input-group-addon input-group-sm"></div>
</div>
<br />
<!-- Notifications content -->
<form class="form-horizontal" method="POST" id="notificationsForm">
<fieldset>
<div class="form-group">
<div class="checkbox">
<input type="checkbox" id="notifyUser" name="Notify">
<label for="notifyUser">@UI.Search_SendNotificationText</label>
</div>
</div>
<div class="form-group">
<div>
<button id="saveNotificationSettings" class="btn btn-primary-outline">@UI.Common_Save</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<!-- Movie and TV Results template -->
<script id="search-template" type="text/x-handlebars-template">
<div class="row">

Loading…
Cancel
Save