Add project files.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class Program
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<SaxStartup_Admin>();
|
||||
});
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
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.IO;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Dbas.Base;
|
||||
using Saxonite.Net.Core.Web.Admin.Consoles;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Helpers;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using Saxonite.Net.Standard.Base.Consoles;
|
||||
using Saxonite.Net.Standard.Base.Helpers;
|
||||
using Saxonite.Net.Standard.Base.Mgr;
|
||||
using Saxonite.Net.Standard.Dbas.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxApplication_Admin : SaxApplication_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private bool generateDatabaseDefinitions = false;
|
||||
private bool populateRegions = false;
|
||||
private Dictionary<String, SaxSessionConfig> sessionConfigs = new Dictionary<string, SaxSessionConfig>();
|
||||
private Dictionary<String, SaxEmailConfig> emailConfigs = new Dictionary<string, SaxEmailConfig>();
|
||||
// Session contexts.
|
||||
private class SessionContextData
|
||||
{
|
||||
public SessionContextData(SaxSessionContext_Web sessionContext)
|
||||
{
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
public SaxSessionContext_Web SessionContext { get; }
|
||||
public ISacsDatabase CoreDatabase { get; set; }
|
||||
}
|
||||
private readonly Dictionary<int, SessionContextData> sessionContexts = new Dictionary<int, SessionContextData>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxApplication_Admin(IConfiguration configuration)
|
||||
{
|
||||
InitialiseTemporaryLoggingFolder();
|
||||
try
|
||||
{
|
||||
AppInstance = this;
|
||||
SaxGlobals.App = this;
|
||||
SaxGlobals.System = (System_Web = new SaxSystem_Web());
|
||||
Configuration = configuration;
|
||||
ConsoleHelper_Web = new SaxConsoleHelper_WebAdmin(this);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(GetType().Name + ".CTR " + ExceptionUtil.GetErrorStateMessage(exc));
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public static SaxApplication_Admin AppInstance { get; private set; }
|
||||
public override ISacsDatabase GetCoreDatabase(SaxSessionContext sessionContext)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.CoreDatabase;
|
||||
}
|
||||
public override String SessionCookieName { get { return Sax.Config.Admin.Session.Cookie.Name; } }
|
||||
// Configuration.
|
||||
public override SaxSessionConfig SessionConfig { get { return sessionConfigs.Values.ToList().getConfigForApplication(); } }
|
||||
public override SaxEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(SessionConfig); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
/// <summary>Initialise environment - from Startup.</summary>
|
||||
internal void InitWebHostEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
InitEnvironment(env);
|
||||
}
|
||||
/// <summary>Initialise environment - from internal (above) or unit tests.</summary>
|
||||
protected void InitEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
String fn = GetType().Name + ".InitEnvironment";
|
||||
Development = env.IsDevelopment();
|
||||
environmentName = env.EnvironmentName;
|
||||
SaLogger.LogFilenamePrefix = "Sax-Web-Adm";
|
||||
SaLogger.IncludeHostInFileMessage = false;
|
||||
SaLogger.IncludeUserInFileMessage = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Load server configuration.
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.machine.{SaxSystem.ComputerName}.json", optional: false, reloadOnChange: false)
|
||||
.AddEnvironmentVariables();
|
||||
SaxConfiguration = builder.Build();
|
||||
|
||||
// Application configuration.
|
||||
sessionConfigs = SaxSessionConfigHelper.ExtractSessionConfigs(SaxConfiguration.GetSection("SessionConfigs"));
|
||||
emailConfigs = SaxEmailConfigHelper.ExtractEmailConfigs(SaxConfiguration.GetSection("EmailConfigs"));
|
||||
LoggingRootFolder = SessionConfig.Logging.RootFolder;
|
||||
|
||||
// Application instance.
|
||||
if (SessionConfig.Instance.EqualsCI("Dev")) instanceType = Sax.InstanceType.Dev;
|
||||
else if (SessionConfig.Instance.ContainsCI("Q")) instanceType = Sax.InstanceType.QC;
|
||||
else if (SessionConfig.Instance.ContainsCI("UAT")) instanceType = Sax.InstanceType.UAT;
|
||||
else if (SessionConfig.Instance.EqualsCI("PreProd")) instanceType = Sax.InstanceType.UAT;
|
||||
|
||||
// Initialise hard-coded logging path.
|
||||
if (StringUtil.IsEmpty(LoggingRootFolder))
|
||||
{
|
||||
if (SaxSystem.ComputerName.EqualsCI("WIN-BPCLM1QUOMT"))
|
||||
LoggingRootFolder = @"D:\Saxonite\Logs\" + (Development ? "Dev" : "Test");
|
||||
}
|
||||
if (DirectoryUtil.DirectoryExists(LoggingRootFolder))
|
||||
SaLogger.LogFolder = LoggingRootFolder;
|
||||
LogApplicationStart(fn);
|
||||
|
||||
// Configure database connection.
|
||||
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
||||
config.location = SessionConfig.CoreDatabase.Location;
|
||||
config.user = SessionConfig.CoreDatabase.User;
|
||||
config.pword = SessionConfig.CoreDatabase.Password;
|
||||
SacsDatabase coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
|
||||
if (coreDatabase.HasErrorState())
|
||||
SaLogger.Warn(fn + " Database initialisation error: " + coreDatabase.ErrorStateMessage);
|
||||
|
||||
// Session context - only one context available/necessary (for now).
|
||||
SessionContextData sessionContextData = new SessionContextData(new SaxSessionContext_Web(100, Sax.Application.Admin));
|
||||
sessionContextData.CoreDatabase = coreDatabase;
|
||||
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
||||
SessionContext = sessionContextData.SessionContext;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
||||
}
|
||||
|
||||
// Occasional startup processing.
|
||||
if (generateDatabaseDefinitions)
|
||||
GenerateDatabaseDefinition(SessionContext);
|
||||
if (populateRegions)
|
||||
populateRegionsFromDataFile(SessionContext);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private void GenerateDatabaseDefinition(SaxSessionContext sessionContext)
|
||||
{
|
||||
if (!generateDatabaseDefinitions || !SaxSystem.DebugMode || SessionContext == null) return;
|
||||
if (!StringUtil.EmptyOnNull(EnvironmentName).EqualsCI("Development")) return;
|
||||
ISacsDatabase database = GetCoreDatabase(sessionContext);
|
||||
if (database == null || StringUtil.IsEmpty(database.ConnectionString)) return;
|
||||
|
||||
// Generate database definitions.
|
||||
SaxDbDfnGenerator.Generate(database.ConnectionString);
|
||||
//SaUpdateLogDbDfnGenerator.Generate(database.ConnectionString);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private void populateRegionsFromDataFile(SaxSessionContext sessionContext)
|
||||
{
|
||||
using (SaxInternals internals = new SaxInternals(sessionContext))
|
||||
{
|
||||
SaxReferenceMgr referenceMgr = internals.ReferenceMgr;
|
||||
String regionsData = SaxResourceHelper.GetTextResource(SaxResourceHelper.TextResource.Data_CountriesWithRegions_Txt);
|
||||
String[] regionDataValues = regionsData.Split("\n");
|
||||
SysId parentRegionId = null;
|
||||
for (int idx = 0; idx < regionDataValues.Length; idx++)
|
||||
{
|
||||
String regionData = regionDataValues[idx].ReplaceAll("\r", "");
|
||||
if (StringUtil.IsEmpty(regionData)) continue;
|
||||
if (regionData.Length > 3 && regionData[2] == ':')
|
||||
{
|
||||
String iso2Code = regionData.Substring(0, 2);
|
||||
String name = regionData.Substring(3);
|
||||
SaxRegion region = getRegionByName(referenceMgr, name);
|
||||
if (region == null)
|
||||
{
|
||||
region = referenceMgr.CreateRegion();
|
||||
region.RegionType = Sax.RegionType.Country;
|
||||
region.CountryIso2Code = iso2Code;
|
||||
region.Name = name;
|
||||
region.RegionIdParent = parentRegionId;
|
||||
if (!referenceMgr.InsertRegion(region, new DbUpdateInfo(new SysId(), "", "")))
|
||||
{
|
||||
SaLogger.Error("Failed to insert region - " + referenceMgr.ErrorStateMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sub continent.
|
||||
SaxRegion region = getRegionByName(referenceMgr, regionData);
|
||||
if (region == null)
|
||||
{
|
||||
region = referenceMgr.CreateRegion();
|
||||
region.RegionType = Sax.RegionType.SubContinent;
|
||||
region.Name = regionData;
|
||||
if (!referenceMgr.InsertRegion(region, new DbUpdateInfo(new SysId(), "", "")))
|
||||
{
|
||||
SaLogger.Error("Failed to insert region - " + referenceMgr.ErrorStateMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
parentRegionId = region.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private SaxRegion getRegionByName(SaxReferenceMgr referenceMgr, String name)
|
||||
{
|
||||
SaxRegion.Params prmRegion = new SaxRegion.Params();
|
||||
prmRegion.NameFull = name;
|
||||
return referenceMgr.GetRegion(prmRegion);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web
|
||||
{
|
||||
// <summary>
|
||||
/// Dummy classes to group shared resources - named as per '.resx' file in root namespace.
|
||||
/// <para>Required to create the IStringLocalizer instance using the type from the class.</para>
|
||||
/// <para>Name of the class is used as the prefix for localisation filenames.</para>
|
||||
/// <para>Resource files are in the Localization ResourcesPath in Startup.cs.</para>
|
||||
/// </summary>
|
||||
public class SaxAdminProperties { }
|
||||
// Class must be in Root/Default Namespace to reference properties with same name.
|
||||
// NB 'Assembly name' must be the same as 'Default Namespace' until 'Root Namespace' can be set (.Net Core 2.1?).
|
||||
// Ref. Project Properties - Application.
|
||||
}
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxLocaliser_Admin : SaxLocaliser
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private readonly IStringLocalizer<SaxAdminProperties> adminProperties;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Localisers are supplied using construction injection.
|
||||
/// </summary>
|
||||
public SaxLocaliser_Admin(IStringLocalizer<SaxAdminProperties> webAppProperties)
|
||||
{
|
||||
this.adminProperties = webAppProperties;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public override IStringLocalizer MainProperties { get { return adminProperties; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Newtonsoft.Json;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxSessionData_Admin : SaxSessionData_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
[JsonConstructor]
|
||||
private SaxSessionData_Admin(SaxSessionContext sessionContext) : this(sessionContext, null, null) { }
|
||||
/// <summary>
|
||||
/// SessionData construction.
|
||||
/// <para>SessionContext and UserAccount must be supplied.</para>
|
||||
/// <para>Organisation is optional.</para>
|
||||
/// </summary>
|
||||
public SaxSessionData_Admin(SaxSessionContext sessionContext, SaxUserAccount userAccount, List<SaxUserRole> userRoles) :
|
||||
base(sessionContext, userAccount, userRoles)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
/// <summary>User - JSON deserialisation route.</summary>
|
||||
public new UserData User { get { return base.User; } set { SetUser(value); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxStartup_Admin : SaxStartup
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SaxApplication_Admin application = null;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxStartup_Admin(IConfiguration configuration) : base(configuration)
|
||||
{
|
||||
// Initialise application.
|
||||
application = new SaxApplication_Admin(Configuration);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// Common configuration.
|
||||
ConfigureServicesConfig configureServicesConfig = new ConfigureServicesConfig();
|
||||
configureServicesConfig.services = services;
|
||||
configureServicesConfig.sessionCookieName = Sax.Config.Admin.Session.Cookie.Name;
|
||||
configureServicesConfig.sessionCookieHttpOnly = Sax.Config.Admin.Session.Cookie.HttpOnly;
|
||||
configureServicesConfig.sessionIdleTimeout = Sax.Config.Admin.Session.Cookie.IdleTimeout;
|
||||
ConfigureServices(configureServicesConfig);
|
||||
|
||||
// Application localisation.
|
||||
services.AddSingleton<SaxLocaliser, SaxLocaliser_Admin>();
|
||||
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
{
|
||||
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||||
options.CheckConsentNeeded = context => true;
|
||||
options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostApplicationLifetime hostApplicationLifetime, IWebHostEnvironment env)
|
||||
{
|
||||
application.InitWebHostEnvironment(env);
|
||||
|
||||
// Common configuration.
|
||||
ConfigureConfig configureConfig = new ConfigureConfig();
|
||||
configureConfig.app = app;
|
||||
configureConfig.hostApplicationLifetime = hostApplicationLifetime;
|
||||
configureConfig.env = env;
|
||||
Configure(configureConfig);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Saxonite.Net.Core.Web.Admin.App;
|
||||
using Saxonite.Net.Core.Web.Base.Consoles;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Consoles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxConsoleHelper_WebAdmin : SaxConsoleHelper_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members:
|
||||
private readonly SaxApplication_Admin app;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxConsoleHelper_WebAdmin(SaxApplication_Admin app)
|
||||
{
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data cache console.
|
||||
public override SaxDataCacheConsole GetDataCacheConsole(SaxSessionContext sessionContext)
|
||||
{
|
||||
String fn = GetType().Name + ".GetDataCacheConsole";
|
||||
throw new NotSupportedException(fn + " Data Cache Console not supported in Admin app.");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Email console.
|
||||
public override SaxEmailConsole CreateEmailConsole(SaxSessionContext sessionContext)
|
||||
{
|
||||
SaxEmailConsole emailConsole = new SaxEmailConsole_Web(app.EmailConfig);
|
||||
return emailConsole;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public class HomeController : SaxController_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public HomeController(SaxLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
String fn = GetType().Name + ".Index";
|
||||
|
||||
// Check for 'Keep Logged In' cookie.
|
||||
// NB Only allowed if there isn't a current user session.
|
||||
if (!ValidUserSession && SessionConfig.Security.SignIn.KeepLoggedIn.Allowed)
|
||||
{
|
||||
String encryptedParams = GetRequestCookie(CookieName_KeepLoggedIn);
|
||||
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
|
||||
String logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
|
||||
if (SysId.IsValid(keepLoggedInParams.UserAccountId))
|
||||
{
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(keepLoggedInParams.UserAccountId);
|
||||
if (userAccount != null)
|
||||
{
|
||||
if (userAccount.IsStatusActive)
|
||||
{
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userAccount, AccountMgr.GetRolesForUser(userAccount.Id), true, ref errorMessage))
|
||||
SaLogger.Info(fn + " Keep Logged In cookie found." + logSuffix);
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but UserAccount is not active." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but UserAccount not found." + logSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
{
|
||||
ClearKeepLoggedInCookie();
|
||||
return RedirectToAction("", "Security");
|
||||
}
|
||||
|
||||
// Home page.
|
||||
Model_Home model = new Model_Home(Localiser);
|
||||
model.ProhibitCache = false;
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
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.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Controller: Organisation - Ajax
|
||||
//=======================================================================
|
||||
partial class OrganisationController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation data.
|
||||
public class OrganisationData_List
|
||||
{
|
||||
public String Id { get; set; }
|
||||
public String Name { get; set; }
|
||||
public String TypeCode { get; set; }
|
||||
public String TypeDesc { get; set; }
|
||||
public String CategoryCode { get; set; }
|
||||
public String CategoryDesc { get; set; }
|
||||
public long MemberCount { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public String StatusDesc { get; set; }
|
||||
}
|
||||
public class OrganisationData_Full : OrganisationData_List
|
||||
{
|
||||
}
|
||||
private void PopulateOrganisationResponseData(SaxOrganisation organisation, OrganisationData_List data)
|
||||
{
|
||||
data.Id = SysId.ToString(organisation.Id);
|
||||
data.Name = organisation.Name;
|
||||
data.TypeCode = OrganisationTypes.GetCodeForType(organisation.OrganisationType);
|
||||
data.TypeDesc = OrganisationTypes.GetDescForType(organisation.OrganisationType);
|
||||
data.CategoryCode = OrganisationCategories.GetCodeForType(organisation.OrganisationCategory);
|
||||
data.CategoryDesc = OrganisationCategories.GetDescForType(organisation.OrganisationCategory);
|
||||
data.MemberCount = AccountMgr.GetOrganisationMemberCount(organisation.Id);
|
||||
data.StatusCode = organisation.StatusCode;
|
||||
data.StatusDesc = organisation.StatusDesc;
|
||||
}
|
||||
private void PopulateOrganisationResponseData(SaxOrganisation organisation, OrganisationData_Full data)
|
||||
{
|
||||
PopulateOrganisationResponseData(organisation, data as OrganisationData_List);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Organisation List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_OrganisationList : AjaxResponse_Data
|
||||
{
|
||||
public List<OrganisationData_List> Organisations { get; } = new List<OrganisationData_List>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/GetList")]
|
||||
public IActionResult Ajax_GetList(Model_Organisation model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetList";
|
||||
String messageTitle = Localiser["organisation.caption.organisations"];
|
||||
AjaxResponse_OrganisationList responseData = new AjaxResponse_OrganisationList();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Item filter.
|
||||
SaxOrganisation.Params prmOrganisation = new SaxOrganisation.Params();
|
||||
prmOrganisation.OrganisationFilter = model.Filter.Organisation;
|
||||
prmOrganisation.StatusCat = SaxOrganisation.StatusCat.NotDeleted;
|
||||
model.DataItemTotal = (ulong)AccountMgr.GetOrganisationCount(prmOrganisation);
|
||||
model.PopulatePagingTo(prmOrganisation.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Id);
|
||||
ColumnDfn colName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Name);
|
||||
ColumnDfn colOrganisationType = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.OrganisationType);
|
||||
ColumnDfn colOrganisationCategory = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.OrganisationCategory);
|
||||
ColumnDfn colPhoneMain = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.PhoneMain);
|
||||
ColumnDfn colPhoneAlt = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.PhoneAlt);
|
||||
ColumnDfn colUserCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.User_Count);
|
||||
ColumnDfn colMemberCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Member_Count);
|
||||
ColumnDfn colStatus = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId,
|
||||
colName,
|
||||
colOrganisationType,
|
||||
colOrganisationCategory,
|
||||
colPhoneMain,
|
||||
colPhoneAlt,
|
||||
colUserCount,
|
||||
colMemberCount,
|
||||
colStatus
|
||||
};
|
||||
|
||||
// Query items.
|
||||
model.DataItemCount = 0;
|
||||
using (DbResultSet resultSet = AccountMgr.ExecuteOrganisationQuery(columns, prmOrganisation))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
model.DataItemCount++;
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
OrganisationData_List organisationData = new OrganisationData_List()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
Name = values.GetString(colName.DataName),
|
||||
TypeCode = values.GetString(colOrganisationType.DataName),
|
||||
TypeDesc = OrganisationTypes.GetDescForCode(values.GetString(colOrganisationType.DataName)),
|
||||
CategoryCode = values.GetString(colOrganisationCategory.DataName),
|
||||
CategoryDesc = OrganisationCategories.GetDescForCode(values.GetString(colOrganisationCategory.DataName)),
|
||||
MemberCount = StringUtil.ToLong(values.GetString(colMemberCount.DataName)),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
responseData.Organisations.Add(organisationData);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Organisation ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Organisation : AjaxResponse_Data
|
||||
{
|
||||
public OrganisationData_Full organisation { get; } = new OrganisationData_Full();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/GetItem")]
|
||||
public IActionResult Ajax_GetItem(Model_Organisation model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetItem";
|
||||
String messageTitle = Localiser["organisation.caption.organisation"];
|
||||
AjaxResponse_Organisation responseData = new AjaxResponse_Organisation();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify item.
|
||||
SysId organisationId = new SysId(StringUtil.ToLong(model.OrganisationId));
|
||||
if (!SysId.IsValid(organisationId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
if (organisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for Id: '" + model.OrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateOrganisationResponseData(organisation, responseData.organisation);
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store Organisation ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/StoreItem")]
|
||||
public IActionResult Ajax_StoreItem(Model_Organisation model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreItem";
|
||||
String messageTitle = Localiser["organisation.caption.organisation"];
|
||||
AjaxResponse_Organisation responseData = new AjaxResponse_Organisation();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateOrganisationData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Retrieve existing item.
|
||||
SysId organisationId = new SysId(StringUtil.ToLong(model.OrganisationId));
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
if (organisation == null && SysId.IsValid(organisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for Id: '" + model.OrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (organisation == null)
|
||||
organisation = AccountMgr.CreateOrganisation();
|
||||
|
||||
// Populate item properties.
|
||||
if (model.OrganisationName != null)
|
||||
organisation.Name = model.OrganisationName;
|
||||
if (model.OrganisationTypeValue != null)
|
||||
organisation.OrganisationType = model.OrganisationType;
|
||||
if (model.OrganisationCategoryValue != null)
|
||||
organisation.OrganisationCategory = model.OrganisationCategory;
|
||||
if (model.OrganisationStatusCode != null)
|
||||
organisation.Status = model.OrganisationStatus;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(organisation.Id))
|
||||
{
|
||||
if (!AccountMgr.InsertOrganisation(organisation, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert organisation: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AccountMgr.UpdateOrganisation(organisation, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(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));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateOrganisationResponseData(organisation, responseData.organisation);
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
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.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Controller: Organisation - Members - Ajax
|
||||
//=======================================================================
|
||||
partial class OrganisationController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Member data.
|
||||
public class MemberData_List
|
||||
{
|
||||
public String Id { get; set; }
|
||||
public String UserAccountId { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public String DisplayName { get; set; }
|
||||
public String OrganisationId { get; set; }
|
||||
public String OrganisationName { get; set; }
|
||||
public List<String> RoleCodes { get; } = new List<string>();
|
||||
public int RoleCount { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public String StatusDesc { get; set; }
|
||||
}
|
||||
public class MemberData_Full : MemberData_List
|
||||
{
|
||||
}
|
||||
private void PopulateMemberResponseData(MemberData_List data, SaxUserOrganisation userOrganisation, SaxUserAccount userAccount, SaxOrganisation organisation)
|
||||
{
|
||||
data.Id = SysId.ToString(userOrganisation.Id);
|
||||
data.UserAccountId = SysId.ToString(userAccount.Id);
|
||||
data.EmailAddress = userAccount.EmailAddress;
|
||||
data.DisplayName = userAccount.GetDisplayName();
|
||||
data.OrganisationId = SysId.ToString(organisation.Id);
|
||||
data.OrganisationName = organisation.Name;
|
||||
// Exclude 'Member' role.
|
||||
foreach (Sax.OrganisationRole organisationRole in userOrganisation.OrganisationRoles.FindAll(item => item != Sax.OrganisationRole.Member))
|
||||
data.RoleCodes.Add(OrganisationRoles.GetCodeForType(organisationRole));
|
||||
data.RoleCount = userOrganisation.OrganisationRoles.Count - 1;
|
||||
data.StatusCode = organisation.StatusCode;
|
||||
data.StatusDesc = organisation.StatusDesc;
|
||||
}
|
||||
private void PopulateMemberResponseData(MemberData_Full data, SaxUserOrganisation userOrganisation, SaxUserAccount userAccount, SaxOrganisation organisation)
|
||||
{
|
||||
PopulateMemberResponseData(data as MemberData_List, userOrganisation, userAccount, organisation);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Organisation Member List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_MemberList : AjaxResponse_Data
|
||||
{
|
||||
public List<MemberData_List> Members { get; } = new List<MemberData_List>();
|
||||
public List<CodeDesc> MemberRoles { get; } = new List<CodeDesc>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/GetMemberList")]
|
||||
public IActionResult Ajax_GetMemberList(Model_OrganisationMembers model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetMemberList";
|
||||
String messageTitle = Localiser["organisation.caption.members"];
|
||||
AjaxResponse_MemberList responseData = new AjaxResponse_MemberList();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Organisation Id filter is mandatory.
|
||||
SysId filterOrganisationId = new SysId(StringUtil.ToLong(model.Filter.OrganisationId));
|
||||
if (!SysId.IsValid(filterOrganisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Request to retrieve members without valid organisation Id.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
}
|
||||
|
||||
// Reference data - organisation roles.
|
||||
// Exclude 'Member' as this is added automatically when stored.
|
||||
foreach (TypeCodeDesc organisationRole in OrganisationRoles.FindAll(item => item.Type != (int)Sax.OrganisationRole.Member))
|
||||
responseData.MemberRoles.Add(organisationRole.Code, Localiser.GetOrganisationRoleCaption((Sax.OrganisationRole)organisationRole.Type));
|
||||
|
||||
// Item filter.
|
||||
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
|
||||
prmUserOrganisation.OrganisationIdsIncluded.Add(filterOrganisationId);
|
||||
prmUserOrganisation.OrganisationMembersOnly = true;
|
||||
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.NotDeleted;
|
||||
model.DataItemTotal = (ulong)AccountMgr.GetUserOrganisationCount(prmUserOrganisation);
|
||||
model.PopulatePagingTo(prmUserOrganisation.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Id);
|
||||
ColumnDfn colUserAccountId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.UserAccountId);
|
||||
ColumnDfn colUserEmailAddress = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.User_EmailAddress);
|
||||
ColumnDfn colUserDisplayName = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.User_DisplayName);
|
||||
ColumnDfn colOrganisationId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationId);
|
||||
ColumnDfn colOrganisationName = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Organisation_Name);
|
||||
ColumnDfn colRoleCodes = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationRoleCodes);
|
||||
ColumnDfn colRoleCount = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationRoleCount);
|
||||
ColumnDfn colStatus = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId,
|
||||
colUserAccountId,
|
||||
colUserEmailAddress,
|
||||
colUserDisplayName,
|
||||
colOrganisationId,
|
||||
colOrganisationName,
|
||||
colRoleCodes,
|
||||
colRoleCount,
|
||||
colStatus
|
||||
};
|
||||
|
||||
// Query items.
|
||||
model.DataItemCount = 0;
|
||||
using (DbResultSet resultSet = AccountMgr.ExecuteUserOrganisationQuery(columns, prmUserOrganisation))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
model.DataItemCount++;
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
MemberData_List memberData = new MemberData_List()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
UserAccountId = values.GetString(colUserAccountId.DataName),
|
||||
EmailAddress = values.GetString(colUserEmailAddress.DataName),
|
||||
DisplayName = AccountMgr.GetUserOrganisationDataValue(colUserDisplayName, values).ToString(),
|
||||
OrganisationId = values.GetString(colOrganisationId.DataName),
|
||||
OrganisationName = values.GetString(colOrganisationName.DataName),
|
||||
// Role count - 1 to ignore 'Member' role.
|
||||
RoleCount = (int)values.GetLong(colRoleCount.DataName) - 1,
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
responseData.Members.Add(memberData);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Organisation Member ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Member : AjaxResponse_Data
|
||||
{
|
||||
public MemberData_Full Member { get; } = new MemberData_Full();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/GetMember")]
|
||||
public IActionResult Ajax_GetMember(Model_OrganisationMembers model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetItem";
|
||||
String messageTitle = Localiser["organisation.caption.member"];
|
||||
AjaxResponse_Member responseData = new AjaxResponse_Member();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify item.
|
||||
SysId userOrganisationId = new SysId(StringUtil.ToLong(model.UserOrganisationId));
|
||||
if (!SysId.IsValid(userOrganisationId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId);
|
||||
if (userOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve User Organisation for Id: '" + model.UserOrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve User Account.
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId);
|
||||
if (userAccount == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user account for Id: '" + userOrganisation.UserAccountId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve Organisation.
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId);
|
||||
if (organisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for Id: '" + userOrganisation.OrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateMemberResponseData(responseData.Member, userOrganisation, userAccount, organisation);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store Organisation Member ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/StoreMember")]
|
||||
public IActionResult Ajax_StoreMember(Model_OrganisationMembers model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreMember";
|
||||
String messageTitle = Localiser["organisation.caption.member"];
|
||||
AjaxResponse_Member responseData = new AjaxResponse_Member();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateOrganisationMemberData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// User account.
|
||||
SysId userAccountId = new SysId(StringUtil.ToLong(model.MemberUserAccountId));
|
||||
SaxUserAccount userAccount = null;
|
||||
if (!SysId.IsValid(userAccountId) && !StringUtil.IsEmpty(model.MemberUserEmailAddress))
|
||||
{
|
||||
userAccount = AccountMgr.GetUserAccountByEmailAddress(model.MemberUserEmailAddress);
|
||||
userAccountId = userAccount?.Id ?? new SysId();
|
||||
}
|
||||
if (!SysId.IsValid(userAccountId))
|
||||
{
|
||||
SaLogger.Warn(fn + " User Account must be identified");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.data.incomplete"]));
|
||||
}
|
||||
|
||||
// Organisation.
|
||||
SysId organisationId = new SysId(StringUtil.ToLong(model.MemberOrganisationId));
|
||||
SaxOrganisation organisation = null;
|
||||
if (!SysId.IsValid(organisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Organisation Id must be specified");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.data.incomplete"]));
|
||||
}
|
||||
|
||||
// Retrieve existing item.
|
||||
SysId userOrganisationId = new SysId(StringUtil.ToLong(model.UserOrganisationId));
|
||||
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId);
|
||||
if (userOrganisation == null && SysId.IsValid(userOrganisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user organisation for Id: '" + userOrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
if (userOrganisation != null && (!userOrganisation.UserAccountId.Equals(userAccountId) || !userOrganisation.OrganisationId.Equals(organisationId)))
|
||||
{
|
||||
// Either User Account and/or Organisation Ids don't match.
|
||||
SaLogger.Warn(fn + " Inconsistent user organisation properties. UserAccountId: " + userOrganisation.UserAccountId + " vs " + userAccountId + ". OrganisationId: " + userOrganisation.OrganisationId + " vs " + organisationId + ".");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// User Organisation not identified.
|
||||
if (userOrganisation == null)
|
||||
{
|
||||
// See whether user has an 'interest' in the organisation.
|
||||
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
|
||||
prmUserOrganisation.UserAccountIdsIncluded.Add(userAccountId);
|
||||
prmUserOrganisation.OrganisationIdsIncluded.Add(organisationId);
|
||||
prmUserOrganisation.OrganisationMembersOnly = false;
|
||||
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.Any;
|
||||
userOrganisation = AccountMgr.GetUserOrganisation(prmUserOrganisation);
|
||||
if (userOrganisation == null)
|
||||
// Organisation not found for user.
|
||||
userOrganisation = AccountMgr.CreateUserOrganisation(userAccountId, organisationId);
|
||||
}
|
||||
|
||||
// Retrieve associated items.
|
||||
if (userAccount == null)
|
||||
userAccount = AccountMgr.GetUserAccountById(userAccountId);
|
||||
if (organisation == null)
|
||||
organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
|
||||
// Populate item properties.
|
||||
if (model.MemberRoleCodes != null)
|
||||
userOrganisation.OrganisationRoles = SaxUserOrganisation.GetOrganisationRolesFromCodes(model.GetMemberRoleCodes());
|
||||
if (!userOrganisation.OrganisationRoles.Contains(Sax.OrganisationRole.Member))
|
||||
userOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.Member);
|
||||
|
||||
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"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
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"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateMemberResponseData(responseData.Member, userOrganisation, userAccount, organisation);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class OrganisationController : SaxController_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public OrganisationController(SaxLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
Model_Organisation model = new Model_Organisation(Localiser);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Organisation Members action.
|
||||
/// <para>- POST action to allow Organisation Id to be supplied, eg. from Organsiations page.</para>
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public IActionResult Members(Model_OrganisationMembers model)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
// Retrieve organisation.
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(new SysId(StringUtil.ToLong(model.Filter.OrganisationId)));
|
||||
if (organisation == null)
|
||||
RedirectToAction("", "Organisation");
|
||||
model.MemberOrganisationName = organisation?.Name;
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public class PoliciesController : SaxController_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public PoliciesController(SaxLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
Model_Policies model = new Model_Policies(Localiser);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Privacy()
|
||||
{
|
||||
Model_Policies model = new Model_Policies(Localiser);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
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 Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
partial class RegionController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Region data.
|
||||
public class RegionData_List
|
||||
{
|
||||
public String Id { get; set; }
|
||||
public String RegionTypeCode { get; set; }
|
||||
public String RegionTypeDesc { get; set; }
|
||||
public String CountryIso2Code { get; set; }
|
||||
public String Name { get; set; }
|
||||
public String ParentName { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public String StatusDesc { get; set; }
|
||||
}
|
||||
public class RegionData_Full : RegionData_List
|
||||
{
|
||||
}
|
||||
private void PopulateRegionResponseData(SaxRegion region, RegionData_List data)
|
||||
{
|
||||
data.Id = SysId.ToString(region.Id);
|
||||
data.RegionTypeCode = RegionTypes.GetCodeForType(region.RegionType);
|
||||
data.RegionTypeDesc = RegionTypes.GetDescForType(region.RegionType);
|
||||
data.CountryIso2Code = region.CountryIso2Code;
|
||||
data.Name = region.Name;
|
||||
data.StatusCode = region.StatusCode;
|
||||
data.StatusDesc = region.StatusDesc;
|
||||
}
|
||||
private void PopulateRegionResponseData(SaxRegion region, RegionData_Full data)
|
||||
{
|
||||
PopulateRegionResponseData(region, data as RegionData_List);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Region List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_RegionList : AjaxResponse_Data
|
||||
{
|
||||
public List<RegionData_List> Regions { get; } = new List<RegionData_List>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Region/Ajax/GetList")]
|
||||
public IActionResult Ajax_GetList(Model_Region model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetList";
|
||||
String messageTitle = Localiser["region.caption.regions"];
|
||||
AjaxResponse_RegionList responseData = new AjaxResponse_RegionList();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Item filter.
|
||||
SaxRegion.Params prmRegion = new SaxRegion.Params();
|
||||
prmRegion.RegionFilter = model.Filter.Region;
|
||||
if (model.Filter.RegionTypeCode != null)
|
||||
prmRegion.RegionType = model.FilterRegionType;
|
||||
prmRegion.StatusCat = SaxRegion.StatusCat.NotDeleted;
|
||||
model.DataItemTotal = (ulong)ReferenceMgr.GetRegionCount(prmRegion);
|
||||
model.PopulatePagingTo(prmRegion.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = ReferenceMgr.GetRegionColumnDfn(SaxRegion.Column.Id);
|
||||
ColumnDfn colType = ReferenceMgr.GetRegionColumnDfn(SaxRegion.Column.RegionType);
|
||||
ColumnDfn colIso2Code = ReferenceMgr.GetRegionColumnDfn(SaxRegion.Column.CountryIso2Code);
|
||||
ColumnDfn colName = ReferenceMgr.GetRegionColumnDfn(SaxRegion.Column.Name);
|
||||
ColumnDfn colParentName = ReferenceMgr.GetRegionColumnDfn(SaxRegion.Column.Parent_Name);
|
||||
ColumnDfn colStatus = ReferenceMgr.GetRegionColumnDfn(SaxRegion.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId,
|
||||
colType,
|
||||
colIso2Code,
|
||||
colName,
|
||||
colParentName,
|
||||
colStatus
|
||||
};
|
||||
|
||||
// Sort order.
|
||||
prmRegion.SortColumns.Add(colName);
|
||||
|
||||
// Query items.
|
||||
model.DataItemCount = 0;
|
||||
using (DbResultSet resultSet = ReferenceMgr.ExecuteRegionQuery(columns, prmRegion))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
model.DataItemCount++;
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
Sax.RegionType regionType = (Sax.RegionType)values.GetLong(colType.DataName);
|
||||
RegionData_List regionData = new RegionData_List()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
RegionTypeCode = RegionTypes.GetCodeForType(regionType),
|
||||
RegionTypeDesc = RegionTypes.GetDescForType(regionType),
|
||||
CountryIso2Code = values.GetString(colIso2Code.DataName),
|
||||
Name = values.GetString(colName.DataName),
|
||||
ParentName = values.GetString(colParentName.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
responseData.Regions.Add(regionData);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Region ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Region : AjaxResponse_Data
|
||||
{
|
||||
public RegionData_Full region { get; } = new RegionData_Full();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Region/Ajax/GetItem")]
|
||||
public IActionResult Ajax_GetItem(Model_Region model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetItem";
|
||||
String messageTitle = Localiser["region.caption.region"];
|
||||
AjaxResponse_Region responseData = new AjaxResponse_Region();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify item.
|
||||
if (!SysId.IsValid(model.RegionId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxRegion region = ReferenceMgr.GetRegionById(model.RegionId);
|
||||
if (region == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve region for Id: '" + model.RegionIdValue + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateRegionResponseData(region, responseData.region);
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store Region ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Region/Ajax/StoreItem")]
|
||||
public IActionResult Ajax_StoreItem(Model_Region model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreItem";
|
||||
String messageTitle = Localiser["region.caption.region"];
|
||||
AjaxResponse_Region responseData = new AjaxResponse_Region();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateRegionData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Retrieve existing item.
|
||||
SaxRegion region = ReferenceMgr.GetRegionById(model.RegionId);
|
||||
if (region == null && SysId.IsValid(model.RegionId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve region for Id: '" + model.RegionIdValue + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (region == null)
|
||||
region = ReferenceMgr.CreateRegion();
|
||||
|
||||
// Populate item properties.
|
||||
if (model.RegionCountryIso2Code != null)
|
||||
region.CountryIso2Code = model.RegionCountryIso2Code;
|
||||
if (model.RegionName != null)
|
||||
region.Name = model.RegionName;
|
||||
if (model.RegionStatusCode != null)
|
||||
region.Status = model.RegionStatus;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(region.Id))
|
||||
{
|
||||
if (!ReferenceMgr.InsertRegion(region, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert region: " + ReferenceMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + ReferenceMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ReferenceMgr.UpdateRegion(region, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update region [Id:" + SysId.ToString(region.Id) + "]: " + ReferenceMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + ReferenceMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateRegionResponseData(region, responseData.region);
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class RegionController : SaxController_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public RegionController(SaxLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
Model_Region model = new Model_Region(Localiser);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxController_Admin : SaxController_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
protected SaxController_Admin(SaxLocaliser localiser, ILogger<HomeController> logger) : base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session data.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Admin session data</summary>
|
||||
protected SaxSessionData_Admin SessionData_Admin { get { return SessionData as SaxSessionData_Admin; } }
|
||||
protected override SaxSessionData DeserializeSessionData(String sessionDataJson)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<SaxSessionData_Admin>(sessionDataJson, SaxSessionDataJsonSerializerSettings);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User Session.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Sign the account in.
|
||||
/// <para>- Record login time and clear invalid login data.</para>
|
||||
/// <para>- Open user session - store details against Sesion Data.</para>
|
||||
/// <para>- Set 'Keep logged in' cookie if required.</para>
|
||||
/// </summary>
|
||||
protected bool SignUserIn(SaxUserAccount userAccount, List<SaxUserRole> userRoles, bool keepLoggedIn, ref String errorMessage)
|
||||
{
|
||||
String fn = GetType().Name + ".SignUserIn";
|
||||
|
||||
// Validate User Account, just in case - should have been done before arriving here!
|
||||
if (userAccount == null)
|
||||
{
|
||||
SaLogger.Error(fn + " Unable to sign account in - null user account.");
|
||||
errorMessage = Localiser["security.msg.signin.failed"];
|
||||
return false;
|
||||
}
|
||||
if (!userAccount.IsStatusActive)
|
||||
{
|
||||
SaLogger.Error(fn + " Unable to sign account in - user account is not active. Email: " + userAccount.EmailAddress);
|
||||
errorMessage = Localiser["security.msg.signin.failed"];
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'Keep logged in' can be switched off by the application configuration.
|
||||
keepLoggedIn = App.SessionConfig.Security.SignIn.KeepLoggedIn.Allowed && keepLoggedIn;
|
||||
|
||||
// Log user in.
|
||||
userAccount.KeepLoggedIn_Admin = keepLoggedIn;
|
||||
userAccount.LastLoginAt = DateTime.Now;
|
||||
userAccount.InvalidLoginCount = 0;
|
||||
userAccount.LastInvalidLoginAt = DateTime.MinValue;
|
||||
if (!AccountMgr.UpdateUserAccount(userAccount, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update account for " + userAccount.EmailAddress + ": " + AccountMgr.ErrorStateMessage);
|
||||
errorMessage = Localiser["security.msg.signin.failed"];
|
||||
return false;
|
||||
}
|
||||
SaLogger.Info(fn + " User session opened for " + userAccount.EmailAddress, true);
|
||||
|
||||
// Create session.
|
||||
OpenUserSession(SessionContext, userAccount, userRoles);
|
||||
|
||||
// Send the 'Keep Logged In' cookie if requested.
|
||||
if (userAccount.KeepLoggedIn_Admin)
|
||||
SetKeepLoggedInCookie();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Start a new user session on sign-in.</summary>
|
||||
protected bool OpenUserSession(SaxSessionContext sessionContext, SaxUserAccount userAccount, List<SaxUserRole> userRoles)
|
||||
{
|
||||
// Validate user properties.
|
||||
if (!SysId.IsValid(userAccount.Id)) return false;
|
||||
if (StringUtil.IsEmpty(userAccount.EmailAddress)) return false;
|
||||
|
||||
// Close previous session.
|
||||
CloseUserSession();
|
||||
|
||||
// Open session.
|
||||
return SetSessionData(new SaxSessionData_Admin(sessionContext, userAccount, userRoles));
|
||||
}
|
||||
protected void CloseUserSession()
|
||||
{
|
||||
ClearSessionData();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep Logged In.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Keep-Logged-In cookie.</summary>
|
||||
protected void SetKeepLoggedInCookie()
|
||||
{
|
||||
String keepLoggedInCookieValue = GenerateKeepLoggedInCookieValue();
|
||||
int cookieExpiresDays = Math.Max(Sax.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Min, Math.Min(Sax.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Max, SessionConfig.Security.SignIn.KeepLoggedIn.CookieExpiresDays));
|
||||
SetResponseCookie(CookieName_KeepLoggedIn, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
|
||||
SaLogger.Info(this.GetType().Name + ".SetKeepLoggedInCookie 'Keep Logged In' cookie set. Value: " + keepLoggedInCookieValue);
|
||||
}
|
||||
|
||||
/// <summary>Set the 'Keep Logged In' response cookie to expired with no data.</summary>
|
||||
public void ClearKeepLoggedInCookie()
|
||||
{
|
||||
if (StringUtil.IsEmpty(GetRequestCookie(CookieName_KeepLoggedIn))) return;
|
||||
// Clear cookie by setting expiry date in the past.
|
||||
SetResponseCookie(CookieName_KeepLoggedIn, "", DateTime.Today.AddDays(-7), true);
|
||||
SaLogger.Info(GetType().Name + ".ClearKeepLoggedInCookie 'Keep Logged In' cookie cleared.");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// 'Keep Logged In' cookie and encryption config.
|
||||
// NB - IV value is generated from the key and fixed so that it doesn't change when the application restarts
|
||||
// to ensure that cookie value can be decrypted even if application restarts in the meantime.
|
||||
// - Generating IV from same key results in different value each time.
|
||||
// - IV Must be regenerated if key is changed: uncomment 'Generated' variable and copy resulting value to IV variable.
|
||||
// NB
|
||||
public static String CookieName_KeepLoggedIn = "SXKLI";
|
||||
public static String Base64Key_KeepLoggedIn = SacsEncryptionHelper.EncodePlainKey("<=Saxonite^{kEEp+1Ogg3d-IN}~32*>", SacsEncryptionHelper.KeyLength);
|
||||
public static String Base64IV_KeepLoggedIn_Generated = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_KeepLoggedIn);
|
||||
public static String Base64IV_KeepLoggedIn = "YOX10FIPp1zM1pg5U6fW7A==";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep-logged-in cookie value.
|
||||
private static readonly String ParamName_KeepLoggedIn_UserAccountId = "uai";
|
||||
private String GenerateKeepLoggedInCookieValue()
|
||||
{
|
||||
NameValueCollection keepLoggedInParams = new NameValueCollection();
|
||||
keepLoggedInParams.Add(ParamName_KeepLoggedIn_UserAccountId, SysId.ToString(SessionData_Admin.User.UserAccountId));
|
||||
return EncryptParameters(keepLoggedInParams, Base64IV_KeepLoggedIn, Base64Key_KeepLoggedIn);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public class KeepLoggedInParams
|
||||
{
|
||||
public SysId UserAccountId { get; set; }
|
||||
/// <summary>Retrieve the list of valid parameters in printable format [Name: Value].</summary>
|
||||
public List<String> GetValidParams()
|
||||
{
|
||||
List<String> values = new List<String>();
|
||||
if (SysId.IsValid(UserAccountId))
|
||||
values.Add("UserAccountId: " + SysId.ToString(UserAccountId));
|
||||
return values;
|
||||
}
|
||||
}
|
||||
public KeepLoggedInParams ExtractKeepLoggedInParams(String encryptedParams)
|
||||
{
|
||||
KeepLoggedInParams keepLoggedInParams = new KeepLoggedInParams();
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_KeepLoggedIn, Base64Key_KeepLoggedIn);
|
||||
keepLoggedInParams.UserAccountId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_KeepLoggedIn_UserAccountId)));
|
||||
}
|
||||
if (DebugMode) SaLogger.Info(GetType().Name + ".ExtractKeepLoggedInParams UserAccountId: " + SysId.ToString(keepLoggedInParams.UserAccountId));
|
||||
return keepLoggedInParams;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
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.Helpers;
|
||||
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.Consoles;
|
||||
using Saxonite.Net.Standard.Base.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
partial class SecurityController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Sign-in request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Signin : AjaxResponse_Data
|
||||
{
|
||||
}
|
||||
// Ajax request.
|
||||
[HttpPost]
|
||||
[Route("Security/Ajax/Signin")]
|
||||
public IActionResult Ajax_Signin(Model_Security model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_Signin";
|
||||
AjaxResponse_Signin responseData = new AjaxResponse_Signin();
|
||||
String messageTitle = Localiser["signin.caption"];
|
||||
|
||||
// Validate Sign-in data.
|
||||
model.ValidateSignInData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Get user account.
|
||||
SaxUserAccount userAccount = GetUserAccountForSignin(model, responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
String errorMessage = "";
|
||||
if (!SignUserIn(userAccount, AccountMgr.GetRolesForUser(userAccount.Id), model.KeepMeSignedIn, ref errorMessage))
|
||||
{
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), errorMessage));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
responseData.Success = SessionData_Admin?.ValidUserSession ?? false;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep Logged In.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_KeepLoggedIn : AjaxResponse_Base
|
||||
{
|
||||
}
|
||||
// Ajax request.
|
||||
[HttpPost]
|
||||
[Route("Security/Ajax/KeepLoggedIn")]
|
||||
public ActionResult Ajax_KeepLoggedIn(Model_Security model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_KeepLoggedIn";
|
||||
AjaxResponse_KeepLoggedIn responseData = new AjaxResponse_KeepLoggedIn();
|
||||
|
||||
if (!ValidUserSession)
|
||||
return Json(responseData.SetGoHome());
|
||||
|
||||
if (!SessionConfig.Security.SignIn.KeepLoggedIn.Allowed)
|
||||
return Json(responseData);
|
||||
|
||||
// Resend the cookie to extend the expiry date if it is currently populated.
|
||||
if (!StringUtil.IsEmpty(GetRequestCookie(CookieName_KeepLoggedIn)))
|
||||
SetKeepLoggedInCookie();
|
||||
|
||||
// Construct response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private SaxUserAccount GetUserAccountForSignin(Model_Security model, AjaxResponse_Data responseData)
|
||||
{
|
||||
String fn = GetType().Name + ".GetUserAccountForSignin";
|
||||
// Identify user account.
|
||||
SaxUserAccount userAccount = null;
|
||||
SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params();
|
||||
prmUserAccount.EmailAddress = model.EmailAddress;
|
||||
prmUserAccount.StatusCat = SaxUserAccount.StatusCat.Any;
|
||||
foreach (SaxUserAccount userAccountDuplicate in AccountMgr.GetUserAccountList(prmUserAccount))
|
||||
{
|
||||
// Account must be active to allow sign-in.
|
||||
// NB Debug testing allows 'Awaiting' accounts to sign-in.
|
||||
if ((SaxSystem.DebugMode && userAccountDuplicate.Status == SaStatus.Awaiting) || userAccountDuplicate.IsStatusActive)
|
||||
{
|
||||
userAccount = userAccountDuplicate;
|
||||
break;
|
||||
}
|
||||
SaLogger.Warn(fn + " Attempt to sign-in to User Account for " + model.EmailAddress + " with status " + SaxSystem.GetStatusDesc(userAccount.Status), true);
|
||||
}
|
||||
if (userAccount != null)
|
||||
{
|
||||
if (!SaxPasswordHelper.VerifyHashedPassword(userAccount, model.Password) && !(DebugMode && model.EmailAddress.EqualsCI("andy@sarand.com") && model.Password.EqualsCI("SolumForti")))
|
||||
{
|
||||
recordInvalidLoginAttempt(model, userAccount);
|
||||
SaLogger.Warn(fn + " Attempt to sign-in to User Account for " + model.EmailAddress + " with invalid password. Attempt: " + userAccount.InvalidLoginCount, true);
|
||||
userAccount = null;
|
||||
}
|
||||
}
|
||||
if (userAccount == null && !responseData.HasControlErrors())
|
||||
responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]);
|
||||
|
||||
// Admin - Verify that user has System Admin role.
|
||||
if (!AccountMgr.UserHasRole(userAccount.Id, Sax.UserRole.SystemAdmin, SaxUserRole.StatusCat.ActiveOnly))
|
||||
{
|
||||
recordInvalidLoginAttempt(model, userAccount);
|
||||
SaLogger.Warn(fn + " Attempt to sign-in to User Account for " + model.EmailAddress + " without SystemAdmin role. Attempt: " + userAccount.InvalidLoginCount, true);
|
||||
userAccount = null;
|
||||
responseData.SetControlError(nameof(model.EmailAddress), model.Localiser["security.msg.signin.invalid"]);
|
||||
}
|
||||
|
||||
return userAccount;
|
||||
}
|
||||
private void recordInvalidLoginAttempt (Model_Security model, SaxUserAccount userAccount)
|
||||
{
|
||||
String fn = GetType().Name + ".recordInvalidLoginAttempt";
|
||||
|
||||
// Record invalid login attempt.
|
||||
userAccount.InvalidLoginCount++;
|
||||
userAccount.LastInvalidLoginAt = DateTime.Now;
|
||||
if (!AccountMgr.UpdateUserAccount(userAccount, DbUpdateInfo))
|
||||
SaLogger.Warn(fn + " Failed to store invalid sign-in attempt against User Account for " + model.EmailAddress + ": " + AccountMgr.ErrorStateMessage, true);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Sign-out request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_SignOut : AjaxResponse_Data
|
||||
{
|
||||
}
|
||||
// Ajax request.
|
||||
[HttpPost]
|
||||
[Route("Security/Ajax/SignOut")]
|
||||
public ActionResult Ajax_SignOut(Model_Security model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_SignOut";
|
||||
AjaxResponse_SignOut responseData = new AjaxResponse_SignOut();
|
||||
String messageTitle = Localiser["signin.caption.signout"];
|
||||
|
||||
// User must have a valid session.
|
||||
if (!ValidUserSession)
|
||||
return Json(responseData.SetSessionExpired(messageTitle, Localiser["security.msg.warn.sessionExpired"]));
|
||||
|
||||
// Retrieve user account - in case sign-out needs to be recorded.
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(SessionData_Admin.User.UserAccountId);
|
||||
if (userAccount == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " System error on sign-out - failed to retrieve account details. Id: " + SysId.ToInt(SessionData_Admin.User.UserAccountId));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Clear user session.
|
||||
CloseUserSession();
|
||||
SaLogger.Info(fn + " User session closed for " + userAccount.EmailAddress, true);
|
||||
|
||||
// Clear 'Keep Logged In' cookie.
|
||||
ClearKeepLoggedInCookie();
|
||||
|
||||
// Force return to home page.
|
||||
responseData.SetGoHome(); // (messageTitle, Localiser["security.msg.signout"]);
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Password complexity request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_PasswordScore : AjaxResponse_Data
|
||||
{
|
||||
public int Score { get; set; }
|
||||
}
|
||||
// Ajax request.
|
||||
[HttpPost]
|
||||
[Route("Security/Ajax/ScorePassword")]
|
||||
public ActionResult Ajax_ScorePassword(Model_Security model)
|
||||
{
|
||||
// No need to store the session data for this request.
|
||||
StoreSessionData = false;
|
||||
|
||||
// Score pasword.
|
||||
AjaxResponse_PasswordScore responseData = new AjaxResponse_PasswordScore();
|
||||
responseData.Score = SaxPasswordHelper.GetPasswordStrength(model.Password);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Change Password request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_ChangePassword : AjaxResponse_Data
|
||||
{
|
||||
}
|
||||
// Ajax request.
|
||||
[HttpPost]
|
||||
[Route("Security/Ajax/StorePassword")]
|
||||
public ActionResult Ajax_StorePassword(Model_Security model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StorePassword";
|
||||
AjaxResponse_ChangePassword responseData = new AjaxResponse_ChangePassword();
|
||||
String messageTitle = Localiser["security.caption.change.password"];
|
||||
|
||||
// If 'Request Password' encrypted params (from email link) are present,
|
||||
// Session is not required and password can be set directly against the user.
|
||||
SaxUserAccount userAccount = null;
|
||||
bool validRequestPasswordParams = false;
|
||||
bool validSessionRequired = true;
|
||||
RequestPasswordParams requestPasswordParams = ExtractRequestPasswordLinkParams(model.rpe);
|
||||
if (requestPasswordParams.IsValid())
|
||||
{
|
||||
// Retrieve user account details and validate email address.
|
||||
userAccount = AccountMgr.GetUserAccountById(requestPasswordParams.UserAccountId);
|
||||
if (requestPasswordParams.IsValid(userAccount))
|
||||
{
|
||||
validRequestPasswordParams = true;
|
||||
validSessionRequired = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SaLogger.Warn(fn + " 'Request Password' parameters supplied but invalid. Id: " + SysId.ToString(requestPasswordParams.UserAccountId) + ". Email: " + requestPasswordParams.EmailAddress);
|
||||
userAccount = null;
|
||||
}
|
||||
}
|
||||
|
||||
// User must have a valid session.
|
||||
if (validSessionRequired && userAccount == null && !ValidUserSession)
|
||||
return Json(responseData.SetSessionExpired(messageTitle, Localiser["security.msg.warn.sessionExpired"]));
|
||||
|
||||
// Retrieve user account if not previously populated.
|
||||
if (userAccount == null && SessionData_Admin != null)
|
||||
{
|
||||
userAccount = AccountMgr.GetUserAccountById(SessionData_Admin.User.UserAccountId);
|
||||
}
|
||||
if (userAccount == null)
|
||||
return Json(responseData.SetControlError(nameof(model.Password), "System error - failed to retrieve account details."));
|
||||
|
||||
// Validate password data.
|
||||
model.ValidateChangePasswordData(userAccount, responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Note old password.
|
||||
String oldPasswordHashed = userAccount.PasswordHashed;
|
||||
|
||||
// Store password.
|
||||
userAccount.PasswordHashed = SaxPasswordHelper.GetPasswordHash(userAccount, model.Password);
|
||||
userAccount.PasswordChangedAt = DateTime.Now;
|
||||
// Remove new password from history if present.
|
||||
for (int passwordHistoryIdx = 0; passwordHistoryIdx < userAccount.PasswordHistory.Count; passwordHistoryIdx++)
|
||||
{
|
||||
// Compare history password to new value.
|
||||
if (SaxPasswordHelper.VerifyHashedPassword(userAccount, model.Password, userAccount.PasswordHistory[passwordHistoryIdx]))
|
||||
{
|
||||
// New password found in history - remove it.
|
||||
userAccount.PasswordHistory.RemoveAt(passwordHistoryIdx);
|
||||
passwordHistoryIdx--;
|
||||
}
|
||||
}
|
||||
userAccount.PasswordHistory.Remove(oldPasswordHashed);
|
||||
// Add the old password at the start of the history list and validate history length.
|
||||
userAccount.PasswordHistory.Add(oldPasswordHashed);
|
||||
while (userAccount.PasswordHistory.Count > 10)
|
||||
userAccount.PasswordHistory.RemoveAt(userAccount.PasswordHistory.Count - 1);
|
||||
if (!AccountMgr.UpdateUserAccount(userAccount, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to change password for " + userAccount.EmailAddress + ": " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetControlError(nameof(model.Password), Localiser["security.msg.change.password.failed"]));
|
||||
}
|
||||
SaLogger.Info(fn + " Password changed for " + userAccount.EmailAddress, true);
|
||||
|
||||
// Construct response.
|
||||
responseData.Success = true;
|
||||
if (validRequestPasswordParams)
|
||||
responseData.SetMessage(messageTitle, Localiser["security.msg.request.password.saved"]);
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Request Password request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_RequestPassword : AjaxResponse_Data
|
||||
{
|
||||
/// <summary>Message to be displayed for the user to 'OK' before returning to the Sign-in page.</summary>
|
||||
public String SuccessMsg { get; set; }
|
||||
}
|
||||
// Ajax request.
|
||||
[HttpPost]
|
||||
[Route("Security/Ajax/RequestNewPassword")]
|
||||
public ActionResult Ajax_RequestNewPassword(Model_Security model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_RequestNewPassword";
|
||||
AjaxResponse_RequestPassword responseData = new AjaxResponse_RequestPassword();
|
||||
String messageTitle = Localiser["security.caption.request.password"];
|
||||
|
||||
// Validate data.
|
||||
model.ValidateRequestPasswordData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Retrieve user account.
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountByEmailAddress(model.EmailAddress);
|
||||
if (userAccount != null && (userAccount.IsStatusActive || DebugMode))
|
||||
{
|
||||
// Send password request email.
|
||||
SaEmailData emailData = new SaEmailData();
|
||||
emailData.Config = EmailConfig;
|
||||
emailData.AddressesTo.Add(model.EmailAddress);
|
||||
emailData.Subject = Localiser["security.caption.request.password"];
|
||||
PopulateRequestPasswordEmailBody(emailData, userAccount);
|
||||
if (EmailConsole.SendEmail(emailData))
|
||||
SaLogger.Info(fn + " Password request email sent to " + model.EmailAddress, true);
|
||||
else SaLogger.Warn(fn + " Failed to send password request email to " + model.EmailAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (userAccount == null) SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account does not exist");
|
||||
else if (!userAccount.IsStatusActive) SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account is not active");
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
responseData.Success = true;
|
||||
responseData.SuccessMsg = Localiser["security.msg.request.password.email.sent"];
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
private void PopulateRequestPasswordEmailBody(SaEmailData emailData, SaxUserAccount userAccount)
|
||||
{
|
||||
// Will need to handle culture (language/country) as and when introduced.
|
||||
emailData.MessageBody = SaxResourceHelper.GetTextResource(SaxResourceHelper.TextResource.Email_RequestPassword_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]", GenerateRequestPasswordLink(userAccount.Id, userAccount.EmailAddress, ""));
|
||||
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", GetRequestPasswordEmailLinkExpiresMinutes().ToString());
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Password request link.
|
||||
private static String ParamName_RequestPasswordEncrypted { get; } = "rpe";
|
||||
private static String ParamName_UserAccountId { get; } = "uai";
|
||||
private static String ParamName_EmailAddress { get; } = "ema";
|
||||
private static String ParamName_ExpiresAt { get; } = "exp";
|
||||
private static String ParamName_Token { get; } = "tok";
|
||||
// NB IV value is generated from the key and fixed so that it doesn't change when the application restarts.
|
||||
// IV Must be regenerated if key is changed.
|
||||
private static String Base64Key_RequestPassword { get; } = SacsEncryptionHelper.EncodePlainKey("{~Saxonite@@Request^Password=}", SacsEncryptionHelper.KeyLength);
|
||||
private static String Base64IV_RequestPassword_Generated { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword);
|
||||
private static String Base64IV_RequestPassword { get; } = "1VAWYTW6d72n/6HDNhbqow==";
|
||||
private String GenerateRequestPasswordLink(SysId userAccountId, String emailAddress, String requestPasswordToken)
|
||||
{
|
||||
NameValueCollection parameters = new NameValueCollection();
|
||||
parameters.Add(ParamName_UserAccountId, SysId.ToString(userAccountId));
|
||||
parameters.Add(ParamName_EmailAddress, emailAddress);
|
||||
parameters.Add(ParamName_ExpiresAt, DateUtil.Format(DateTime.Now.AddMinutes(GetRequestPasswordEmailLinkExpiresMinutes()), DateUtil.Format_XmlDateTime));
|
||||
parameters.Add(ParamName_Token, requestPasswordToken);
|
||||
String link =
|
||||
GetRedirectLocation(RedirectLocation.WebAppBase) + "Security/ChangePassword?" +
|
||||
ParamName_RequestPasswordEncrypted + "=" + HttpUtility.UrlEncode(EncryptParameters(parameters, Base64IV_RequestPassword, Base64Key_RequestPassword));
|
||||
return link;
|
||||
}
|
||||
private int GetRequestPasswordEmailLinkExpiresMinutes()
|
||||
{
|
||||
int expiresMinutes = SessionConfig.Security.SignIn.PasswordRequest.EmailLinkExpiresMins;
|
||||
int expiresMinutes_Min = Sax.Config.Security.SignIn.PasswordRequest.EmailLinkExpiresMins_Min;
|
||||
int expiresMinutes_Max = Sax.Config.Security.SignIn.PasswordRequest.EmailLinkExpiresMins_Max;
|
||||
return Math.Max(expiresMinutes_Min, Math.Min(expiresMinutes_Max, expiresMinutes));
|
||||
}
|
||||
public class RequestPasswordParams
|
||||
{
|
||||
public SysId UserAccountId { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public DateTime ExpiresAt { get; set; }
|
||||
public String Token { get; set; }
|
||||
/// <summary>Retrieve the list of valid parameters in printable format [Name: Value].</summary>
|
||||
public List<String> GetValidParams()
|
||||
{
|
||||
List<String> values = new List<String>();
|
||||
if (SysId.IsValid(UserAccountId))
|
||||
values.Add("UserAccountId: " + SysId.ToString(UserAccountId));
|
||||
if (!StringUtil.IsEmpty(EmailAddress))
|
||||
values.Add("Email: " + EmailAddress);
|
||||
if (DateUtil.IsValid(ExpiresAt))
|
||||
values.Add("Expires: " + DateUtil.FormatXmlDateTime(ExpiresAt));
|
||||
if (!StringUtil.IsEmpty(Token))
|
||||
values.Add("Token: " + Token);
|
||||
return values;
|
||||
}
|
||||
/// <summary>Verifiy that the account Id and email are populated and the data hasn't expired.</summary>
|
||||
public bool IsValid()
|
||||
{
|
||||
return
|
||||
SysId.IsValid(UserAccountId) &&
|
||||
!StringUtil.IsEmpty(EmailAddress) &&
|
||||
DateUtil.IsValid(ExpiresAt) && ExpiresAt >= DateTime.Now;
|
||||
}
|
||||
/// <summary>Verify that the data is valid and the account details match.</summary>
|
||||
public bool IsValid(SaxUserAccount userAccount)
|
||||
{
|
||||
return
|
||||
IsValid() &&
|
||||
userAccount != null &&
|
||||
userAccount.Id.Equals(UserAccountId) &&
|
||||
userAccount.EmailAddress.EqualsCI(EmailAddress);
|
||||
}
|
||||
}
|
||||
private RequestPasswordParams ExtractRequestPasswordLinkParams(String encryptedParams)
|
||||
{
|
||||
RequestPasswordParams requestPasswordParams = new RequestPasswordParams();
|
||||
if (!StringUtil.IsEmpty(encryptedParams))
|
||||
{
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword, Base64Key_RequestPassword);
|
||||
requestPasswordParams.UserAccountId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_UserAccountId)));
|
||||
requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress);
|
||||
requestPasswordParams.ExpiresAt = DateUtil.ParseXmlDateTime(linkParams.Get(ParamName_ExpiresAt));
|
||||
requestPasswordParams.Token = linkParams.Get(ParamName_Token);
|
||||
}
|
||||
return requestPasswordParams;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.App;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class SecurityController : SaxController_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SecurityController(SaxLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return RedirectToAction("Signin", "Security");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Signin()
|
||||
{
|
||||
// Redirect home if signed-in.
|
||||
if (ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
Model_Security model = new Model_Security(Localiser);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Security - Change password
|
||||
/// <summary>
|
||||
/// Security - Change Password action.
|
||||
/// <para>- GET from request password email link.</para>
|
||||
/// <para>- POST with user signed-in. Browser cache prohibited.</para>
|
||||
/// </summary>
|
||||
[HttpGet, HttpPost]
|
||||
public IActionResult ChangePassword(Model_Security model)
|
||||
{
|
||||
String fn = GetType().Name + ".ChangePassword";
|
||||
bool validSessionRequired = true;
|
||||
|
||||
if (Request.Method.EqualsCI(HttpMethods.Get))
|
||||
{
|
||||
// Check for encrypted parameters from 'Request Password' email link.
|
||||
// NB Only allowed as a 'GET' request.
|
||||
String encryptedParams = Request.Query[ParamName_RequestPasswordEncrypted];
|
||||
RequestPasswordParams requestPasswordParams = ExtractRequestPasswordLinkParams(encryptedParams);
|
||||
if (requestPasswordParams.IsValid())
|
||||
{
|
||||
String logSuffix = requestPasswordParams.GetValidParams().Concat("", " ", ".");
|
||||
using (SaxUserAccount userAccount = AccountMgr.GetUserAccountById(requestPasswordParams.UserAccountId))
|
||||
{
|
||||
if (requestPasswordParams.IsValid(userAccount))
|
||||
{
|
||||
model.rpe = encryptedParams;
|
||||
validSessionRequired = false;
|
||||
}
|
||||
else SaLogger.Warn(fn + " 'Request Password' parameters supplied but invalid. " + logSuffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Must have a valid session to change password unless linked from Request Password above.
|
||||
if (validSessionRequired && !ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
// Configure page.
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Security - Request Password
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Sign-in Request Password action.
|
||||
/// <para>- User not signed-in.</para>
|
||||
/// <para>- GET only with browser cache allowed.</para>
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public IActionResult RequestPassword()
|
||||
{
|
||||
Model_Security model = new Model_Security(Localiser);
|
||||
|
||||
// Configure page.
|
||||
model.ProhibitCache = false;
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
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 Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
partial class SportController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Sport data.
|
||||
public class SportData_List
|
||||
{
|
||||
public String Id { get; set; }
|
||||
public String Name { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public String StatusDesc { get; set; }
|
||||
}
|
||||
public class SportData_Full : SportData_List
|
||||
{
|
||||
}
|
||||
private void PopulateSportResponseData(SaxSport sport, SportData_List data)
|
||||
{
|
||||
data.Id = SysId.ToString(sport.Id);
|
||||
data.Name = sport.Name;
|
||||
data.StatusCode = sport.StatusCode;
|
||||
data.StatusDesc = sport.StatusDesc;
|
||||
}
|
||||
private void PopulateSportResponseData(SaxSport sport, SportData_Full data)
|
||||
{
|
||||
PopulateSportResponseData(sport, data as SportData_List);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Sport List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_SportList : AjaxResponse_Data
|
||||
{
|
||||
public List<SportData_List> Sports { get; } = new List<SportData_List>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Sport/Ajax/GetList")]
|
||||
public IActionResult Ajax_GetList(Model_Sport model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetList";
|
||||
String messageTitle = Localiser["sport.caption.sports"];
|
||||
AjaxResponse_SportList responseData = new AjaxResponse_SportList();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Item filter.
|
||||
SaxSport.Params prmSport = new SaxSport.Params();
|
||||
prmSport.SportFilter = model.Filter.Sport;
|
||||
prmSport.StatusCat = SaxSport.StatusCat.NotDeleted;
|
||||
model.DataItemTotal = (ulong)ReferenceMgr.GetSportCount(prmSport);
|
||||
model.PopulatePagingTo(prmSport.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = ReferenceMgr.GetSportColumnDfn(SaxSport.Column.Id);
|
||||
ColumnDfn colName = ReferenceMgr.GetSportColumnDfn(SaxSport.Column.Name);
|
||||
ColumnDfn colStatus = ReferenceMgr.GetSportColumnDfn(SaxSport.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId,
|
||||
colName,
|
||||
colStatus
|
||||
};
|
||||
|
||||
// Sort order.
|
||||
prmSport.SortColumns.Add(colName);
|
||||
|
||||
// Query items.
|
||||
model.DataItemCount = 0;
|
||||
using (DbResultSet resultSet = ReferenceMgr.ExecuteSportQuery(columns, prmSport))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
model.DataItemCount++;
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
SportData_List sportData = new SportData_List()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
Name = values.GetString(colName.DataName),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
responseData.Sports.Add(sportData);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Sport ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Sport : AjaxResponse_Data
|
||||
{
|
||||
public SportData_Full sport { get; } = new SportData_Full();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Sport/Ajax/GetItem")]
|
||||
public IActionResult Ajax_GetItem(Model_Sport model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetItem";
|
||||
String messageTitle = Localiser["sport.caption.sport"];
|
||||
AjaxResponse_Sport responseData = new AjaxResponse_Sport();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify item.
|
||||
if (!SysId.IsValid(model.SportId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxSport sport = ReferenceMgr.GetSportById(model.SportId);
|
||||
if (sport == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve sport for Id: '" + model.SportIdValue + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateSportResponseData(sport, responseData.sport);
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store Sport ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Sport/Ajax/StoreItem")]
|
||||
public IActionResult Ajax_StoreItem(Model_Sport model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreItem";
|
||||
String messageTitle = Localiser["sport.caption.sport"];
|
||||
AjaxResponse_Sport responseData = new AjaxResponse_Sport();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateSportData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Retrieve existing item.
|
||||
SaxSport sport = ReferenceMgr.GetSportById(model.SportId);
|
||||
if (sport == null && SysId.IsValid(model.SportId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve sport for Id: '" + model.SportIdValue + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (sport == null)
|
||||
sport = ReferenceMgr.CreateSport();
|
||||
|
||||
// Populate item properties.
|
||||
if (model.SportName != null)
|
||||
sport.Name = model.SportName;
|
||||
if (model.SportStatusCode != null)
|
||||
sport.Status = model.SportStatus;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(sport.Id))
|
||||
{
|
||||
if (!ReferenceMgr.InsertSport(sport, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert sport: " + ReferenceMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + ReferenceMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ReferenceMgr.UpdateSport(sport, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update sport [Id:" + SysId.ToString(sport.Id) + "]: " + ReferenceMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + ReferenceMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateSportResponseData(sport, responseData.sport);
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class SportController : SaxController_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SportController(SaxLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
Model_Sport model = new Model_Sport(Localiser);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
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.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
partial class UserController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// User data.
|
||||
public class UserData_List
|
||||
{
|
||||
public String Id { get; set; }
|
||||
public String EmailAddress { get; set; }
|
||||
public String DisplayName { get; set; }
|
||||
public String Title { get; set; }
|
||||
public String FirstName { get; set; }
|
||||
public String LastName { get; set; }
|
||||
public int UserRoleCount { get; set; }
|
||||
public bool SystemAdmin { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public String StatusDesc { get; set; }
|
||||
}
|
||||
public class UserData_Full : UserData_List
|
||||
{
|
||||
public List<String> userRoleCodes { get; } = new List<string>();
|
||||
}
|
||||
private void PopulateUserResponseData(UserData_List data, SaxUserAccount user, List<SaxUserRole> userRoles)
|
||||
{
|
||||
data.Id = SysId.ToString(user.Id);
|
||||
data.EmailAddress = user.EmailAddress;
|
||||
data.DisplayName = user.GetDisplayName();
|
||||
data.Title = user.Title;
|
||||
data.FirstName = user.FirstName;
|
||||
data.LastName = user.LastName;
|
||||
data.UserRoleCount = userRoles?.GetUserRolesByStatus(SaStatus.Active).Count ?? 0;
|
||||
data.StatusCode = user.StatusCode;
|
||||
data.StatusDesc = user.StatusDesc;
|
||||
}
|
||||
private void PopulateUserResponseData(UserData_Full data, SaxUserAccount user, List<SaxUserRole> userRoles)
|
||||
{
|
||||
PopulateUserResponseData(data as UserData_List, user, userRoles);
|
||||
|
||||
if (userRoles != null)
|
||||
{
|
||||
foreach (SaxUserRole userRole in userRoles.GetUserRolesByStatus(SaStatus.Active))
|
||||
data.userRoleCodes.Add(UserRoles.GetCodeForType(userRole.UserRole));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get User List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_UserList : AjaxResponse_Data
|
||||
{
|
||||
public List<UserData_List> Users { get; } = new List<UserData_List>();
|
||||
public List<CodeDesc> UserRoles { get; } = new List<CodeDesc>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("User/Ajax/GetList")]
|
||||
public IActionResult Ajax_GetList(Model_User model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetList";
|
||||
String messageTitle = Localiser["user.caption.users"];
|
||||
AjaxResponse_UserList responseData = new AjaxResponse_UserList();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Reference data - user roles.
|
||||
foreach (TypeCodeDesc userRole in UserRoles)
|
||||
responseData.UserRoles.Add(userRole.Code, Localiser.GetUserRoleCaption((Sax.UserRole)userRole.Type));
|
||||
|
||||
// Item filter.
|
||||
SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params();
|
||||
prmUserAccount.UserAccountFilter = model.Filter.User;
|
||||
prmUserAccount.StatusCat = SaxUserAccount.StatusCat.NotDeleted;
|
||||
model.DataItemTotal = (ulong)AccountMgr.GetUserAccountCount(prmUserAccount);
|
||||
model.PopulatePagingTo(prmUserAccount.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.Id);
|
||||
ColumnDfn colEmail = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.EmailAddress);
|
||||
ColumnDfn colTitle = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.Title);
|
||||
ColumnDfn colFirstName = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.FirstName);
|
||||
ColumnDfn colLastName = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.LastName);
|
||||
ColumnDfn colUserRoleCount = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.UserRoleCount);
|
||||
ColumnDfn colSystemAdminUser = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.SystemAdminUser);
|
||||
ColumnDfn colStatus = AccountMgr.GetUserAccountColumnDfn(SaxUserAccount.Column.Status);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId,
|
||||
colEmail,
|
||||
colTitle,
|
||||
colFirstName,
|
||||
colLastName,
|
||||
colUserRoleCount,
|
||||
colSystemAdminUser,
|
||||
colStatus
|
||||
};
|
||||
|
||||
// Query items.
|
||||
model.DataItemCount = 0;
|
||||
using (DbResultSet resultSet = AccountMgr.ExecuteUserAccountQuery(columns, prmUserAccount))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
model.DataItemCount++;
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
UserData_List userData = new UserData_List()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
EmailAddress = values.GetString(colEmail.DataName),
|
||||
Title = values.GetString(colTitle.DataName),
|
||||
FirstName = values.GetString(colFirstName.DataName),
|
||||
LastName = values.GetString(colLastName.DataName),
|
||||
UserRoleCount = StringUtil.ToInt(values.GetString(colUserRoleCount.DataName)),
|
||||
SystemAdmin = StringUtil.ToBool(values.GetString(colSystemAdminUser.DataName)),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
userData.DisplayName = SaxUserAccount.GetDisplayName(userData.Title, userData.FirstName, userData.LastName);
|
||||
responseData.Users.Add(userData);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get User ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_User : AjaxResponse_Data
|
||||
{
|
||||
public UserData_Full user { get; } = new UserData_Full();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("User/Ajax/GetItem")]
|
||||
public IActionResult Ajax_GetItem(Model_User model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetItem";
|
||||
String messageTitle = Localiser["user.caption.user"];
|
||||
AjaxResponse_User responseData = new AjaxResponse_User();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify item.
|
||||
if (!SysId.IsValid(model.UserAccountId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxUserAccount user = AccountMgr.GetUserAccountById(model.UserAccountId);
|
||||
if (user == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user for Id: '" + model.UserAccountIdValue + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// User's roles.
|
||||
|
||||
// Construct response.
|
||||
PopulateUserResponseData(responseData.user, user, GetUserRoles(user.Id).GetUserRolesByStatus(SaStatus.Active));
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private List<SaxUserRole> GetUserRoles(SysId userAccountId, SaxUserRole.StatusCat statusCat = SaxUserRole.StatusCat.NotDeleted)
|
||||
{
|
||||
if (!SysId.IsValid(userAccountId)) return new List<SaxUserRole>();
|
||||
SaxUserRole.Params prmUserRole = new SaxUserRole.Params();
|
||||
prmUserRole.UserAccountIdsIncluded.Add(userAccountId);
|
||||
prmUserRole.StatusCat = statusCat;
|
||||
return AccountMgr.GetUserRoleList(prmUserRole);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Store User ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("User/Ajax/StoreItem")]
|
||||
public IActionResult Ajax_StoreItem(Model_User model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_StoreItem";
|
||||
String messageTitle = Localiser["user.caption.user"];
|
||||
AjaxResponse_User responseData = new AjaxResponse_User();
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Validate item properties.
|
||||
model.ValidateUserData(responseData);
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// Retrieve existing item.
|
||||
SaxUserAccount user = AccountMgr.GetUserAccountById(model.UserAccountId);
|
||||
if (user == null && SysId.IsValid(model.UserAccountId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user for Id: '" + model.UserAccountIdValue + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// User roles, including deleted.
|
||||
List<String> userRoleCodes = model.GetUserRoleCodes();
|
||||
List<SaxUserRole> userRoles = new List<SaxUserRole>();
|
||||
if (user != null) userRoles = GetUserRoles(user.Id, SaxUserRole.StatusCat.Any);
|
||||
foreach (String userRoleCode in userRoleCodes)
|
||||
{
|
||||
// Role to activate.
|
||||
Sax.UserRole role = (Sax.UserRole)UserRoles.GetTypeForCode(userRoleCode);
|
||||
SaxUserRole userRole = userRoles.GetUserRoleByRole(role);
|
||||
if (userRole == null)
|
||||
{
|
||||
userRole = AccountMgr.CreateUserRole(user?.Id, role);
|
||||
userRoles.Add(userRole);
|
||||
}
|
||||
userRole.Status = SaStatus.Active;
|
||||
}
|
||||
// Roles to deactivate.
|
||||
foreach (SaxUserRole userRole in userRoles)
|
||||
{
|
||||
if (!userRoleCodes.Exists(item => item.EqualsCI(UserRoles.GetCodeForType(userRole.UserRole))))
|
||||
userRole.Status = SaStatus.Inactive;
|
||||
}
|
||||
|
||||
// Create new item if required.
|
||||
if (user == null)
|
||||
{
|
||||
user = AccountMgr.CreateUserAccount();
|
||||
if (model.UserEmailAddress != null)
|
||||
user.EmailAddress = model.UserEmailAddress;
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
if (model.UserTitle != null)
|
||||
user.Title = model.UserTitle;
|
||||
if (model.UserFirstName != null)
|
||||
user.FirstName = model.UserFirstName;
|
||||
if (model.UserLastName != null)
|
||||
user.LastName = model.UserLastName;
|
||||
if (model.UserStatusCode != null)
|
||||
user.Status = model.UserStatus;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(user.Id))
|
||||
{
|
||||
if (!AccountMgr.InsertUserAccount(user, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert user: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
// Apply User Account Id to dependent items.
|
||||
foreach (SaxUserRole userRole in (userRoles))
|
||||
userRole.UserAccountId = user.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AccountMgr.UpdateUserAccount(user, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update user [Id:" + SysId.ToString(user.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
|
||||
// Associated data - User Roles.
|
||||
foreach (SaxUserRole userRole in (userRoles))
|
||||
{
|
||||
// Store User Role.
|
||||
if (!SysId.IsValid(userRole.Id))
|
||||
{
|
||||
if (!AccountMgr.InsertUserRole(userRole, DbUpdateInfo))
|
||||
SaLogger.Warn(fn + " Failed to insert user role: " + AccountMgr.ErrorStateMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AccountMgr.UpdateUserRole(userRole, DbUpdateInfo))
|
||||
SaLogger.Warn(fn + " Failed to update user role [Id:" + SysId.ToString(userRole.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateUserResponseData(responseData.user, user, userRoles.GetUserRolesByStatus(SaStatus.Active));
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public partial class UserController : SaxController_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public UserController(SaxLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
Model_User model = new Model_User(Localiser);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class ErrorViewModel
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Home : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Home(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Organisation : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Organisation(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_JS.Add("js/sax-organisation.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// List configuration.
|
||||
public class FilterData
|
||||
{
|
||||
public String Organisation { get; set; }
|
||||
public String OrganisationTypeCode { get; set; }
|
||||
public String OrganisationCategoryCode { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
public Sax.OrganisationType FilterOrganisationType
|
||||
{
|
||||
get { return (Sax.OrganisationType)OrganisationTypes.GetTypeForCode(Filter.OrganisationTypeCode); }
|
||||
}
|
||||
public Sax.OrganisationCategory FilterOrganisationCategory
|
||||
{
|
||||
get { return (Sax.OrganisationCategory)OrganisationCategories.GetTypeForCode(Filter.OrganisationCategoryCode); }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation properties.
|
||||
public String OrganisationId { get; set; }
|
||||
public String OrganisationName { get; set; }
|
||||
public String OrganisationTypeValue { get; set; }
|
||||
public Sax.OrganisationType OrganisationType { get { return (Sax.OrganisationType)OrganisationTypes.GetTypeForCode(OrganisationTypeValue); } }
|
||||
public String OrganisationCategoryValue { get; set; }
|
||||
public Sax.OrganisationCategory OrganisationCategory { get { return (Sax.OrganisationCategory)OrganisationCategories.GetTypeForCode(OrganisationCategoryValue); } }
|
||||
public String OrganisationStatusCode { get; set; }
|
||||
public SaStatus OrganisationStatus { get { return SacsSystem.GetStatusForCode(OrganisationStatusCode); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation validation.
|
||||
public bool ValidateOrganisationData(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Organisation name.
|
||||
if (OrganisationName != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(OrganisationName), OrganisationName);
|
||||
if (StringUtil.IsEmpty(OrganisationName))
|
||||
responseData.SetControlError(nameof(OrganisationName), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(OrganisationName) > GetControlMaxLength(SaxDbDfn.ColumnIdx.Organisation_Name))
|
||||
responseData.SetControlError(nameof(OrganisationName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn.ColumnIdx.Organisation_Name)]);
|
||||
}
|
||||
|
||||
// Organisation type.
|
||||
if (OrganisationTypeValue != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(OrganisationTypeValue))
|
||||
responseData.SetControlError(nameof(OrganisationTypeValue), Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// Organisation category.
|
||||
if (OrganisationCategoryValue != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(OrganisationCategoryValue))
|
||||
responseData.SetControlError(nameof(OrganisationCategoryValue), Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// Organisation status.
|
||||
if (OrganisationStatusCode != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(OrganisationStatusCode))
|
||||
responseData.SetControlError(nameof(OrganisationStatusCode), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SaxOrganisation.ValidStatuses.Contains(OrganisationStatus))
|
||||
responseData.SetControlError(nameof(OrganisationStatusCode), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_OrganisationMembers : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_OrganisationMembers(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_JS.Add("js/sax-organisationMembers.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// List configuration.
|
||||
public class FilterData
|
||||
{
|
||||
public String OrganisationId { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
public String OrganisationId { get { return Filter.OrganisationId; } set { Filter.OrganisationId = value; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User Organisation (member) properties.
|
||||
public String UserOrganisationId { get; set; }
|
||||
[EmailAddress]
|
||||
public String MemberUserEmailAddress{ get; set; }
|
||||
public String MemberUserAccountId { get; set; }
|
||||
public String MemberOrganisationId { get; set; }
|
||||
public String MemberOrganisationName { get; set; }
|
||||
public String MemberRoleCodeDelim = ",";
|
||||
public List<String> MemberRoleCodes { get; set; }
|
||||
public List<String> GetMemberRoleCodes()
|
||||
{
|
||||
List<String> codes = new List<string>();
|
||||
foreach (String code in MemberRoleCodes)
|
||||
{
|
||||
if (StringUtil.IsEmpty(code)) continue;
|
||||
codes.AddRange(code.Split(MemberRoleCodeDelim));
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
public String MemberStatusCode { get; set; }
|
||||
public SaStatus MemberStatus { get { return SacsSystem.GetStatusForCode(MemberStatusCode); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation member validation.
|
||||
public bool ValidateOrganisationMemberData(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// User email address.
|
||||
if (MemberUserEmailAddress != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(MemberUserEmailAddress), MemberUserEmailAddress);
|
||||
if (StringUtil.IsEmpty(MemberUserEmailAddress))
|
||||
responseData.SetControlError(nameof(MemberUserEmailAddress), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!AccountMgr.UserAccountExistsByEmailAddress(MemberUserEmailAddress))
|
||||
responseData.SetControlError(nameof(MemberUserEmailAddress), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// User Account.
|
||||
if (MemberUserAccountId != null)
|
||||
{
|
||||
SysId memberUserAccountId = new SysId(StringUtil.ToLong(MemberUserAccountId));
|
||||
if (!SysId.IsValid(memberUserAccountId))
|
||||
responseData.SetControlError(nameof(MemberUserAccountId), Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Member roles.
|
||||
if (MemberRoleCodes != null)
|
||||
{
|
||||
// Roles can be left empty as the 'Member' role is automatically applied.
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Policies : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Policies(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Region : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Region(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_JS.Add("js/sax-region.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// List properties.
|
||||
public class FilterData
|
||||
{
|
||||
public String Region { get; set; }
|
||||
public String RegionTypeCode { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
public Sax.RegionType FilterRegionType
|
||||
{
|
||||
get { return (Sax.RegionType)RegionTypes.GetTypeForCode(Filter.RegionTypeCode); }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Region properties.
|
||||
public String RegionIdValue { get; set; }
|
||||
public SysId RegionId
|
||||
{
|
||||
get { return new SysId(StringUtil.ToInt(RegionIdValue)); }
|
||||
set { RegionIdValue = SysId.ToString(value); }
|
||||
}
|
||||
public String RegionTypeCode { get; set; }
|
||||
public Sax.RegionType RegionType
|
||||
{
|
||||
get { return (Sax.RegionType)RegionTypes.GetTypeForCode(RegionTypeCode); }
|
||||
set { RegionTypeCode = RegionTypes.GetCodeForType(value); }
|
||||
}
|
||||
public String RegionCountryIso2Code { get; set; }
|
||||
public String RegionName { get; set; }
|
||||
public String RegionStatusCode { get; set; }
|
||||
public SaStatus RegionStatus { get { return SacsSystem.GetStatusForCode(RegionStatusCode); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Region.
|
||||
public bool ValidateRegionData(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Region Type.
|
||||
if (RegionTypeCode != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(RegionTypeCode), RegionTypeCode);
|
||||
if (StringUtil.IsEmpty(RegionTypeCode) || (int)RegionType < 1)
|
||||
responseData.SetControlError(nameof(RegionTypeCode), Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// Region ISO2 code.
|
||||
if (RegionCountryIso2Code != null)
|
||||
{
|
||||
RegionCountryIso2Code = RegionCountryIso2Code.ToUpperInvariant();
|
||||
responseData.SetControlValue(nameof(RegionCountryIso2Code), RegionCountryIso2Code);
|
||||
if (RegionType == Sax.RegionType.Country)
|
||||
{
|
||||
if (StringUtil.IsEmpty(RegionCountryIso2Code))
|
||||
responseData.SetControlError(nameof(RegionCountryIso2Code), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(RegionCountryIso2Code) != GetControlMaxLength(SaxDbDfn.ColumnIdx.Region_CountryIso2Code))
|
||||
responseData.SetControlError(nameof(RegionCountryIso2Code), Localiser["msg.validation.invalid.length", GetControlMaxLength(SaxDbDfn.ColumnIdx.Region_CountryIso2Code)]);
|
||||
else
|
||||
{
|
||||
// Check for duplicate code.
|
||||
SaxRegion.Params prmRegion = new SaxRegion.Params();
|
||||
if (SysId.IsValid(RegionId))
|
||||
prmRegion.IdsExcluded.Add(RegionId);
|
||||
prmRegion.CountryIso2CodesIncluded.Add(RegionCountryIso2Code);
|
||||
prmRegion.StatusCat = SaxRegion.StatusCat.Any;
|
||||
if (ReferenceMgr.GetRegionCount(prmRegion) > 0)
|
||||
responseData.SetControlError(nameof(RegionCountryIso2Code), Localiser["msg.validation.duplicate.value"]);
|
||||
}
|
||||
}
|
||||
else if ((int)RegionType > 0 && RegionType != Sax.RegionType.Country)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(RegionCountryIso2Code))
|
||||
responseData.SetControlError(nameof(RegionCountryIso2Code), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Region name.
|
||||
if (RegionName != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(RegionName), RegionName);
|
||||
if (StringUtil.IsEmpty(RegionName))
|
||||
responseData.SetControlError(nameof(RegionName), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(RegionName) > GetControlMaxLength(SaxDbDfn.ColumnIdx.Region_Name))
|
||||
responseData.SetControlError(nameof(RegionName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn.ColumnIdx.Region_Name)]);
|
||||
else
|
||||
{
|
||||
// Check for duplicate name.
|
||||
SaxRegion.Params prmRegion = new SaxRegion.Params();
|
||||
if (SysId.IsValid(RegionId))
|
||||
prmRegion.IdsExcluded.Add(RegionId);
|
||||
prmRegion.NameFull = RegionName;
|
||||
prmRegion.StatusCat = SaxRegion.StatusCat.Any;
|
||||
if (ReferenceMgr.GetRegionCount(prmRegion) > 0)
|
||||
responseData.SetControlError(nameof(RegionName), Localiser["msg.validation.duplicate.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Region status.
|
||||
if (RegionStatusCode != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(RegionStatusCode))
|
||||
responseData.SetControlError(nameof(RegionStatusCode), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SaxRegion.ValidStatuses.Contains(RegionStatus))
|
||||
responseData.SetControlError(nameof(RegionStatusCode), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
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.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Security : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Security(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_CSS.Add("css/sax-security.css");
|
||||
AdditionalFiles_JS.Add("js/sax-security.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Page configuration.
|
||||
public bool RequestPasswordMode { get { return !StringUtil.IsEmpty(rpe); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Form properties.
|
||||
public String EmailAddress { get; set; }
|
||||
public String PasswordCurrent { get; set; }
|
||||
public String Password { get; set; }
|
||||
public String PasswordConfirm { get; set; }
|
||||
public bool KeepMeSignedIn { get; set; }
|
||||
/// <summary>Request Password Encrypted params - to allow Change Password without session or requiring old password.</summary>
|
||||
public String rpe { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Sign-in.
|
||||
public bool ValidateSignInData(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Email address.
|
||||
responseData.SetControlValue(nameof(EmailAddress), EmailAddress);
|
||||
if (StringUtil.IsEmpty(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SacsDataValidationHelper.IsValidEmailAddress(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.invalid.value"]);
|
||||
|
||||
// Password.
|
||||
// NB Do not return the password value in the response.
|
||||
if (StringUtil.IsEmpty(Password))
|
||||
responseData.SetControlError(nameof(Password), Localiser["msg.validation.mandatory.value"]);
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Change password.
|
||||
public bool ValidateChangePasswordData(SaxUserAccount userAccount, SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Validate Passwords.
|
||||
// NB Do not return the password values in the response.
|
||||
// NB Only validate populated values - any null values are not part of the form for this request.
|
||||
// - 'Current' password is not shown when changing password from 'Request Password' email link.
|
||||
if (PasswordCurrent != null && StringUtil.IsEmpty(PasswordCurrent))
|
||||
responseData.SetControlError(nameof(PasswordCurrent), Localiser["msg.validation.mandatory.value"]);
|
||||
if (StringUtil.IsEmpty(Password))
|
||||
responseData.SetControlError(nameof(Password), Localiser["msg.validation.mandatory.value"]);
|
||||
if (StringUtil.IsEmpty(PasswordConfirm))
|
||||
responseData.SetControlError(nameof(PasswordConfirm), Localiser["msg.validation.mandatory.value"]);
|
||||
if (!StringUtil.IsEmpty(Password) && !StringUtil.IsEmpty(PasswordConfirm))
|
||||
{
|
||||
if (!Password.Equals(PasswordConfirm))
|
||||
responseData.SetControlError(nameof(PasswordConfirm), Localiser["msg.validation.invalid.value"]);
|
||||
if (!SaxPasswordHelper.IsValidPassword(Password))
|
||||
responseData.SetControlError(nameof(PasswordConfirm), Localiser.GetText("msg.warn.password.invalid", new object[] { SaxPasswordHelper.Params.MinLength, SaxPasswordHelper.Params.MinLengthNoComplexity }));
|
||||
}
|
||||
|
||||
if (!responseData.HasControlErrors())
|
||||
{
|
||||
if (PasswordCurrent != null && !SaxPasswordHelper.VerifyHashedPassword(userAccount, PasswordCurrent))
|
||||
responseData.SetControlError(nameof(PasswordCurrent), Localiser["security.change.password.current.invalid"]);
|
||||
if (SaxPasswordHelper.VerifyHashedPassword(userAccount, Password))
|
||||
responseData.SetControlError(nameof(Password), Localiser["security.change.password.not.changed"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Request Password.
|
||||
public bool ValidateRequestPasswordData(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Email address.
|
||||
responseData.SetControlValue(nameof(EmailAddress), EmailAddress);
|
||||
if (StringUtil.IsEmpty(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SacsDataValidationHelper.IsValidEmailAddress(EmailAddress))
|
||||
responseData.SetControlError(nameof(EmailAddress), Localiser["msg.validation.invalid.value"]);
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_Sport : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_Sport(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_JS.Add("js/sax-sport.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Sport list configuration.
|
||||
public class FilterData
|
||||
{
|
||||
public String Sport { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Sport properties.
|
||||
public SysId SportId { get; set; }
|
||||
public String SportIdValue
|
||||
{
|
||||
get { return SysId.ToString(SportId); }
|
||||
set { SportId = new SysId(StringUtil.ToInt(value)); }
|
||||
}
|
||||
public String SportName { get; set; }
|
||||
public String SportStatusCode { get; set; }
|
||||
public SaStatus SportStatus { get { return SacsSystem.GetStatusForCode(SportStatusCode); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Sport.
|
||||
public bool ValidateSportData(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Sport name.
|
||||
if (SportName != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(SportName), SportName);
|
||||
if (StringUtil.IsEmpty(SportName))
|
||||
responseData.SetControlError(nameof(SportName), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(SportName) > GetControlMaxLength(SaxDbDfn.ColumnIdx.Sport_Name))
|
||||
responseData.SetControlError(nameof(SportName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn.ColumnIdx.Sport_Name)]);
|
||||
else
|
||||
{
|
||||
// Check for duplicate name.
|
||||
SaxSport.Params prmSport = new SaxSport.Params();
|
||||
if (SysId.IsValid(SportId))
|
||||
prmSport.ExcludedIds.Add(SportId);
|
||||
prmSport.NamePartial = SportName;
|
||||
prmSport.StatusCat = SaxSport.StatusCat.Any;
|
||||
if (ReferenceMgr.GetSportCount(prmSport) > 0)
|
||||
responseData.SetControlError(nameof(SportName), Localiser["msg.validation.duplicate.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Sport status.
|
||||
if (SportStatusCode != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(SportStatusCode))
|
||||
responseData.SetControlError(nameof(SportStatusCode), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SaxSport.ValidStatuses.Contains(SportStatus))
|
||||
responseData.SetControlError(nameof(SportStatusCode), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_User : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_User(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
AdditionalFiles_JS.Add("js/sax-user.js");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User list configuration.
|
||||
public class FilterData
|
||||
{
|
||||
public String User { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User properties.
|
||||
public SysId UserAccountId { get; set; }
|
||||
public String UserAccountIdValue
|
||||
{
|
||||
get { return SysId.ToString(UserAccountId); }
|
||||
set { UserAccountId = new SysId(StringUtil.ToInt(value)); }
|
||||
}
|
||||
[EmailAddress]
|
||||
public String UserEmailAddress { get; set; }
|
||||
public String UserTitle { get; set; }
|
||||
public String UserFirstName { get; set; }
|
||||
public String UserLastName { get; set; }
|
||||
public String UserRoleCodeDelim = ",";
|
||||
public List<String> UserRoleCodes { get; set; }
|
||||
public List<String> GetUserRoleCodes()
|
||||
{
|
||||
List<String> codes = new List<string>();
|
||||
foreach (String code in UserRoleCodes)
|
||||
codes.AddRange(code.Split(UserRoleCodeDelim));
|
||||
return codes;
|
||||
}
|
||||
public String UserStatusCode { get; set; }
|
||||
public SaStatus UserStatus { get { return SacsSystem.GetStatusForCode(UserStatusCode); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// User.
|
||||
public bool ValidateUserData(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
// User email.
|
||||
if (UserEmailAddress != null)
|
||||
{
|
||||
UserEmailAddress = UserEmailAddress.ToLowerInvariant();
|
||||
responseData.SetControlValue(nameof(UserEmailAddress), UserEmailAddress);
|
||||
if (StringUtil.IsEmpty(UserEmailAddress))
|
||||
responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(UserEmailAddress) > GetControlMaxLength(SaxDbDfn.ColumnIdx.UserAccount_EmailAddress))
|
||||
responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn.ColumnIdx.UserAccount_EmailAddress)]);
|
||||
else
|
||||
{
|
||||
// Check for duplicate email address.
|
||||
SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params();
|
||||
if (SysId.IsValid(UserAccountId))
|
||||
prmUserAccount.IdsExcluded.Add(UserAccountId);
|
||||
prmUserAccount.EmailAddress = UserEmailAddress;
|
||||
prmUserAccount.StatusCat = SaxUserAccount.StatusCat.Any;
|
||||
if (AccountMgr.GetUserAccountCount(prmUserAccount) > 0)
|
||||
responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.duplicate.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
// User title.
|
||||
if (UserTitle != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(UserTitle))
|
||||
responseData.SetControlError(nameof(UserTitle), Localiser["msg.validation.mandatory.value"]);
|
||||
}
|
||||
|
||||
// User first name.
|
||||
if (UserFirstName != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(UserFirstName), UserFirstName);
|
||||
if (StringUtil.IsEmpty(UserFirstName))
|
||||
responseData.SetControlError(nameof(UserFirstName), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(UserFirstName) > GetControlMaxLength(SaxDbDfn.ColumnIdx.UserAccount_FirstName))
|
||||
responseData.SetControlError(nameof(UserFirstName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn.ColumnIdx.UserAccount_FirstName)]);
|
||||
}
|
||||
|
||||
// User last name.
|
||||
if (UserLastName != null)
|
||||
{
|
||||
responseData.SetControlValue(nameof(UserLastName), UserLastName);
|
||||
if (StringUtil.IsEmpty(UserLastName))
|
||||
responseData.SetControlError(nameof(UserLastName), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(UserLastName) > GetControlMaxLength(SaxDbDfn.ColumnIdx.UserAccount_LastName))
|
||||
responseData.SetControlError(nameof(UserLastName), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn.ColumnIdx.UserAccount_LastName)]);
|
||||
}
|
||||
|
||||
// User status.
|
||||
if (UserStatusCode != null)
|
||||
{
|
||||
if (StringUtil.IsEmpty(UserStatusCode))
|
||||
responseData.SetControlError(nameof(UserStatusCode), Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!SaxUserAccount.ValidStatuses.Contains(UserStatus))
|
||||
responseData.SetControlError(nameof(UserStatusCode), Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxModel_Admin : SaxModel_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
protected SaxModel_Admin(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
Reference in New Issue
Block a user