mirror of
https://github.com/sphildreth/roadie
synced 2025-02-16 13:08:25 +00:00
password reset
This commit is contained in:
parent
74d0aa591e
commit
b09aa752a6
6 changed files with 148 additions and 8 deletions
64
Roadie.Api.Services/EmailSenderService.cs
Normal file
64
Roadie.Api.Services/EmailSenderService.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using Mapster;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Extensions;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Collections;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Statistics;
|
||||
using Roadie.Library.Models.Users;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
using data = Roadie.Library.Data;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
{
|
||||
public class EmailSenderService : IEmailSender
|
||||
{
|
||||
protected IRoadieSettings Configuration { get;}
|
||||
|
||||
public EmailSenderService(IRoadieSettings configuration)
|
||||
{
|
||||
this.Configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task SendEmailAsync(string email, string subject, string htmlMessage)
|
||||
{
|
||||
using (MailMessage mail = new MailMessage(this.Configuration.SmtpFromAddress, email))
|
||||
{
|
||||
using (SmtpClient client = new SmtpClient())
|
||||
{
|
||||
client.Port = this.Configuration.SmtpPort;
|
||||
client.EnableSsl = this.Configuration.SmtpUseSSl;
|
||||
client.DeliveryMethod = SmtpDeliveryMethod.Network;
|
||||
client.UseDefaultCredentials = false;
|
||||
client.Credentials = new NetworkCredential(this.Configuration.SmtpUsername, this.Configuration.SmtpPassword);
|
||||
client.Host = this.Configuration.SmtpHost;
|
||||
mail.Subject = subject;
|
||||
mail.IsBodyHtml = true;
|
||||
mail.Body = htmlMessage;
|
||||
ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
await client.SendMailAsync(mail);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,4 +17,10 @@
|
|||
<ProjectReference Include="..\Roadie.Api.Library\Roadie.Api.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Identity.UI">
|
||||
<HintPath>..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.identity.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -12,6 +14,7 @@ using System;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Api.Controllers
|
||||
|
@ -30,6 +33,7 @@ namespace Roadie.Api.Controllers
|
|||
private IRoadieSettings RoadieSettings { get; }
|
||||
private ICacheManager CacheManager { get; }
|
||||
private IAdminService AdminService { get; }
|
||||
private IEmailSender EmailSender { get; }
|
||||
|
||||
public AccountController(
|
||||
IAdminService adminService,
|
||||
|
@ -38,7 +42,8 @@ namespace Roadie.Api.Controllers
|
|||
IConfiguration configuration,
|
||||
ILogger<AccountController> logger,
|
||||
ITokenService tokenService,
|
||||
ICacheManager cacheManager)
|
||||
ICacheManager cacheManager,
|
||||
IEmailSender emailSender)
|
||||
{
|
||||
this.UserManager = userManager;
|
||||
this.SignInManager = signInManager;
|
||||
|
@ -50,6 +55,7 @@ namespace Roadie.Api.Controllers
|
|||
this.RoadieSettings = new RoadieSettings();
|
||||
configuration.GetSection("RoadieSettings").Bind(this.RoadieSettings);
|
||||
this.AdminService = adminService;
|
||||
this.EmailSender = emailSender;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
@ -74,6 +80,12 @@ namespace Roadie.Api.Controllers
|
|||
await UserManager.UpdateAsync(user);
|
||||
var t = await this.TokenService.GenerateToken(user, this.UserManager);
|
||||
this.Logger.LogInformation($"Successfully authenticated User [{ model.Username}]");
|
||||
if(!user.EmailConfirmed)
|
||||
{
|
||||
var code = await this.UserManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, Request.Scheme);
|
||||
await this.EmailSender.SendEmailAsync(user.Email, $"Confirm your { this.RoadieSettings.SiteName } email", $"Please confirm your { this.RoadieSettings.SiteName } account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
||||
}
|
||||
this.CacheManager.ClearRegion(EntityControllerBase.ControllerCacheRegionUrn);
|
||||
var avatarUrl = $"{this.Request.Scheme}://{this.Request.Host}/images/user/{ user.RoadieId }/{ this.RoadieSettings.ThumbnailImageSize.Width }/{ this.RoadieSettings.ThumbnailImageSize.Height }";
|
||||
return Ok(new
|
||||
|
@ -138,6 +150,10 @@ namespace Roadie.Api.Controllers
|
|||
{
|
||||
await this.AdminService.DoInitialSetup(user, this.UserManager);
|
||||
}
|
||||
var code = await this.UserManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, Request.Scheme);
|
||||
await this.EmailSender.SendEmailAsync(user.Email, $"Confirm your { this.RoadieSettings.SiteName } email", $"Please confirm your { this.RoadieSettings.SiteName } account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
||||
|
||||
await SignInManager.SignInAsync(user, isPersistent: false);
|
||||
var t = await this.TokenService.GenerateToken(user, this.UserManager);
|
||||
this.Logger.LogInformation($"Successfully created and authenticated User [{ registerModel.Username}]");
|
||||
|
@ -162,7 +178,34 @@ namespace Roadie.Api.Controllers
|
|||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[HttpGet("confirmemail")]
|
||||
public IActionResult ConfirmEmail(string userid, string code)
|
||||
{
|
||||
var user = this.UserManager.FindByIdAsync(userid).Result;
|
||||
IdentityResult result = this.UserManager.ConfirmEmailAsync(user, code).Result;
|
||||
if (result.Succeeded)
|
||||
{
|
||||
this.Logger.LogInformation("User [{0}] Confirmed Email Successfully", userid);
|
||||
return Content($"Email for { this.RoadieSettings.SiteName } account confirmed successfully!");
|
||||
}
|
||||
else
|
||||
{
|
||||
return Content("Error while confirming your email!");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("sendpasswordresetemail")]
|
||||
public async Task<IActionResult> SendPasswordResetEmail(string username, string callbackUrl)
|
||||
{
|
||||
var user = await UserManager.FindByNameAsync(username);
|
||||
var token = await this.UserManager.GeneratePasswordResetTokenAsync(user);
|
||||
callbackUrl = callbackUrl + "?username=" + username + "&token=" + token;
|
||||
await this.EmailSender.SendEmailAsync(user.Email, $"Reset your { this.RoadieSettings.SiteName } password", $"A request has been made to reset your password for your { this.RoadieSettings.SiteName } account. To proceed <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>click here</a>.");
|
||||
this.Logger.LogInformation("User [{0}] Email [{1}] Requested Password Reset Callback [{2}]", username, user.Email, callbackUrl);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost("resetpassword")]
|
||||
public async Task<IActionResult> ResetPassword([FromBody] ResetPasswordModel resetPasswordModel)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
|
@ -179,7 +222,18 @@ namespace Roadie.Api.Controllers
|
|||
{
|
||||
this.CacheManager.ClearRegion(EntityControllerBase.ControllerCacheRegionUrn);
|
||||
await SignInManager.SignInAsync(user, isPersistent: false);
|
||||
return Ok(this.TokenService.GenerateToken(user, this.UserManager));
|
||||
var avatarUrl = $"{this.Request.Scheme}://{this.Request.Host}/images/user/{ user.RoadieId }/{ this.RoadieSettings.ThumbnailImageSize.Width }/{ this.RoadieSettings.ThumbnailImageSize.Height }";
|
||||
var t = await this.TokenService.GenerateToken(user, this.UserManager);
|
||||
return Ok(new
|
||||
{
|
||||
Username = user.UserName,
|
||||
user.Email,
|
||||
user.LastLogin,
|
||||
avatarUrl,
|
||||
Token = t,
|
||||
user.Timeformat,
|
||||
user.Timezone
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -13,10 +13,11 @@ by editing this MSBuild file. In order to learn more about this please visit htt
|
|||
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
|
||||
<ExcludeApp_Data>False</ExcludeApp_Data>
|
||||
<ProjectGuid>68c80416-0d72-409d-b727-3fea7ab7fd2c</ProjectGuid>
|
||||
<publishUrl>bin\x64\Debug\netcoreapp2.1\publish\</publishUrl>
|
||||
<publishUrl>bin\x64\Debug\netcoreapp2.2\publish\</publishUrl>
|
||||
<DeleteExistingFiles>False</DeleteExistingFiles>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<SelfContained>false</SelfContained>
|
||||
<_IsPortable>true</_IsPortable>
|
||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
|
@ -23,6 +24,7 @@ using Roadie.Library.Identity;
|
|||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Roadie.Api
|
||||
{
|
||||
|
@ -88,8 +90,8 @@ namespace Roadie.Api
|
|||
}));
|
||||
|
||||
services.AddSingleton<ITokenService, TokenService>();
|
||||
|
||||
services.AddSingleton<IHttpEncoder, HttpEncoder>();
|
||||
services.AddSingleton<IEmailSender, EmailSenderService>();
|
||||
|
||||
var cacheManager = new DictionaryCacheManager(this._loggerFactory.CreateLogger<DictionaryCacheManager>(), new CachePolicy(TimeSpan.FromHours(4)));
|
||||
services.AddSingleton<ICacheManager>(cacheManager);
|
||||
|
@ -112,7 +114,8 @@ namespace Roadie.Api
|
|||
|
||||
services.AddIdentity<ApplicationUser, ApplicationRole>()
|
||||
.AddRoles<ApplicationRole>()
|
||||
.AddEntityFrameworkStores<ApplicationUserDbContext>();
|
||||
.AddEntityFrameworkStores<ApplicationUserDbContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
|
@ -134,7 +137,13 @@ namespace Roadie.Api
|
|||
var integrationKeys = this._configuration.GetSection("IntegrationKeys")
|
||||
.Get<IntegrationKey>();
|
||||
|
||||
settings.Integrations.ApiKeys = new System.Collections.Generic.List<ApiKey>
|
||||
if(integrationKeys == null)
|
||||
{
|
||||
Console.WriteLine("Unable to find IntegrationKeys, Integrations will not have proper API keys setup.");
|
||||
}
|
||||
else if (integrationKeys != null)
|
||||
{
|
||||
settings.Integrations.ApiKeys = new System.Collections.Generic.List<ApiKey>
|
||||
{
|
||||
new ApiKey
|
||||
{
|
||||
|
@ -154,6 +163,7 @@ namespace Roadie.Api
|
|||
Key = integrationKeys.BingImageSearch
|
||||
}
|
||||
};
|
||||
}
|
||||
return settings;
|
||||
});
|
||||
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
|
||||
|
|
|
@ -82,6 +82,11 @@
|
|||
"OGGConvertCommand": "ffmpeg -i \"{0}\" -acodec libmp3lame -q:a 0 \"{1}\"\"",
|
||||
"APEConvertCommand": "ffmpeg -i \"{0}\" \"{1}\""
|
||||
},
|
||||
"SmtpFromAddress": "roadie@hildreth.email",
|
||||
"SmtpPort": 587,
|
||||
"SmtpUsername": "roadie@hildreth.email",
|
||||
"SmtpHost": "box.hildreth.email",
|
||||
"SmtpUseSSl": true,
|
||||
"Integrations": {
|
||||
"ITunesProviderEnabled": true,
|
||||
"MusicBrainzProviderEnabled": true,
|
||||
|
|
Loading…
Add table
Reference in a new issue