#189 self delete: phase 1: sending verification email

This commit is contained in:
Hamid Reza Mohammadi 2021-08-16 21:03:24 +04:30
parent ab17c0ce95
commit 6b43bf485d
9 changed files with 267 additions and 201 deletions

View File

@ -4,6 +4,14 @@ using RSecurityBackend.Services;
using RSecurityBackend.Controllers;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authorization;
using System.Net;
using System.Threading.Tasks;
using System;
using System.Linq;
using RSecurityBackend.Models.Generic;
using RSecurityBackend.Models.Auth.ViewModels;
using RSecurityBackend.Models.Auth.Db;
namespace RMuseum.Controllers
{
@ -29,5 +37,39 @@ namespace RMuseum.Controllers
{
}
/// <summary>
/// start user self delete process (send a verification email to user)
/// </summary>
/// <param name="viewModel"></param>
/// <returns></returns>
[HttpPost("selfdelete/start")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public virtual async Task<IActionResult> StartLeaving(SelfDeleteViewModel viewModel)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
Guid sessionId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value);
string clientIPAddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
var verifyRes = (await _appUserService.StartLeaving(loggedOnUserId, sessionId, clientIPAddress)).Result;
var user = (await _appUserService.GetUserInformation(loggedOnUserId)).Result;
try
{
await _emailSender.SendEmailAsync
(
user.Email,
_appUserService.GetEmailSubject(RVerifyQueueType.UserSelfDelete, verifyRes.Secret),
_appUserService.GetEmailHtmlContent(RVerifyQueueType.UserSelfDelete, verifyRes.Secret, viewModel.CallbackUrl)
);
return Ok();
}
catch (Exception exp)
{
return BadRequest("Error sending email: " + exp.ToString());
}
}
}
}

View File

@ -21,6 +21,13 @@
<param name="imageFileService"></param>
<param name="captchaService"></param>
</member>
<member name="M:RMuseum.Controllers.AppUserController.StartLeaving(RSecurityBackend.Models.Auth.ViewModels.SelfDeleteViewModel)">
<summary>
start user self delete process (send a verification email to user)
</summary>
<param name="viewModel"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.ArtifactController.Get(RSecurityBackend.Models.Generic.PagingParameterModel)">
<summary>
get all published artifacts (including CoverImage info but not items info)
@ -8991,40 +8998,25 @@
IMemoryCache
</summary>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorAppUserService.GetSignUpEmailSubject(System.String)">
<member name="M:RMuseum.Services.Implementation.GanjoorAppUserService.GetEmailSubject(RSecurityBackend.Models.Auth.Db.RVerifyQueueType,System.String)">
<summary>
Sign Up Email Subject
</summary>
<returns>
subject
</returns>
<param name="op"></param>
<param name="secretCode"></param>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorAppUserService.GetSignUpEmailHtmlContent(System.String,System.String)">
<member name="M:RMuseum.Services.Implementation.GanjoorAppUserService.GetEmailHtmlContent(RSecurityBackend.Models.Auth.Db.RVerifyQueueType,System.String,System.String)">
<summary>
Sign Up Email Html Content
</summary>
<param name="op"></param>
<param name="secretCode"></param>
<param name="signupCallbackUrl"></param>
<returns>html content</returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorAppUserService.GetForgotPasswordEmailSubject(System.String)">
<summary>
Forgot Password Email Subject
</summary>
<returns>
subject
</returns>
<param name="secretCode"></param>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorAppUserService.GetForgotPasswordEmailHtmlContent(System.String,System.String)">
<summary>
Forgot Password Email Html Content
</summary>
<param name="secretCode"></param>
<param name="forgotPasswordCallbackUrl"></param>
<returns>html content</returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorAppUserService.FinalizeSignUp(System.String,System.String,System.String,System.String,System.String)">
<summary>
finalize signup and assign his or him comments to him or her

View File

@ -48,20 +48,29 @@ namespace RMuseum.Services.Implementation
/// <returns>
/// subject
/// </returns>
/// <param name="op"></param>
/// <param name="secretCode"></param>
public override string GetSignUpEmailSubject(string secretCode)
public override string GetEmailSubject(RVerifyQueueType op, string secretCode)
{
return $"{secretCode} کد ثبت نام شما در گنجور";
string opString = op == RVerifyQueueType.SignUp ? "ثبت نام" : op == RVerifyQueueType.ForgotPassword ? "بازیابی کلمهٔ عبور" : "حذف کاربر";
return $"{secretCode} کد {opString} شما در گنجور";
}
/// <summary>
/// Sign Up Email Html Content
/// </summary>
/// <param name="op"></param>
/// <param name="secretCode"></param>
/// <param name="signupCallbackUrl"></param>
/// <returns>html content</returns>
public override string GetSignUpEmailHtmlContent(string secretCode, string signupCallbackUrl)
public override string GetEmailHtmlContent(RVerifyQueueType op, string secretCode, string signupCallbackUrl)
{
string opString = op == RVerifyQueueType.SignUp ? "ثبت نام" : op == RVerifyQueueType.ForgotPassword ? "بازیابی کلمهٔ عبور" : "حذف کاربر";
string ifNot = op == RVerifyQueueType.SignUp ? "اگر در گنجور ثبت نام نکرده‌اید لطفاً این نامه را نادیده بگیرید."
: op == RVerifyQueueType.ForgotPassword ?
"اگر در گنجور فراموشی گذرواژه را نزده‌اید یا گذرواژه‌تان را به خاطر آوردید لطفاً این نامه را نادیده بگیرید."
:
"";
string content =
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
+
@ -71,7 +80,7 @@ namespace RMuseum.Services.Implementation
+
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"
+
$"<title>کد ثبت نام شما در گنجور: {secretCode}</title>"
$"<title>کد {opString} شما در گنجور: {secretCode}</title>"
+
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>"
+
@ -95,16 +104,16 @@ namespace RMuseum.Services.Implementation
+
(
string.IsNullOrEmpty(signupCallbackUrl) ?
$"<p style=\"font:normal 12px tahoma;direction:rtl\">لطفاً جهت تکمیل ثبت نام در گنجور کد <strong>{secretCode}</strong> را به عنوان رمز دریافتی در صفحهٔ ثبت نام وارد کنید.</p>"
$"<p style=\"font:normal 12px tahoma;direction:rtl\">لطفاً جهت تکمیل {opString} در گنجور کد <strong>{secretCode}</strong> را به عنوان رمز دریافتی در صفحهٔ {opString} وارد کنید.</p>"
:
$"<p style=\"font:normal 12px tahoma;direction:rtl\">لطفاً جهت تکمیل ثبت نام در گنجور <a href=\"{signupCallbackUrl}?secret={secretCode}\">اینجا</a> کلیک کنید یا اگر صفحهٔ ثبت نام هنوز باز است کد <strong>{secretCode}</strong> را در آن وارد کنید.</p>"
$"<p style=\"font:normal 12px tahoma;direction:rtl\">لطفاً جهت تکمیل {opString} در گنجور <a href=\"{signupCallbackUrl}?secret={secretCode}\">اینجا</a> کلیک کنید یا اگر صفحهٔ {opString} هنوز باز است کد <strong>{secretCode}</strong> را در آن وارد کنید.</p>"
)
+
"</td></tr>"
+
"<tr><td>"
+
"<p style=\"font:normal 12px tahoma;direction:rtl\">اگر در گنجور ثبت نام نکرده‌اید لطفاً این نامه را نادیده بگیرید. به این نامه پاسخ ندهید، کسی پاسخگوی شما نخواهد بود.</p>"
$"<p style=\"font:normal 12px tahoma;direction:rtl\">{ifNot} به این نامه پاسخ ندهید، کسی پاسخگوی شما نخواهد بود.</p>"
+
"</td></tr>"
+
@ -118,82 +127,6 @@ namespace RMuseum.Services.Implementation
return content;
}
/// <summary>
/// Forgot Password Email Subject
/// </summary>
/// <returns>
/// subject
/// </returns>
/// <param name="secretCode"></param>
public override string GetForgotPasswordEmailSubject(string secretCode)
{
return $"{secretCode} کد بازیابی کلمهٔ عبور شما در گنجور";
}
/// <summary>
/// Forgot Password Email Html Content
/// </summary>
/// <param name="secretCode"></param>
/// <param name="forgotPasswordCallbackUrl"></param>
/// <returns>html content</returns>
public override string GetForgotPasswordEmailHtmlContent(string secretCode, string forgotPasswordCallbackUrl)
{
string content =
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
+
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"fa\">"
+
"<head>"
+
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"
+
$"<title>کد تغییر گذرواژهٔ شما در گنجور: {secretCode}</title>"
+
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>"
+
"</head>"
+
"<body style=\"font:normal 12px tahoma;direction:rtl\">"
+
"<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"600\">"
+
"<tr>"
+
"<td align=\"center\" style=\"padding: 40px 0 30px 0;\">"
+
"<img src=\"https://i.ganjoor.net/gm.gif\" alt=\"گنجور\" width=\"150\" height=\"150\" style=\"display: block;\" />"
+
"</td>"
+
"</tr>"
+
"<tr><td>"
+
(
string.IsNullOrEmpty(forgotPasswordCallbackUrl) ?
$"<p style=\"font:normal 12px tahoma;direction:rtl\">لطفاً جهت تکمیل فرایند فراموشی گذرواژه در گنجور کد <strong>{secretCode}</strong> را به عنوان رمز دریافتی در صفحهٔ بازیابی گذرواژه وارد کنید.</p>"
:
$"<p style=\"font:normal 12px tahoma;direction:rtl\">لطفاً جهت تکمیل فرایند فراموشی گذرواژه در گنجور <a href=\"{forgotPasswordCallbackUrl}?secret={secretCode}\">اینجا</a> کلیک کنید یا اگر صفحهٔ فراموشی گذرواژه هنوز باز است کد <strong>{secretCode}</strong> را در آن وارد کنید.</p>"
)
+
"</td></tr>"
+
"<tr><td>"
+
"<p style=\"font:normal 12px tahoma;direction:rtl\">اگر در گنجور فراموشی گذرواژه را نزده‌اید یا گذرواژه‌تان را به خاطر آوردید لطفاً این نامه را نادیده بگیرید. به این نامه پاسخ ندهید، کسی پاسخگوی شما نخواهد بود.</p>"
+
"</td></tr>"
+
"</table>"
+
"</body>"
+
"</html>"
;
return content;
}
/// <summary>
/// finalize signup and assign his or him comments to him or her
/// </summary>

View File

@ -414,7 +414,7 @@ namespace RSecurityBackend.Controllers
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public async Task<IActionResult> Delete(Guid id)
public virtual async Task<IActionResult> Delete(Guid id)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult<bool> isAdmin = await _appUserService.IsAdmin(loggedOnUserId);
@ -482,7 +482,6 @@ namespace RSecurityBackend.Controllers
return Ok(res.Result);
}
/// <summary>
/// View User Sessions (user needs user:sessions permission to view other users sessions)
/// </summary>
@ -854,8 +853,8 @@ namespace RSecurityBackend.Controllers
await _emailSender.SendEmailAsync
(
signUpViewModel.Email,
_appUserService.GetSignUpEmailSubject(res.Result.Secret),
_appUserService.GetSignUpEmailHtmlContent(res.Result.Secret, signUpViewModel.CallbackUrl)
_appUserService.GetEmailSubject(RVerifyQueueType.SignUp, res.Result.Secret),
_appUserService.GetEmailHtmlContent(RVerifyQueueType.SignUp, res.Result.Secret, signUpViewModel.CallbackUrl)
);
return Ok("verify");
}
@ -950,8 +949,8 @@ namespace RSecurityBackend.Controllers
await _emailSender.SendEmailAsync
(
fpwdViewModel.Email,
_appUserService.GetForgotPasswordEmailSubject(res.Result.Secret),
_appUserService.GetForgotPasswordEmailHtmlContent(res.Result.Secret, fpwdViewModel.CallbackUrl)
_appUserService.GetEmailSubject(RVerifyQueueType.ForgotPassword, res.Result.Secret),
_appUserService.GetEmailHtmlContent(RVerifyQueueType.ForgotPassword, res.Result.Secret, fpwdViewModel.CallbackUrl)
);
}
catch (Exception exp)

View File

@ -12,6 +12,10 @@
/// <summary>
/// Forgot Password by email
/// </summary>
ForgotPassword = 1
ForgotPassword = 1,
/// <summary>
/// delete user by himself/hersef
/// </summary>
UserSelfDelete = 2
}
}

View File

@ -0,0 +1,13 @@
namespace RSecurityBackend.Models.Auth.ViewModels
{
/// <summary>
/// User Self Delete View Model
/// </summary>
public class SelfDeleteViewModel
{
/// <summary>
///CallbackUrl
/// </summary>
public string CallbackUrl { get; set; }
}
}

View File

@ -1040,6 +1040,11 @@
Forgot Password by email
</summary>
</member>
<member name="F:RSecurityBackend.Models.Auth.Db.RVerifyQueueType.UserSelfDelete">
<summary>
delete user by himself/hersef
</summary>
</member>
<member name="T:RSecurityBackend.Models.Auth.Memory.SecurableItem">
<summary>
securable itmes: forms and ...
@ -1462,6 +1467,16 @@
Test!123
</example>
</member>
<member name="T:RSecurityBackend.Models.Auth.ViewModels.SelfDeleteViewModel">
<summary>
User Self Delete View Model
</summary>
</member>
<member name="P:RSecurityBackend.Models.Auth.ViewModels.SelfDeleteViewModel.CallbackUrl">
<summary>
CallbackUrl
</summary>
</member>
<member name="T:RSecurityBackend.Models.Auth.ViewModels.SetPasswordModel">
<summary>
set password model
@ -2330,6 +2345,15 @@
<param name="userId"></param>
<returns>true if succeeds</returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.StartLeaving(System.Guid,System.Guid,System.String)">
<summary>
start leaving
</summary>
<param name="userId"></param>
<param name="sessionId"></param>
<param name="clientIPAddress"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.SetUserImage(System.Guid,Microsoft.AspNetCore.Http.IFormFileCollection)">
<summary>
Set User Image
@ -2345,6 +2369,14 @@
<param name="userId">if null is passed returns all sessions</param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.GetUserSession(System.Guid,System.Guid)">
<summary>
Get User Session
</summary>
<param name="userId"></param>
<param name="sessionId"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.GetUserImage(System.Guid)">
<summary>
Get User Image
@ -2414,40 +2446,25 @@
<param name="email"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.GetSignUpEmailSubject(System.String)">
<member name="M:RSecurityBackend.Services.IAppUserService.GetEmailSubject(RSecurityBackend.Models.Auth.Db.RVerifyQueueType,System.String)">
<summary>
Sign Up Email Subject
Sign Up/forget passsword/delete Email Subject
</summary>
<returns>
subject
</returns>
<param name="op"></param>
<param name="secretCode"></param>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.GetSignUpEmailHtmlContent(System.String,System.String)">
<member name="M:RSecurityBackend.Services.IAppUserService.GetEmailHtmlContent(RSecurityBackend.Models.Auth.Db.RVerifyQueueType,System.String,System.String)">
<summary>
Sign Up Email Html Content
Sign Up/forget passsword/delete Email Html Content
</summary>
<param name="op"></param>
<param name="secretCode"></param>
<param name="signupCallbackUrl"></param>
<returns>html content</returns>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.GetForgotPasswordEmailSubject(System.String)">
<summary>
Forgot Password Email Subject
</summary>
<returns>
subject
</returns>
<param name="secretCode"></param>
</member>
<member name="M:RSecurityBackend.Services.IAppUserService.GetForgotPasswordEmailHtmlContent(System.String,System.String)">
<summary>
Forgot Password Email Html Content
</summary>
<param name="secretCode"></param>
<param name="forgotPasswordCallbackUrl"></param>
<returns>html content</returns>
</member>
<member name="P:RSecurityBackend.Services.IAppUserService.TokenSecret">
<summary>
secret used for generating Jwt token
@ -2686,6 +2703,14 @@
<param name="userId">if null is passed returns all sessions</param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.GetUserSession(System.Guid,System.Guid)">
<summary>
Get User Session
</summary>
<param name="userId"></param>
<param name="sessionId"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.IsAdmin(System.Guid)">
<summary>
is user admin?
@ -2778,6 +2803,15 @@
<param name="userId"></param>
<returns>true if succeeds</returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.StartLeaving(System.Guid,System.Guid,System.String)">
<summary>
start leaving
</summary>
<param name="userId"></param>
<param name="sessionId"></param>
<param name="clientIPAddress"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.SetUserImage(System.Guid,Microsoft.AspNetCore.Http.IFormFileCollection)">
<summary>
Set User Image
@ -2908,40 +2942,25 @@
<param name="errors"></param>
<returns></returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.GetSignUpEmailSubject(System.String)">
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.GetEmailSubject(RSecurityBackend.Models.Auth.Db.RVerifyQueueType,System.String)">
<summary>
Sign Up Email Subject
Sign Up/forget passsword/delete Email Subject
</summary>
<returns>
subject
</returns>
<param name="op"></param>
<param name="secretCode"></param>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.GetSignUpEmailHtmlContent(System.String,System.String)">
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.GetEmailHtmlContent(RSecurityBackend.Models.Auth.Db.RVerifyQueueType,System.String,System.String)">
<summary>
Sign Up Email Html Content
Sign Up/forget passsword/delete Email Html Content
</summary>
<param name="op"></param>
<param name="secretCode"></param>
<param name="signupCallbackUrl"></param>
<returns>html content</returns>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.GetForgotPasswordEmailSubject(System.String)">
<summary>
Forgot Password Email Subject
</summary>
<returns>
subject
</returns>
<param name="secretCode"></param>
</member>
<member name="M:RSecurityBackend.Services.Implementation.AppUserService.GetForgotPasswordEmailHtmlContent(System.String,System.String)">
<summary>
Forgot Password Email Html Content
</summary>
<param name="secretCode"></param>
<param name="forgotPasswordCallbackUrl"></param>
<returns>html content</returns>
</member>
<member name="F:RSecurityBackend.Services.Implementation.AppUserService._context">
<summary>
Main Database context

View File

@ -170,6 +170,15 @@ namespace RSecurityBackend.Services
/// <returns>true if succeeds</returns>
Task<RServiceResult<bool>> DeleteUser(Guid userId);
/// <summary>
/// start leaving
/// </summary>
/// <param name="userId"></param>
/// <param name="sessionId"></param>
/// <param name="clientIPAddress"></param>
/// <returns></returns>
Task<RServiceResult<RVerifyQueueItem>> StartLeaving(Guid userId, Guid sessionId, string clientIPAddress);
/// <summary>
/// Set User Image
/// </summary>
@ -186,6 +195,14 @@ namespace RSecurityBackend.Services
/// <returns></returns>
Task<RServiceResult<PublicRUserSession[]>> GetUserSessions(Guid? userId);
/// <summary>
/// Get User Session
/// </summary>
/// <param name="userId"></param>
/// <param name="sessionId"></param>
/// <returns></returns>
Task<RServiceResult<PublicRUserSession>> GetUserSession(Guid userId, Guid sessionId);
/// <summary>
/// Get User Image
/// </summary>
@ -257,38 +274,23 @@ namespace RSecurityBackend.Services
Task<RServiceResult<PublicRAppUser>> FindUserByEmail(string email);
/// <summary>
/// Sign Up Email Subject
/// Sign Up/forget passsword/delete Email Subject
/// </summary>
/// <returns>
/// subject
/// </returns>
/// <param name="op"></param>
/// <param name="secretCode"></param>
string GetSignUpEmailSubject(string secretCode);
string GetEmailSubject(RVerifyQueueType op, string secretCode);
/// <summary>
/// Sign Up Email Html Content
/// Sign Up/forget passsword/delete Email Html Content
/// </summary>
/// <param name="op"></param>
/// <param name="secretCode"></param>
/// <param name="signupCallbackUrl"></param>
/// <returns>html content</returns>
string GetSignUpEmailHtmlContent(string secretCode, string signupCallbackUrl);
/// <summary>
/// Forgot Password Email Subject
/// </summary>
/// <returns>
/// subject
/// </returns>
/// <param name="secretCode"></param>
string GetForgotPasswordEmailSubject(string secretCode);
/// <summary>
/// Forgot Password Email Html Content
/// </summary>
/// <param name="secretCode"></param>
/// <param name="forgotPasswordCallbackUrl"></param>
/// <returns>html content</returns>
string GetForgotPasswordEmailHtmlContent(string secretCode, string forgotPasswordCallbackUrl);
string GetEmailHtmlContent(RVerifyQueueType op, string secretCode, string signupCallbackUrl);
/// <summary>
/// secret used for generating Jwt token

View File

@ -410,6 +410,46 @@ namespace RSecurityBackend.Services.Implementation
}
/// <summary>
/// Get User Session
/// </summary>
/// <param name="userId"></param>
/// <param name="sessionId"></param>
/// <returns></returns>
public virtual async Task<RServiceResult<PublicRUserSession>> GetUserSession(Guid userId, Guid sessionId)
{
RTemporaryUserSession rUserSession =
await _context.Sessions.Where(s => s.RAppUserId == userId && s.Id == sessionId).SingleAsync();
return new RServiceResult<PublicRUserSession>
(
new PublicRUserSession()
{
Id = rUserSession.Id,
RAppUser = new PublicRAppUser()
{
Id = rUserSession.RAppUser.Id,
Username = rUserSession.RAppUser.UserName,
Email = rUserSession.RAppUser.Email,
FirstName = rUserSession.RAppUser.FirstName,
SureName = rUserSession.RAppUser.SureName,
PhoneNumber = rUserSession.RAppUser.PhoneNumber,
RImageId = rUserSession.RAppUser.RImageId,
Status = rUserSession.RAppUser.Status,
NickName = rUserSession.RAppUser.NickName,
Website = rUserSession.RAppUser.Website,
Bio = rUserSession.RAppUser.Bio,
EmailConfirmed = rUserSession.RAppUser.EmailConfirmed
},
ClientAppName = rUserSession.ClientAppName,
ClientIPAddress = rUserSession.ClientIPAddress,
Language = rUserSession.Language,
LastRenewal = rUserSession.LastRenewal,
LoginTime = rUserSession.LoginTime
}
);
}
/// <summary>
/// is user admin?
/// </summary>
@ -855,6 +895,46 @@ namespace RSecurityBackend.Services.Implementation
}
/// <summary>
/// start leaving
/// </summary>
/// <param name="userId"></param>
/// <param name="sessionId"></param>
/// <param name="clientIPAddress"></param>
/// <returns></returns>
public virtual async Task<RServiceResult<RVerifyQueueItem>> StartLeaving(Guid userId, Guid sessionId, string clientIPAddress)
{
var session = await GetUserSession(userId, sessionId);
var user = (await GetUserInformation(userId)).Result;
//checking this queue for previous signup attempts is unnecessary and is not done intentionally
RVerifyQueueItem item = new RVerifyQueueItem()
{
QueueType = RVerifyQueueType.UserSelfDelete,
Email = user.Email,
DateTime = DateTime.Now,
ClientIPAddress = clientIPAddress,
ClientAppName = session.Result.ClientAppName,
Secret = $"{(new Random(DateTime.Now.Millisecond)).Next(0, 99999)}".PadLeft(6, '0'),
Language = session.Result.Language
};
var existingSecrets = await _context.VerifyQueueItems.Where(i => i.Secret == item.Secret).ToListAsync();
if (existingSecrets.Count > 0)
{
_context.VerifyQueueItems.RemoveRange(existingSecrets);
await _context.SaveChangesAsync();
}
await _context.VerifyQueueItems.AddAsync
(
item
);
await _context.SaveChangesAsync();
return new RServiceResult<RVerifyQueueItem>(item);
}
/// <summary>
/// Set User Image
/// </summary>
@ -1489,52 +1569,34 @@ namespace RSecurityBackend.Services.Implementation
#region Signup/Forget password email related overridables
/// <summary>
/// Sign Up Email Subject
/// Sign Up/forget passsword/delete Email Subject
/// </summary>
/// <returns>
/// subject
/// </returns>
/// <param name="op"></param>
/// <param name="secretCode"></param>
public virtual string GetSignUpEmailSubject(string secretCode)
public virtual string GetEmailSubject(RVerifyQueueType op, string secretCode)
{
return $"Ganjoor SignUp Code:{secretCode}";
string opString = op == RVerifyQueueType.SignUp ? "SignUp" : op == RVerifyQueueType.ForgotPassword ? "Forgot Password" : "Self Delete User";
return $"Ganjoor {opString} Code:{secretCode}";
}
/// <summary>
/// Sign Up Email Html Content
/// Sign Up/forget passsword/delete Email Html Content
/// </summary>
/// <param name="op"></param>
/// <param name="secretCode"></param>
/// <param name="signupCallbackUrl"></param>
/// <returns>html content</returns>
public virtual string GetSignUpEmailHtmlContent(string secretCode, string signupCallbackUrl)
public virtual string GetEmailHtmlContent(RVerifyQueueType op, string secretCode, string signupCallbackUrl)
{
if (string.IsNullOrEmpty(signupCallbackUrl))
return $"{signupCallbackUrl}?secret={secretCode}";
return $"لطفا {secretCode} را در صفحهٔ ثبت نام وارد کنید.";
}
/// <summary>
/// Forgot Password Email Subject
/// </summary>
/// <returns>
/// subject
/// </returns>
/// <param name="secretCode"></param>
public virtual string GetForgotPasswordEmailSubject(string secretCode)
{
return $"Ganjoor Forgot Password Code:{secretCode}";
}
/// <summary>
/// Forgot Password Email Html Content
/// </summary>
/// <param name="secretCode"></param>
/// <param name="forgotPasswordCallbackUrl"></param>
/// <returns>html content</returns>
public virtual string GetForgotPasswordEmailHtmlContent(string secretCode, string forgotPasswordCallbackUrl)
{
return $"{forgotPasswordCallbackUrl}?secret={secretCode}";
string opString = op == RVerifyQueueType.SignUp ? "ثبت نام" : op == RVerifyQueueType.ForgotPassword ? "فراموشی رمز" : "حذف کاربر";
return $"لطفا {secretCode} را در صفحهٔ {opString} وارد کنید.";
}
#endregion
/// <summary>