Web app logon.
This commit is contained in:
@@ -1,25 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Sarand.BusinessMgr.Net.Core</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Sarand.BusinessMgr.Net.Core</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.16" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.31" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsCoreWeb\SacsCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardDbas\SacsStandardDbas.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardBase\SaBusMgrStandardBase.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardDbas\SaBusMgrStandardDbas.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsCoreWeb\SacsCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardDbas\SacsStandardDbas.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardBase\SaBusMgrStandardBase.csproj" />
|
||||
<ProjectReference Include="..\SaBusMgrStandardDbas\SaBusMgrStandardDbas.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Web\Core\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Web\Core\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -38,61 +38,87 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
|
||||
if (configSection != null)
|
||||
{
|
||||
// Environments.
|
||||
foreach (ConfigurationSection environment in configSection.GetSection("Environments").GetChildren())
|
||||
environments.Add(StringUtil.TrimAll(environment.Value));
|
||||
foreach (ConfigurationSection environmentSection in configSection.GetSection("Environments").GetChildren())
|
||||
environments.Add(StringUtil.TrimAll(environmentSection.Value));
|
||||
Instance = StringUtil.OnEmpty(configSection["Instance"], Instance);
|
||||
// Security.
|
||||
IConfigurationSection security = configSection.GetSection("Security");
|
||||
if (security.Exists())
|
||||
IConfigurationSection securitySection = configSection.GetSection("Security");
|
||||
if (securitySection.Exists())
|
||||
{
|
||||
// Security - Password.
|
||||
IConfigurationSection securityPassword = security.GetSection("Password");
|
||||
if (securityPassword.Exists())
|
||||
IConfigurationSection securityPasswordSection = securitySection.GetSection("Password");
|
||||
if (securityPasswordSection.Exists())
|
||||
{
|
||||
Security.Password.MinLength = StringUtil.ToInt(securityPassword["MinLength"], Security.Password.MinLength);
|
||||
Security.Password.MinLength = StringUtil.ToInt(securityPasswordSection["MinLength"], Security.Password.MinLength);
|
||||
}
|
||||
// Security - Sign-Up.
|
||||
IConfigurationSection securitySignUp = security.GetSection("SignUp");
|
||||
if (securitySignUp.Exists())
|
||||
IConfigurationSection securitySignUpSection = securitySection.GetSection("SignUp");
|
||||
if (securitySignUpSection.Exists())
|
||||
{
|
||||
}
|
||||
// Security - Sign-In.
|
||||
IConfigurationSection securitySignIn = security.GetSection("SignIn");
|
||||
if (securitySignIn.Exists())
|
||||
IConfigurationSection securitySignInSection = securitySection.GetSection("SignIn");
|
||||
if (securitySignInSection.Exists())
|
||||
{
|
||||
IConfigurationSection keepLoggedIn = securitySignIn.GetSection("SignIn");
|
||||
if (keepLoggedIn.Exists())
|
||||
IConfigurationSection keepLoggedInSection = securitySignInSection.GetSection("SignIn");
|
||||
if (keepLoggedInSection.Exists())
|
||||
{
|
||||
Security.SignIn.KeepLoggedIn.Allowed = StringUtil.ToBool(StringUtil.OnEmpty(keepLoggedIn["Allowed"], Security.SignIn.KeepLoggedIn.Allowed.ToString()));
|
||||
Security.SignIn.KeepLoggedIn.CookieExpiresDays = StringUtil.ToInt(keepLoggedIn["CookieExpiresDays"], Security.SignIn.KeepLoggedIn.CookieExpiresDays);
|
||||
Security.SignIn.KeepLoggedIn.Allowed = StringUtil.ToBool(StringUtil.OnEmpty(keepLoggedInSection["Allowed"], Security.SignIn.KeepLoggedIn.Allowed.ToString()));
|
||||
Security.SignIn.KeepLoggedIn.CookieExpiresDays = StringUtil.ToInt(keepLoggedInSection["CookieExpiresDays"], Security.SignIn.KeepLoggedIn.CookieExpiresDays);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Email.
|
||||
IConfigurationSection email = configSection.GetSection("Email");
|
||||
if (email.Exists())
|
||||
IConfigurationSection emailSection = configSection.GetSection("Email");
|
||||
if (emailSection.Exists())
|
||||
{
|
||||
Email.Context = email["Context"];
|
||||
PopulateEmailConfig(Email.ContactUs, email.GetSection("ContactUs"));
|
||||
PopulateEmailConfig(Email.Signup_Activate, email.GetSection("Signup").GetSection("Activate"));
|
||||
PopulateEmailConfig(Email.Signup_Welcome, email.GetSection("Signup").GetSection("Welcome"));
|
||||
Email.Context = emailSection["Context"];
|
||||
PopulateEmailConfig(Email.ContactUs, emailSection.GetSection("ContactUs"));
|
||||
PopulateEmailConfig(Email.Signup_Activate, emailSection.GetSection("Signup").GetSection("Activate"));
|
||||
PopulateEmailConfig(Email.Signup_Welcome, emailSection.GetSection("Signup").GetSection("Welcome"));
|
||||
}
|
||||
|
||||
// Documents.
|
||||
IConfigurationSection documents = configSection.GetSection("Documents");
|
||||
if (documents.Exists())
|
||||
IConfigurationSection documentsSection = configSection.GetSection("Documents");
|
||||
if (documentsSection.Exists())
|
||||
{
|
||||
Documents.RootFolder = StringUtil.OnEmpty(documents["RootFolder"], Documents.RootFolder);
|
||||
Documents.RootFolder = StringUtil.OnEmpty(documentsSection["RootFolder"], Documents.RootFolder);
|
||||
}
|
||||
|
||||
// Logging.
|
||||
IConfigurationSection logging = configSection.GetSection("Logging");
|
||||
if (logging.Exists())
|
||||
IConfigurationSection loggingSection = configSection.GetSection("Logging");
|
||||
if (loggingSection.Exists())
|
||||
{
|
||||
Logging.RootFolder = StringUtil.OnEmpty(logging["RootFolder"], Logging.RootFolder);
|
||||
Logging.RootFolder = StringUtil.OnEmpty(loggingSection["RootFolder"], Logging.RootFolder);
|
||||
}
|
||||
// Databases.
|
||||
extractDatabaseConfig(ControlDatabase, configSection.GetSection("ControlDatabase"));
|
||||
extractDatabaseConfig(BusMgrDatabase, configSection.GetSection("BusMgrDatabase"));
|
||||
extractDatabaseConfig(TemplateDatabase, configSection.GetSection("TemplateDatabase"));
|
||||
|
||||
// Control database.
|
||||
IConfigurationSection controlDatabaseSection = configSection.GetSection("ControlDatabase");
|
||||
if (controlDatabaseSection.Exists())
|
||||
{
|
||||
ControlDatabase = new DatabaseConfig();
|
||||
extractDatabaseConfig(ControlDatabase, controlDatabaseSection);
|
||||
}
|
||||
// Template database.
|
||||
IConfigurationSection templateDatabaseSection = configSection.GetSection("TemplateDatabase");
|
||||
if (templateDatabaseSection.Exists())
|
||||
{
|
||||
TemplateDatabase = new DatabaseConfig();
|
||||
extractDatabaseConfig(TemplateDatabase, templateDatabaseSection);
|
||||
}
|
||||
// BusinessMgr databases.
|
||||
IConfigurationSection busMgrDatabasesSection = configSection.GetSection("BusMgrDatabases");
|
||||
if (busMgrDatabasesSection.Exists())
|
||||
{
|
||||
foreach (IConfigurationSection busMgrDbSection in busMgrDatabasesSection.GetChildren())
|
||||
{
|
||||
SbmAppConfig.DatabaseConfig dbConfig = new SbmAppConfig.DatabaseConfig();
|
||||
extractDatabaseConfig(dbConfig, busMgrDbSection);
|
||||
BusMgrDatabases.Add(dbConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// Variants.
|
||||
foreach (ConfigurationSection variantSection in configSection.GetSection("Variants").GetChildren())
|
||||
{
|
||||
@@ -117,6 +143,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
|
||||
private void extractDatabaseConfig(DatabaseConfig database, IConfigurationSection databaseSection)
|
||||
{
|
||||
if (!databaseSection.Exists()) return;
|
||||
IConfigurationSection identifiersSection = databaseSection.GetSection("Identifiers");
|
||||
if (identifiersSection.Exists())
|
||||
{
|
||||
foreach (var identifier in identifiersSection.GetChildren())
|
||||
database.Identifiers.Add(StringUtil.TrimAll(identifier.Value));
|
||||
}
|
||||
database.Location = StringUtil.OnEmpty(databaseSection["Location"], database.Location);
|
||||
database.User = StringUtil.OnEmpty(databaseSection["User"], database.User);
|
||||
database.Password = StringUtil.OnEmpty(databaseSection["Password"], database.Password);
|
||||
@@ -179,13 +211,14 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
|
||||
// Databases.
|
||||
public class DatabaseConfig
|
||||
{
|
||||
public List<String> Identifiers { get; } = new List<string>();
|
||||
public String Location { get; internal set; }
|
||||
public String User { get; internal set; }
|
||||
public String Password { get; internal set; }
|
||||
}
|
||||
public DatabaseConfig ControlDatabase { get; } = new DatabaseConfig();
|
||||
public DatabaseConfig BusMgrDatabase { get; } = new DatabaseConfig();
|
||||
public DatabaseConfig TemplateDatabase { get; } = new DatabaseConfig();
|
||||
public DatabaseConfig ControlDatabase { get; private set; }
|
||||
public DatabaseConfig TemplateDatabase { get; private set; }
|
||||
public List<DatabaseConfig> BusMgrDatabases { get; } = new List<DatabaseConfig>();
|
||||
// Documents.
|
||||
public class DocumentsConfig
|
||||
{
|
||||
|
||||
@@ -68,7 +68,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
|
||||
applicationParams.Add("Configuration", SbmSystem.DebugMode ? "Debug" : "Release");
|
||||
applicationParams.Add("Environment", EnvironmentName);
|
||||
applicationParams.Add("Control database", AppConfig.ControlDatabase.Location);
|
||||
applicationParams.Add("BusMgr database", AppConfig.BusMgrDatabase.Location);
|
||||
foreach (SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases)
|
||||
applicationParams.Add("BusMgr database", (dbConfig.Identifiers.Any() ? $"[{String.Join(",", dbConfig.Identifiers)}] " : "") + dbConfig.Location);
|
||||
applicationParams.Add("Application root", SbmSystem.ApplicationFolder);
|
||||
if (!StringUtil.IsEmpty(AppConfig.Documents.RootFolder))
|
||||
applicationParams.Add("Documents root", AppConfig.Documents.RootFolder);
|
||||
|
||||
@@ -20,16 +20,22 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
|
||||
{
|
||||
securityProfile = new SbmSecurityProfile(this, false);
|
||||
}
|
||||
// Protected construction.
|
||||
protected SbmSessionData_Web(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation) :
|
||||
base(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation)
|
||||
{
|
||||
securityProfile = new SbmSecurityProfile(this, false);
|
||||
}
|
||||
// Protected construction.
|
||||
protected SbmSessionData_Web(SbmSessionContext sessionContext) :
|
||||
base(sessionContext)
|
||||
{
|
||||
securityProfile = new SbmSecurityProfile(this, false);
|
||||
}
|
||||
// Protected construction.
|
||||
protected SbmSessionData_Web(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation) :
|
||||
base(sessionContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation)
|
||||
{
|
||||
securityProfile = new SbmSecurityProfile(this, false);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Security Profile.
|
||||
private readonly SbmSecurityProfile securityProfile;
|
||||
//-------------------------------------------------------------------
|
||||
// Security Profile.
|
||||
private readonly SbmSecurityProfile securityProfile;
|
||||
public ISbmSecurityProfile SecurityProfile { get { return securityProfile; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.App
|
||||
public class SbmUserContext_Web : SbmUserContext
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data memebrs.
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
|
||||
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Sacs.Web.Components;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Models;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
@@ -40,7 +41,7 @@ using System.Web;
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SbmController_Base : Controller
|
||||
public abstract class SbmController_Base : SaController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
@@ -67,27 +68,11 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public bool DebugMode { get; } = SacsSystem.DebugMode;
|
||||
protected SbmApplication_Web App { get { return SbmGlobals_Web.Application; } }
|
||||
public SbmAppConfig AppConfig { get { return App.AppConfig; } }
|
||||
public SbmSessionContext SessionContext { get { return SessionData?.SessionContext ?? null; } }
|
||||
public ISbmUserContext UserContext { get { return SessionData; } }
|
||||
protected SbmLocaliser Localiser { get; }
|
||||
/// <summary>
|
||||
/// Indicate whether session data should be stored by action.
|
||||
/// <para>Any action that might modify the session data must store it.</para>
|
||||
/// <para>Some actions such as scoring a password's complexity don't need to.</para>
|
||||
/// </summary>
|
||||
public virtual bool StoreSessionData { get; protected set; } = true;
|
||||
// Culture.
|
||||
private string LanguageIso2
|
||||
{
|
||||
get
|
||||
{
|
||||
var feature = HttpContext.Features.Get<IRequestCultureFeature>();
|
||||
return feature.RequestCulture.UICulture.TwoLetterISOLanguageName.ToLower();
|
||||
}
|
||||
}
|
||||
// Business components.
|
||||
public SbmInternals Internals { get { if (internals == null) internals = new SbmInternals(UserContext); return internals; } }
|
||||
// Managers.
|
||||
@@ -119,36 +104,6 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers
|
||||
public SaEmailConfig EmailConfig { get { return Internals.EmailConfig; } }
|
||||
public SbmEmailConsole EmailConsole { get { return Internals.EmailConsole; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Redirection locations.
|
||||
//-------------------------------------------------------------------
|
||||
public static readonly String ParamName_SessionExpired = "SessionExpired";
|
||||
protected enum RedirectLocation
|
||||
{
|
||||
WebAppBase,
|
||||
WebAppHome,
|
||||
WebAppHome_SessionExpired,
|
||||
}
|
||||
protected String GetRedirectLocation(RedirectLocation redirectLocation)
|
||||
{
|
||||
string protocol = Request.Scheme;
|
||||
var parameters = new RouteValueDictionary();
|
||||
String homeAction = Url.Action("Index", "Home", parameters, protocol);
|
||||
switch (redirectLocation)
|
||||
{
|
||||
case RedirectLocation.WebAppBase:
|
||||
return Regex.Replace(homeAction, "\\/$", "") + "/";
|
||||
case RedirectLocation.WebAppHome:
|
||||
return homeAction;
|
||||
case RedirectLocation.WebAppHome_SessionExpired:
|
||||
// Set the session expired parameter so that the page can report it.
|
||||
// NB Paramater must have a value to be included in the URL query string.
|
||||
parameters.Add(ParamName_SessionExpired, "1");
|
||||
return homeAction;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Action execution events.
|
||||
//-------------------------------------------------------------------
|
||||
@@ -205,6 +160,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers
|
||||
if (model == null) return;
|
||||
|
||||
// Session data.
|
||||
model.Controller = this;
|
||||
model.SessionData_Web = SessionData;
|
||||
|
||||
// Redirect locations.
|
||||
@@ -213,73 +169,6 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers
|
||||
model.RedirectLocation.Home_SessionExpired = GetRedirectLocation(RedirectLocation.WebAppHome_SessionExpired);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Parameters.
|
||||
//-------------------------------------------------------------------
|
||||
public String EncryptParameters(NameValueCollection parameters, String base64IV, String base64Key)
|
||||
{
|
||||
String fn = nameof(ControllerBase) + ".EncryptParameters";
|
||||
try
|
||||
{
|
||||
// Copy the list of parameters, adding a random name/value pair to randomise the encryption.
|
||||
NameValueCollection parametersToEncrypt = new NameValueCollection(parameters);
|
||||
// NB Range 10-189 intended to have equal chance of 2 or 3 digit number.
|
||||
parametersToEncrypt.Add("!" + SacsRandomHelper.GetInt32(10, 190).ToString(), SacsRandomHelper.GetInt32(10, 190).ToString());
|
||||
|
||||
// Sort the keys to ensure that the random '!' param is first in the query string.
|
||||
String[] paramKeys = parametersToEncrypt.AllKeys;
|
||||
Array.Sort(paramKeys);
|
||||
|
||||
// Serialise parameters as if in a URL query string - so that they can be deserialised in DecryptParameters() below.
|
||||
string queryString = String.Join("&", paramKeys.Select(a => a + "=" + HttpUtility.UrlEncode(parametersToEncrypt[a])));
|
||||
String encrypted = SacsEncryptionHelper.Encrypt(queryString, base64IV, base64Key);
|
||||
if (DebugMode)
|
||||
{
|
||||
SaLogger.Debug(fn + " Encrypted: " + encrypted);
|
||||
NameValueCollection decryptedParams = DecryptParameters(encrypted, base64IV, base64Key);
|
||||
}
|
||||
return encrypted;
|
||||
}
|
||||
catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return "";
|
||||
}
|
||||
public NameValueCollection DecryptParameters(String encrypted, String base64IV, String base64Key)
|
||||
{
|
||||
String fn = nameof(ControllerBase) + ".DecryptParameters";
|
||||
if (DebugMode) SaLogger.Debug(fn + " \n\tEncrypted: " + encrypted + "\n\tIV: " + base64IV + "\n\tKey: " + base64Key);
|
||||
try
|
||||
{
|
||||
String queryString = SacsEncryptionHelper.Decrypt(encrypted, base64IV, base64Key);
|
||||
return HttpUtility.ParseQueryString(queryString);
|
||||
}
|
||||
catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return new NameValueCollection();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Cookies.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Retrieve the value from the named request cookie.</summary>
|
||||
public String GetRequestCookie(String key)
|
||||
{
|
||||
if (Request.Cookies.ContainsKey(key))
|
||||
return Request.Cookies[key];
|
||||
return null;
|
||||
}
|
||||
/// <summary>Set the value against the named response cookie.</summary>
|
||||
public void SetResponseCookie(string key, string value, DateTime? expiresAt = null, bool isEssential = false)
|
||||
{
|
||||
CookieOptions options = new CookieOptions();
|
||||
options.HttpOnly = true;
|
||||
options.Secure = true;
|
||||
options.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
|
||||
if (expiresAt.HasValue)
|
||||
options.Expires = expiresAt;
|
||||
if (isEssential)
|
||||
options.IsEssential = true;
|
||||
Response.Cookies.Append(key, value, options);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session.
|
||||
//-------------------------------------------------------------------
|
||||
@@ -366,193 +255,6 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Controllers
|
||||
}
|
||||
protected abstract SbmSessionData_Web DeserializeSessionData(String sessionDataJson);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Ajax actions.
|
||||
//-------------------------------------------------------------------
|
||||
protected static readonly Encoding ajaxResponseEncoding = Encoding.UTF8;
|
||||
protected IActionResult GetAjaxResult_GoHome(AjaxResponse_Base responseData)
|
||||
{
|
||||
responseData.SetGoHome();
|
||||
return Json(responseData);
|
||||
}
|
||||
protected IActionResult GetAjaxResult_InvalidSession(AjaxResponse_Base responseData)
|
||||
{
|
||||
responseData.SetGoHome();
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Base Ajax Response Data.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Base
|
||||
{
|
||||
// Response status.
|
||||
public bool? Success { get; set; } = null;
|
||||
public bool? Error { get; set; } = null;
|
||||
public bool? SessionExpired { get; protected set; } = null;
|
||||
public bool? GoHome { get; protected set; } = null;
|
||||
public AjaxResponse_Base SetSessionExpired(String title, String text)
|
||||
{
|
||||
SessionExpired = true;
|
||||
return SetMessage(title, text);
|
||||
}
|
||||
public AjaxResponse_Base SetGoHome()
|
||||
{
|
||||
GoHome = true;
|
||||
return this;
|
||||
}
|
||||
public AjaxResponse_Base SetGoHome(String title, String text)
|
||||
{
|
||||
GoHome = true;
|
||||
return SetMessage(title, text);
|
||||
}
|
||||
// Message - displays alert popup.
|
||||
public class MessageData
|
||||
{
|
||||
public String Title { get; set; }
|
||||
public String Text { get; set; }
|
||||
}
|
||||
public MessageData Message { get; private set; }
|
||||
public AjaxResponse_Base SetMessage(String title, String text)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(text))
|
||||
Message = new MessageData() { Title = title, Text = text };
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Ajax Response Data.
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Data : AjaxResponse_Base
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
// Construction.
|
||||
protected AjaxResponse_Data(SbmModel_Base model)
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Common item response data properties.
|
||||
/// <para>- Null values are ignored by the JSON serialiser.</para>
|
||||
/// <para>- Return null for false boolean values where possible.</para>
|
||||
/// <para>- Return null for blank string values where possible.</para>
|
||||
/// </summary>
|
||||
public class ItemData
|
||||
{
|
||||
public String Id { get; set; }
|
||||
private String notes;
|
||||
public String Notes { get { return StringUtil.OnEmpty(notes, null); } set { notes = StringUtil.EmptyOnNull(value).Trim(); } }
|
||||
public String StatusCode { get; set; }
|
||||
public String StatusDesc { get; set; }
|
||||
public bool? Awaiting { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Awaiting)) ? true : (bool?)null; } }
|
||||
public bool? Active { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Active)) ? true : (bool?)null; } }
|
||||
public bool? Deleted { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Deleted)) ? true : (bool?)null; } }
|
||||
public String CreatedOn { get; set; }
|
||||
public String CreatedOnFmt { get; set; }
|
||||
public String UpdatedOn { get; set; }
|
||||
public String UpdatedOnFmt { get; set; }
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Form data.
|
||||
public class FormControlValue
|
||||
{
|
||||
public FormControlValue(String controlName, String value, String error)
|
||||
{
|
||||
ControlName = controlName;
|
||||
Value = value;
|
||||
Error = error;
|
||||
}
|
||||
public String ControlName { get; }
|
||||
public String Value { get; set; }
|
||||
public String Error { get; set; }
|
||||
}
|
||||
private readonly Dictionary<String, FormControlValue> controlValues = new Dictionary<String, FormControlValue>();
|
||||
public List<FormControlValue> ControlValues { get { return controlValues.Count > 0 ? controlValues.Values.ToList() : null; } }
|
||||
public void SetControlValue(String controlName, String value, String error = null)
|
||||
{
|
||||
if (controlValues.ContainsKey(controlName))
|
||||
{
|
||||
// Modify existing entry in the list.
|
||||
FormControlValue controlValue = controlValues[controlName];
|
||||
if (value != null) controlValue.Value = value;
|
||||
if (error != null) controlValue.Error = error;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new control to list.
|
||||
controlValues.Add(controlName, new FormControlValue(controlName, value, error));
|
||||
}
|
||||
}
|
||||
/// <summary>Assign the error to the control by name and return this response data.</summary>
|
||||
public AjaxResponse_Data SetControlError(String controlName, String error)
|
||||
{
|
||||
return SetControlError(controlName, error, this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Assign the error to the control by name and return the specified value.
|
||||
/// <para>- Allows alternative return values to be specified (eg. 'false') to avoid separate return statement in calling routine.</para>
|
||||
/// </summary>
|
||||
public T SetControlError<T>(String controlName, String error, T returnValue)
|
||||
{
|
||||
SetControlValue(controlName, null, error);
|
||||
return returnValue;
|
||||
}
|
||||
public bool HasControlErrors()
|
||||
{
|
||||
foreach (FormControlValue controlValue in controlValues.Values)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(controlValue.Error)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Notification - briefly displays after response received.
|
||||
public class NotificationData
|
||||
{
|
||||
public String Title { get; set; }
|
||||
public String Message { get; set; }
|
||||
}
|
||||
public NotificationData Notification { get; private set; }
|
||||
public AjaxResponse_Data SetNotification(String title, String message)
|
||||
{
|
||||
Notification = new NotificationData() { Title = title, Message = message };
|
||||
return this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Paged data.
|
||||
public class PagingData
|
||||
{
|
||||
public PagingData(SbmModel_Base model) :
|
||||
this(model.Paging.PageNo, model.Paging.PageLength, model.Paging.ItemCount, model.Paging.ItemTotal)
|
||||
{ }
|
||||
public PagingData(uint pageNo, ushort pageLength, ushort itemCount, ulong itemTotal)
|
||||
{
|
||||
PageNo = pageNo;
|
||||
PageLength = pageLength;
|
||||
ItemCount = itemCount;
|
||||
ItemTotal = itemTotal;
|
||||
}
|
||||
public bool Paged { get { return (PageNo > 0 && PageLength > 0 && ItemTotal > PageLength); } }
|
||||
public uint PageNo { get; } = 0;
|
||||
public ushort PageLength { get; } = 0;
|
||||
public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / PageLength) : 0); } }
|
||||
public ushort ItemCount { get; } = 0;
|
||||
public ulong ItemTotal { get; } = 0;
|
||||
}
|
||||
public PagingData Paging { get; private set; }
|
||||
public void SetPaging(SbmModel_Base model)
|
||||
{
|
||||
Paging = new PagingData(model);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
@@ -37,13 +37,13 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Helpers
|
||||
/// Identify the session context that corresponds with the BusinessMgr
|
||||
/// database for the specified user by email address.
|
||||
/// </summary>
|
||||
public static List<ushort> GetSessionContextIdxsForUsersBusMgrDatabase(String emailAddress)
|
||||
public static List<ushort> GetSessionContextIdxsForContextUserEmail(String dbIdentifier, String emailAddress)
|
||||
{
|
||||
String fn = className + ".GetSessionContextIdxForUsersBusMgrDatabase";
|
||||
String alias_SecurityItem = "SecItm";
|
||||
String alias_Affiliate = "Affil";
|
||||
List<ushort> sessionContextIdxs = new List<ushort>();
|
||||
if (StringUtil.IsEmpty(emailAddress)) return sessionContextIdxs;
|
||||
if (SacsSystem.DebugMode) SaLogger.Info($"{SysUtil.Fn} Searching for database. Identifier: {dbIdentifier}. Email address: {emailAddress}");
|
||||
|
||||
// Get the session context indices defined by the application.
|
||||
SbmApplication_Web app = SbmGlobals_Web.Application;
|
||||
@@ -53,16 +53,20 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Helpers
|
||||
SbmSessionContext sessionContext = app.GetSessionContext(sessionContextIdx);
|
||||
if (sessionContext == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve SessionContext for idx: " + sessionContextIdx);
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve SessionContext for idx: " + sessionContextIdx);
|
||||
continue;
|
||||
}
|
||||
// Retrieve the BusinessMgr database.
|
||||
ISacsDatabase db = app.GetBusMgrDatabase(sessionContext);
|
||||
// Verify Db Identifier.
|
||||
List<string> dbIdentifiers = app.GetDbIdentifiers(sessionContext);
|
||||
if (!dbIdentifiers.ContainsCI(dbIdentifier))
|
||||
continue;
|
||||
ISacsDatabase db = app.GetBusMgrDatabase(sessionContext);
|
||||
if (db == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve SessionContext for idx: " + sessionContextIdx);
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to retrieve Database for idx: " + sessionContextIdx);
|
||||
continue;
|
||||
}
|
||||
if (SacsSystem.DebugMode) SaLogger.Info($"{SysUtil.Fn} Database: " + db.DatabaseName);
|
||||
|
||||
// Query to check for Security Item matching the email with associated Affiliate.
|
||||
// NB This is done independently for each database in case there are different
|
||||
@@ -70,6 +74,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Helpers
|
||||
DbQuery qry = new DbQuery(db.DbmsType);
|
||||
qry.Tables.Add(SaSecurityDbDfn.GetTableName(SaSecurityDbDfn.TableIdx.SaSecItem), alias_SecurityItem);
|
||||
qry.Columns.Add(SaSecurityDbDfn.GetColumnNameQual(SaSecurityDbDfn.ColumnIdx.SaSecItem_Id, alias_SecurityItem));
|
||||
qry.Columns.Add(SaSecurityDbDfn.GetColumnNameQual(SaSecurityDbDfn.ColumnIdx.SaSecItem_Id, alias_SecurityItem));
|
||||
qry.Filters.Add(SaSecurityDbDfn.GetColumnNameQual(SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress, alias_SecurityItem) + "='" + DbQuery.FormatForCondition(emailAddress) + "'");
|
||||
// Join to the Affiliate table.
|
||||
DbQueryJoin joinAffiliate = new DbQueryJoin(DbJoinType.FullOuter);
|
||||
@@ -80,7 +85,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Helpers
|
||||
using (DbResultSet resultSet = DbResultSet_DataReader.ExecuteQuery(db, qry.BuildQuery()))
|
||||
{
|
||||
if (resultSet != null && resultSet.NextRecord())
|
||||
{
|
||||
if (SacsSystem.DebugMode) SaLogger.Info($"{SysUtil.Fn} Database contains email: " + db.DatabaseName);
|
||||
sessionContextIdxs.Add(sessionContextIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sessionContextIdxs;
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Middleware
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
await Task.CompletedTask;
|
||||
return AuthenticateResult.NoResult();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -56,10 +57,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Middleware
|
||||
string fn = GetType().Name + ".SetProperty";
|
||||
//if (SbmSystem.DebugMode) Logger.Debug(fn + " Form property " + modelName + ": '" + result.Model.ToString() + ".");
|
||||
object originalValue = result.Model;
|
||||
// Exclude properties that retain leading/trailing whitespace.
|
||||
if (result.Model is string)
|
||||
// Anything that looks like a password will be left as is.
|
||||
bool password = modelName.ContainsCI("Password");
|
||||
// Exclude properties that retain leading/trailing whitespace.
|
||||
if (result.Model is string)
|
||||
{
|
||||
if (!modelName.ContainsCI("Password"))
|
||||
if (!password)
|
||||
{
|
||||
string value = result.Model as string;
|
||||
|
||||
@@ -89,9 +92,16 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Middleware
|
||||
result = ModelBindingResult.Success(value);
|
||||
}
|
||||
}
|
||||
if (result.Model != null && SbmSystem.DebugMode)
|
||||
SaLogger.Debug(fn + " Form property " + modelName + ": '" + result.Model.ToString() + "'." + (originalValue != null && !originalValue.Equals(result.Model) ? " Original value: '" + originalValue.ToString() + "'" : ""));
|
||||
base.SetProperty(bindingContext, modelName, propertyMetadata, result);
|
||||
// Log property details.
|
||||
if (result.Model != null && SbmSystem.DebugMode &&
|
||||
// Ignore passwords.
|
||||
!password &&
|
||||
// Ignore items that correspond with objects in the model rather than values.
|
||||
!result.Model.ToString().Equals(result.Model.GetType().FullName) &&
|
||||
// Ignore form files.
|
||||
!result.Model.ToString().ContainsCI("Microsoft.AspNetCore.Http.IFormFile"))
|
||||
SaLogger.Debug(SysUtil.Fn + " Form property " + modelName + ": '" + result.Model.ToString() + "'." + (originalValue != null && !originalValue.Equals(result.Model) ? " Original value: '" + originalValue.ToString() + "'" : ""));
|
||||
base.SetProperty(bindingContext, modelName, propertyMetadata, result);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Middleware
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
||||
throw exc;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Sacs.Web.Components;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
|
||||
@@ -18,19 +20,17 @@ using Sarand.Net.Standard.Base.UpdateLog;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.BusinessMgr.Net.Core.Web.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmModel_Base
|
||||
public class SbmModel_Base : SaModel
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SbmInternals internals;
|
||||
private readonly List<String> infoMessages = new List<string>();
|
||||
private readonly List<String> warningMessages = new List<string>();
|
||||
private readonly List<String> errorMessages = new List<string>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
@@ -49,16 +49,14 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Models
|
||||
public SbmSessionData_Web SessionData_Web { get; set; }
|
||||
public SbmSessionContext SessionContext { get { return SessionData?.SessionContext ?? null; } }
|
||||
public DbUpdateInfo DbUpdateInfo { get { return SessionData?.DbUpdateInfo ?? new DbUpdateInfo(null, "", SbmSystem.ComputerName); } }
|
||||
public bool DebugMode { get { return SbmSystem.DebugMode; } }
|
||||
public SbmLocaliser Localiser { get; }
|
||||
// Request properties.
|
||||
public SbmController_Base Controller { get; set; }
|
||||
public CultureInfo SessionCulture { get { return Controller?.SessionCulture ?? CultureInfo.InvariantCulture; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Page configuration.
|
||||
public bool OK { get { return !HasMessages(); } }
|
||||
public virtual bool ProhibitCache { get; set; } = true;
|
||||
public String PageCaption { get; set; }
|
||||
public String InstanceVersion { get { return !StringUtil.IsEmpty(App.AppConfig.Instance) ? App.AppConfig.Instance + " v" + Sbm.Version.GetFullVersion() : "v" + Sbm.Version.GetAppVersion(); } }
|
||||
public bool IncludeGoogleAnalytics { get; set; } = false;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Business components.
|
||||
@@ -100,7 +98,23 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Models
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Form control value max length.
|
||||
/// Form control value max length - Security tables.
|
||||
/// <para>In many cases the database columns allow plenty of extra space for the value, in case they need to be encrypted.</para>
|
||||
/// <para>Hence, several cases where the value entered in the control isn't allowed the full database length.</para>
|
||||
/// </summary>
|
||||
public int GetControlMaxLength(SaSecurityDbDfn.ColumnIdx column)
|
||||
{
|
||||
int maxLength = (int)SaSecurityDbDfn.GetColTextLen(column);
|
||||
switch (column)
|
||||
{
|
||||
case SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress:
|
||||
return Math.Min(maxLength, 100);
|
||||
}
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Form control value max length - BusinessMgr tables.
|
||||
/// <para>In many cases the database columns allow plenty of extra space for the value, in case they need to be encrypted.</para>
|
||||
/// <para>Hence, several cases where the value entered in the control isn't allowed the full database length.</para>
|
||||
/// </summary>
|
||||
@@ -110,7 +124,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Models
|
||||
switch (column)
|
||||
{
|
||||
case SbmDbDfn.ColumnIdx.Affiliate_Email:
|
||||
return Math.Min(maxLength, 60);
|
||||
return Math.Min(maxLength, 100);
|
||||
case SbmDbDfn.ColumnIdx.Affiliate_FirstName:
|
||||
case SbmDbDfn.ColumnIdx.Affiliate_LastName:
|
||||
return Math.Min(maxLength, 40);
|
||||
@@ -138,6 +152,17 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Models
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Display data - Dates.
|
||||
public String FormatDateForDisplay(DateTime value)
|
||||
{
|
||||
return DateUtil.Format(value, "d-MMM-yy", SessionCulture);
|
||||
}
|
||||
public String FormatDateTimeForDisplay(DateTime value)
|
||||
{
|
||||
return StringUtil.TrimAll(DateUtil.Format(value, "d-MMM-yy HH:mm", SessionCulture));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Form data - Dates.
|
||||
// Format may depend on locale, but as long as these methods are used consistently,
|
||||
@@ -208,71 +233,10 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Models
|
||||
/// <summary>List of Commodity Types for dropdown.</summary>
|
||||
public IEnumerable<SelectListItem> GetCommodityTypeCodesForSelect()
|
||||
{
|
||||
|
||||
|
||||
return new SelectList(GetCodesOfType(Sbm.SystemCode.CommodityType), "Code", "Desc");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Version parameter for includes.
|
||||
public String HrefVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime versionDate = SbmSystem.AssemblyBuildAt;
|
||||
if (!DateUtil.IsValid(versionDate) || SbmSystem.DebugMode)
|
||||
versionDate = DateTime.Now;
|
||||
return DateUtil.Format(versionDate, "yyyyMMdd" /*+ (SacsSystem.Debug ? "HHmm" : "")*/);
|
||||
}
|
||||
}
|
||||
// Additional includes.
|
||||
public List<String> AdditionalFiles_CSS { get; set; } = new List<string>();
|
||||
public List<String> AdditionalFiles_JS { get; set; } = new List<string>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Redirection locations.
|
||||
public class RedirectLocationData
|
||||
{
|
||||
// Properties populated in Controller_Base.OnActionExecuted.
|
||||
public String Base { get; internal set; }
|
||||
public String Home { get; internal set; }
|
||||
public String Home_SessionExpired { get; internal set; }
|
||||
}
|
||||
public RedirectLocationData RedirectLocation { get; } = new RedirectLocationData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Paging properties.
|
||||
public class DataPaging
|
||||
{
|
||||
private DbQuery.Paging paging { get; } = new DbQuery.Paging();
|
||||
public void PopulatePagingTo(DbQuery.Paging resultsPaging)
|
||||
{
|
||||
resultsPaging.PageLength = paging.PageLength;
|
||||
resultsPaging.PageNo = paging.PageNo;
|
||||
}
|
||||
public bool IsPaged { get { return paging.Paged; } }
|
||||
public uint PageNo { get { return paging.PageNo; } set { paging.PageNo = value; } }
|
||||
public ushort PageLength { get { return paging.PageLength; } set { paging.PageLength = value; } }
|
||||
public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / PageLength) : 0); } }
|
||||
public ushort ItemCount { get; set; }
|
||||
private ulong itemTotal = 0;
|
||||
public ulong ItemTotal
|
||||
{
|
||||
get { return itemTotal; }
|
||||
set
|
||||
{
|
||||
itemTotal = value;
|
||||
// Check whether the total number of items is less than the current page and reduce page no if needed.
|
||||
if (IsPaged && (PageNo - 1) * PageLength > itemTotal)
|
||||
PageNo = (uint)((itemTotal - 1) / PageLength + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
public DataPaging Paging { get; } = new DataPaging();
|
||||
public void PopulatePagingTo(DbQuery.Paging resultsPaging)
|
||||
{
|
||||
Paging.PopulatePagingTo(resultsPaging);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Form properties.
|
||||
/// <summary>
|
||||
@@ -280,38 +244,9 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Models
|
||||
/// <para>Equivalent to the Site index on the login form.</para>
|
||||
/// <para>Populates value on logout form to identify default site for next login.</para>
|
||||
/// </summary>
|
||||
public ushort SessionIdx { get { return SessionContext.Index; } }
|
||||
public ushort SessionIdx { get { return SessionContext?.Index ?? 0; } }
|
||||
public String FormAction { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Messages.
|
||||
//-------------------------------------------------------------------
|
||||
public bool HasMessages()
|
||||
{
|
||||
return infoMessages.Count > 0 || warningMessages.Count > 0 || errorMessages.Count > 0;
|
||||
}
|
||||
public List<String> InfoMessages { get { return new List<string>(infoMessages); } }
|
||||
public List<String> WarningMessages { get { return new List<string>(warningMessages); } }
|
||||
public List<String> ErrorMessages { get { return new List<string>(errorMessages); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Form messages.
|
||||
public void AddInfoMessage(String message)
|
||||
{
|
||||
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||
infoMessages.Add(message);
|
||||
}
|
||||
public void AddWarningMessage(String message)
|
||||
{
|
||||
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||
warningMessages.Add(message);
|
||||
}
|
||||
public void AddErrorMessage(String message)
|
||||
{
|
||||
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||
errorMessages.Add(message);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
Reference in New Issue
Block a user