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.Dbas; using Sarand.Net.Standard.Base.Email; using Sarand.Net.Standard.Base.Utils; using Saxonite.Net.Core.Web.Online.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.Online.Controllers { //======================================================================= // Online Organisation Controller - Members - Ajax actions. //======================================================================= partial class OrganisationController { //------------------------------------------------------------------- // Organisation Member data. private class MemberData_List : AjaxResponse_Data.ItemData_Base { public String UserAccountId { get; set; } public bool? CurrentUser { get; set; } = null; public String EmailAddress { get; set; } public String DisplayName { get; set; } public List RoleCodes { get; set; } = new List(); public List Roles { get; set; } = new List(); public String AdminComment { get; set; } } private class MemberData_Full : MemberData_List { public String Title { get; set; } public String FirstName { get; set; } public String LastName { get; set; } } private void PopulateMemberResponseData(Model_Organisation_Members model, SaxUserOrganisation userOrganisation, SaxUserAccount userAccount, SaxOrganisation organisation, MemberData_List data) { data.Id = SysId.ToString(userOrganisation.Id); data.UserAccountId = SysId.ToString(userOrganisation.UserAccountId); if (userOrganisation.UserAccountId.Equals(SessionData.User.UserAccountId)) data.CurrentUser = true; data.EmailAddress = userAccount.EmailAddress; data.DisplayName = userAccount.GetDisplayName(); data.RoleCodes.Clear(); data.Roles.Clear(); foreach (String memberRoleCode in userOrganisation.GetOrganisationRoleCodes()) { if (StringUtil.IsEmpty(memberRoleCode.Trim())) continue; Sax.OrganisationRole organisationRole = (Sax.OrganisationRole)OrganisationRoleCodes.GetTypeForCode(memberRoleCode); if (organisationRole <= 0 || organisationRole == Sax.OrganisationRole.Member) continue; data.RoleCodes.Add(memberRoleCode); data.Roles.Add(memberRoleCode, Localiser.GetOrganisationRoleCaption(organisationRole)); } data.AdminComment = userOrganisation.AdminComment; // NB UserAccount status (not UserOrganisation). data.StatusCode = userAccount.StatusCode; data.StatusDesc = userAccount.StatusDesc; data.CreatedOnFmt = Localiser.FormatDate(userOrganisation.CreateStamp.On); } private void PopulateMemberResponseData(Model_Organisation_Members model, SaxUserOrganisation userOrganisation, SaxUserAccount userAccount, SaxOrganisation organisation, MemberData_Full data) { PopulateMemberResponseData(model, userOrganisation, userAccount, organisation, data as MemberData_List); data.Title = userAccount.Title; data.FirstName = userAccount.FirstName; data.LastName = userAccount.LastName; } //------------------------------------------------------------------- // Get Member List ajax request. //------------------------------------------------------------------- private class AjaxResponse_MemberList : AjaxResponse_Data { // Construction. public AjaxResponse_MemberList(SaxModel_Online model) : base(model) { } // Member list. public List Members { get; } = new List(); // User profile. public class UserData { public bool CanManage { get; set; } } public UserData User { get; } = new UserData(); // Reference data. public List Titles { get; } = new List(); public List MemberRoles { get; } = new List(); } //------------------------------------------------------------------- [HttpPost] [Route("Organisation/Ajax/GetMemberList")] [Route("Organisation/Ajax/GetMembers")] public IActionResult Ajax_GetMemberList(Model_Organisation_Members model) { String fn = GetType().Name + ".Ajax_GetMemberList"; String messageTitle = Localiser["organisation.members"]; AjaxResponse_MemberList responseData = new AjaxResponse_MemberList(model); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); // Organisation. SysId organisationId = model.ExtractSysId(model.Filter.OrganisationId); SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId); if (organisation == null || !organisation.IsStatusActive) { SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " organisation for Member list. OrganisationId: '" + model.Filter.OrganisationId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } if (organisation != null) { // Store filter data. SessionData_Online.Filter.SetMemberOrganisation(organisation); // Reference data - titles. foreach (TypeCodeDesc title in SaxSystem.GetCodesOfType(Sax.CodeType.Title)) // ToDo Title translations. responseData.Titles.Add(title.Code, title.Desc); // Reference data - member roles. foreach (TypeCodeDesc memberRole in OrganisationRoleCodes.FindAll( item => item.Type != (int)Sax.OrganisationRole.Member)) responseData.MemberRoles.Add(memberRole.Code, Localiser.GetOrganisationRoleCaption((Sax.OrganisationRole)memberRole.Type)); // Session User roles. responseData.User.CanManage = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisationId, Sax.OrganisationRole.MemberAdmin); // Item filter. SaxUserOrganisation.Params prmMember = new SaxUserOrganisation.Params(); prmMember.OrganisationIdsIncluded.Add(organisationId); prmMember.UserAccountStatusCat = responseData.User.CanManage ? SaxUserAccount.StatusCat.AwaitingOrActive : SaxUserAccount.StatusCat.ActiveOnly; prmMember.OrganisationMembersOnly = true; //prmMember.MemberFilter = model.Filter.Member; prmMember.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly; model.Paging.ItemTotal = (ulong)AccountMgr.GetUserOrganisationCount(prmMember); model.PopulatePagingTo(prmMember.ResultsPaging); // Item columns. ColumnDfn colId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Id); ColumnDfn colUserAccountId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.UserAccountId); ColumnDfn colEmailAddress = responseData.User.CanManage ? AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.User_EmailAddress) : new ColumnDfn(-1, ""); ColumnDfn colDisplayName = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.User_DisplayName); ColumnDfn colOrganisationRoleCodes = responseData.User.CanManage ? AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationRoleCodes) : new ColumnDfn(-1, ""); ColumnDfn colUserStatus = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.User_Status); ColumnDfn colAdminComment = responseData.User.CanManage ? AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.AdminComment) : new ColumnDfn(-1, ""); ColumnDfn colCreatedOn = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.CreateOn_Date); List columns = new List() { colId, colUserAccountId , colEmailAddress, colDisplayName, colOrganisationRoleCodes, colUserStatus, colAdminComment, colCreatedOn }; // Sort columns. colCreatedOn.SortAscending = false; prmMember.SortColumns.Add(colDisplayName); // Query items. using (DbResultSet resultSet = AccountMgr.ExecuteUserOrganisationQuery(columns, prmMember)) { while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) { NamedValue.Map values = resultSet.GetRecordValues(); MemberData_List memberData = new MemberData_List() { Id = values.GetLong(colId.DataName).ToString(), UserAccountId = values.GetString(colUserAccountId.DataName), EmailAddress = values.GetString(colEmailAddress.DataName), DisplayName = AccountMgr.GetUserOrganisationDataValue(colDisplayName, values).ToString(), CreatedOnFmt = Localiser.FormatDate(values.GetDateTime(colCreatedOn.DataName)), AdminComment = values.GetString(colAdminComment.DataName), // NB UserAccount status (not UserOrganisation). StatusCode = values.GetString(colUserStatus.DataName), StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colUserStatus.DataName)) }; if (model.ExtractSysId(memberData.UserAccountId).Equals(SessionData.User.UserAccountId)) memberData.CurrentUser = true; String memberRoleCodes = values.GetString(colOrganisationRoleCodes.DataName); foreach (String memberRoleCode in StringListUtil.Split(memberRoleCodes, SaxUserOrganisation.UserOrgnisationRoleDelim)) { if (StringUtil.IsEmpty(memberRoleCode.Trim())) continue; Sax.OrganisationRole organisationRole = (Sax.OrganisationRole)OrganisationRoleCodes.GetTypeForCode(memberRoleCode); if (organisationRole <= 0 || organisationRole == Sax.OrganisationRole.Member) continue; memberData.RoleCodes.Add(memberRoleCode); memberData.Roles.Add(memberRoleCode, Localiser.GetOrganisationRoleCaption(organisationRole)); } responseData.Members.Add(memberData); } } } if (model.Paging.IsPaged) model.Paging.ItemCount = (ushort)responseData.Members.Count; // Complete response. responseData.SetPaging(model); responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- // Get Member ajax request. //------------------------------------------------------------------- private class AjaxResponse_Member : AjaxResponse_Data { // Construction. public AjaxResponse_Member(SaxModel_Online model) : base(model) { } // Member details. public MemberData_Full Member { get; } = new MemberData_Full(); } //------------------------------------------------------------------- [HttpPost] [Route("Organisation/Ajax/GetMember")] public IActionResult Ajax_GetMember(Model_Organisation_Members model) { String fn = GetType().Name + ".Ajax_GetMember"; String messageTitle = Localiser["label.member"]; AjaxResponse_Member responseData = new AjaxResponse_Member(model); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); // Identify item. SysId memberId = model.ExtractSysId(model.MemberId); if (!SysId.IsValid(memberId)) return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); // Retrieve item. using (SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(memberId)) { if (userOrganisation == null) { SaLogger.Warn(fn + " Failed to retrieve Organisation Member for Id: '" + model.MemberId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } // Validate organisation. using (SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId)) { if (organisation == null || !organisation.IsStatusActive) { SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " Organisation for Member. Id: '" + userOrganisation.OrganisationId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } // Session User roles. bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisation.Id, Sax.OrganisationRole.MemberAdmin); // Validate user account. using (SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId)) { bool userActive = userAccount.IsStatusActive || (userAccount.IsStatusAwaiting && userCanManageMembers); if (userAccount == null || !userActive) { SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " User Account for Member. Id: '" + userOrganisation.UserAccountId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } // Make a note of the selected Organisation. SessionData_Online.Filter.SetMemberOrganisation(organisation); PopulateMemberResponseData(model, userOrganisation, userAccount, organisation, responseData.Member); } } } // Construct response. responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- // Store Member ajax request. //------------------------------------------------------------------- private class AjaxResponse_StoreMember : AjaxResponse_Data { // Construction. public AjaxResponse_StoreMember(SaxModel_Online model) : base(model) { } // Member details. public MemberData_Full Member { get; } = new MemberData_Full(); // Feedback. public bool? MemberNameRequired { get; set; } = null; } [HttpPost] [Route("Organisation/Ajax/StoreMember")] public IActionResult Ajax_StoreMember(Model_Organisation_Members model) { String fn = GetType().Name + ".Ajax_StoreMember"; String messageTitle = Localiser["label.member"]; AjaxResponse_StoreMember responseData = new AjaxResponse_StoreMember(model); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); // Validate item properties. model.ValidateMemberData(responseData); if (responseData.HasControlErrors()) return Json(responseData); //--------------------------------------------------------------- // User Organisation identifiers. // New Member: // Organisation Id [MemberOrganisationId]. // Email address [MemberEmailAddress]. // Existing member: // User Organisation Id [MemberId]. //--------------------------------------------------------------- // Validate Member against Id against 'Exists' flag. SysId memberId = model.ExtractSysId(model.MemberId); bool memberExists = StringUtil.ToBool(model.MemberExists); if (memberExists && !SysId.IsValid(memberId)) { SaLogger.Warn(fn + " Id not specified for existing User Organisation."); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } if (!memberExists && SysId.IsValid(memberId)) { SaLogger.Warn(fn + " Id specified for new User Organisation: '" + model.MemberId + "'"); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Record disposable items as they are created so all can be disposed when needed. using (DisposableCollection disposableItems = new DisposableCollection()) { // Retrieve existing item. SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(memberId); disposableItems.Add(userOrganisation); if (userOrganisation == null && SysId.IsValid(memberId)) { SaLogger.Warn(fn + " Failed to retrieve User Organisation for Id: '" + model.MemberId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); } // Validate the Organisation. SysId organisationId = userOrganisation != null ? userOrganisation.OrganisationId : model.ExtractSysId(model.MemberOrganisationId); if (!SysId.IsValid(organisationId)) { SaLogger.Warn(fn + " Organisation Id not specified for Member."); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId); disposableItems.Add(organisation); if (organisation == null || !organisation.IsStatusActive) { SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " Organisation for User Organisation. OrganisationId: '" + model.MemberOrganisationId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } if (userOrganisation != null && !userOrganisation.OrganisationId.Equals(organisationId)) { SaLogger.Warn(fn + " Inconsistent Organisation Id specified for User Organisation. Expected: " + userOrganisation.OrganisationId + ". Found: " + organisationId); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Ensure that the user has the correct role to update Members for this organisation. bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisationId, Sax.OrganisationRole.MemberAdmin); if (!userCanManageMembers) { SaLogger.Warn(fn + " User doesn't have 'Member Admin' role for Organisation Id: " + organisationId); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Validate the User Account for an existing member. SaxUserAccount userAccount = null; if (userOrganisation != null) { userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId); disposableItems.Add(userAccount); bool userActive = userAccount.IsStatusActive || (userAccount.IsStatusAwaiting && userCanManageMembers); if (userAccount == null || !userActive) { SaLogger.Warn(fn + " " + (userAccount == null ? "Invalid" : "Inactive") + " User Account for User Organisation. UserAccountId: '" + userOrganisation.UserAccountId + "'"); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } if (userOrganisation != null && !userOrganisation.UserAccountId.Equals(userAccount.Id)) { SaLogger.Warn(fn + " Inconsistent User Account Id specified for User Organisation. Expected: " + userOrganisation.UserAccountId + ". Found: " + userAccount.Id); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } } // New member - Lookup user by email and create new account if needed. if (userAccount == null) { // Check if account exists for email. userAccount = AccountMgr.GetUserAccountByEmailAddress(model.MemberEmailAddress); if (userAccount != null) { // Existing User Account - get User Organisation if available. userOrganisation = AccountMgr.GetUserOrganisationByUserOrganisation(userAccount.Id, organisation.Id); disposableItems.Add(userOrganisation); } else { // If name hasn't been specified, return to page to complete details. if (!StringUtil.ToBool(model.MemberNameSupplied)) { responseData.SetControlError(nameof(model.MemberFirstName), Localiser["msg.validation.mandatory.value"]); responseData.SetControlError(nameof(model.MemberLastName), Localiser["msg.validation.mandatory.value"]); responseData.MemberNameRequired = true; responseData.Success = true; return Json(responseData); } // Create new User Account. userAccount = AccountMgr.CreateUserAccount(); userAccount.EmailAddress = model.MemberEmailAddress; userAccount.Status = SaStatus.Awaiting; } disposableItems.Add(userAccount); } // Store user account. if (StringUtil.ToBool(model.MemberNameSupplied)) { if (model.MemberTitle != null) userAccount.Title = model.MemberTitle; if (model.MemberFirstName != null) userAccount.FirstName = model.MemberFirstName; if (model.MemberLastName != null) userAccount.LastName = model.MemberLastName; } if (!SysId.IsValid(userAccount.Id)) { if (!AccountMgr.InsertUserAccount(userAccount, DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to insert User Account: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"])); } } else { if (!AccountMgr.UpdateUserAccount(userAccount, DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to insert User Account: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"])); } } // Create new item if required. if (userOrganisation == null) { userOrganisation = AccountMgr.CreateUserOrganisation(userAccount.Id, organisation.Id); disposableItems.Add(userOrganisation); } // User Organisation Roles. if (model.MemberRoleCodes != null) userOrganisation.OrganisationRoles = SaxUserOrganisation.GetOrganisationRolesFromCodes(model.GetMemberRoleCodes()); // Ensure user has member role. userOrganisation.AddOrganisationRole(Sax.OrganisationRole.Member); // Validate roles. if (userOrganisation.UserAccountId.Equals(SessionData.User.UserAccountId)) { // User is modifying their own member. if (!userOrganisation.HasOrganisationRole(Sax.OrganisationRole.MemberAdmin)) { SaLogger.Warn(fn + " Unable to store member - user is attempting to remove their own 'Member Admin' role."); return Json(responseData.SetMessage(messageTitle, Localiser["organisation.members.msg.remove.own.admin.role"])); } } // User organisation properties. if (model.MemberAdminComment != null) userOrganisation.AdminComment = model.MemberAdminComment; userOrganisation.Status = SaStatus.Active; // Store item. if (!SysId.IsValid(userOrganisation.Id)) { if (!AccountMgr.InsertUserOrganisation(userOrganisation, DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to insert User Organisation: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"])); } } else { if (!AccountMgr.UpdateUserOrganisation(userOrganisation, DbUpdateInfo)) { SaLogger.Warn(fn + " Failed to update User Organisation [Id:" + SysId.ToString(userOrganisation.Id) + "]: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"])); } } // Construct response. PopulateMemberResponseData(model, userOrganisation, userAccount, organisation, responseData.Member); } // Complete response. responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- // Activate Member ajax request. //------------------------------------------------------------------- private class AjaxResponse_ActivateMember : AjaxResponse_Data { // Construction. public AjaxResponse_ActivateMember(SaxModel_Online model) : base(model) { } // Member details. public MemberData_Full Member { get; } = new MemberData_Full(); } [HttpPost] [Route("Organisation/Ajax/ActivateMember")] public IActionResult Ajax_ActivateMember(Model_Organisation_Members model) { String fn = GetType().Name + ".Ajax_ActivateMember"; String messageTitle = Localiser["label.member"]; AjaxResponse_ActivateMember responseData = new AjaxResponse_ActivateMember(model); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); // Record disposable items as they are created so all can be disposed when needed. using (DisposableCollection disposableItems = new DisposableCollection()) { // Retrieve User Organisation [MemberId). SysId userOrganisationId = model.ExtractSysId(model.MemberId); SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId); disposableItems.Add(userOrganisation); if (userOrganisation == null || !userOrganisation.IsStatusActive) { SaLogger.Warn(fn + " User Organisation not found or not active. Id: " + SysId.ToString(userOrganisationId)); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Retrieve the Organisation. SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId); disposableItems.Add(organisation); if (organisation == null || !organisation.IsStatusActive) { SaLogger.Warn(fn + " Organisation not found or not active. Id: " + SysId.ToString(userOrganisation.OrganisationId)); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } // Ensure that the user has the correct role to update Members for this organisation. bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisation.Id, Sax.OrganisationRole.MemberAdmin); if (!userCanManageMembers) { SaLogger.Warn(fn + " User doesn't have 'Member Admin' role for Organisation Id: " + organisation.Id); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Retrieve User Account. SaxUserAccount userAccount = null; userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId); disposableItems.Add(userAccount); if (userAccount == null) { SaLogger.Warn(fn + " Failed to retrieve User Account. Id: " + userOrganisation.UserAccountId); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } if (!userAccount.IsStatusAwaiting) { SaLogger.Warn(fn + " User Account is not awaiting. Id: " + userOrganisation.UserAccountId + ". Status: " + userAccount.StatusDesc); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } // Update user's status. userAccount.Status = SaStatus.Active; if (AccountMgr.UpdateUserAccount(userAccount, DbUpdateInfo)) { // Send activation email. SaEmailData emailData = new SaEmailData(); emailData.Config = EmailConfig; emailData.AddressesTo.Add(userAccount.EmailAddress); emailData.Subject = Localiser["account.activate.email.subject"]; PopulateAccountActivatedEmailBody(emailData, userAccount); if (EmailConsole.SendEmail(emailData)) SaLogger.Info(fn + " User Activation email sent to " + userAccount.EmailAddress, true); else SaLogger.Warn(fn + " Failed to send User Activation email to " + userAccount.EmailAddress); // Treat the activation as successful regardless of whether the email was sent. responseData.SetNotification(messageTitle, Localiser["account.activate.notify"]); } else { SaLogger.Warn(fn + " Failed to insert User Account: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"])); } // Construct response. PopulateMemberResponseData(model, userOrganisation, userAccount, organisation, responseData.Member); } // Complete response. responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- private void PopulateAccountActivatedEmailBody(SaEmailData emailData, SaxUserAccount userAccount) { // Will need to handle culture (language/country) as and when introduced. emailData.MessageBody = SaxResourceHelper.GetTextResource(SaxResourceHelper.TextResource.Email_Security_AccountActivated_Html); emailData.HtmlBody = true; // Replace dynamic tags. EmailConsole.ReplaceDynamicEmailBodyTags(emailData, null, userAccount); // Replace dynamic tag for link back to change password page. SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", SecurityController.GenerateRequestPasswordLink(this, userAccount.Id, userAccount.EmailAddress, "")); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.SignIn]", GetRedirectLocation(RedirectLocation.WebAppBase) + "Security/SignIn"); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", SecurityController.GetRequestPasswordEmailLinkExpiresMinutes(this).ToString()); } //------------------------------------------------------------------- // Remove Member ajax request. //------------------------------------------------------------------- private class AjaxResponse_RemoveMember : AjaxResponse_Data { // Construction. public AjaxResponse_RemoveMember(SaxModel_Online model) : base(model) { } // Member details. public MemberData_Full Member { get; } = new MemberData_Full(); } [HttpPost] [Route("Organisation/Ajax/RemoveMember")] public IActionResult Ajax_RemoveMember(Model_Organisation_Members model) { String fn = GetType().Name + ".Ajax_RemoveMember"; String messageTitle = Localiser["label.member"]; AjaxResponse_RemoveMember responseData = new AjaxResponse_RemoveMember(model); // Validate session and referrer. if (!ValidReferer) return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); RefreshModel(model); // Record disposable items as they are created so all can be disposed when needed. using (DisposableCollection disposableItems = new DisposableCollection()) { // Retrieve User Organisation [MemberId). SysId userOrganisationId = model.ExtractSysId(model.MemberId); SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId); disposableItems.Add(userOrganisation); if (userOrganisation == null || !userOrganisation.IsStatusActive) { SaLogger.Warn(fn + " User Organisation not found or not active. Id: " + SysId.ToString(userOrganisationId)); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Retrieve the Organisation. SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId); disposableItems.Add(organisation); if (organisation == null || !organisation.IsStatusActive) { SaLogger.Warn(fn + " Organisation not found or not active. Id: " + SysId.ToString(userOrganisation.OrganisationId)); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } // Ensure that the user has the correct role to update Members for this organisation. bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisation.Id, Sax.OrganisationRole.MemberAdmin); if (!userCanManageMembers) { SaLogger.Warn(fn + " User doesn't have 'Member Admin' role for Organisation Id: " + organisation.Id); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); } // Retrieve User Account. SaxUserAccount userAccount = null; userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId); disposableItems.Add(userAccount); if (userAccount == null) { SaLogger.Warn(fn + " Failed to retrieve User Account. Id: " + userOrganisation.UserAccountId); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } if (!userAccount.IsStatusAwaiting && !userAccount.IsStatusActive) { SaLogger.Warn(fn + " User Account is not awaiting or active. Id: " + userOrganisation.UserAccountId); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"])); } // Remove User Organisation roles. userOrganisation.ClearOrganisationRoles(); if (AccountMgr.UpdateUserOrganisation(userOrganisation, DbUpdateInfo)) { responseData.SetNotification(messageTitle, Localiser["msg.item.removed"]); } else { SaLogger.Warn(fn + " Failed to update User Organisation: " + AccountMgr.ErrorStateMessage); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"])); } // Construct response. PopulateMemberResponseData(model, userOrganisation, userAccount, organisation, responseData.Member); } // Complete response. responseData.Success = true; return Json(responseData); } //------------------------------------------------------------------- } //======================================================================= }