3.0.0.1 Demo repository registration
This commit is contained in:
@@ -9,6 +9,7 @@ using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.Utils;
|
||||
using Sarand.BusinessMgr.Web.Control.Consoles;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
@@ -18,6 +19,9 @@ using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.IO;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Dbas.Base;
|
||||
using Sarand.Net.Standard.Dbas.CodeType;
|
||||
using Sarand.Net.Standard.Dbas.ItemOptions;
|
||||
using Sarand.Net.Standard.Dbas.Security;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -28,9 +32,15 @@ namespace Sarand.BusinessMgr.Web.Control.App
|
||||
public class SbmApplication_Control : SbmApplication_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
// Processing indicators.
|
||||
private bool generateDatabaseDefinitions_Control = false;
|
||||
private bool generateDatabaseDefinitions_BusMgr = false;
|
||||
private bool generateDatabaseDefinitions_Security = false;
|
||||
private bool generateDatabaseDefinitions_CodeTypes = false;
|
||||
private bool generateDatabaseDefinitions_ItemOptions = false;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private static SbmApplication_Control appInstance;
|
||||
private PropertySet propertySet;
|
||||
private Dictionary<String, Net.Core.Web.App.SbmAppConfig> appConfigs = new Dictionary<string, Net.Core.Web.App.SbmAppConfig>();
|
||||
@@ -136,7 +146,7 @@ namespace Sarand.BusinessMgr.Web.Control.App
|
||||
if (repository != null)
|
||||
{
|
||||
// Core database connection.
|
||||
SacsDatabaseConsole.OdbcConfig odbcConfig = SbmCoreInstanceConsole_Control.GetRepositoryOdbcConfig(repository);
|
||||
SacsDatabaseConsole.OdbcConfig odbcConfig = SbmCoreInstanceConsole_Dbas.GetRepositoryOdbcConfig(repository);
|
||||
SacsDatabase busMgrDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
|
||||
if (busMgrDatabase.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} BusMgr Database: " + busMgrDatabase.DatabaseName + ". Initialisation error: " + busMgrDatabase.ErrorStateMessage);
|
||||
@@ -222,7 +232,7 @@ namespace Sarand.BusinessMgr.Web.Control.App
|
||||
|
||||
// Application configuration.
|
||||
appConfigs = SbmAppConfigHelper.ExtractAppConfigs(SbmConfiguration.GetSection("AppConfigs"));
|
||||
emailConfigs = SbmEmailConfigHelper.ExtractEmailConfigs(SbmConfiguration.GetSection("Email/Configs"));
|
||||
emailConfigs = SbmEmailConfigHelper.ExtractEmailConfigs(SbmConfiguration.GetSection("Email").GetSection("Configs"));
|
||||
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
||||
|
||||
// Application instance.
|
||||
@@ -279,6 +289,18 @@ namespace Sarand.BusinessMgr.Web.Control.App
|
||||
config.Password = AppConfig.TemplateDatabase.Password;
|
||||
GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance.Core, GetTemplateDatabase());
|
||||
}
|
||||
if (generateDatabaseDefinitions_Security)
|
||||
{
|
||||
SaSecurityDbDfnGenerator.Generate(GetTemplateDatabase()?.ConnectionString ?? "");
|
||||
}
|
||||
if (generateDatabaseDefinitions_CodeTypes)
|
||||
{
|
||||
SaCodeTypeDbDfnGenerator.Generate(GetTemplateDatabase()?.ConnectionString ?? "");
|
||||
}
|
||||
if (generateDatabaseDefinitions_ItemOptions)
|
||||
{
|
||||
SaItemOptionsDbDfnGenerator.Generate(GetTemplateDatabase()?.ConnectionString ?? "");
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
|
||||
@@ -36,57 +37,57 @@ namespace Sarand.BusinessMgr.Web.Control.App
|
||||
// Consoles.
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
public override SbmSessionConsole CreateSessionConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SbmSessionConsole CreateSessionConsole(SbmInternals internals)
|
||||
{
|
||||
return SbmSessionConsole.CreateConsole(userContext);
|
||||
return SbmSessionConsole.CreateConsole(internals);
|
||||
}
|
||||
|
||||
public override SaDiaryConsole CreateDiaryConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaDiaryConsole CreateDiaryConsole(SbmInternals internals)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override SaCodeTypeConsole CreateCodeTypeConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaCodeTypeConsole CreateCodeTypeConsole(SbmInternals internals)
|
||||
{
|
||||
return new SbmCodeTypeConsole_Web(userContext);
|
||||
return new SbmCodeTypeConsole_Web(internals);
|
||||
}
|
||||
|
||||
public override SaItemDataConsole CreateItemDataConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaItemDataConsole CreateItemDataConsole(SbmInternals internals)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override SaItemDocConsole CreateItemDocConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaItemDocConsole CreateItemDocConsole(SbmInternals internals)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override SaItemOptionConsole CreateItemOptionConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaItemOptionConsole CreateItemOptionConsole(SbmInternals internals)
|
||||
{
|
||||
return new SbmItemOptionConsole_Web(userContext);
|
||||
return new SbmItemOptionConsole_Web(internals);
|
||||
}
|
||||
|
||||
public override SaInterfaceConsole CreateInterfaceConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaInterfaceConsole CreateInterfaceConsole(SbmInternals internals)
|
||||
{
|
||||
return new SbmInterfaceConsole_Web(userContext);
|
||||
return new SbmInterfaceConsole_Web(internals);
|
||||
}
|
||||
|
||||
public override SaUpdateLogConsole CreateUpdateLogConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaUpdateLogConsole CreateUpdateLogConsole(SbmInternals internals)
|
||||
{
|
||||
return new SbmUpdateLogConsole_Web(userContext);
|
||||
return new SbmUpdateLogConsole_Web(internals);
|
||||
}
|
||||
|
||||
public override SaSecurityConsole CreateSecurityConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaSecurityConsole CreateSecurityConsole(SbmInternals internals)
|
||||
{
|
||||
return new SbmSecurityConsole_Web(userContext);
|
||||
return new SbmSecurityConsole_Web(internals);
|
||||
}
|
||||
|
||||
public override SaReferenceDataConsole CreateReferenceDataConsole(ISbmUserOrganisationContext userContext)
|
||||
public override SaReferenceDataConsole CreateReferenceDataConsole(SbmInternals internals)
|
||||
{
|
||||
return new SbmReferenceDataConsole_Control(userContext);
|
||||
return new SbmReferenceDataConsole_Control(internals);
|
||||
}
|
||||
|
||||
public override SbmEmailConsole CreateEmailConsole(ISbmUserOrganisationContext userContext, SbmEmailConfig emailConfig)
|
||||
public override SbmEmailConsole CreateEmailConsole(SbmEmailConfig emailConfig)
|
||||
{
|
||||
return SbmApplication_Control.CreateEmailConsole_Control(emailConfig);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SbmInternals_Control internals_Control;
|
||||
private SbmEmailConsole_Control emailConsole;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -38,17 +37,12 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (internals_Control != null) internals_Control.Dispose(); internals_Control = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public 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; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session data.
|
||||
@@ -98,7 +92,7 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
}
|
||||
if (!userAccount.IsStatusActive)
|
||||
{
|
||||
SaLogger.Error($"{SysUtil.Fn} Unable to sign account in - user account is not active. Email: " + userAccount.EmailAddress);
|
||||
SaLogger.Error($"{SysUtil.Fn} Unable to sign account in - user account is not active. Email: {userAccount.EmailAddress}");
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
@@ -112,11 +106,11 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
userAccount.LastInvalidLoginAt = null;
|
||||
if (!ControlAccountMgr.UpdateUserAccount(userAccount, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update User Account for " + userAccount.EmailAddress + ": " + ControlAccountMgr.ErrorStateMessage);
|
||||
SaLogger.Warn($"{SysUtil.Fn} Failed to update User Account for {userAccount.EmailAddress}: {ControlAccountMgr.ErrorStateMessage}");
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
SaLogger.Info($"{SysUtil.Fn} User session opened for " + userAccount.EmailAddress, true);
|
||||
SaLogger.Info($"{SysUtil.Fn} User session opened for {userAccount.EmailAddress}", true);
|
||||
|
||||
// Create session.
|
||||
OpenUserSession(SessionContext, userAccount);
|
||||
@@ -176,14 +170,14 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
if (SignUserIn(userAccount, true, ref errorMessage))
|
||||
{
|
||||
// Successful login.
|
||||
SaLogger.Info($"{SysUtil.Fn} Keep Logged In cookie found." + logSuffix);
|
||||
SaLogger.Info($"{SysUtil.Fn} Keep Logged In cookie found.{logSuffix}");
|
||||
return true;
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but failed to sign user in: {errorMessage}.{logSuffix}");
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but UserAccount is not active." + logSuffix);
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but UserAccount is not active.{logSuffix}");
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but UserAccount not found." + logSuffix);
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Keep Logged In cookie found but UserAccount not found.{logSuffix}");
|
||||
}
|
||||
}
|
||||
ClearKeepLoggedInCookie();
|
||||
@@ -197,7 +191,7 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
string keepLoggedInCookieValue = GenerateKeepLoggedInCookieValue();
|
||||
int cookieExpiresDays = Math.Max(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Min, Math.Min(Sbm.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Max, AppConfig.Security.SignIn.KeepLoggedIn.CookieExpiresDays));
|
||||
SetResponseCookie(KeepLoggedIn.CookieName, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
|
||||
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie set. Value: " + keepLoggedInCookieValue);
|
||||
SaLogger.Debug($"{SysUtil.Fn} 'Keep Logged In' cookie set. Value: {keepLoggedInCookieValue}");
|
||||
}
|
||||
|
||||
/// <summary>Set the 'Keep Logged In' response cookie to expired with no data.</summary>
|
||||
@@ -242,7 +236,7 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
{
|
||||
List<string> values = new List<string>();
|
||||
if (SysId.IsValid(UserAccountId))
|
||||
values.Add("UserAccountId: " + SysId.ToString(UserAccountId));
|
||||
values.Add("UserAccountId: {SysId.ToLong(UserAccountId)}.");
|
||||
return values;
|
||||
}
|
||||
/// <summary>Verifiy that the account details are populated.</summary>
|
||||
@@ -260,7 +254,7 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
NameValueCollection linkParams = DecryptParameters(encryptedParams, KeepLoggedIn.Base64IV, KeepLoggedIn.Base64Key);
|
||||
keepLoggedInParams.UserAccountId = new SysId(linkParams.Get(ParamName_KeepLoggedIn_UserAccountId).ToInt());
|
||||
}
|
||||
if (DebugMode) SaLogger.Info($"{SysUtil.Fn} UserAccountId: " + SysId.ToString(keepLoggedInParams.UserAccountId));
|
||||
if (DebugMode && SysId.IsValid(keepLoggedInParams.UserAccountId)) SaLogger.Info($"{SysUtil.Fn} UserAccountId: {SysId.ToLong(keepLoggedInParams.UserAccountId)}.");
|
||||
return keepLoggedInParams;
|
||||
}
|
||||
|
||||
@@ -269,7 +263,7 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
//-------------------------------------------------------------------
|
||||
// Encryption key is the same for all users each time the application is started,
|
||||
// but a different IV value is generated for each session so that the links/parameters cannot be shared.
|
||||
public static string Base64Key_ControlApp { get; } = SacsEncryptionHelper.EncodePlainKey("BusinessMgr=Control&Encryption-" + DateTime.Today.Format("ddMMyy"), SacsEncryptionHelper.KeyLength);
|
||||
public static string Base64Key_ControlApp { get; } = SacsEncryptionHelper.EncodePlainKey($"BusinessMgr=Control&Encryption-{DateTime.Today.Format("ddMMyy")}", SacsEncryptionHelper.KeyLength);
|
||||
protected string EncryptSessionParams(NameValueCollection parameters)
|
||||
{
|
||||
return HttpUtility.UrlEncode(EncryptParameters(parameters, SessionData_Control.Base64IV_ControlApp, Base64Key_ControlApp));
|
||||
|
||||
@@ -3,6 +3,7 @@ using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.Components;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Web.Control.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
@@ -26,6 +27,10 @@ namespace Sarand.BusinessMgr.Web.Control.Components
|
||||
protected SbmApplication_Control App_Control { get { return SbmApplication_Control.Instance; } }
|
||||
protected SbmSessionData_Control SessionData_Control { get { return SessionData_Web as SbmSessionData_Control; } }
|
||||
|
||||
// Core instance properties.
|
||||
public SbmInternals CoreInternals { get; set; }
|
||||
protected override SbmInstanceSchemaConsole InstanceSchemaConsole { get { if (CoreInternals != null) { return CoreInternals.InstanceSchemaConsole; } return null; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public IEnumerable<SelectListItem> GetInstanceContextsForSelect()
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
|
||||
using Sarand.BusinessMgr.Web.Control.App;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
@@ -18,64 +19,52 @@ using System.Linq;
|
||||
namespace Sarand.BusinessMgr.Web.Control.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SbmCoreInstanceConsole_Control : SbmCoreInstanceConsole_Base
|
||||
public class SbmCoreInstanceConsole_Control : SbmCoreInstanceConsole_Dbas
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private readonly SacsDatabase coreDatabase;
|
||||
private readonly SysId ownerId;
|
||||
private readonly SysId repositoryId;
|
||||
private SbmInternals internals;
|
||||
private class DataMembers
|
||||
{
|
||||
public SysId OwnerId { get; set; }
|
||||
public SysId RepositoryId { get; set; }
|
||||
public SbmInternals Internals { get; set; }
|
||||
}
|
||||
private DataMembers mbr { get; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SbmCoreInstanceConsole_Control(SbmSessionData_Control sessionData_Control, SbmcRepository repository)
|
||||
{
|
||||
ownerId = repository.OwnerId;
|
||||
repositoryId = repository.Id;
|
||||
mbr = new DataMembers();
|
||||
mbr.OwnerId = repository.OwnerId;
|
||||
mbr.RepositoryId = repository.Id;
|
||||
this.SessionData_Control = sessionData_Control;
|
||||
|
||||
// Repository connection.
|
||||
SacsDatabaseConsole.OdbcConfig config = GetRepositoryOdbcConfig(repository);
|
||||
coreDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
|
||||
if (coreDatabase.HasErrorState())
|
||||
SetErrorState(coreDatabase.ErrorStateMessage);
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (mbr.Internals != null) mbr.Internals.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public static SbmApplication_Control App_Control { get { return SbmApplication_Control.Instance; } }
|
||||
public SbmSessionData_Control SessionData_Control { get; }
|
||||
public override ISacsDatabase Database_Core { get { return coreDatabase; } }
|
||||
public override SbmInternals Internals_Core { get { if (internals == null) { internals = CreateCoreInternals(); } return internals; } }
|
||||
public override DbUpdateInfo DbUpdateInfo_Core { get { return Internals_Core.DbUpdateInfo; } }
|
||||
private static SbmApplication_Control App_Control { get { return SbmApplication_Control.Instance; } }
|
||||
private SbmSessionData_Control SessionData_Control { get; }
|
||||
public override SbmInternals Internals { get { if (mbr.Internals == null) { mbr.Internals = CreateCoreInternals(); } return mbr.Internals; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Utilities.
|
||||
|
||||
public static SacsDatabaseConsole.OdbcConfig GetRepositoryOdbcConfig(SbmcRepository repository)
|
||||
{
|
||||
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
||||
config.Location = $"MsSql:{repository.ServerName}\\{repository.InstanceName}.{repository.DatabaseName}";
|
||||
config.User = repository.UserName;
|
||||
config.Password = repository.Password;
|
||||
return config;
|
||||
}
|
||||
|
||||
/// <summary>Core internals for accessing core managers etc.</summary>
|
||||
protected SbmInternals CreateCoreInternals()
|
||||
{
|
||||
ushort sessionIndex = App_Control.GetCoreSessionIndexForControlRepository(ownerId, repositoryId);
|
||||
ushort sessionIndex = App_Control.GetCoreSessionIndexForControlRepository(mbr.OwnerId, mbr.RepositoryId);
|
||||
SbmSessionContext sessionContext = App_Control.GetSessionContextByIndex(sessionIndex);
|
||||
return new SbmInternals(sessionContext);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Control.Consoles
|
||||
@@ -12,8 +13,8 @@ namespace Sarand.BusinessMgr.Web.Control.Consoles
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SbmReferenceDataConsole_Control(ISbmUserOrganisationContext userContext) :
|
||||
base(userContext)
|
||||
public SbmReferenceDataConsole_Control(SbmInternals internals) :
|
||||
base(internals)
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
};
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = instanceConsole.Database_Core.ExecuteQuery(String.Join("\n", sql)))
|
||||
using (DbResultSet resultSet = instanceConsole.Database.ExecuteQuery(String.Join("\n", sql)))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
|
||||
+19
-17
@@ -6,6 +6,7 @@ using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Data;
|
||||
using Sarand.BusinessMgr.Web.Control.Components;
|
||||
using Sarand.BusinessMgr.Web.Control.Consoles;
|
||||
using Sarand.BusinessMgr.Web.Control.Models.Instance;
|
||||
@@ -135,12 +136,12 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
// Query Organisations.
|
||||
SbmAssociation.Params prm = new SbmAssociation.Params();
|
||||
prm.AssociationType = Sbm.AssociationType.Internal;
|
||||
prm.StatusCat = SbmAssociation.StatusCat.Current;
|
||||
foreach (SbmAssociation association in instanceConsole.Internals_Core.AccountMgr.GetAssociationList(prm))
|
||||
prm.StatusCat = SbmAssociation.StatusCat.CurrentOnly;
|
||||
foreach (SbmAssociation association in instanceConsole.Internals.AccountMgr.GetAssociationList(prm))
|
||||
{
|
||||
// Retrieve Organisation details.
|
||||
disposables.Add(association);
|
||||
SbmAffiliate affiliateOrganisation = instanceConsole.Internals_Core.AccountMgr.GetAffiliateById(association.AffiliateIdOwner);
|
||||
SbmAffiliate affiliateOrganisation = instanceConsole.Internals.AccountMgr.GetAffiliateById(association.AffiliateIdOwner);
|
||||
disposables.Add(affiliateOrganisation);
|
||||
|
||||
// Organisation details.
|
||||
@@ -159,19 +160,19 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
prmAffiliateUser.AffiliateIdAssocOwner = affiliateOrganisation.Id;
|
||||
prmAffiliateUser.AssociationType = Sbm.AssociationType.Member;
|
||||
prmAffiliateUser.StatusCat = SbmAffiliate.StatusCat.CurrentOnly;
|
||||
prmAffiliateUser.SortColumns.Add(instanceConsole.Internals_Core.AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Id));
|
||||
foreach (SbmAffiliate affiliateUser in instanceConsole.Internals_Core.AccountMgr.GetAffiliateList(prmAffiliateUser))
|
||||
prmAffiliateUser.SortColumns.Add(instanceConsole.Internals.AccountMgr.GetAffiliateColumnDfn(SbmAffiliate.Column.Id));
|
||||
foreach (SbmAffiliate affiliateUser in instanceConsole.Internals.AccountMgr.GetAffiliateList(prmAffiliateUser))
|
||||
{
|
||||
disposables.Add(affiliateUser);
|
||||
|
||||
// Lookup security details.
|
||||
if (!SysId.IsValid(affiliateUser.UserId)) continue;
|
||||
SaSecurityItem securityItemUser = instanceConsole.Internals_Core.SecurityConsole.GetSecurityItemById(SaSecurity.ItemType.User, affiliateUser.UserId);
|
||||
SaSecurityItem securityItemUser = instanceConsole.Internals.SecurityConsole.GetSecurityItemById(SaSecurity.ItemType.User, affiliateUser.UserId);
|
||||
disposables.Add(securityItemUser);
|
||||
if (securityItemUser == null) continue;
|
||||
|
||||
// Confirm security rights (SuperUser).
|
||||
SaSecurityProfile securityProfile = instanceConsole.Internals_Core.SecurityConsole.GetUserSecurityProfile(securityItemUser.Id);
|
||||
SaSecurityProfile securityProfile = instanceConsole.Internals.SecurityConsole.GetUserSecurityProfile(securityItemUser.Id);
|
||||
if (!securityProfile.Groups.Any(group => group.Code.EqualsCI(SaSecurityConsole.GroupCode_Super))) continue;
|
||||
|
||||
// Add User to the Organisation.
|
||||
@@ -252,7 +253,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
}
|
||||
|
||||
// Validate Organisation Affiliate.
|
||||
SbmAffiliate affiliateOrganisation = instanceConsole.Internals_Core.AccountMgr.GetAffiliateById(affiliateIdOrganisation);
|
||||
SbmAffiliate affiliateOrganisation = instanceConsole.Internals.AccountMgr.GetAffiliateById(affiliateIdOrganisation);
|
||||
disposables.Add(affiliateOrganisation);
|
||||
if (affiliateOrganisation == null)
|
||||
{
|
||||
@@ -276,7 +277,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
else
|
||||
{
|
||||
// Validate Internal Association.
|
||||
SbmAssociation associationOrganisation = instanceConsole.Internals_Core.AccountMgr.GetAssociationById(associationIdInternal);
|
||||
SbmAssociation associationOrganisation = instanceConsole.Internals.AccountMgr.GetAssociationById(associationIdInternal);
|
||||
disposables.Add(associationOrganisation);
|
||||
if (associationOrganisation == null)
|
||||
{
|
||||
@@ -303,12 +304,12 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
else
|
||||
{
|
||||
// Organisation does not exist.
|
||||
if (!SysId.IsValid(SysId.ToSysId(model.Organisation.AffiliateId)))
|
||||
if (SysId.IsValid(SysId.ToSysId(model.Organisation.AffiliateId)))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Affiliate Id specified for new Organisation. Id: {model.Organisation.AffiliateId}.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!SysId.IsValid(SysId.ToSysId(model.Organisation.AssociationId)))
|
||||
if (SysId.IsValid(SysId.ToSysId(model.Organisation.AssociationId)))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Association Id specified for new Organisation. Id: {model.Organisation.AssociationId}.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
@@ -327,7 +328,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
}
|
||||
|
||||
// Validate User Affiliate.
|
||||
SbmAffiliate affiliateUser = instanceConsole.Internals_Core.AccountMgr.GetAffiliateById(affiliateIdUser);
|
||||
SbmAffiliate affiliateUser = instanceConsole.Internals.AccountMgr.GetAffiliateById(affiliateIdUser);
|
||||
disposables.Add(affiliateUser);
|
||||
if (affiliateUser == null)
|
||||
{
|
||||
@@ -350,7 +351,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
else
|
||||
{
|
||||
// Validate User Security Item.
|
||||
SaSecurityItem securityItemUser = instanceConsole.Internals_Core.SecurityConsole.GetSecurityItemById(SaSecurity.ItemType.User, secItemIdUser);
|
||||
SaSecurityItem securityItemUser = instanceConsole.Internals.SecurityConsole.GetSecurityItemById(SaSecurity.ItemType.User, secItemIdUser);
|
||||
disposables.Add(securityItemUser);
|
||||
if (securityItemUser == null)
|
||||
{
|
||||
@@ -367,12 +368,12 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
else
|
||||
{
|
||||
// User does not exist.
|
||||
if (!SysId.IsValid(SysId.ToSysId(model.User.AffiliateId)))
|
||||
if (SysId.IsValid(SysId.ToSysId(model.User.AffiliateId)))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Affiliate Id specified for new User. Id: {model.User.AffiliateId}.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (!SysId.IsValid(SysId.ToSysId(model.User.SecurityItemId)))
|
||||
if (SysId.IsValid(SysId.ToSysId(model.User.SecurityItemId)))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Security Item Id specified for new User. Id: {model.User.SecurityItemId}.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
@@ -388,7 +389,7 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
SbmCoreInstanceConsole_Control repositoryConsole = new SbmCoreInstanceConsole_Control(SessionData_Control, repository);
|
||||
disposables.Add(repositoryConsole);
|
||||
|
||||
SbmCoreInstanceConsole_Base.RepositoryInitialisationData repoInitData = new SbmCoreInstanceConsole_Base.RepositoryInitialisationData();
|
||||
SbmRepositoryInitialisationData repoInitData = new SbmRepositoryInitialisationData();
|
||||
repoInitData.Organisation.AffiliateId = SysId.ToSysId(model.Organisation.AffiliateId);
|
||||
repoInitData.Organisation.AssociationId = SysId.ToSysId(model.Organisation.AssociationId);
|
||||
repoInitData.Organisation.Name = model.Organisation.Name;
|
||||
@@ -400,7 +401,8 @@ namespace Sarand.BusinessMgr.Web.Control.Controllers.Instance
|
||||
repoInitData.User.LastName = model.User.LastName;
|
||||
repoInitData.User.Email = model.User.Email;
|
||||
repoInitData.User.SecurityItemId = SysId.ToSysId(model.User.SecurityItemId);
|
||||
repoInitData.User.Code = model.User.Code;
|
||||
// User Email is used for the Security Item Code for login.
|
||||
repoInitData.User.Code = model.User.Email;
|
||||
repoInitData.User.Password = model.User.Password;
|
||||
repoInitData.User.PasswordSet = StringUtil.ToBool(model.User.PasswordSet);
|
||||
if (!repositoryConsole.InitialiseRepository(repoInitData))
|
||||
|
||||
+489
@@ -0,0 +1,489 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.App;
|
||||
using Sarand.BusinessMgr.Web.Control.Components;
|
||||
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 Sarand.Net.Standard.Dbas.Data;
|
||||
using Sarand.Net.Standard.Dbas.Proc;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Sarand.BusinessMgr.Web.Control.Models.System;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using System.Linq;
|
||||
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
||||
using Sarand.Net.Standard.Dbas.Base;
|
||||
using Sarand.BusinessMgr.Web.Control.Consoles;
|
||||
using System.Reflection;
|
||||
using static Sarand.BusinessMgr.Net.Standard.Dbas.Utils.SbmDbDfnGenerator;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
{
|
||||
//======================================================================
|
||||
// System Controller - Ajax - Database.
|
||||
//======================================================================
|
||||
partial class SystemController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Database data.
|
||||
private class DatabaseTableData
|
||||
{
|
||||
public String SchemaName { get; set; }
|
||||
public String TableName { get; set; }
|
||||
public String QualifiedName { get; set; }
|
||||
public int RowCount { get; set; }
|
||||
public int ColumnCount { get; set; }
|
||||
public int IndexCount { get; set; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Database Table List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_DatabaseTableList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_DatabaseTableList(SbmModel_Control model) : base(model) { }
|
||||
// Table list.
|
||||
public List<DatabaseTableData> Tables { get; } = new List<DatabaseTableData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/GetDatabaseTables")]
|
||||
public IActionResult Ajax_GetDatabaseTables(Model_System model)
|
||||
{
|
||||
String messageTitle = Localiser["system.caption.database"];
|
||||
AjaxResponse_DatabaseTableList responseData = new AjaxResponse_DatabaseTableList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
// Database connection.
|
||||
Sbm.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseFilter.Instance), Sbm.Database.Unknown);
|
||||
if (databaseInstance <= 0)
|
||||
return Json(responseData.SetMessage(messageTitle, $"Database instance must be specified."));
|
||||
ISacsDatabase db = GetDatabase(databaseInstance);
|
||||
if (db == null)
|
||||
return Json(responseData.SetMessage(messageTitle, $"Database unavailable for instance '{databaseInstance}'."));
|
||||
|
||||
// Database table row counts.
|
||||
Dictionary<String, int> tableRowCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
String query =
|
||||
"SELECT QUOTENAME(SCHEMA_NAME(sOBJ.schema_id)) + '.' + QUOTENAME(sOBJ.name) As [TableName], SUM(sPTN.Rows) As [RowCount] " +
|
||||
"FROM sys.objects AS sOBJ " +
|
||||
"INNER JOIN sys.partitions AS sPTN ON sOBJ.object_id = sPTN.object_id " +
|
||||
"WHERE sOBJ.type = 'U' AND sOBJ.is_ms_shipped = 0x0 AND index_id< 2 /*Index Id: 0:Heap,1:Clustered*/ " +
|
||||
"GROUP BY sOBJ.schema_id, sOBJ.name";
|
||||
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query))
|
||||
{
|
||||
while (dbResultSet != null && dbResultSet.NextRecord())
|
||||
{
|
||||
tableRowCounts.Add(dbResultSet.GetRecordValues().GetValue("TableName").ToString(), (int)dbResultSet.GetRecordValues().GetValue("RowCount").AsLong());
|
||||
}
|
||||
}
|
||||
|
||||
// Database tables.
|
||||
List<DbDfnTable> tableDfns = db.GetTableDfns();
|
||||
foreach (DbDfnTable tableDfn in tableDfns.OrderBy(item => item.Name))
|
||||
{
|
||||
// Filter by table name.
|
||||
if (!StringUtil.IsEmpty(model.DatabaseFilter.Search) && !tableDfn.Name.ContainsCI(model.DatabaseFilter.Search))
|
||||
continue;
|
||||
|
||||
DatabaseTableData tableData = new DatabaseTableData();
|
||||
tableData.SchemaName = tableDfn.Schema;
|
||||
tableData.TableName = tableDfn.Name;
|
||||
tableData.QualifiedName = tableDfn.QualifiedName;
|
||||
tableData.ColumnCount = tableDfn.ColumnCount;
|
||||
tableData.IndexCount = tableDfn.IndexCount;
|
||||
|
||||
// Row count.
|
||||
tableData.RowCount = tableRowCounts.GetValueOrDefault(tableDfn.QuotedQualifiedName, 0);
|
||||
|
||||
responseData.Tables.Add(tableData);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Get database by type.
|
||||
/// </summary>
|
||||
private ISacsDatabase GetDatabase(Sbm.Database databaseInstance)
|
||||
{
|
||||
switch (databaseInstance)
|
||||
{
|
||||
case Sbm.Database.Control:
|
||||
return App.GetControlDatabase();
|
||||
case Sbm.Database.Template:
|
||||
return GetDatabaseByContext(Sbm.RepositoryContext_Template);
|
||||
case Sbm.Database.Demo:
|
||||
return GetDatabaseByContext(Sbm.RepositoryContext_Demo);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Get database by Instance Context.
|
||||
/// </summary>
|
||||
private ISacsDatabase GetDatabaseByContext(String instanceContext)
|
||||
{
|
||||
SbmcRepository repository = ControlInstanceMgr.GetRepositoryByContext(instanceContext);
|
||||
if (repository != null)
|
||||
{
|
||||
SacsDatabaseConsole.OdbcConfig config = SbmCoreInstanceConsole_Dbas.GetRepositoryOdbcConfig(repository);
|
||||
return SacsDatabaseConsole.OpenOdbcDatabase(config);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validate Database Schema ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class DbSchemaItemResponseData
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public String SchemaName { get; set; }
|
||||
public String TableName { get; set; }
|
||||
public String ColumnName { get; set; }
|
||||
public int ColumnPosition { get; set; }
|
||||
public String IndexName { get; set; }
|
||||
public String Comment { get; set; }
|
||||
}
|
||||
private class AjaxResponse_ValidateDatabaseSchema : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_ValidateDatabaseSchema(SbmModel_Control model) : base(model) { }
|
||||
// Database instance.
|
||||
public String Instance { get; set; }
|
||||
// Schema validation list.
|
||||
public List<DbSchemaItemResponseData> Items { get; } = new List<DbSchemaItemResponseData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/ValidateDatabaseSchema")]
|
||||
public IActionResult Ajax_ValidateDatabaseSchema(Model_System model)
|
||||
{
|
||||
String messageTitle = Localiser["system.caption.database"];
|
||||
AjaxResponse_ValidateDatabaseSchema responseData = new AjaxResponse_ValidateDatabaseSchema(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
|
||||
// Database instance.
|
||||
Sbm.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseFilter.Instance), Sbm.Database.Unknown);
|
||||
if (databaseInstance <= 0)
|
||||
return Json(responseData.SetMessage(messageTitle, "Database instance must be specified"));
|
||||
responseData.Instance = databaseInstance.ToString();
|
||||
|
||||
// Database connection.
|
||||
ISacsDatabase db = GetDatabase(databaseInstance);
|
||||
if (db == null)
|
||||
return Json(responseData.SetMessage(messageTitle, $"Unrecognised database instance specified: '{model.DatabaseFilter.Instance}'."));
|
||||
|
||||
// Retrieve XML database schema definition.
|
||||
Dictionary<String, String> xmlSchemas = GetSmlSchema(databaseInstance);
|
||||
if (!xmlSchemas.Any())
|
||||
return Json(responseData.SetMessage(messageTitle, "Failed to extract XML schema definitions."));
|
||||
|
||||
// Extract schema from XML definition.
|
||||
SaDbProcess_ConvertDbSchema.Config cfgSchemaConvert = new SaDbProcess_ConvertDbSchema.Config();
|
||||
SaDbProcess_ConvertDbSchema procSchemaConvert = new SaDbProcess_ConvertDbSchema(cfgSchemaConvert);
|
||||
List<DbDfnTable> tables = new List<DbDfnTable>();
|
||||
foreach (String schemaName in xmlSchemas.Keys)
|
||||
{
|
||||
String xmlSchema = xmlSchemas[schemaName];
|
||||
foreach (DbDfnTable table in procSchemaConvert.ConvertXmlToTables(xmlSchema))
|
||||
{
|
||||
if (tables.Any(item => item.Matches(table)))
|
||||
{
|
||||
SaLogger.Debug($"{SysUtil.Fn} Duplicate table '{table.QualifiedName}' found in schema '{schemaName}'.");
|
||||
continue;
|
||||
}
|
||||
tables.Add(table);
|
||||
}
|
||||
if (procSchemaConvert.HasErrorMessage())
|
||||
return Json(responseData.SetMessage(messageTitle, $"Failed to convert XML schema '{schemaName}': {procSchemaConvert.GetErrorMessage().TrimEnd('.')}."));
|
||||
}
|
||||
|
||||
SaDbProcess_CompareDatabaseSchemas.Config cfgSchemaCompare = new SaDbProcess_CompareDatabaseSchemas.Config(tables, db);
|
||||
cfgSchemaCompare.HideIdenticalObjects = true;
|
||||
cfgSchemaCompare.IgnorePosition = true;
|
||||
SaDbProcess_CompareDatabaseSchemas procSchemaCompare = new SaDbProcess_CompareDatabaseSchemas(cfgSchemaCompare);
|
||||
procSchemaCompare.OnSchemaComparisonItemAdded += OnSchemaComparisonItemAdded;
|
||||
procSchemaCompare.RunProcess();
|
||||
|
||||
List<SaDbProcess_CompareDatabaseSchemas.SchemaComparisonItem> schemaComparisonItems = procSchemaCompare.GetSchemaComparisonItems();
|
||||
foreach (SaDbProcess_CompareDatabaseSchemas.SchemaComparisonItem schemaComparisonItem in schemaComparisonItems)
|
||||
{
|
||||
DbSchemaItemResponseData item = new DbSchemaItemResponseData()
|
||||
{
|
||||
Id = schemaComparisonItem.Id,
|
||||
SchemaName = schemaComparisonItem.SchemaName,
|
||||
TableName = schemaComparisonItem.TableName,
|
||||
ColumnName = schemaComparisonItem.ColumnName,
|
||||
ColumnPosition = schemaComparisonItem.ColumnPosition,
|
||||
IndexName = schemaComparisonItem.IndexName,
|
||||
Comment = schemaComparisonItem.Comment
|
||||
};
|
||||
responseData.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
private Dictionary<String, String> GetSmlSchema(Sbm.Database databaseInstance)
|
||||
{
|
||||
Dictionary<String, String> schemas = new Dictionary<String, String>();
|
||||
switch (databaseInstance)
|
||||
{
|
||||
case Sbm.Database.Control:
|
||||
{
|
||||
var assembly = typeof(SbmSystem_Dbas).GetTypeInfo().Assembly;
|
||||
schemas.Add("SbmDbDfn_Control.xml", SacsResourceHelper.GetManifestResourceAsText(assembly, "", "SbmDbDfn_Control.xml"));
|
||||
break;
|
||||
}
|
||||
case Sbm.Database.Template:
|
||||
case Sbm.Database.Demo:
|
||||
{
|
||||
var assembly = typeof(SbmSystem_Dbas).GetTypeInfo().Assembly;
|
||||
schemas.Add("SbmDbDfn.xml", SacsResourceHelper.GetManifestResourceAsText(assembly, "", "SbmDbDfn.xml"));
|
||||
assembly = typeof(SacsDatabase).GetTypeInfo().Assembly;
|
||||
HashSet<String> schemaNames = new HashSet<String>()
|
||||
{
|
||||
// Originally included common database definitions but these tables are now in the main BusMgr schema definition.
|
||||
//"SaSecurityDbDfn.xml","SaCodeTypeDbDfn.xml", "SaReferenceDataDbDfn.xml", "SaItemOptionDbDfn.xml",
|
||||
//"SaInterfaceDbDfn.xml", "SaItemDataDbDfn.xml", "SaItemDocsDbDfn.xml", "SaUpdateLogDbDfn.xml"
|
||||
};
|
||||
foreach (String schemaName in schemaNames)
|
||||
schemas.Add(schemaName, SacsResourceHelper.GetManifestResourceAsText(assembly, "", schemaName));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return schemas;
|
||||
}
|
||||
|
||||
|
||||
// Processing events.
|
||||
public void OnSchemaComparisonItemAdded(object sender, SaDbProcess_CompareDatabaseSchemas.SchemaComparisonItemAddedEventArgs e)
|
||||
{
|
||||
SaDbProcess_CompareDatabaseSchemas proc = sender as SaDbProcess_CompareDatabaseSchemas;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Database Table ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponseData_Table
|
||||
{
|
||||
public AjaxResponseData_Table(DbDfnTable tableDfn)
|
||||
{
|
||||
Schema = tableDfn.Schema;
|
||||
Name = tableDfn.Name;
|
||||
if (!StringUtil.IsEmpty(tableDfn.Remarks))
|
||||
Remarks = tableDfn.Remarks;
|
||||
foreach (DbDfnColumn columnDfn in tableDfn.Columns)
|
||||
Columns.Add(new AjaxResponseData_Column(columnDfn));
|
||||
foreach (DbDfnIndex indexDfn in tableDfn.Indices)
|
||||
Indices.Add(new AjaxResponseData_Index(indexDfn));
|
||||
}
|
||||
public String Schema { get; }
|
||||
public String Name { get; }
|
||||
public String QualifiedName { get { return (!StringUtil.IsEmpty(Schema) ? Schema + "." : "") + Name; } }
|
||||
public String QuotedQualifiedName { get { return (!StringUtil.IsEmpty(Schema) ? "[" + Schema + "]." : "") + "[" + Name + "]"; } }
|
||||
public String Remarks { get; set; } = String.Empty;
|
||||
public List<AjaxResponse_Data.ItemLabelValue> Properties { get; } = new List<AjaxResponse_Data.ItemLabelValue>();
|
||||
public List<AjaxResponseData_Column> Columns { get; } = new List<AjaxResponseData_Column>();
|
||||
public List<AjaxResponseData_Index> Indices { get; } = new List<AjaxResponseData_Index>();
|
||||
}
|
||||
private class AjaxResponseData_Column
|
||||
{
|
||||
public int Pos { get; }
|
||||
public String Name { get; }
|
||||
public String Format { get; }
|
||||
public String DataTypeName { get; }
|
||||
public short? DataTypeNative { get; }
|
||||
public String DataTypeNameNative { get; }
|
||||
public bool? IsIdentity { get; }
|
||||
public long? Size { get; }
|
||||
public long? BufferLen { get; }
|
||||
public short? DecimalDigits { get; }
|
||||
public bool? Nullable { get; }
|
||||
public bool? IsNullable { get; }
|
||||
public String Remarks { get; }
|
||||
public AjaxResponseData_Column(DbDfnColumn columnDfn)
|
||||
{
|
||||
Pos = columnDfn.Pos;
|
||||
Name = columnDfn.Name;
|
||||
Format = columnDfn.GetFormat();
|
||||
if (!StringUtil.IsEmpty(columnDfn.DataTypeName))
|
||||
DataTypeName = columnDfn.DataTypeName;
|
||||
if (columnDfn.DataTypeNative > 0)
|
||||
DataTypeNative = columnDfn.DataTypeNative;
|
||||
if (!StringUtil.IsEmpty(columnDfn.DataTypeNameNative))
|
||||
DataTypeNameNative = columnDfn.DataTypeNameNative;
|
||||
if (columnDfn.IsIdentity)
|
||||
IsIdentity = columnDfn.IsIdentity;
|
||||
if (columnDfn.Size > 0)
|
||||
Size = columnDfn.Size;
|
||||
if (columnDfn.BufferLen > 0)
|
||||
BufferLen = columnDfn.BufferLen;
|
||||
if (columnDfn.DecimalDigits > 0)
|
||||
DecimalDigits = columnDfn.DecimalDigits;
|
||||
if (columnDfn.Nullable == DbColumnNullable.Nullable)
|
||||
Nullable = true;
|
||||
if (columnDfn.IsNullable)
|
||||
IsNullable = columnDfn.IsNullable;
|
||||
if (!StringUtil.IsEmpty(columnDfn.Remarks))
|
||||
Remarks = columnDfn.Remarks;
|
||||
}
|
||||
}
|
||||
private class AjaxResponseData_Index
|
||||
{
|
||||
public String Name { get; }
|
||||
public int? IndexType { get; }
|
||||
public bool? Unique { get; }
|
||||
public bool? Primary { get; }
|
||||
public bool? Clustered { get; }
|
||||
public bool? Nullable { get; }
|
||||
public int? Pages { get; }
|
||||
public int? UniqueValues { get; }
|
||||
public List<AjaxResponseData_IndexColumn> Columns { get; } = new List<AjaxResponseData_IndexColumn>();
|
||||
public AjaxResponseData_Index(DbDfnIndex indexDfn)
|
||||
{
|
||||
Name = indexDfn.Name;
|
||||
if (indexDfn.IndexType > 0)
|
||||
IndexType = indexDfn.IndexType;
|
||||
if (indexDfn.Unique)
|
||||
Unique = indexDfn.Unique;
|
||||
if (indexDfn.Primary)
|
||||
Primary = indexDfn.Primary;
|
||||
if (indexDfn.Clustered)
|
||||
Clustered = indexDfn.Clustered;
|
||||
if (indexDfn.Nullable)
|
||||
Nullable = indexDfn.Nullable;
|
||||
if (indexDfn.Pages > 0)
|
||||
Pages = indexDfn.Pages;
|
||||
if (indexDfn.UniqueValues > 0)
|
||||
UniqueValues = indexDfn.UniqueValues;
|
||||
foreach (DbDfnIndexColumn indexColumnDfn in indexDfn.Columns)
|
||||
Columns.Add(new AjaxResponseData_IndexColumn(indexColumnDfn));
|
||||
}
|
||||
}
|
||||
private class AjaxResponseData_IndexColumn
|
||||
{
|
||||
public short Seq { get; }
|
||||
public String Name { get; }
|
||||
public bool? Desc { get; }
|
||||
public AjaxResponseData_IndexColumn(DbDfnIndexColumn indexColumnDfn)
|
||||
{
|
||||
Seq = indexColumnDfn.Seq;
|
||||
Name = indexColumnDfn.Name;
|
||||
if (!indexColumnDfn.Ascend)
|
||||
Desc = true;
|
||||
}
|
||||
}
|
||||
private class AjaxResponse_DatabaseTable : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_DatabaseTable(SbmModel_Control model) : base(model) { }
|
||||
// Database table.
|
||||
public String PopupTitle { get; set; }
|
||||
public AjaxResponseData_Table Table { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/GetDatabaseTable")]
|
||||
public IActionResult Ajax_GetDatabaseTable(Model_System model)
|
||||
{
|
||||
String messageTitle = Localiser["system.caption.database"];
|
||||
AjaxResponse_DatabaseTable responseData = new AjaxResponse_DatabaseTable(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
|
||||
// Parameters.
|
||||
if (StringUtil.IsEmpty(model.DatabaseTable.Name))
|
||||
return Json(responseData.SetMessage(messageTitle, "Table name must be supplied."));
|
||||
|
||||
// Database instance.
|
||||
Sbm.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseTable.Instance), Sbm.Database.Unknown);
|
||||
if (databaseInstance <= 0)
|
||||
return Json(responseData.SetMessage(messageTitle, "Database instance must be specified"));
|
||||
|
||||
// Database connection.
|
||||
ISacsDatabase db = GetDatabase(databaseInstance);
|
||||
|
||||
// Table definition.
|
||||
DbDfnTable tableDfn = db.GetTableDfn(model.DatabaseTable.Name, true);
|
||||
if (tableDfn == null)
|
||||
return Json(responseData.SetMessage(messageTitle, "Invalid Table name supplied."));
|
||||
|
||||
// Populate table response.
|
||||
responseData.Table = new AjaxResponseData_Table(tableDfn);
|
||||
responseData.PopupTitle = Localiser["label.table"] + ": " + tableDfn.Name;
|
||||
|
||||
// Database sizing.
|
||||
String query = "Exec sp_SpaceUsed [" + tableDfn.QualifiedName + "];";
|
||||
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query))
|
||||
{
|
||||
if (dbResultSet != null && dbResultSet.NextRecord())
|
||||
{
|
||||
// Row count.
|
||||
long rows = StringUtil.ToLong(dbResultSet.GetRecordValues().GetValue("rows").ToString());
|
||||
if (rows > 0)
|
||||
responseData.Table.Properties.Add(new AjaxResponse_Data.ItemLabelValue() { Label = "Rows", Value = rows.ToString() });
|
||||
// Reserved space.
|
||||
String reserved = dbResultSet.GetRecordValues().GetValue("reserved").AsString();
|
||||
if (!StringUtil.IsEmpty(reserved))
|
||||
responseData.Table.Properties.Add(new AjaxResponse_Data.ItemLabelValue() { Label = "Reserved", Value = reserved });
|
||||
// Data space.
|
||||
String data = dbResultSet.GetRecordValues().GetValue("data").AsString();
|
||||
if (!StringUtil.IsEmpty(data))
|
||||
responseData.Table.Properties.Add(new AjaxResponse_Data.ItemLabelValue() { Label = "Data", Value = data });
|
||||
// Index space.
|
||||
String index = dbResultSet.GetRecordValues().GetValue("index_size").AsString();
|
||||
if (!StringUtil.IsEmpty(index))
|
||||
responseData.Table.Properties.Add(new AjaxResponse_Data.ItemLabelValue() { Label = "Indices", Value = index });
|
||||
// Unused space.
|
||||
String unused = dbResultSet.GetRecordValues().GetValue("unused").AsString();
|
||||
if (!StringUtil.IsEmpty(unused))
|
||||
responseData.Table.Properties.Add(new AjaxResponse_Data.ItemLabelValue() { Label = "Unused", Value = unused });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Control.Components;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Control.Controllers.System
|
||||
{
|
||||
//======================================================================
|
||||
public partial class SystemController : SbmController_Control
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SystemController(SbmLocaliser localiser, ILogger<HomeController> logger) :
|
||||
base(localiser, logger)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// System - Home.
|
||||
/// <para>- No 'System' home page for now, redirect to home page.</para>
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return RedirectToAction("", "");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//======================================================================
|
||||
}
|
||||
@@ -34,8 +34,8 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
UserFirstName,
|
||||
UserLastName,
|
||||
UserEmail,
|
||||
UserCode,
|
||||
UserPassword,
|
||||
UserPasswordConfirm,
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -89,8 +89,8 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
public String FirstName { get; set; }
|
||||
public String LastName { get; set; }
|
||||
public String Email { get; set; }
|
||||
public String Code { get; set; }
|
||||
public String Password { get; set; }
|
||||
public String PasswordConfirm { get; set; }
|
||||
public String PasswordSet { get; set; }
|
||||
}
|
||||
public UserData User { get; } = new UserData();
|
||||
@@ -139,7 +139,7 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
else
|
||||
{
|
||||
// Check that organisation name is not already in use.
|
||||
if (instanceConsole.Internals_Core.AccountMgr.OrganisationExistsByName(Organisation.Name, GetOrganisationAffiliateId()))
|
||||
if (instanceConsole.Internals.AccountMgr.OrganisationExistsByName(Organisation.Name, GetOrganisationAffiliateId()))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.duplicate.value"]);
|
||||
}
|
||||
}
|
||||
@@ -198,30 +198,30 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
if (User.Email != null)
|
||||
{
|
||||
String controlName = GetControlName(Control.UserEmail);
|
||||
User.Email = User.Email.ToLowerInvariant();
|
||||
responseData.SetControlValue(controlName, User.Email);
|
||||
if (StringUtil.IsBlank(User.Email))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(User.Email) > GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email))
|
||||
else if (!SacsDataValidationHelper.IsValidEmailAddress(User.Email))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
// Email address must fit in both the Security Item Email and Code fields.
|
||||
else if (StringUtil.GetLength(User.Email) > GetControlMaxLength(SaSecurityDbDfn.ColumnIdx.SaSecItem_EmailAddress) || StringUtil.GetLength(User.Email) > GetControlMaxLength(SaSecurityDbDfn.ColumnIdx.SaSecItem_Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email)]);
|
||||
}
|
||||
|
||||
// User Code.
|
||||
if (User.Code != null)
|
||||
{
|
||||
String controlName = GetControlName(Control.UserCode);
|
||||
responseData.SetControlValue(controlName, User.Code);
|
||||
if (StringUtil.IsBlank(User.Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(User.Code) > GetControlMaxLength(SaSecurityDbDfn.ColumnIdx.SaSecItem_Code))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaSecurityDbDfn.ColumnIdx.SaSecItem_Code)]);
|
||||
else
|
||||
{
|
||||
// Ensure that user name is not already in use.
|
||||
SysId securityItemId = instanceConsole.Internals_Core.SecurityConsole.GetIdForItemCode(SaSecurity.ItemType.User, User.Code);
|
||||
// Ensure that Email is not already in use as a User Code.
|
||||
SysId securityItemId = instanceConsole.Internals.SecurityConsole.GetIdForItemCode(SaSecurity.ItemType.User, User.Email);
|
||||
if (SysId.IsValid(securityItemId) && !securityItemId.Equals(GetUserSecurityItemId()))
|
||||
{
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.duplicate.value"]);
|
||||
|
||||
}
|
||||
// Ensure that Email is not already in use as a User Email.
|
||||
SaSecurityItem.Params prmSecurityItem = new SaSecurityItem.Params();
|
||||
prmSecurityItem.IdsExcluded.AddId(GetUserSecurityItemId());
|
||||
prmSecurityItem.SecurityItemType = SaSecurity.ItemType.User;
|
||||
prmSecurityItem.EmailAddress = User.Email;
|
||||
prmSecurityItem.StatusCat = SaSecurityItem.StatusCat.Any;
|
||||
if (instanceConsole.Internals.SecurityConsole.GetSecurityItemCount(prmSecurityItem) > 0)
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.duplicate.value"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,6 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
if (User.Password != null && (StringUtil.ToBool(User.PasswordSet) || !StringUtil.ToBool(User.Exists)))
|
||||
{
|
||||
String controlName = GetControlName(Control.UserPassword);
|
||||
responseData.SetControlValue(controlName, User.Password);
|
||||
if (StringUtil.IsBlank(User.Password))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (StringUtil.GetLength(User.Password) < Sbm.Config.Security.Password.MinLength)
|
||||
@@ -238,6 +237,14 @@ namespace Sarand.BusinessMgr.Web.Control.Models.Instance
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", Sbm.Config.Security.Password.MaxLength]);
|
||||
}
|
||||
|
||||
// User Password.
|
||||
if (User.PasswordConfirm != null && User.Password != null && (StringUtil.ToBool(User.PasswordSet) || !StringUtil.ToBool(User.Exists)))
|
||||
{
|
||||
String controlName = GetControlName(Control.UserPasswordConfirm);
|
||||
if (!User.PasswordConfirm.Equals(User.Password))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Sarand.BusinessMgr.Net.Core.Web.App;
|
||||
using Sarand.BusinessMgr.Web.Control.Components;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Sarand.BusinessMgr.Web.Control.Models.System
|
||||
{
|
||||
//=======================================================================
|
||||
public class Model_System : SbmModel_Control
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_System(SbmLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Database page properties.
|
||||
public class DatabaseFilterData
|
||||
{
|
||||
public String Instance { get; set; }
|
||||
public String Search { get; set; }
|
||||
}
|
||||
public DatabaseFilterData DatabaseFilter { get; } = new DatabaseFilterData();
|
||||
public class DatabaseTableData
|
||||
{
|
||||
public String Instance { get; set; }
|
||||
public String Name { get; set; }
|
||||
}
|
||||
public DatabaseTableData DatabaseTable { get; } = new DatabaseTableData();
|
||||
|
||||
public IEnumerable<SelectListItem> GetDatabases()
|
||||
{
|
||||
List<CodeDesc> items = new List<CodeDesc>();
|
||||
if (ValidUserSession)
|
||||
{
|
||||
items.Add("Core", Localiser["label.core"]);
|
||||
items.Add("Reference", Localiser["label.reference"]);
|
||||
items.Add("Support", Localiser["label.support"]);
|
||||
}
|
||||
return new SelectList(items, "Code", "Desc");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Logs page properties.
|
||||
public String LoggingRootFolder { get; } = Regex.Replace(SaLogger.LogFolder, "[\\\\/]Admin$", "");
|
||||
// Log file filter.
|
||||
public class LogsFilterData
|
||||
{
|
||||
public String Folder { get; set; }
|
||||
public String Year { get; set; }
|
||||
public String Month { get; set; }
|
||||
public String Filename { get; set; }
|
||||
}
|
||||
public LogsFilterData LogsFilter { get; } = new LogsFilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -471,4 +471,40 @@
|
||||
<data name="label.count" xml:space="preserve">
|
||||
<value>Count</value>
|
||||
</data>
|
||||
<data name="label.password.confirm" xml:space="preserve">
|
||||
<value>Password confirm</value>
|
||||
</data>
|
||||
<data name="caption.database.schemas" xml:space="preserve">
|
||||
<value>Database Schemas</value>
|
||||
</data>
|
||||
<data name="caption.database.control" xml:space="preserve">
|
||||
<value>Control Database</value>
|
||||
</data>
|
||||
<data name="caption.database.template" xml:space="preserve">
|
||||
<value>Template Database</value>
|
||||
</data>
|
||||
<data name="caption.database.demo" xml:space="preserve">
|
||||
<value>Demo Database</value>
|
||||
</data>
|
||||
<data name="msg.database.schema.valid" xml:space="preserve">
|
||||
<value>Database schema is valid.</value>
|
||||
</data>
|
||||
<data name="label.column" xml:space="preserve">
|
||||
<value>Column</value>
|
||||
</data>
|
||||
<data name="label.comment" xml:space="preserve">
|
||||
<value>Comment</value>
|
||||
</data>
|
||||
<data name="label.index" xml:space="preserve">
|
||||
<value>Index</value>
|
||||
</data>
|
||||
<data name="msg.warn.password.invalid" xml:space="preserve">
|
||||
<value>Password must be a minimum of {0} characters with upper and lower case letters, at least one number and special character unless at least {1} characters long.</value>
|
||||
</data>
|
||||
<data name="label.password.current" xml:space="preserve">
|
||||
<value>Current password</value>
|
||||
</data>
|
||||
<data name="label.strength" xml:space="preserve">
|
||||
<value>Strength</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -26,8 +26,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Control\Controllers\NewFolder\" />
|
||||
<Folder Include="Control\Controllers\System\" />
|
||||
<Folder Include="Views\Security\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
@inject SbmLocaliser Localiser
|
||||
@{
|
||||
ViewData["Title"] = "Home Page";
|
||||
Model.AdditionalFiles_JS.Add("js/sbc-home.js");
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
@@ -54,3 +55,98 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@* Database Schema form. *@
|
||||
<script>
|
||||
sbc.msg.dbSchemaValid = '@Localiser.GetJavascriptText("msg.database.schema.valid")';
|
||||
</script>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmDatabaseSchema" }))
|
||||
{
|
||||
<input type="hidden" name="DatabaseFilter.Instance" class="DatabaseInstance" />
|
||||
}
|
||||
|
||||
<style>
|
||||
.sbc-panel-info
|
||||
{
|
||||
max-width: 960px;
|
||||
}
|
||||
|
||||
.sax-panel-results .sax-panel-info.DbSchema > .sax-content
|
||||
{
|
||||
max-height: auto;
|
||||
}
|
||||
|
||||
.sax-panel-results .sax-panel-info.DbSchema .sax-panel-messages
|
||||
{
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.sax-panel-results .sax-panel-info.DbSchema table.sax-item-list thead tr th
|
||||
{
|
||||
background-color: #ffc8c7;
|
||||
}
|
||||
</style>
|
||||
|
||||
@* Database Schema Verification *@
|
||||
<div class="sbc-panel-info sbc-panel-results">
|
||||
|
||||
<div class="sbc-header">
|
||||
<div class="sbc-caption">@Localiser["caption.database.schemas"]</div>
|
||||
</div>
|
||||
<div class="sbc-content">
|
||||
|
||||
@* Database Schema - Control *@
|
||||
<div class="sbc-panel-info DbSchema Control">
|
||||
<div class="sbc-header">
|
||||
<div class="sbc-caption">@Localiser["caption.database.control"]</div>
|
||||
</div>
|
||||
<div class="sbc-panel-messages"></div>
|
||||
</div>
|
||||
|
||||
@* Database Schema - Template *@
|
||||
<div class="sbc-panel-info DbSchema Template">
|
||||
<div class="sbc-header">
|
||||
<div class="sbc-caption">@Localiser["caption.database.template"]</div>
|
||||
</div>
|
||||
<div class="sbc-panel-messages"></div>
|
||||
</div>
|
||||
|
||||
@* Database Schema - Demo *@
|
||||
<div class="sbc-panel-info DbSchema Demo">
|
||||
<div class="sbc-header">
|
||||
<div class="sbc-caption">@Localiser["caption.database.demo"]</div>
|
||||
</div>
|
||||
<div class="sbc-panel-messages"></div>
|
||||
</div>
|
||||
|
||||
@* Db Schema templates *@
|
||||
<div class="sbc-panel-item-template">
|
||||
@* Db Schema table template *@
|
||||
<div class="sbc-panel-item-table DbSchema" style="min-height:48px;max-height:240px;overflow-y:auto;">
|
||||
<table class="sbc-item-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="">@Localiser["label.schema"]</th>
|
||||
<th class="">@Localiser["label.table"]</th>
|
||||
<th class="">@Localiser["label.column"]</th>
|
||||
<th class="">@Localiser["label.index"]</th>
|
||||
<th class="" style="min-width:50%;">@Localiser["label.comment"]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
@* Db Schema Item row *@
|
||||
<table>
|
||||
<tr class="sbc-row-item DbSchemaItem">
|
||||
<td class=""><div class="SchemaName"></div></td>
|
||||
<td class=""><div class="TableName"></div></td>
|
||||
<td class=""><div class="ColumnName"></div></td>
|
||||
<td class=""><div class="IndexName"></div></td>
|
||||
<td class=""><div class="Comment"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbc-label">
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.first.name"]</span></label>
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.first.name"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
@@ -156,7 +156,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbc-label">
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.last.name"]</span></label>
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.last.name"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
@@ -173,29 +173,12 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbc-label">
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.email"]</span></label>
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.email"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbc-control">
|
||||
@Html.TextBox("User.Email", "", new { @id = "", @class = "UserEmail sbc-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email) })
|
||||
</div>
|
||||
<div class="sbc-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* User Code *@
|
||||
<div class="sbc-form-control @Model_RepositoryInit.GetControlName(Model_RepositoryInit.Control.UserCode)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbc-label">
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.login.code"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbc-control">
|
||||
@Html.TextBox("User.Code", "", new { @id = "", @class = "UserCode sbc-input", @maxlength = @Model.GetControlMaxLength(Sarand.Net.Standard.Base.Security.SaSecurityDbDfn.ColumnIdx.SaSecItem_Code) })
|
||||
@Html.TextBox("User.Email", "", new { @id = "", @class = "UserEmail sbc-input lower", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email) })
|
||||
</div>
|
||||
<div class="sbc-message"></div>
|
||||
</div>
|
||||
@@ -207,7 +190,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbc-label">
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.password"]</span></label>
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.password"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
@@ -220,6 +203,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* User Password Confirm *@
|
||||
<div class="sbc-form-control @Model_RepositoryInit.GetControlName(Model_RepositoryInit.Control.UserPasswordConfirm)">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sbc-label">
|
||||
<label for="ifRepositoryContext"><span>@Localiser["label.password.confirm"]</span><span class="required"> *</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="sbc-control">
|
||||
@Html.Password("User.PasswordConfirm", "", new { @id = "", @class = "UserPasswordConfirm sbc-input", @maxlength = Sbm.Config.Security.Password.MaxLength })
|
||||
</div>
|
||||
<div class="sbc-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer2"></div>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-auto sbc-label-text pt4">@Localiser["label.strength"] </div>
|
||||
<div id="" class="col-auto"><div id="prgPasswordStrength" class="col-auto"></div></div>
|
||||
<div id="" class="col-auto"><div id="" class="sbc-password-strength col-auto"></div></div>
|
||||
</div>
|
||||
<div class="sbc-message"></div>
|
||||
</div>
|
||||
|
||||
@@ -183,12 +183,15 @@
|
||||
@* Footer *@
|
||||
<footer id="sbc-page-footer" class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
@(Model.CopyrightNotice) - Sarand BusinessMgr
|
||||
<div class="row">
|
||||
<div class="col">BusinessMgr v@(Sbm.Version.GetAppVersion())</div>
|
||||
<div class="fixed">@(Model.CopyrightNotice) - Sarand</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@* Form to allow page navigation. *@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmNavigate" })) { }
|
||||
@using (@Html.BeginForm("", null, FormMethod.Post, new { @id = "frmNavigate" })) { }
|
||||
<div id='sbc-please-wait'></div>
|
||||
|
||||
@* Scripts *@
|
||||
|
||||
@@ -235,7 +235,7 @@ td.action
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.width50pc
|
||||
.halfwidth, .width50pc
|
||||
{
|
||||
width: 50%;
|
||||
}
|
||||
@@ -245,7 +245,17 @@ td.action
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fullheight
|
||||
.height25pc
|
||||
{
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.halfheight, .height50pc
|
||||
{
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.fullheight, .height100pc
|
||||
{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ ul.nav.sbc-burger ul.sbc-dropdown-menu li.sbc-action.sbc-dropdown-item:hover .sb
|
||||
|
||||
.sbc-panel-messages
|
||||
{
|
||||
margin: 8px 16px;
|
||||
margin: 5px 12px;
|
||||
padding: 2px 12px 2px 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@@ -248,9 +248,9 @@
|
||||
|
||||
/* Password strength */
|
||||
|
||||
#prgPasswordStrength
|
||||
.sbc-password-strength
|
||||
{
|
||||
width: 200px;
|
||||
width: 96%;
|
||||
height: 18px;
|
||||
margin: 6px 24px;
|
||||
border-color: #595959;
|
||||
@@ -259,7 +259,7 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#prgPasswordStrength .ui-widget-header
|
||||
.sbc-password-strength .ui-widget-header
|
||||
{
|
||||
margin: 0;
|
||||
height: 20px;
|
||||
@@ -269,19 +269,19 @@
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#prgPasswordStrength.amber .ui-widget-header
|
||||
.sbc-password-strength.amber .ui-widget-header
|
||||
{
|
||||
background-color: #FFBF00;
|
||||
border-color: #FFBF00;
|
||||
}
|
||||
|
||||
#prgPasswordStrength.green .ui-widget-header
|
||||
.sbc-password-strength.green .ui-widget-header
|
||||
{
|
||||
background-color: #238823;
|
||||
border-color: #238823;
|
||||
}
|
||||
|
||||
#prgPasswordStrength.ui-corner-all
|
||||
.sbc-password-strength.ui-corner-all
|
||||
{
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* BusMgr Control - Home scripts.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let ch = sbc.controlHome = {};
|
||||
let $pnl = ch.$pnl = {}, $dlg = ch.$dlg = {}, $frm = ch.$frm = {};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ch.refreshApplicationStats = function (delay)
|
||||
{
|
||||
}
|
||||
ch.handleStatsResponse = function (response)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ch.refreshDbSchema = function (instance, delay)
|
||||
{
|
||||
if (sbc.awaitingLogin) return;
|
||||
if (!ch.awaitingSchemaResponse)
|
||||
{
|
||||
let $pnlSchema = $('.sbc-panel-results .sbc-panel-info.DbSchema.' + instance);
|
||||
var $items = $('.sbc-panel-item-list', $pnlSchema).fadeOut(200).empty();
|
||||
var $msgs = $('.sbc-panel-messages', $pnlSchema).hide().empty().append($('<div class="sbc-message">' + sbc.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
$('.DatabaseInstance', $frm.dbSchema).val(instance);
|
||||
sbc.ajax.dbSchema = sbc.ajax.dbSchema || { url: sbc.url.base + 'System/Ajax/ValidateDatabaseSchema', formId: $frm.dbSchema.prop('id'), callbackFn: ch.handleDbSchemaResponse, noWaitIcon: true };
|
||||
sbc.doAjaxRequest(sbc.ajax.dbSchema, delay || 50);
|
||||
ch.awaitingSchemaResponse = true;
|
||||
}
|
||||
ch.handleDbSchemaResponse = function (response)
|
||||
{
|
||||
sbc.debug('handleDbSchemaResponse', response);
|
||||
delete ch.awaitingSchemaResponse;
|
||||
let $pnlSchema = $('.sbc-panel-results .sbc-panel-info.DbSchema.' + response.instance);
|
||||
var $msgs = $('.sbc-panel-messages', $pnlSchema).hide().empty();
|
||||
var $tablePanel = $('.sbc-panel-item-table', $pnlSchema).hide();
|
||||
var $table = $('table.sbc-item-list', $tablePanel);
|
||||
sbc.debug($table);
|
||||
$('tbody tr', $table).remove();
|
||||
if (!response.success) return;
|
||||
if (response.instance == 'Control') ch.toSchema = setTimeout(function () { ch.refreshDbSchema('Template'); }, 250);
|
||||
if (response.instance == 'Template') ch.toSchema = setTimeout(function () { ch.refreshDbSchema('Demo'); }, 250);
|
||||
// Items.
|
||||
var items = response.items;
|
||||
if (!items.length)
|
||||
return $msgs.append($('<div class="sbc-message">' + sbc.msg.dbSchemaValid + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$table.append(ch.populateDbSchemaItem(ch.getDbSchemaRowTemplate(), items[itemIdx]));
|
||||
$tablePanel.show();
|
||||
}
|
||||
ch.getDbSchemaTableTemplate = function ()
|
||||
{
|
||||
return $('.sbc-panel-results .sbc-panel-item-template .sbc-panel-item-table.DbSchema').clone().hide();
|
||||
}
|
||||
ch.getDbSchemaRowTemplate = function ()
|
||||
{
|
||||
return $('.sbc-panel-results .sbc-panel-item-template .sbc-row-item.DbSchemaItem').clone();
|
||||
}
|
||||
ch.populateDbSchemaItem = function ($item, item)
|
||||
{
|
||||
if (!item) return;
|
||||
$item.prop('id', sbc.itemIdPrefix + item.id);
|
||||
$('.SchemaName', $item).text(item.schemaName);
|
||||
$('.TableName', $item).text(item.tableName);
|
||||
$('.IndexName', $item).text(item.indexName);
|
||||
$('.ColumnName', $item).text(item.columnName);
|
||||
$('.Comment', $item).text(item.comment);
|
||||
return $item;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$frm.dbSchema = $('#frmDatabaseSchema');
|
||||
$pnl.dbSchemaControl = $('.sbc-panel-info.DbSchema.Control').append(ch.getDbSchemaTableTemplate());
|
||||
$pnl.dbSchemaTemplate = $('.sbc-panel-info.DbSchema.Template'); $pnl.dbSchemaTemplate.append(ch.getDbSchemaTableTemplate());
|
||||
$pnl.dbSchemaDemo = $('.sbc-panel-info.DbSchema.Demo').append(ch.getDbSchemaTableTemplate());
|
||||
|
||||
ch.toSchema = setTimeout(function () { ch.refreshDbSchema('Control'); }, 600);
|
||||
// NB Can only request one of the database schemas at a time as they share the same ajax config.
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -255,7 +255,7 @@
|
||||
var opt = sbc.dlgOpts();
|
||||
sbc.$dlg.alert = $('<div id="dlgAlert"><div id="dlgAlertMsg"></div></div>').dialog(opt);
|
||||
}
|
||||
$('#dlgAlertMsg', sbc.$dlg.alert).html(msg.replace(/\\n/g, '<br>'));
|
||||
$('#dlgAlertMsg', sbc.$dlg.alert).html(msg.replace(/\n/g, '<br>'));
|
||||
let btns = {};
|
||||
btns[sbc.lbl.ok] = function () { $(this).dialog('close'); if (onOk) onOk(); };
|
||||
sbc.$dlg.alert.dialog('option', { title: title || sbc.dlg.title.alert, buttons: btns });
|
||||
@@ -277,7 +277,7 @@
|
||||
btns[sbc.lbl.yes] = function () { $(this).dialog('close'); if (onOk) onOk(); };
|
||||
btns[sbc.lbl.no] = function () { $(this).dialog('close'); if (onCancel) onCancel(); };
|
||||
sbc.$dlg.confirm.dialog('option', { title: title || sbc.dlg.title.confirm, buttons: btns });
|
||||
$('#dlgConfirmMsg').html(msg.replace(/\\n/g, '<br>'));
|
||||
$('#dlgConfirmMsg').html(msg.replace(/\n/g, '<br>'));
|
||||
sbc.openDialog(sbc.$dlg.confirm);
|
||||
}
|
||||
sbc.doProgress = function (title, msg, delay)
|
||||
@@ -295,7 +295,7 @@
|
||||
opt.hide = { effect: 'fade', duration: 200 };
|
||||
sbc.$dlg.progress = $('<div id="dlgProgress"><div id="dlgProgressMsg"></div></div>').dialog(opt);
|
||||
}
|
||||
$('#dlgProgressMsg').html(msg.replace(/\\n/g, '<br>'));
|
||||
$('#dlgProgressMsg').html(msg.replace(/\n/g, '<br>'));
|
||||
sbc.$dlg.progress.dialog('option', { title: title || sbc.dlg.title.progress });
|
||||
if (delay > 0) sbc.toShowProgress = setTimeout(function () { sbc.$dlg.progress.dialog('open'); }, delay);
|
||||
else sbc.$dlg.progress.dialog('open');
|
||||
|
||||
@@ -76,11 +76,11 @@
|
||||
$('#ifEmailAddress,#ifPasswordCurrent,#ifPassword,#ifPasswordConfirm').on('input', function () { sbc.clearControlError(this); });
|
||||
sbc.$frm.signIn = $('#frmSignIn');
|
||||
sbc.$frm.signIn.on('keypress', '#ifEmailAddress,#ifPassword,#chkKeepMeSignedIn', function (e) { if (e.which == 13 && $('#ifEmailAddress', sbc.$frm.signIn).val() && $('#ifPassword', sbc.$frm.signIn).val()) sbc.doSignin(); });
|
||||
sbc.$frm.signIn.on('click', '#pbSignIn', function () { sbc.doSignin(); }).on('keypress', '#pbSignIn', function (e) { if (e.which == 13) sbc.doSignin(); });;
|
||||
sbc.$frm.signIn.on('click', '#pbSignIn', function () { sbc.doSignin(); }).on('keypress', '#pbSignIn', function (e) { if (e.which == 13) sbc.doSignin(); });
|
||||
sbc.$frm.chgPword = $('#frmChangePassword');
|
||||
sbc.$frm.chgPword.on('keypress', '#ifPasswordCurrent,#ifPassword,#ifPasswordConfirm', function (e) { if (e.which == 13) sbc.doChangePassword(); });
|
||||
sbc.$frm.chgPword.on('keyup', '#ifPassword', sbc.doScorePassword);
|
||||
sbc.$prgPwordStrength = $('#prgPasswordStrength', sbc.$frm.chgPword).progressbar({ 'max': 5 });
|
||||
sbc.$prgPwordStrength = $('.sbc-password-strength', sbc.$frm.chgPword).progressbar({ 'max': 5 });
|
||||
$('#pbChangePassword', sbc.$frm.chgPword).on('click', function () { sbc.doChangePassword(); }).on('keypress', function (e) { if (e.which == 13) sbc.doChangePassword(); });
|
||||
sbc.$frm.reqPword = $('#frmRequestPassword');
|
||||
sbc.$frm.reqPword.on('keypress', '#ifEmailAddress', function (e) { if (e.which == 13) sbc.doRequestPassword(); });
|
||||
|
||||
Reference in New Issue
Block a user