refactoring email verification
This commit is contained in:
parent
0aed11e71c
commit
ee682516c3
|
@ -50,15 +50,24 @@
|
||||||
public string Password = "";
|
public string Password = "";
|
||||||
public bool Remember = false;
|
public bool Remember = false;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
if (PageState.QueryString.ContainsKey("returnurl"))
|
if (PageState.QueryString.ContainsKey("returnurl"))
|
||||||
{
|
{
|
||||||
ReturnUrl = PageState.QueryString["returnurl"];
|
ReturnUrl = PageState.QueryString["returnurl"];
|
||||||
}
|
}
|
||||||
if (PageState.QueryString.ContainsKey("verified"))
|
if (PageState.QueryString.ContainsKey("name"))
|
||||||
{
|
{
|
||||||
if (PageState.QueryString["verified"] == "1")
|
Username = PageState.QueryString["name"];
|
||||||
|
}
|
||||||
|
if (PageState.QueryString.ContainsKey("token"))
|
||||||
|
{
|
||||||
|
User user = new User();
|
||||||
|
user.SiteId = PageState.Site.SiteId;
|
||||||
|
user.Username = Username;
|
||||||
|
user = await UserService.VerifyEmailAsync(user, PageState.QueryString["token"]);
|
||||||
|
|
||||||
|
if (user != null)
|
||||||
{
|
{
|
||||||
Message = "User Account Verified Successfully. You Can Now Login With Your Username And Password Below.";
|
Message = "User Account Verified Successfully. You Can Now Login With Your Username And Password Below.";
|
||||||
}
|
}
|
||||||
|
@ -141,7 +150,7 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Message = "Please Enter The Username Related To Your Account And Then Click The Forgot Password Option";
|
Message = "Please Enter The Username Related To Your Account And Then Select The Forgot Password Option Again";
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
User user = new User();
|
User user = new User();
|
||||||
user.SiteId = PageState.Site.SiteId;
|
user.SiteId = PageState.Site.SiteId;
|
||||||
user.Username = Username;
|
user.Username = Username;
|
||||||
user.DisplayName = Username;
|
|
||||||
user.Password = Password;
|
user.Password = Password;
|
||||||
user = await UserService.ResetPasswordAsync(user, PageState.QueryString["token"]);
|
user = await UserService.ResetPasswordAsync(user, PageState.QueryString["token"]);
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,7 @@ else
|
||||||
string modifiedby;
|
string modifiedby;
|
||||||
DateTime modifiedon;
|
DateTime modifiedon;
|
||||||
|
|
||||||
protected override async Task
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
await logger.LogError(ex, "An Error Occurred Loading Html/Text Content. " + ex.Message);
|
||||||
AddModuleMessage(ex.Message, MessageType.Error);
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace Oqtane.Services
|
||||||
|
|
||||||
Task LogoutUserAsync(User User);
|
Task LogoutUserAsync(User User);
|
||||||
|
|
||||||
|
Task<User> VerifyEmailAsync(User User, string Token);
|
||||||
|
|
||||||
Task ForgotPasswordAsync(User User);
|
Task ForgotPasswordAsync(User User);
|
||||||
|
|
||||||
Task<User> ResetPasswordAsync(User User, string Token);
|
Task<User> ResetPasswordAsync(User User, string Token);
|
||||||
|
|
|
@ -87,6 +87,11 @@ namespace Oqtane.Services
|
||||||
await http.PostJsonAsync(apiurl + "/logout", User);
|
await http.PostJsonAsync(apiurl + "/logout", User);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<User> VerifyEmailAsync(User User, string Token)
|
||||||
|
{
|
||||||
|
return await http.PostJsonAsync<User>(apiurl + "/verify?token=" + Token, User);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task ForgotPasswordAsync(User User)
|
public async Task ForgotPasswordAsync(User User)
|
||||||
{
|
{
|
||||||
await http.PostJsonAsync(apiurl + "/forgot", User);
|
await http.PostJsonAsync(apiurl + "/forgot", User);
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/5?userid=x
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public Folder Get(int id)
|
public Folder Get(int id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -108,8 +108,7 @@ namespace Oqtane.Controllers
|
||||||
notification.ToEmail = "";
|
notification.ToEmail = "";
|
||||||
notification.Subject = "User Account Verification";
|
notification.Subject = "User Account Verification";
|
||||||
string token = await IdentityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
string token = await IdentityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||||
string alias = Tenants.GetAlias().Path;
|
string url = HttpContext.Request.Scheme + "://" + Tenants.GetAlias().Name + "/login?name=" + User.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||||
string url = HttpContext.Request.Scheme + "://" + HttpContext.Request.Host + "/pages/verify?name=" + User.Username + "&token=" + WebUtility.UrlEncode(token) + "&returnurl=" + (alias == "" ? "/" : alias);
|
|
||||||
notification.Body = "Dear " + User.DisplayName + ",\n\nIn Order To Complete The Registration Of Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!";
|
notification.Body = "Dear " + User.DisplayName + ",\n\nIn Order To Complete The Registration Of Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!";
|
||||||
notification.ParentId = null;
|
notification.ParentId = null;
|
||||||
notification.CreatedOn = DateTime.Now;
|
notification.CreatedOn = DateTime.Now;
|
||||||
|
@ -254,6 +253,35 @@ namespace Oqtane.Controllers
|
||||||
logger.Log(LogLevel.Information, this, LogFunction.Security, "User Logout {Username}", User.Username);
|
logger.Log(LogLevel.Information, this, LogFunction.Security, "User Logout {Username}", User.Username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST api/<controller>/verify
|
||||||
|
[HttpPost("verify")]
|
||||||
|
public async Task<User> Verify([FromBody] User User, string token)
|
||||||
|
{
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
IdentityUser identityuser = await IdentityUserManager.FindByNameAsync(User.Username);
|
||||||
|
if (identityuser != null)
|
||||||
|
{
|
||||||
|
var result = await IdentityUserManager.ConfirmEmailAsync(identityuser, token);
|
||||||
|
if (result.Succeeded)
|
||||||
|
{
|
||||||
|
logger.Log(LogLevel.Information, this, LogFunction.Security, "Email Verified For {Username}", User.Username);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Log(LogLevel.Error, this, LogFunction.Security, "Email Verification Failed For {Username}", User.Username);
|
||||||
|
User = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Log(LogLevel.Error, this, LogFunction.Security, "Email Verification Failed For {Username}", User.Username);
|
||||||
|
User = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return User;
|
||||||
|
}
|
||||||
|
|
||||||
// POST api/<controller>/forgot
|
// POST api/<controller>/forgot
|
||||||
[HttpPost("forgot")]
|
[HttpPost("forgot")]
|
||||||
public async Task Forgot([FromBody] User User)
|
public async Task Forgot([FromBody] User User)
|
||||||
|
@ -290,7 +318,6 @@ namespace Oqtane.Controllers
|
||||||
[HttpPost("reset")]
|
[HttpPost("reset")]
|
||||||
public async Task<User> Reset([FromBody] User User, string token)
|
public async Task<User> Reset([FromBody] User User, string token)
|
||||||
{
|
{
|
||||||
User user = null;
|
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
IdentityUser identityuser = await IdentityUserManager.FindByNameAsync(User.Username);
|
IdentityUser identityuser = await IdentityUserManager.FindByNameAsync(User.Username);
|
||||||
|
@ -299,21 +326,22 @@ namespace Oqtane.Controllers
|
||||||
var result = await IdentityUserManager.ResetPasswordAsync(identityuser, token, User.Password);
|
var result = await IdentityUserManager.ResetPasswordAsync(identityuser, token, User.Password);
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
user = User;
|
|
||||||
user.Password = "";
|
|
||||||
logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset For {Username}", User.Username);
|
logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset For {Username}", User.Username);
|
||||||
|
User.Password = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Log(LogLevel.Error, this, LogFunction.Security, "Password Reset Failed For {Username}", User.Username);
|
logger.Log(LogLevel.Error, this, LogFunction.Security, "Password Reset Failed For {Username}", User.Username);
|
||||||
|
User = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Log(LogLevel.Error, this, LogFunction.Security, "Password Reset Failed For {Username}", User.Username);
|
logger.Log(LogLevel.Error, this, LogFunction.Security, "Password Reset Failed For {Username}", User.Username);
|
||||||
|
User = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return user;
|
return User;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/current
|
// GET api/<controller>/current
|
||||||
|
|
|
@ -37,6 +37,10 @@ namespace Oqtane.Pages
|
||||||
await IdentitySignInManager.SignInAsync(identityuser, remember);
|
await IdentitySignInManager.SignInAsync(identityuser, remember);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (returnurl == null)
|
||||||
|
{
|
||||||
|
returnurl = "";
|
||||||
|
}
|
||||||
if (!returnurl.StartsWith("/"))
|
if (!returnurl.StartsWith("/"))
|
||||||
{
|
{
|
||||||
returnurl = "/" + returnurl;
|
returnurl = "/" + returnurl;
|
||||||
|
|
|
@ -14,6 +14,10 @@ namespace Oqtane.Pages
|
||||||
{
|
{
|
||||||
await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme);
|
await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme);
|
||||||
|
|
||||||
|
if (returnurl == null)
|
||||||
|
{
|
||||||
|
returnurl = "";
|
||||||
|
}
|
||||||
if (!returnurl.StartsWith("/"))
|
if (!returnurl.StartsWith("/"))
|
||||||
{
|
{
|
||||||
returnurl = "/" + returnurl;
|
returnurl = "/" + returnurl;
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
@page "/pages/verify"
|
|
||||||
@namespace Oqtane.Pages
|
|
||||||
@model Oqtane.Pages.VerifyModel
|
|
|
@ -1,42 +0,0 @@
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Oqtane.Models;
|
|
||||||
using Oqtane.Repository;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Oqtane.Pages
|
|
||||||
{
|
|
||||||
[AllowAnonymous]
|
|
||||||
public class VerifyModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly IUserRepository Users;
|
|
||||||
private readonly UserManager<IdentityUser> IdentityUserManager;
|
|
||||||
|
|
||||||
public VerifyModel(IUserRepository Users, UserManager<IdentityUser> IdentityUserManager)
|
|
||||||
{
|
|
||||||
this.Users = Users;
|
|
||||||
this.IdentityUserManager = IdentityUserManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGet(string name, string token, string returnurl)
|
|
||||||
{
|
|
||||||
int verified = 0;
|
|
||||||
IdentityUser identityuser = await IdentityUserManager.FindByNameAsync(name);
|
|
||||||
if (identityuser != null)
|
|
||||||
{
|
|
||||||
var result = await IdentityUserManager.ConfirmEmailAsync(identityuser, token);
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
verified = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!returnurl.StartsWith("/"))
|
|
||||||
{
|
|
||||||
returnurl += "/" + returnurl;
|
|
||||||
}
|
|
||||||
return Redirect(HttpContext.Request.Scheme + "://" + HttpContext.Request.Host + returnurl + "login?verified=" + verified.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,6 +19,7 @@ namespace Oqtane.Repository
|
||||||
public virtual DbSet<Log> Log { get; set; }
|
public virtual DbSet<Log> Log { get; set; }
|
||||||
public virtual DbSet<Notification> Notification { get; set; }
|
public virtual DbSet<Notification> Notification { get; set; }
|
||||||
public virtual DbSet<Folder> Folder { get; set; }
|
public virtual DbSet<Folder> Folder { get; set; }
|
||||||
|
public virtual DbSet<File> File { get; set; }
|
||||||
|
|
||||||
public TenantDBContext(ITenantResolver TenantResolver, IHttpContextAccessor accessor) : base(TenantResolver, accessor)
|
public TenantDBContext(ITenantResolver TenantResolver, IHttpContextAccessor accessor) : base(TenantResolver, accessor)
|
||||||
{
|
{
|
||||||
|
|
62
Oqtane.Server/Repository/FileRepository.cs
Normal file
62
Oqtane.Server/Repository/FileRepository.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Oqtane.Models;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository
|
||||||
|
{
|
||||||
|
public class FileRepository : IFileRepository
|
||||||
|
{
|
||||||
|
private TenantDBContext db;
|
||||||
|
private readonly IPermissionRepository Permissions;
|
||||||
|
|
||||||
|
public FileRepository(TenantDBContext context, IPermissionRepository Permissions)
|
||||||
|
{
|
||||||
|
db = context;
|
||||||
|
this.Permissions = Permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<File> GetFiles(int FolderId)
|
||||||
|
{
|
||||||
|
IEnumerable<Permission> permissions = Permissions.GetPermissions("Folder", FolderId);
|
||||||
|
IEnumerable<File> files = db.File.Where(item => item.FolderId == FolderId);
|
||||||
|
foreach (File file in files)
|
||||||
|
{
|
||||||
|
file.Folder.Permissions = Permissions.EncodePermissions(FolderId, permissions);
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File AddFile(File File)
|
||||||
|
{
|
||||||
|
db.File.Add(File);
|
||||||
|
db.SaveChanges();
|
||||||
|
return File;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File UpdateFile(File File)
|
||||||
|
{
|
||||||
|
db.Entry(File).State = EntityState.Modified;
|
||||||
|
db.SaveChanges();
|
||||||
|
return File;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File GetFile(int FileId)
|
||||||
|
{
|
||||||
|
File file = db.File.Find(FileId);
|
||||||
|
if (file != null)
|
||||||
|
{
|
||||||
|
IEnumerable<Permission> permissions = Permissions.GetPermissions("Folder", file.FolderId);
|
||||||
|
file.Folder.Permissions = Permissions.EncodePermissions(file.FolderId, permissions);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteFile(int FileId)
|
||||||
|
{
|
||||||
|
File File = db.File.Find(FileId);
|
||||||
|
db.File.Remove(File);
|
||||||
|
db.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
Oqtane.Server/Repository/Interfaces/IFileRepository.cs
Normal file
14
Oqtane.Server/Repository/Interfaces/IFileRepository.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Models;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository
|
||||||
|
{
|
||||||
|
public interface IFileRepository
|
||||||
|
{
|
||||||
|
IEnumerable<File> GetFiles(int FolderId);
|
||||||
|
File AddFile(File File);
|
||||||
|
File UpdateFile(File File);
|
||||||
|
File GetFile(int FileId);
|
||||||
|
void DeleteFile(int FileId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -275,6 +275,24 @@ CREATE TABLE [dbo].[Folder](
|
||||||
)
|
)
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
CREATE TABLE [dbo].[File](
|
||||||
|
[FileId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
|
[FolderId] [int] NOT NULL,
|
||||||
|
[Name] [nvarchar](50) NOT NULL,
|
||||||
|
[CreatedBy] [nvarchar](256) NOT NULL,
|
||||||
|
[CreatedOn] [datetime] NOT NULL,
|
||||||
|
[ModifiedBy] [nvarchar](256) NOT NULL,
|
||||||
|
[ModifiedOn] [datetime] NOT NULL,
|
||||||
|
[DeletedBy] [nvarchar](256) NULL,
|
||||||
|
[DeletedOn] [datetime] NULL,
|
||||||
|
[IsDeleted][bit] NOT NULL,
|
||||||
|
CONSTRAINT [PK_File] PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[FileId] ASC
|
||||||
|
)
|
||||||
|
)
|
||||||
|
GO
|
||||||
|
|
||||||
CREATE TABLE [dbo].[HtmlText](
|
CREATE TABLE [dbo].[HtmlText](
|
||||||
[HtmlTextId] [int] IDENTITY(1,1) NOT NULL,
|
[HtmlTextId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
[ModuleId] [int] NOT NULL,
|
[ModuleId] [int] NOT NULL,
|
||||||
|
@ -361,6 +379,11 @@ REFERENCES [dbo].[Site] ([SiteId])
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
ALTER TABLE [dbo].[File] WITH CHECK ADD CONSTRAINT [FK_File_Folder] FOREIGN KEY([FolderId])
|
||||||
|
REFERENCES [dbo].[Folder] ([FolderId])
|
||||||
|
ON DELETE CASCADE
|
||||||
|
GO
|
||||||
|
|
||||||
ALTER TABLE [dbo].[HtmlText] WITH CHECK ADD CONSTRAINT [FK_HtmlText_Module] FOREIGN KEY([ModuleId])
|
ALTER TABLE [dbo].[HtmlText] WITH CHECK ADD CONSTRAINT [FK_HtmlText_Module] FOREIGN KEY([ModuleId])
|
||||||
REFERENCES [dbo].[Module] ([ModuleId])
|
REFERENCES [dbo].[Module] ([ModuleId])
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
|
|
21
Oqtane.Shared/Models/File.cs
Normal file
21
Oqtane.Shared/Models/File.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Oqtane.Models
|
||||||
|
{
|
||||||
|
public class File : IAuditable
|
||||||
|
{
|
||||||
|
public int FileId { get; set; }
|
||||||
|
public int FolderId { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string CreatedBy { get; set; }
|
||||||
|
public DateTime CreatedOn { get; set; }
|
||||||
|
public string ModifiedBy { get; set; }
|
||||||
|
public DateTime ModifiedOn { get; set; }
|
||||||
|
public string DeletedBy { get; set; }
|
||||||
|
public DateTime? DeletedOn { get; set; }
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
|
||||||
|
public Folder Folder { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user