Files

223 lines
9.2 KiB
C#

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Data;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Sarand.BusinessMgr.Net.Core.Web.Components
{
//=======================================================================
public abstract class SbmController_Web : SbmController_Base
{
//-------------------------------------------------------------------
// Data members.
private SbmInternals_Control internals_Control;
//-------------------------------------------------------------------
// Protected construction.
protected SbmController_Web(SbmLocaliser localiser) : base(localiser)
{
// Initialise console (debug) logging listener.
//if (Directory.Exists(App.LoggingRootFolder) && SbmSystem.DebugMode)
// SbmConsoleListener.ConfigureDebugListener(App.LoggingRootFolder);
if (DebugMode) SaLogger.Trace($"{GetType().Name}.CTR");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (internals_Control != null) internals_Control.Dispose(); internals_Control = null;
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
protected override SbmSessionContext SessionContext { get { return SessionData?.SessionContext ?? null; } }
// Control database.
protected SbmInternals_Control Internals_Control { get { if (internals_Control == null) { internals_Control = new SbmInternals_Control(); } return internals_Control; } }
protected SbmcAccountMgr ControlAccountMgr { get { return Internals_Control.ControlAccountMgr; } }
protected SbmcInstanceMgr ControlInstanceMgr { get { return Internals_Control.ControlInstanceMgr; } }
protected SbmcItemMgr ControlItemMgr { get { return Internals_Control.ControlItemMgr; } }
//-------------------------------------------------------------------
// Action execution events.
//-------------------------------------------------------------------
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//if (DebugMode) SaLogger.Debug($"{SysUtil.Fn}" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
// Refreh model properties.
SbmModel_Base baseModel = ViewData.Model as SbmModel_Base;
RefreshModel(baseModel);
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//if (DebugMode) SaLogger.Debug($"{SysUtil.Fn}" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
// Refreh model properties.
SbmModel_Base baseModel = ViewData.Model as SbmModel_Base;
RefreshModel(baseModel);
// Store session data if present - as potentially modfied.
if (SessionData != null)
{
// Most actions will store the session data in case it's been modified.
// Some actions (eg. score password) don't need to.
if (StoreSessionData)
{
string sessionDataJson = JsonConvert.SerializeObject(SessionData, SessionDataJsonSerializerSettings);
HttpContext.Session.Set(SessionStorage.SessionKey_SessionData, SessionStorage.sessionDataEncoding.GetBytes(sessionDataJson));
}
}
else HttpContext.Session.Remove(SessionStorage.SessionKey_SessionData);
// Response headers.
if (baseModel != null && baseModel.ProhibitCache)
{
if (Response.Headers.ContainsKey(HeaderNames.CacheControl))
Response.Headers.Remove(HeaderNames.CacheControl);
Response.Headers.Append(HeaderNames.CacheControl, "no-cache, no-store, must-revalidate");
Response.Headers.Append(HeaderNames.Pragma, "no-cache");
Response.Headers.Append(HeaderNames.Expires, "0");
}
base.OnActionExecuted(filterContext);
}
//-------------------------------------------------------------------
// Model.
protected virtual void RefreshModel(SbmModel_Base model)
{
if (model == null) return;
// Session data.
model.SetController(this);
model.SetSessionData(SessionData);
// Redirect locations.
model.RedirectLocation.Base = GetRedirectLocation(RedirectLocation.WebAppBase);
model.RedirectLocation.Home = GetRedirectLocation(RedirectLocation.WebAppHome);
model.RedirectLocation.Home_SessionExpired = GetRedirectLocation(RedirectLocation.WebAppHome_SessionExpired);
}
//-------------------------------------------------------------------
// Online encryption parameters.
//-------------------------------------------------------------------
// Portal Request Password encryption key is defined in
// the base Controller so that they can be shared with the Control application.
protected static string Base64Key_RequestPassword_Portal { get; } = SacsEncryptionHelper.EncodePlainKey("[5Abus1neSSmGR~Request#Password}", SacsEncryptionHelper.KeyLength);
//-------------------------------------------------------------------
// Session.
//-------------------------------------------------------------------
protected bool ValidUserSession { get { return SessionData?.ValidUser ?? false; } }
protected DbUpdateInfo DbUpdateInfo { get { return SessionData?.DbUpdateInfo ?? new DbUpdateInfo(null, "", SacsSystem.ComputerName); } }
// Referrer.
protected string Referer { get { return Request.Headers["Referer"].ToString(); } }
protected bool ValidReferer { get { return !Referer.IsEmpty(); } }
/// <summary>Store session data, eg. to start a new user session on sign-in.</summary>
protected bool SetSessionData(SbmSessionData_Web sessionData)
{
if (sessionStorage.SessionData != null) return false;
sessionStorage.SessionData = sessionData;
return true;
}
protected void ClearSessionData()
{
if (HttpContext.Session.IsAvailable)
HttpContext.Session.Clear();
sessionStorage.SessionData = null;
}
//-------------------------------------------------------------------
// Session storage.
public class SessionStorage
{
public SbmSessionData_Web SessionData { get; set; }
public static string SessionKey_SessionData { get; } = "SbmSessionData";
public static Encoding sessionDataEncoding { get; } = Encoding.UTF8;
//JSON Serialisation.
public class SbmSessionDataContractResolver : DefaultContractResolver
{
// To allow private properties to be deserialised.
// NB Only applies to top level properties in the serialised object.
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
MemberInfo[] fields = objectType.GetFields(flags);
return fields
.Concat(objectType.GetProperties(flags).Where(propInfo => propInfo.CanWrite))
.ToList();
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, MemberSerialization.Fields);
}
};
public static JsonSerializerSettings JsonSerialisationSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
public static JsonSerializerSettings JsonDeserialisationSettings = new JsonSerializerSettings
{
ContractResolver = new SbmSessionDataContractResolver(),
// Force all deserialised objects to be replaced - to avoid proxy lists not populating.
ObjectCreationHandling = ObjectCreationHandling.Replace,
NullValueHandling = NullValueHandling.Ignore
};
}
private readonly SessionStorage sessionStorage = new SessionStorage();
public static JsonSerializerSettings SessionDataJsonSerializerSettings { get { return SessionStorage.JsonSerialisationSettings; } }
public static JsonSerializerSettings SessionDataJsonDeserializerSettings { get { return SessionStorage.JsonDeserialisationSettings; } }
//-------------------------------------------------------------------
public SbmSessionData_Web SessionData
{
get
{
try
{
// Retrieve session data if not already in controller.
if (sessionStorage.SessionData == null)
{
byte[] sessionDataBytes = null;
HttpContext.Session.TryGetValue(SessionStorage.SessionKey_SessionData, out sessionDataBytes);
if (sessionDataBytes != null)
{
string sessionDataJson = SessionStorage.sessionDataEncoding.GetString(sessionDataBytes);
sessionStorage.SessionData = DeserializeSessionData(sessionDataJson);
}
}
return sessionStorage.SessionData;
}
catch (Exception exc)
{
SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetErrorStateMessage(exc)}{exc.GetStackEntries().Concat("", "\n\t")}");
}
return null;
}
}
protected abstract SbmSessionData_Web DeserializeSessionData(string sessionDataJson);
//-------------------------------------------------------------------
}
//=======================================================================
}