256 lines
11 KiB
C#
256 lines
11 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Bus;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Email;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
using Saxonite.Net.Core.Web.Admin.Models;
|
|
using Saxonite.Net.Standard.Base.App;
|
|
using Saxonite.Net.Standard.Base.Bus;
|
|
using Saxonite.Net.Standard.Base.Helpers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
|
{
|
|
//=======================================================================
|
|
// Controller: Organisation - Ajax - Activation
|
|
//=======================================================================
|
|
partial class OrganisationController
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Get Organisation Activation Info ajax request.
|
|
//-------------------------------------------------------------------
|
|
private class AjaxResponse_OrganisationActivationInfo : AjaxResponse_Data
|
|
{
|
|
// Construction.
|
|
public AjaxResponse_OrganisationActivationInfo(SaxModel_Admin model) : base(model) { }
|
|
// Organisation details.
|
|
public OrganisationItemData organisation { get; } = new OrganisationItemData();
|
|
// Member awaiting activation.
|
|
public List<MemberListData> Members { get; } = new List<MemberListData>();
|
|
}
|
|
//-------------------------------------------------------------------
|
|
[HttpPost]
|
|
[Route("Organisation/Ajax/GetActivationInfo")]
|
|
public IActionResult Ajax_GetActivationInfo(Model_Organisation model)
|
|
{
|
|
String messageTitle = Localiser["caption.organisation"];
|
|
AjaxResponse_OrganisationActivationInfo responseData = new AjaxResponse_OrganisationActivationInfo(model);
|
|
|
|
// Validate session.
|
|
if (!ValidUserSession)
|
|
return GetAjaxResult_InvalidSession(responseData);
|
|
|
|
// Record disposable items as they are created so all can be disposed when needed.
|
|
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
|
{
|
|
|
|
if (StringUtil.IsEmpty(AppConfig.URL.Online.Root))
|
|
return Json(responseData.SetMessage(messageTitle, "Root online URL not specified."));
|
|
|
|
// Identify item.
|
|
SysId organisationId = SysId.ToSysId(model.OrganisationId);
|
|
if (!SysId.IsValid(organisationId))
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} Request to get activation info without valid organisation Id.");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
|
}
|
|
|
|
// Retrieve item.
|
|
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
|
disposableItems.Add(organisation);
|
|
if (organisation == null)
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve organisation. Id: '{model.OrganisationId}'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
|
}
|
|
|
|
// Organisation address.
|
|
SaxItemAddress address = ItemDataMgr.GetFirstItemAddressByItemAndType(organisation.GetItemId());
|
|
disposableItems.Add(address);
|
|
|
|
// Construct response.
|
|
PopulateOrganisationResponseItemData(organisation, address, responseData.organisation);
|
|
GetOrganisationMembers(model, organisationId, responseData.Members, true);
|
|
}
|
|
|
|
// Complete response.
|
|
responseData.Success = true;
|
|
|
|
return Json(responseData);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private class OrganisationMemberData : SacsDisposable
|
|
{
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
if (UserOrganisation != null) UserOrganisation.Dispose(); UserOrganisation = null;
|
|
if (UserAccount != null) UserAccount.Dispose(); UserAccount = null;
|
|
}
|
|
}
|
|
public SaxUserOrganisation UserOrganisation { get; set; }
|
|
public SaxUserAccount UserAccount { get; set; }
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Activate Organisation ajax request.
|
|
//-------------------------------------------------------------------
|
|
[HttpPost]
|
|
[Route("Organisation/Ajax/Activate")]
|
|
[Route("Organisation/Ajax/ActivateItem")]
|
|
public IActionResult Ajax_Activate(Model_OrganisationActivation model)
|
|
{
|
|
String messageTitle = Localiser["caption.organisation"];
|
|
AjaxResponse_Organisation responseData = new AjaxResponse_Organisation(model);
|
|
|
|
// Validate session.
|
|
if (!ValidUserSession)
|
|
return GetAjaxResult_InvalidSession(responseData);
|
|
|
|
// Record disposable items as they are created so all can be disposed when needed.
|
|
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
|
{
|
|
|
|
// Retrieve existing item.
|
|
SysId organisationId = SysId.ToSysId(model.OrganisationId);
|
|
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
|
disposableItems.Add(organisation);
|
|
if (organisation == null)
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve organisation. Id: '{model.OrganisationId}'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
|
}
|
|
|
|
// Organisation address.
|
|
SaxItemAddress address = ItemDataMgr.GetFirstItemAddressByItemAndType(organisation.GetItemId());
|
|
disposableItems.Add(address);
|
|
|
|
// Retrieve users.
|
|
List<OrganisationMemberData> organisationMembersToActivate = new List<OrganisationMemberData>();
|
|
foreach (String userOrganisationId in model.OrganisationMemberIds)
|
|
{
|
|
if (userOrganisationId == null) continue;
|
|
OrganisationMemberData organisationMember = new OrganisationMemberData();
|
|
disposableItems.Add(organisationMember);
|
|
organisationMember.UserOrganisation = AccountMgr.GetUserOrganisationById(SysId.ToSysId(userOrganisationId));
|
|
organisationMember.UserAccount = AccountMgr.GetUserAccountById(organisationMember.UserOrganisation?.UserAccountId ?? null);
|
|
if (organisationMember.UserOrganisation == null)
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve user organisation. Id: '{userOrganisationId}'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
if (organisationMember.UserAccount == null)
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve user account . Id: '{organisationMember.UserOrganisation.UserAccountId}'");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
if (organisationMember.UserAccount.Status != SaStatus.Awaiting)
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} User organisation is not awaiting. Id: '{userOrganisationId}'. Status: {organisationMember.UserAccount.StatusDesc}");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
|
}
|
|
// Check if this user is to be activated.
|
|
bool activateUser = false;
|
|
String controlName_Activate = $"MemberActivate_{userOrganisationId}";
|
|
foreach (String key in Request.Form.Keys)
|
|
{
|
|
if (key.EqualsCI(controlName_Activate))
|
|
{
|
|
activateUser = true;
|
|
break;
|
|
}
|
|
}
|
|
if (activateUser)
|
|
organisationMembersToActivate.Add(organisationMember);
|
|
}
|
|
|
|
if (organisationMembersToActivate.IsEmpty())
|
|
{
|
|
// No users to be activated.
|
|
// Check that organisation already has active members.
|
|
if (AccountMgr.GetOrganisationMemberCount(organisation.Id) < 1)
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} Unable to activate Organisation - no active members. Id: '{SysId.ToString(organisationId)}");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["organisation.activate.msg.no.active.members"]));
|
|
}
|
|
}
|
|
|
|
// Activate organisation.
|
|
organisation.Status = Sarand.Net.Standard.Base.Core.SaStatus.Active;
|
|
if (!AccountMgr.UpdateOrganisation(organisation, DbUpdateInfo))
|
|
{
|
|
SaLogger.Warn($"{SysUtil.Fn} Failed to update organisation [Id:{SysId.ToString(organisation.Id)}]: {AccountMgr.ErrorStateMessage}");
|
|
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
|
}
|
|
|
|
// Activate awaiting members and send welcome email to each.
|
|
foreach (OrganisationMemberData organisationMember in organisationMembersToActivate)
|
|
{
|
|
if (organisationMember.UserOrganisation == null) continue;
|
|
if (AccountMgr.UpdateUserOrganisation(organisationMember.UserOrganisation, DbUpdateInfo))
|
|
{
|
|
if (organisationMember.UserAccount == null) continue;
|
|
organisationMember.UserAccount.Status = SaStatus.Active;
|
|
if (AccountMgr.UpdateUserAccount(organisationMember.UserAccount, DbUpdateInfo))
|
|
{
|
|
// Send activation email.
|
|
if (SendAccountActivatedEmail(this, organisationMember.UserAccount))
|
|
SaLogger.Info($"{SysUtil.Fn} User Activation email sent to {organisationMember.UserAccount.EmailAddress}", true);
|
|
else SaLogger.Warn($"{SysUtil.Fn} Failed to send User Activation email to {organisationMember.UserAccount.EmailAddress}");
|
|
}
|
|
else
|
|
SaLogger.Warn($"{SysUtil.Fn} Failed to update user account [Id:{SysId.ToString(organisationMember.UserAccount.Id)}]: {AccountMgr.ErrorStateMessage}");
|
|
}
|
|
else
|
|
SaLogger.Warn($"{SysUtil.Fn} Failed to update user organisation [Id:{SysId.ToString(organisationMember.UserOrganisation.Id)}]: {AccountMgr.ErrorStateMessage}");
|
|
}
|
|
|
|
// Construct response.
|
|
PopulateOrganisationResponseItemData(organisation, address, responseData.organisation);
|
|
}
|
|
|
|
// Complete response.
|
|
responseData.Success = true;
|
|
return Json(responseData);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>
|
|
/// Generate the User Activation email.
|
|
/// <para>NB URL must be to the Online application.</para>
|
|
/// <para>NB Encryption must be done with the Online logic.</para>
|
|
/// </summary>
|
|
public static bool SendAccountActivatedEmail(SaxController_Admin controller, SaxUserAccount userAccount)
|
|
{
|
|
SaEmailData emailData = new SaEmailData();
|
|
emailData.Config = controller.EmailConfig;
|
|
emailData.AddressesTo.Add(userAccount.EmailAddress);
|
|
emailData.Subject = controller.Localiser["user.activate.email.subject"];
|
|
PopulateAccountActivatedEmailBody(controller, emailData, userAccount);
|
|
return controller.EmailConsole.SendEmail(emailData);
|
|
}
|
|
private static void PopulateAccountActivatedEmailBody(SaxController_Admin controller, SaEmailData emailData, SaxUserAccount userAccount)
|
|
{
|
|
// Will need to handle culture (language/country) as and when introduced.
|
|
emailData.MessageBody = SaxResourceHelper.GetResourceText(SaxResourceHelper.TextResource.Email_Security_AccountActivated_Html);
|
|
emailData.HtmlBody = true;
|
|
|
|
// Replace dynamic tags.
|
|
controller.EmailConsole.ReplaceDynamicEmailBodyTags(emailData, null, userAccount);
|
|
|
|
// Replace dynamic tag for link back to change password page.
|
|
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", SecurityController.GenerateRequestPasswordLink(controller, userAccount.Id, userAccount.EmailAddress, "", true));
|
|
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.SignIn]", controller.AppConfig.URL.Online.Root + "Security/SignIn");
|
|
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", SecurityController.GetRequestPasswordEmailLinkExpiresMinutes(controller).ToString());
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
}
|