setup login for web
This commit is contained in:
parent
83f92ea6c8
commit
cf1a8e74a6
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using DocumentFormat.OpenXml.Office2010.ExcelAc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
|
namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
|
||||||
{
|
{
|
||||||
|
|
@ -34,6 +36,10 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
|
||||||
public string? DesignationName { get; set; }
|
public string? DesignationName { get; set; }
|
||||||
public EnumLoginStatus LoginStatus { get; set; }
|
public EnumLoginStatus LoginStatus { get; set; }
|
||||||
public DateTime? NextLoginTime { get; set; }
|
public DateTime? NextLoginTime { get; set; }
|
||||||
|
public int NotificationCount { get; set; }
|
||||||
|
|
||||||
|
public List<string> ModuleIds { get; set; } = new List<string>();
|
||||||
|
public List<int> TeamSpaceIds { get; set; } = new List<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoginHistory
|
public class LoginHistory
|
||||||
|
|
|
||||||
|
|
@ -27,46 +27,28 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems
|
||||||
public DateTime? Expires { get; set; }
|
public DateTime? Expires { get; set; }
|
||||||
public DateTime SystemDate { get; set; }
|
public DateTime SystemDate { get; set; }
|
||||||
public string LoginTime { get; set; }
|
public string LoginTime { get; set; }
|
||||||
public int LogId { get; set; }
|
|
||||||
public DateTime? LogoutTime { get; private set; }
|
public DateTime? LogoutTime { get; private set; }
|
||||||
public string MenuLayout { get; set; }
|
|
||||||
public string ThemeName { get; set; }
|
|
||||||
public string SchemeName { get; set; }
|
|
||||||
public bool DbOnStartup { get; set; }
|
|
||||||
public bool ViewOwnTaskOnly { get; private set; }
|
|
||||||
public int? EmployeeId { get; private set; }
|
|
||||||
public int NotificationCount { get; private set; }
|
public int NotificationCount { get; private set; }
|
||||||
public int IdleTime { get; set; }
|
|
||||||
public int PingTime { get; set; }
|
|
||||||
public int TimeoutTime { get; set; }
|
|
||||||
public bool BatchEnabled { get; private set; }
|
|
||||||
public int BmProcessId { get; private set; }
|
|
||||||
public int PrProcessId { get; private set; }
|
|
||||||
public string IdsValue { get; set; }
|
|
||||||
|
|
||||||
//public List<string> ModuleIds { get; set; } = [];
|
public List<string> ModuleIds { get; set; } = [];
|
||||||
|
|
||||||
public void Map(User source)
|
public string RefreshToken { get;set; }
|
||||||
|
public UserPlatFormType? UserPlatFormType { get; set; }
|
||||||
|
public UserRoleTypeEnum? UserRoleType { get; set; }
|
||||||
|
public string? EmployeeNumber { get; set; }
|
||||||
|
|
||||||
|
public void Map(User source)
|
||||||
{
|
{
|
||||||
Id = source.UserId;
|
Id = source.UserId;
|
||||||
LoginId = source.LoginId;
|
LoginId = source.LoginId;
|
||||||
UserName = source.UserName;
|
UserName = source.UserName;
|
||||||
ThemeName = source.ThemeName;
|
ModuleIds = source.ModuleIds;
|
||||||
//ModuleIds = source.ModuleIds;
|
|
||||||
LogoutTime = source.LogoutTime;
|
LogoutTime = source.LogoutTime;
|
||||||
SchemeName = source.SchemeName;
|
|
||||||
MenuLayout = source.MenuLayout;
|
|
||||||
LoginStatus = source.LoginStatus;
|
LoginStatus = source.LoginStatus;
|
||||||
//DbOnStartup = source.DbOnStartup;
|
UserPlatFormType = source.UserPlatFormType;
|
||||||
//TimeoutTime = source.TimeoutTime;
|
UserRoleType = source.UserRoleType;
|
||||||
//BmProcessId = source.BmProcessId;
|
EmployeeNumber = source.EmployeeNumber;
|
||||||
//PrProcessId = source.PrProcessId;
|
}
|
||||||
//BatchEnabled = source.BatchEnabled;
|
|
||||||
//ViewOwnTaskOnly = source.ViewOwnTaskOnly;
|
|
||||||
//NotificationCount = source.NotificationCount;
|
|
||||||
//AuthRequiredAtLogin = source.AuthRequiredAtLogin;
|
|
||||||
//IdsValue = Newtonsoft.Json.JsonConvert.SerializeObject(source.ModuleIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MenuResponse
|
public class MenuResponse
|
||||||
|
|
|
||||||
|
|
@ -267,8 +267,8 @@ public class RefreshTokenService : IRefreshTokenService
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
TokenHash = tokenHash,
|
TokenHash = tokenHash,
|
||||||
IpAddress = ipAddress,
|
IpAddress = ipAddress,
|
||||||
CreatedAt = DateTime.UtcNow,
|
CreatedAt = DateTime.Now,
|
||||||
ExpiresAt = DateTime.UtcNow.AddDays(_settings.RefreshTokenDuration)
|
ExpiresAt = DateTime.Now.AddMinutes(_settings.RefreshTokenDuration)
|
||||||
};
|
};
|
||||||
|
|
||||||
AddAsync(tc,refreshToken);
|
AddAsync(tc,refreshToken);
|
||||||
|
|
@ -276,7 +276,7 @@ public class RefreshTokenService : IRefreshTokenService
|
||||||
return new GenerateRefreshTokenResponse
|
return new GenerateRefreshTokenResponse
|
||||||
{
|
{
|
||||||
RefreshToken = tokenHash,
|
RefreshToken = tokenHash,
|
||||||
ExpireTime = DateTime.UtcNow.AddDays(_settings.RefreshTokenDuration)
|
ExpireTime = DateTime.Now.AddMinutes(_settings.RefreshTokenDuration)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,220 +95,192 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
//if (user.LoginStatus != EnumLoginStatus.VersionMismatch)
|
if (user.LoginStatus != EnumLoginStatus.VersionMismatch)
|
||||||
//{
|
{
|
||||||
// #region Read User data using authentication data
|
#region Read User data using authentication data
|
||||||
|
|
||||||
// string commandText;
|
string commandText = SQLParser.MakeSQL("SELECT UserId,LoginId, UserName, Status,AccessStatus,NeverExpires, MobileNo, EmailAddress, "
|
||||||
// if (!checkPwd)
|
+ " IsLocked, UserPlatformId, UserRoleType, EmployeeNumber FROM Users"
|
||||||
// {
|
+ " WHERE (LoginID=%s OR MobileNo=%s OR EmailAddress=%s) AND Password=%s", request.LoginId, request.LoginId, request.LoginId, password);
|
||||||
// commandText = SQLParser.MakeSQL("SELECT UserId, UserName, Status, MobileNo, EmailAddress, AuthReqAtlogin, AuthMethod,"
|
|
||||||
// + " AuthKey, AppId, AccessStatus, NeverExpire, LastPasswords, LastPassChgDate, ExpireDate, ThemeName, SchemeName, MenuLayout,"
|
|
||||||
// + " IsLocked, NextLoginTime, DBOnStartup, DAMultiLogin, ViewOwnTaskOnly, EmployeeId, LoginID, EmployeeCode FROM Users WHERE LoginID=%s", request.LoginId);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// commandText = SQLParser.MakeSQL("SELECT UserId, UserName, Status, MobileNo, EmailAddress, AuthReqAtlogin, AuthMethod,"
|
|
||||||
// + " AuthKey, AppId, AccessStatus, NeverExpire, LastPasswords, LastPassChgDate, ExpireDate, ThemeName, SchemeName, MenuLayout,"
|
|
||||||
// + " IsLocked, NextLoginTime, DBOnStartup, DAMultiLogin, ViewOwnTaskOnly, EmployeeId, LoginID, EmployeeCode FROM Users"
|
|
||||||
// + " WHERE (LoginID=%s OR MobileNo=%s OR EmailAddress=%s) AND Password=%s", request.LoginId, request.LoginId, request.LoginId, password);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// using (IDataReader dr = tc.ExecuteReader(commandText: commandText))
|
using (IDataReader dr = tc.ExecuteReader(commandText: commandText))
|
||||||
// {
|
{
|
||||||
// if (dr.Read())
|
if (dr.Read())
|
||||||
// {
|
{
|
||||||
// user = new User
|
user = new User
|
||||||
// {
|
{
|
||||||
// Id = dr.GetInt32(0),
|
UserId = dr.GetInt32(0),
|
||||||
// UserName = dr.GetString(1),
|
LoginId = dr.GetString(1),
|
||||||
// Status = (EnumStatus)dr.GetInt16(2),
|
UserName = dr.GetString(2),
|
||||||
// MobileNo = dr.GetString(3),
|
Status = (EnumStatus)dr.GetInt32(3),
|
||||||
// EmailAddress = dr.GetString(4),
|
AccessStatus = (EnumAccessStatus)dr.GetInt32(4),
|
||||||
// AuthRequiredAtLogin = !dr.IsDBNull(5) && dr.GetInt16(5) > 0,
|
NeverExpires = dr.GetBoolean(5),
|
||||||
// AuthMethod = (EnumAuthenticationMethod)dr.GetInt16(6),
|
MobileNo = dr.IsDBNull(6) ? null : dr.GetString(6),
|
||||||
// AuthKey = dr.IsDBNull(7) ? string.Empty : dr.GetString(7),
|
EmailAddress = dr.IsDBNull(7) ? null : dr.GetString(7),
|
||||||
// AppId = dr.IsDBNull(8) ? string.Empty : dr.GetString(8),
|
IsLocked = dr.GetBoolean(8),
|
||||||
// AccessStatus = (EnumAccessStatus)dr.GetInt16(9),
|
UserPlatFormType = dr.IsDBNull(9) ? null : (UserPlatFormType)dr.GetInt32(9),
|
||||||
// NeverExpires = !dr.IsDBNull(10) && dr.GetInt16(10) > 0,
|
UserRoleType = dr.IsDBNull(10) ? null : (UserRoleTypeEnum)dr.GetInt32(10),
|
||||||
// LastPasswords = dr.IsDBNull(11) ? string.Empty : dr.GetString(11),
|
EmployeeNumber = dr.IsDBNull(11) ? null : dr.GetString(11),
|
||||||
// LastPassChgDate = dr.IsDBNull(12) ? null : dr.GetDateTime(12),
|
LoginStatus = EnumLoginStatus.Success
|
||||||
// ExpireDate = dr.IsDBNull(13) ? null : dr.GetDateTime(13),
|
};
|
||||||
// ThemeName = dr.IsDBNull(14) ? "yellow" : dr.GetString(14),
|
}
|
||||||
// SchemeName = dr.IsDBNull(15) ? "dark" : dr.GetString(15),
|
dr.Close();
|
||||||
// MenuLayout = dr.IsDBNull(16) ? "static" : dr.GetString(16),
|
}
|
||||||
// IsLocked = !dr.IsDBNull(17) && dr.GetInt16(17) > 0,
|
|
||||||
// NextLoginTime = dr.IsDBNull(18) ? null : dr.GetDateTime(18),
|
|
||||||
// DbOnStartup = dr.GetInt16(19) != 0,
|
|
||||||
// DisallowMultiLogin = dr.GetInt16(20) != 0,
|
|
||||||
// ViewOwnTaskOnly = dr.GetInt16(21) != 0,
|
|
||||||
// EmployeeId = dr.IsDBNull(22) ? null : dr.GetInt32(22),
|
|
||||||
// LoginId = dr.GetString(23),
|
|
||||||
// EmployeeCode = dr.IsDBNull(24) ? string.Empty : dr.GetString(24),
|
|
||||||
|
|
||||||
// TeamSpaceIds = [],
|
#endregion
|
||||||
// IdleTime = idleTime,
|
|
||||||
// PingTime = pingTime,
|
|
||||||
// SystemDate = sysDate,
|
|
||||||
// TimeoutTime = timeoutTime,
|
|
||||||
// PrProcessId = prProcessId,
|
|
||||||
// BmProcessId = bmProcessId,
|
|
||||||
// BatchEnabled = batchEnabled,
|
|
||||||
// LoginStatus = EnumLoginStatus.Success
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// dr.Close();
|
|
||||||
|
|
||||||
// user.MinReportDate = marMonths <= 0 ? new DateTime(year: 2015, month: 1, day: 1, hour: 0, minute: 0, second: 0, kind: DateTimeKind.Local) : sysDate.AddMonths(-1 * marMonths);
|
#region If the user was locked, try set set unlock if Time expired
|
||||||
// }
|
|
||||||
|
|
||||||
// #endregion
|
if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && user.IsLocked)
|
||||||
|
{
|
||||||
|
int isSuccessful = 0;
|
||||||
|
SqlParameter[] p =
|
||||||
|
[
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 30),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
|
||||||
|
SqlHelperExtension.CreateOutParam(pName: "@IsSuccessful", pType: SqlDbType.Int, pValue: isSuccessful),
|
||||||
|
];
|
||||||
|
_ = tc.ExecuteNonQuerySp(spName: "dbo.DoUnlockUser", parameterValues: p);
|
||||||
|
if (p[2] != null && p[2].Value != null && p[2].Value != DBNull.Value)
|
||||||
|
isSuccessful = Convert.ToInt32(p[2].Value);
|
||||||
|
|
||||||
// #region If the user was locked, try set set unlock if Time expired
|
if (isSuccessful == 1)
|
||||||
|
user.IsLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
// if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && user.IsLocked)
|
#endregion
|
||||||
// {
|
|
||||||
// int isSuccessful = 0;
|
|
||||||
// SqlParameter[] p =
|
|
||||||
// [
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 30),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
|
|
||||||
// SqlHelperExtension.CreateOutParam(pName: "@IsSuccessful", pType: SqlDbType.Int, pValue: isSuccessful),
|
|
||||||
// ];
|
|
||||||
// _ = tc.ExecuteNonQuerySp(spName: "dbo.DoUnlockUser", parameterValues: p);
|
|
||||||
// if (p[2] != null && p[2].Value != null && p[2].Value != DBNull.Value)
|
|
||||||
// isSuccessful = Convert.ToInt32(p[2].Value);
|
|
||||||
|
|
||||||
// if (isSuccessful == 1)
|
#region Keep log for unauthrise access and Set user lock if exceeds max try
|
||||||
// user.IsLocked = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #endregion
|
if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && maxTryCount > 0 && user.LoginStatus == EnumLoginStatus.Unsuccessful)
|
||||||
|
{
|
||||||
|
int remainsTry = 0;
|
||||||
|
DateTime? nextLoginTime = null;
|
||||||
|
string tryLoginInfo = $"{request.LoginId}~{password}~13";
|
||||||
|
SqlParameter[] p =
|
||||||
|
[
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 30),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@TryLoginInfo", pType: SqlDbType.VarChar, pValue: tryLoginInfo, size: 100),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@MaxTryCount", pType: SqlDbType.SmallInt, pValue: maxTryCount),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
|
||||||
|
SqlHelperExtension.CreateOutParam(pName: "@RemainingTry", pType: SqlDbType.SmallInt, pValue: remainsTry),
|
||||||
|
SqlHelperExtension.CreateOutParam(pName: "@NextLoginTime", pType: SqlDbType.DateTime, pValue: nextLoginTime),
|
||||||
|
];
|
||||||
|
_ = tc.ExecuteNonQuerySp(spName: "dbo.LogUnauthorizeAccess", parameterValues: p);
|
||||||
|
if (p[5] != null && p[5].Value != null && p[5].Value != DBNull.Value)
|
||||||
|
remainsTry = Convert.ToInt32(p[5].Value);
|
||||||
|
|
||||||
// #region Keep log for unauthrise access and Set user lock if exceeds max try
|
if (p[6] != null && p[6].Value != null && p[6].Value != DBNull.Value)
|
||||||
|
nextLoginTime = Convert.ToDateTime(p[6].Value);
|
||||||
|
|
||||||
// if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && maxTryCount > 0 && user.LoginStatus == EnumLoginStatus.Unsuccessful)
|
if (remainsTry <= 0)
|
||||||
// {
|
{
|
||||||
// int remainsTry = 0;
|
user.IsLocked = true;
|
||||||
// DateTime? nextLoginTime = null;
|
if (lockTime <= 0)
|
||||||
// string tryLoginInfo = $"{request.LoginId}~{password}~13";
|
{
|
||||||
// SqlParameter[] p =
|
user.NextLoginTime = nextLoginTime;
|
||||||
// [
|
user.UnsuccessfulMsg = "Please contact with Head office to Unlock";
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 30),
|
}
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@TryLoginInfo", pType: SqlDbType.VarChar, pValue: tryLoginInfo, size: 100),
|
else
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
{
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@MaxTryCount", pType: SqlDbType.SmallInt, pValue: maxTryCount),
|
user.NextLoginTime = nextLoginTime;
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
|
user.UnsuccessfulMsg = $"You can Login after {user.NextLoginTime:dd-MMM-yyyy H:mm:ss}";
|
||||||
// SqlHelperExtension.CreateOutParam(pName: "@RemainingTry", pType: SqlDbType.SmallInt, pValue: remainsTry),
|
}
|
||||||
// SqlHelperExtension.CreateOutParam(pName: "@NextLoginTime", pType: SqlDbType.DateTime, pValue: nextLoginTime),
|
}
|
||||||
// ];
|
else
|
||||||
// _ = tc.ExecuteNonQuerySp(spName: "dbo.LogUnauthorizeAccess", parameterValues: p);
|
{
|
||||||
// if (p[5] != null && p[5].Value != null && p[5].Value != DBNull.Value)
|
user.UnsuccessfulMsg = $"{remainsTry} More attempt{(remainsTry > 1 ? "s" : "")} remaining";
|
||||||
// remainsTry = Convert.ToInt32(p[5].Value);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if (p[6] != null && p[6].Value != null && p[6].Value != DBNull.Value)
|
#endregion
|
||||||
// nextLoginTime = Convert.ToDateTime(p[6].Value);
|
|
||||||
|
|
||||||
// if (remainsTry <= 0)
|
|
||||||
// {
|
|
||||||
// user.IsLocked = true;
|
|
||||||
// if (lockTime <= 0)
|
|
||||||
// {
|
|
||||||
// user.NextLoginTime = nextLoginTime;
|
|
||||||
// user.UnsuccessfulMsg = "Please contact with Head office to Unlock";
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// user.NextLoginTime = nextLoginTime;
|
|
||||||
// user.UnsuccessfulMsg = $"You can Login after {user.NextLoginTime:dd-MMM-yyyy H:mm:ss}";
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// user.UnsuccessfulMsg = $"{remainsTry} More attempt{(remainsTry > 1 ? "s" : "")} remaining";
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #endregion
|
#region If login successful and user is active read module id for this user
|
||||||
|
|
||||||
// #region Generate and Save Otp if Otp is enabled and send thru SMS/Email
|
if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && !user.IsLocked)
|
||||||
|
{
|
||||||
|
SqlParameter[] p =
|
||||||
|
[
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.UserId),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LoginTime", pType: SqlDbType.DateTime, pValue: DateTime.Now),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LogoutTime", pType: SqlDbType.DateTime, pValue: null)
|
||||||
|
];
|
||||||
|
|
||||||
// if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && (user.AuthMethod == EnumAuthenticationMethod.Email || user.AuthMethod == EnumAuthenticationMethod.MobileSMS))
|
_ = tc.ExecuteNonQuerySp(spName: "dbo.SaveAccessLog", parameterValues: p);
|
||||||
// {
|
}
|
||||||
// string secretKey = $"{user.Id}~{user.LoginId}";
|
|
||||||
// secretKey = secretKey.EncodeAsBase32String(addPadding: false);
|
|
||||||
// user.AuthValue = TOtpService.GetCurrentPIN(secretKey: secretKey);
|
|
||||||
// SetAuthValue(tc: tc, authValue: user.AuthValue, validMinutes: 5, userId: user.Id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #endregion
|
#endregion
|
||||||
|
|
||||||
// #region If login successful and user is active read module id for this user
|
|
||||||
|
|
||||||
// if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && !user.IsLocked)
|
#region If login successful and user is active read module id for this user
|
||||||
// {
|
|
||||||
// int logId = 0;
|
|
||||||
// DateTime? logoutTime = null;
|
|
||||||
// SqlParameter[] p =
|
|
||||||
// [
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.Id),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@AppId", pType: SqlDbType.VarChar, pValue: request.AppId, size: 250),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@AttendanceLogin", pType: SqlDbType.Int, pValue: request.AttendanceLogin? 1:0),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LocalIp", pType: SqlDbType.VarChar, pValue: request.IpAddress, size: 20),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@MacAddress", pType: SqlDbType.VarChar, pValue: request.MacAddress, size: 30),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@HostName", pType: SqlDbType.VarChar, pValue: request.HostName, size: 100),
|
|
||||||
// SqlHelperExtension.CreateInParam(pName: "@LoginRemarks", pType: SqlDbType.VarChar, pValue: request.LoginRemarks, size: 50)
|
|
||||||
// ];
|
|
||||||
// using (IDataReader dr = tc.ExecuteReaderSp(spName: "dbo.GetPermissionKeys", parameterValues: p))
|
|
||||||
// {
|
|
||||||
// user.ModuleIds = [];
|
|
||||||
// while (dr.Read())
|
|
||||||
// {
|
|
||||||
// string moduleId = dr.GetString(0);
|
|
||||||
// user.ModuleIds.Add(moduleId);
|
|
||||||
|
|
||||||
// logId = dr.GetInt32(1);
|
if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && !user.IsLocked)
|
||||||
|
{
|
||||||
|
int logId = 0;
|
||||||
|
DateTime? logoutTime = null;
|
||||||
|
SqlParameter[] p =
|
||||||
|
[
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.UserId),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@AppId", pType: SqlDbType.VarChar, pValue: request.AppId, size: 250),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@AttendanceLogin", pType: SqlDbType.Int, pValue: request.AttendanceLogin? 1:0),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LocalIp", pType: SqlDbType.VarChar, pValue: request.IpAddress, size: 20),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@MacAddress", pType: SqlDbType.VarChar, pValue: request.MacAddress, size: 30),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@HostName", pType: SqlDbType.VarChar, pValue: request.HostName, size: 100),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LoginRemarks", pType: SqlDbType.VarChar, pValue: request.LoginRemarks, size: 50)
|
||||||
|
];
|
||||||
|
using (IDataReader dr = tc.ExecuteReaderSp(spName: "dbo.GetPermissionKeys", parameterValues: p))
|
||||||
|
{
|
||||||
|
user.ModuleIds = [];
|
||||||
|
while (dr.Read())
|
||||||
|
{
|
||||||
|
string moduleId = dr.GetString(0);
|
||||||
|
user.ModuleIds.Add(moduleId);
|
||||||
|
|
||||||
// if (dr.GetInt16(2) != 0) //Alow add
|
logId = dr.GetInt32(1);
|
||||||
// {
|
|
||||||
// user.ModuleIds.Add($"{moduleId}_1");
|
|
||||||
// }
|
|
||||||
// if (dr.GetInt16(3) != 0) //Alow edit
|
|
||||||
// {
|
|
||||||
// user.ModuleIds.Add($"{moduleId}_2");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (dr.GetInt16(4) != 0) //Allow Delete
|
if (dr.GetInt16(2) != 0) //Alow add
|
||||||
// {
|
{
|
||||||
// user.ModuleIds.Add($"{moduleId}_3");
|
user.ModuleIds.Add($"{moduleId}_1");
|
||||||
// }
|
}
|
||||||
|
if (dr.GetInt16(3) != 0) //Alow edit
|
||||||
|
{
|
||||||
|
user.ModuleIds.Add($"{moduleId}_2");
|
||||||
|
}
|
||||||
|
|
||||||
// logoutTime = dr.IsDBNull(5) ? null : dr.GetDateTime(5);
|
if (dr.GetInt16(4) != 0) //Allow Delete
|
||||||
// }
|
{
|
||||||
// dr.Close();
|
user.ModuleIds.Add($"{moduleId}_3");
|
||||||
// }
|
}
|
||||||
// user.LogId = logId;
|
|
||||||
// user.LogoutTime = logoutTime;
|
|
||||||
|
|
||||||
// //Read User TeamSpace Ids
|
logoutTime = dr.IsDBNull(5) ? null : dr.GetDateTime(5);
|
||||||
// using (IDataReader dr = tc.ExecuteReader("SELECT TeamSpaceId FROM TeamSpaceUsers WHERE UserId=%n", user.Id))
|
}
|
||||||
// {
|
dr.Close();
|
||||||
// while (dr.Read())
|
}
|
||||||
// {
|
user.LogoutTime = logoutTime;
|
||||||
// user.TeamSpaceIds.Add(dr.GetInt32(0));
|
|
||||||
// }
|
|
||||||
// dr.Close();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //Pending Notification count
|
//Read User TeamSpace Ids
|
||||||
// user.NotificationCount = GetPendingNotifCount(tc: tc, userId: user.Id);
|
using (IDataReader dr = tc.ExecuteReader("SELECT TeamSpaceId FROM TeamSpaceUsers WHERE UserId=%n", user.UserId))
|
||||||
// }
|
{
|
||||||
|
while (dr.Read())
|
||||||
|
{
|
||||||
|
user.TeamSpaceIds.Add(dr.GetInt32(0));
|
||||||
|
}
|
||||||
|
dr.Close();
|
||||||
|
}
|
||||||
|
|
||||||
// #endregion
|
//Pending Notification count
|
||||||
//}
|
//user.NotificationCount = GetPendingNotifCount(tc: tc, userId: user.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
tc.End();
|
tc.End();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers
|
||||||
loginReponse.LoginId = loginReponse.LoginId;
|
loginReponse.LoginId = loginReponse.LoginId;
|
||||||
loginReponse.AccessToken = userToken;
|
loginReponse.AccessToken = userToken;
|
||||||
loginReponse.RefreshToken = refreshToken.RefreshToken;
|
loginReponse.RefreshToken = refreshToken.RefreshToken;
|
||||||
loginReponse.AccessTokenExpiryTime = DateTime.UtcNow.AddHours(12);
|
loginReponse.AccessTokenExpiryTime = DateTime.Now.AddMinutes(_appSettings.AccessTokenDuration);
|
||||||
loginReponse.RefreshTokenExpiryTime = refreshToken.ExpireTime;
|
loginReponse.RefreshTokenExpiryTime = refreshToken.ExpireTime;
|
||||||
|
|
||||||
return Ok(MobileResponseBase<AppAuthUserResponse>.Success(loginReponse));
|
return Ok(MobileResponseBase<AppAuthUserResponse>.Success(loginReponse));
|
||||||
|
|
@ -217,7 +217,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers
|
||||||
Helper.CreateClaim("UserId", $"{userRefreshToken.UserId}"),
|
Helper.CreateClaim("UserId", $"{userRefreshToken.UserId}"),
|
||||||
Helper.CreateClaim("HashKey", Guid.NewGuid().ToString())
|
Helper.CreateClaim("HashKey", Guid.NewGuid().ToString())
|
||||||
]),
|
]),
|
||||||
Expires = DateTime.UtcNow.AddHours(12),
|
Expires = DateTime.UtcNow.AddMinutes(_appSettings.AccessTokenDuration),
|
||||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,5 @@
|
||||||
using Asp.Versioning;
|
using Asp.Versioning;
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Configurations;
|
using Google.Apis.Auth.OAuth2.Requests;
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
|
|
||||||
using OnlineSalesAutoCrop.CoreAPI.SignalRHub;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
@ -18,6 +7,20 @@ using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Configurations;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Objects;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Requests;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Responses;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
|
||||||
|
using OnlineSalesAutoCrop.CoreAPI.SignalRHub;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.DirectoryServices;
|
using System.DirectoryServices;
|
||||||
|
|
@ -45,11 +48,11 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.Web
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0")]
|
||||||
[Route("api/users")]
|
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
[Route("api/v{version:apiVersion}/users")]
|
[Route("api/v{version:apiVersion}/users")]
|
||||||
|
|
||||||
public class UserController(IUserService service, IOptions<AppSettings> appSettings, IEaseCache cache, ILogger<IntegrationAuthController> logger, IHubContext<NotificationHub, INotificationHub> hub) : ControllerBase
|
public class UserController(IUserService service, IOptions<AppSettings> appSettings, IEaseCache cache, ILogger<IntegrationAuthController> logger,
|
||||||
|
IHubContext<NotificationHub, INotificationHub> hub, IRefreshTokenService refreshTokenService) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger = logger;
|
private readonly ILogger _logger = logger;
|
||||||
private readonly IEaseCache _cache = cache;
|
private readonly IEaseCache _cache = cache;
|
||||||
|
|
@ -57,6 +60,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.Web
|
||||||
private readonly AppSettings _appSettings = appSettings?.Value;
|
private readonly AppSettings _appSettings = appSettings?.Value;
|
||||||
private readonly DateTimeOffset _options = Helper.CreateEaseCacheOptions();
|
private readonly DateTimeOffset _options = Helper.CreateEaseCacheOptions();
|
||||||
private readonly IHubContext<NotificationHub, INotificationHub> _hub = hub;
|
private readonly IHubContext<NotificationHub, INotificationHub> _hub = hub;
|
||||||
|
private readonly IRefreshTokenService _refreshTokenService= refreshTokenService;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Login using your credential data retrieve from SqlServer
|
/// Login using your credential data retrieve from SqlServer
|
||||||
|
|
@ -215,17 +219,15 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.Web
|
||||||
{
|
{
|
||||||
Subject = new ClaimsIdentity(
|
Subject = new ClaimsIdentity(
|
||||||
[
|
[
|
||||||
//Helper.CreateClaim("UserId", $"{user.Id}"),
|
Helper.CreateClaim("UserId", $"{user.UserId}"),
|
||||||
//Helper.CreateClaim("LoginId", user.LoginId),
|
Helper.CreateClaim("LoginId", user.LoginId),
|
||||||
//Helper.CreateClaim("UserPwd", userPwd),
|
Helper.CreateClaim("AuthKey", $"{user.AuthKey}"),
|
||||||
//Helper.CreateClaim("AuthKey", $"{user.AuthKey}"),
|
Helper.CreateClaim("TeamSpaceIds", $"{string.Join(',',user.TeamSpaceIds)}"),
|
||||||
//Helper.CreateClaim("TeamSpaceIds", $"{string.Join(',',user.TeamSpaceIds)}"),
|
Helper.CreateClaim("UserPlatformId", ((int)user.UserPlatFormType).ToString()),
|
||||||
//Helper.CreateClaim("BatchEnabled", user.BatchEnabled ? "1" : "0"),
|
Helper.CreateClaim("UserRoleType", $"{user.UserRoleType}"),
|
||||||
//Helper.CreateClaim("BmProcessId", $"{user.BmProcessId}"),
|
Helper.CreateClaim("EmployeeCode", $"{user.EmployeeNumber}")
|
||||||
//Helper.CreateClaim("PrProcessId", $"{user.PrProcessId}"),
|
|
||||||
//Helper.CreateClaim("EmployeeId", $"{user.EmployeeCode}")
|
|
||||||
]),
|
]),
|
||||||
Expires = DateTime.UtcNow.AddHours(12),
|
Expires = DateTime.UtcNow.AddMinutes(_appSettings.AccessTokenDuration),
|
||||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -246,37 +248,17 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.Web
|
||||||
response.AuthenticationToken = userToken;
|
response.AuthenticationToken = userToken;
|
||||||
response.LoginTime = $"{DateTime.Now:dd-MM-yy H:mm:ss}";
|
response.LoginTime = $"{DateTime.Now:dd-MM-yy H:mm:ss}";
|
||||||
|
|
||||||
//await HttpContext.Session.SetModulesToSession(key: userToken, value: user.ModuleIds);
|
GenerateRefreshTokenRequest refreshTokenRequest = new GenerateRefreshTokenRequest()
|
||||||
//if (user.LoginStatus == EnumLoginStatus.Success)
|
{
|
||||||
//{
|
UserId = user.UserId,
|
||||||
// if (user.AuthMethod == EnumAuthenticationMethod.Email && !string.IsNullOrEmpty(user.EmailAddress) && !string.IsNullOrWhiteSpace(user.EmailAddress) && !string.IsNullOrWhiteSpace(user.AuthValue))
|
IpAddress = ipAddress,
|
||||||
// {
|
RawRefreshToken = string.Empty
|
||||||
// List<string> to = [.. user.EmailAddress.Split(separator: ';', options: StringSplitOptions.RemoveEmptyEntries)];
|
};
|
||||||
// await MailHelper.SendMailMessageAsync(settings: _appSettings, to: to,
|
|
||||||
// cc: null, bcc: null, attachments: null, embeddedImages: null, isHtmlBody: false, priority: System.Net.Mail.MailPriority.Normal,
|
|
||||||
// subject: "Your OTP", messageBody: string.Format("Your OTP: {0} and is valid for 5 minutes only", user.AuthValue));
|
|
||||||
// }
|
|
||||||
// else if (user.AuthMethod == EnumAuthenticationMethod.MobileSMS && !string.IsNullOrEmpty(user.MobileNo) && !string.IsNullOrWhiteSpace(user.MobileNo) && !string.IsNullOrWhiteSpace(user.AuthValue))
|
|
||||||
// {
|
|
||||||
// MailHelper.SendSMSOrWhatsAppMessage(settings: _appSettings, whatsAppMsg: false, msg: string.Format("Your OTP: {0} and is valid for 5 minutes only", user.AuthValue), mobileNumber: user.MobileNo);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (user.DisallowMultiLogin)
|
var refreshToken = await _refreshTokenService.GenerateRefreshTokenByUserAsync(refreshTokenRequest);
|
||||||
//{
|
|
||||||
// await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 1, itemId: 0, ipAddress: ipAddress);
|
|
||||||
// if (request.AttendanceLogin)
|
|
||||||
// await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress);
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 2, itemId: 0, ipAddress: ipAddress);
|
|
||||||
// if (request.AttendanceLogin)
|
|
||||||
// await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress);
|
|
||||||
//}
|
|
||||||
//response.IdsValue = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(data: Newtonsoft.Json.JsonConvert.SerializeObject(user.ModuleIds), privateKey: cipherSecretKey, publicKey: cipherSecretKey, output: 2);
|
|
||||||
|
|
||||||
return Ok(response);
|
response.RefreshToken = refreshToken.RefreshToken;
|
||||||
|
return Ok(response);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@
|
||||||
"WaAuthToken": "024a6897584671d9f9fa588d7c94aa96",
|
"WaAuthToken": "024a6897584671d9f9fa588d7c94aa96",
|
||||||
"WaMsgSvcSid": "MG8401d33a9a3b2aea95619bda3e5757b5",
|
"WaMsgSvcSid": "MG8401d33a9a3b2aea95619bda3e5757b5",
|
||||||
"WaSenderId": "+8801326755660",
|
"WaSenderId": "+8801326755660",
|
||||||
"RefreshTokenDuration": "15",
|
"RefreshTokenDuration": "2",
|
||||||
"AccessTokenDuration": "60",
|
"AccessTokenDuration": "1",
|
||||||
"AutoCropSAPApi": {
|
"AutoCropSAPApi": {
|
||||||
"BaseUrl": "https://accl-test-pad-l06vsvh7.it-cpi004-rt.cfapps.ap11.hana.ondemand.com/",
|
"BaseUrl": "https://accl-test-pad-l06vsvh7.it-cpi004-rt.cfapps.ap11.hana.ondemand.com/",
|
||||||
"UserName": "sb-1635ae0e-9941-4998-962f-e23f592d29b5!b45657|it-rt-accl-test-pad-l06vsvh7!b68",
|
"UserName": "sb-1635ae0e-9941-4998-962f-e23f592d29b5!b45657|it-rt-accl-test-pad-l06vsvh7!b68",
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,7 @@ export class AppBreadcrumbComponent implements OnDestroy
|
||||||
{
|
{
|
||||||
if (this.authService?.currentUserValue)
|
if (this.authService?.currentUserValue)
|
||||||
{
|
{
|
||||||
if (this.authService.currentUserValue.dbOnStartup)
|
this.router.navigate(['/home']);
|
||||||
this.router.navigate(['/dashboard']);
|
|
||||||
else
|
|
||||||
this.router.navigate(['/home']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { Component, Input, OnInit, AfterViewInit, forwardRef, inject } from '@an
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { UserService } from '../providers/user/user.service.';
|
import { UserService } from '../providers/user/user.service.';
|
||||||
import { MenuItemComponent } from './components/menu/menuitem.component';
|
import { MenuItemComponent } from './components/menu/menuitem.component';
|
||||||
|
import { MENU_DEFINITION, PROFILE_MENU, MenuNode, buildPermittedMenu } from './components/models/menu.definition';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
|
@ -28,6 +29,7 @@ export class AppMenuComponent implements OnInit, AfterViewInit
|
||||||
public isAuthenicated: boolean = false;
|
public isAuthenicated: boolean = false;
|
||||||
|
|
||||||
private menuItems: any;
|
private menuItems: any;
|
||||||
|
private routePaths: Set<string>;
|
||||||
|
|
||||||
ngOnInit()
|
ngOnInit()
|
||||||
{
|
{
|
||||||
|
|
@ -43,15 +45,14 @@ export class AppMenuComponent implements OnInit, AfterViewInit
|
||||||
}
|
}
|
||||||
|
|
||||||
this.reloadMenu();
|
this.reloadMenu();
|
||||||
this.modelUngrouped = [{ label: 'Main Menu', icon: 'fa fa-home', items: this.modelGrouped }];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private reloadMenu()
|
private reloadMenu()
|
||||||
{
|
{
|
||||||
if (this.isAuthenicated && this.service?.authService?.currentUserValue?.moduleIds)
|
const currentUser = this.service?.authService?.currentUserValue;
|
||||||
|
if (this.isAuthenicated && currentUser?.moduleIds)
|
||||||
{
|
{
|
||||||
const dbOnStartup = this.service.authService.currentUserValue.dbOnStartup;
|
this.app.detailInfo = `Version: ${this.app.swVersion} | User: ${currentUser.userName} | Login Time: ${currentUser.loginTime}`;
|
||||||
this.app.detailInfo = `Version: ${this.app.swVersion} | User: ${this.service.authService.currentUserValue.userName} | Login Time: ${this.service.authService.currentUserValue.loginTime}`;
|
|
||||||
this.modelGrouped =
|
this.modelGrouped =
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|
@ -59,7 +60,7 @@ export class AppMenuComponent implements OnInit, AfterViewInit
|
||||||
items:
|
items:
|
||||||
[
|
[
|
||||||
{ label: 'Logout', icon: 'fa fa-power-off', routerLink: ['/logout'] },
|
{ label: 'Logout', icon: 'fa fa-power-off', routerLink: ['/logout'] },
|
||||||
{ label: dbOnStartup ? 'Dashboard' : 'Home', icon: dbOnStartup ? 'fa fa-dashboard' : 'fa fa-home', routerLink: [dbOnStartup ? '/dashboard' : '/home'] }
|
{ label: 'Home', icon: 'fa fa-home', routerLink: ['/home'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -79,6 +80,8 @@ export class AppMenuComponent implements OnInit, AfterViewInit
|
||||||
items: [{ label: 'Login', icon: 'fa fa-sign-in', routerLink: ['/login'] }]
|
items: [{ label: 'Login', icon: 'fa fa-sign-in', routerLink: ['/login'] }]
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.modelUngrouped = [{ label: 'Main Menu', icon: 'fa fa-home', items: this.modelGrouped }];
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit()
|
ngAfterViewInit()
|
||||||
|
|
@ -129,35 +132,18 @@ export class AppMenuComponent implements OnInit, AfterViewInit
|
||||||
private onAuthenication(value: any): void
|
private onAuthenication(value: any): void
|
||||||
{
|
{
|
||||||
this.isAuthenicated = value.loggedIn;
|
this.isAuthenicated = value.loggedIn;
|
||||||
if (value.loggedIn && value.userId && value.userId !=0)
|
const currentUser = this.service.authService.currentUserValue;
|
||||||
|
if (value.loggedIn && value.userId && value.userId != 0 && currentUser)
|
||||||
{
|
{
|
||||||
this.service.loadMenu(value.userId).subscribe(
|
this.menuItems = { items: this.buildMenuItems(currentUser.moduleIds) };
|
||||||
{
|
this.app.userId = currentUser.id;
|
||||||
next: (resp: any) =>
|
this.app.loginId = currentUser.loginId;
|
||||||
{
|
this.app.layoutMode = currentUser.menuLayout;
|
||||||
this.menuItems = resp || [];
|
this.app.notificationCount = currentUser.notificationCount;
|
||||||
this.app.userId = this.service.authService.currentUserValue?.id;
|
this.app.autoScrollMenu = (this.app.layoutMode === 'static' || this.app.layoutMode === 'overlay') ? 'auto-scroll-menu' : '';
|
||||||
this.app.loginId = this.service.authService.currentUserValue?.loginId;
|
this.changeTheme(currentUser.themeName, currentUser.schemeName);
|
||||||
this.app.layoutMode = this.service.authService.currentUserValue?.menuLayout;
|
|
||||||
this.app.notificationCount = this.service.authService.currentUserValue?.notificationCount;
|
|
||||||
this.app.autoScrollMenu = (this.app.layoutMode === 'static' || this.app.layoutMode === 'overlay') ? 'auto-scroll-menu' : '';
|
|
||||||
this.changeTheme(this.service.authService.currentUserValue?.themeName, this.service.authService.currentUserValue?.schemeName);
|
|
||||||
|
|
||||||
this.reloadMenu();
|
this.reloadMenu();
|
||||||
},
|
|
||||||
error: () =>
|
|
||||||
{
|
|
||||||
this.menuItems = [];
|
|
||||||
this.app.layoutMode = 'overlay'
|
|
||||||
this.app.loginId = this.app.autoScrollMenu = '';
|
|
||||||
this.app.userId = this.app.notificationCount = 0;
|
|
||||||
|
|
||||||
this.service.authService.loggedout(false);
|
|
||||||
this.reloadMenu();
|
|
||||||
|
|
||||||
this.router.navigate(['/login']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -172,6 +158,28 @@ export class AppMenuComponent implements OnInit, AfterViewInit
|
||||||
this.router.navigate(['/login']);
|
this.router.navigate(['/login']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the activity menu out of the permission keys the login endpoint returned
|
||||||
|
* in `moduleIds`, the profile pages are always available to a logged in user.
|
||||||
|
*/
|
||||||
|
private buildMenuItems(moduleIds: string[]): MenuNode[]
|
||||||
|
{
|
||||||
|
const routeExists = (routerLink: string): boolean => this.registeredRoutes.has(routerLink);
|
||||||
|
|
||||||
|
const items: MenuNode[] = buildPermittedMenu([PROFILE_MENU], moduleIds, routeExists);
|
||||||
|
items.push(...buildPermittedMenu(MENU_DEFINITION, moduleIds, routeExists));
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Paths registered in the router, keeps permitted but not yet implemented pages out of the sidebar. */
|
||||||
|
private get registeredRoutes(): Set<string>
|
||||||
|
{
|
||||||
|
this.routePaths ??= new Set(this.router.config.map(route => route.path).filter(path => !!path && path !== '**'));
|
||||||
|
|
||||||
|
return this.routePaths;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
|
||||||
424
App/ClientApp/src/app/components/models/menu.definition.ts
Normal file
424
App/ClientApp/src/app/components/models/menu.definition.ts
Normal file
|
|
@ -0,0 +1,424 @@
|
||||||
|
/**
|
||||||
|
* Client side mirror of the server menu (GlobalFunctions.BuildMenu).
|
||||||
|
*
|
||||||
|
* The login response returns the permission keys of the logged in user in `moduleIds`,
|
||||||
|
* so the sidebar is built here instead of calling `v1/users/loadMenu`.
|
||||||
|
*
|
||||||
|
* `moduleIds` holds one entry per permitted module plus the operation suffixes:
|
||||||
|
* ELIT.1.2.2 -> select (the page itself)
|
||||||
|
* ELIT.1.2.2_1 -> add
|
||||||
|
* ELIT.1.2.2_2 -> edit
|
||||||
|
* ELIT.1.2.2_3 -> delete
|
||||||
|
*
|
||||||
|
* Only items that are visible on the server menu are listed below, permission only
|
||||||
|
* keys (ELIT.1.1A, ELIT.4.1.10, ...) never render so they are left out.
|
||||||
|
*/
|
||||||
|
export interface MenuNode
|
||||||
|
{
|
||||||
|
label: string;
|
||||||
|
icon?: string;
|
||||||
|
moduleId?: string;
|
||||||
|
routerLink?: string;
|
||||||
|
items?: MenuNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Always available to a logged in user, the server adds these without any permission check. */
|
||||||
|
export const PROFILE_MENU: MenuNode =
|
||||||
|
{
|
||||||
|
label: 'User Profile', icon: 'fa fa-user-md',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ label: 'My Profile', icon: 'fa fa-user', routerLink: 'myprofile' },
|
||||||
|
{ label: 'Change My Password', icon: 'fa fa-unlock', routerLink: 'changemypwd' },
|
||||||
|
{ label: 'Change My Theme', icon: 'fa fa-user', routerLink: 'changemytheme' },
|
||||||
|
{ label: 'WhatsApp Message', icon: 'fa fa-whatsapp', routerLink: 'sendwhatsappmsg' },
|
||||||
|
{ label: 'Access Log', icon: 'fa fa-list-alt', routerLink: 'accesslog' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MENU_DEFINITION: MenuNode[] =
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.1', label: 'System Setup', icon: 'fa fa-sun-o',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.1.3', label: 'Label Setting', icon: 'fa fa-sliders', routerLink: 'labelsetting' },
|
||||||
|
{ moduleId: 'ELIT.1.1', label: 'System Information', icon: 'fa fa-cog', routerLink: 'thissystem' },
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.1.2', label: 'User Management', icon: 'fa fa-users',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.1.2.1', label: 'Groups', icon: 'fa fa-address-book-o', routerLink: 'groups' },
|
||||||
|
{ moduleId: 'ELIT.1.2.2', label: 'Users', icon: 'fa fa-address-card-o', routerLink: 'users' },
|
||||||
|
{ moduleId: 'ELIT.1.2.4', label: 'Force Logout', icon: 'fa fa-address-card-o', routerLink: 'forcelogout' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ moduleId: 'ELIT.1.3A', label: 'Lookup Data', icon: 'fa fa-sliders', routerLink: 'lookupdata' },
|
||||||
|
{ moduleId: 'ELIT.1.4', label: 'Custom Report Setup', icon: 'fa fa-table', routerLink: 'customreports' },
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.1.5', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.1.5.1', label: 'Clients', icon: 'fa fa-address-card-o', routerLink: 'clients' },
|
||||||
|
{ moduleId: 'ELIT.1.5.2', label: 'Suppliers', icon: 'fa fa-credit-card', routerLink: 'suppliers' },
|
||||||
|
{ moduleId: 'ELIT.1.5.3', label: 'Employees', icon: 'fa fa-user-plus', routerLink: 'employees' },
|
||||||
|
{ moduleId: 'ELIT.1.5.4', label: 'Project Leads', icon: 'fa fa-user-circle-o', routerLink: 'projectleads' },
|
||||||
|
{ moduleId: 'ELIT.1.5.5', label: 'Project Managers', icon: 'fa fa-user-circle-o', routerLink: 'projectmgts' },
|
||||||
|
{ moduleId: 'ELIT.1.5.6', label: 'Projects', icon: 'fa fa-product-hunt', routerLink: 'projects' },
|
||||||
|
{ moduleId: 'ELIT.1.5.7', label: 'Stores', icon: 'fa fa-pencil-square', routerLink: 'stores' },
|
||||||
|
{ moduleId: 'ELIT.1.5.8', label: 'Banks & Branches', icon: 'fa fa-university', routerLink: 'bankbranches' },
|
||||||
|
{ moduleId: 'ELIT.1.5.9', label: 'Bank Accounts', icon: 'fa fa-credit-card', routerLink: 'bankaccounts' },
|
||||||
|
{ moduleId: 'ELIT.1.5.10', label: 'GL Codes', icon: 'fa fa-book', routerLink: 'glcodes' },
|
||||||
|
{ moduleId: 'ELIT.1.5.11', label: 'User Clients & Projects', icon: 'fa fa-product-hunt', routerLink: 'userprojects' },
|
||||||
|
{ moduleId: 'ELIT.1.5.12', label: 'User Suppliers', icon: 'fa fa-product-hunt', routerLink: 'usersuppliers' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.2', label: 'Authentication Process', icon: 'fa fa-cogs',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.2.1', label: 'Authentication', icon: 'fa fa-check', routerLink: 'authentications' },
|
||||||
|
{ moduleId: 'ELIT.2.2', label: 'Authorization', icon: 'fa fa-check-square-o', routerLink: 'authorizations' },
|
||||||
|
{ moduleId: 'ELIT.2.3', label: 'Deactivation', icon: 'fa fa-window-close-o', routerLink: 'deactivations' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.3', label: 'General Ledger', icon: 'fa fa-university',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.3.1', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.3.1.1', label: 'Chart of Accounts', icon: 'fa fa-th-list', routerLink: 'chartofaccounts' },
|
||||||
|
{ moduleId: 'ELIT.3.1.2', label: 'Fix GL Balance', icon: 'fa fa-wrench', routerLink: 'fixBalance' },
|
||||||
|
{ moduleId: 'ELIT.3.1.3', label: 'GL Head Identification', icon: 'fa fa-cog', routerLink: 'identifyglhead' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.3.2', label: 'Transactions', icon: 'fa fa-building',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.3.2.1', label: 'GL Transactions', icon: 'fa fa-archive', routerLink: 'gltrans' },
|
||||||
|
{ moduleId: 'ELIT.3.2.2', label: 'Upload Auto Voucher', icon: 'fa fa-upload', routerLink: 'gltranav' },
|
||||||
|
{ moduleId: 'ELIT.3.2.3', label: 'Year End Process', icon: 'fa fa-cog', routerLink: 'yearendprocess' },
|
||||||
|
{ moduleId: 'ELIT.3.2.4', label: 'Undo Year End', icon: 'fa fa-undo', routerLink: 'undoyearend' },
|
||||||
|
{ moduleId: 'ELIT.3.2.5', label: 'Authorize Transactions', icon: 'fa fa-check-square', routerLink: 'authgltrans' },
|
||||||
|
{ moduleId: 'ELIT.3.2.7', label: 'Rollback Transactions', icon: 'fa fa-undo', routerLink: 'rollbackgltrans' },
|
||||||
|
{ moduleId: 'ELIT.3.2.8', label: 'Dashboard Processor', icon: 'fa fa-cog', routerLink: 'dbprocessor' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.3.3', label: 'Reports', icon: 'fa fa-newspaper-o',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.3.3.1', label: 'Ledger', icon: 'fa fa-file-text-o', routerLink: 'glledger' },
|
||||||
|
{ moduleId: 'ELIT.3.3.2', label: 'Monthly Turnover', icon: 'fa fa-file-text-o', routerLink: 'turnover' },
|
||||||
|
{ moduleId: 'ELIT.3.3.3', label: 'Trial Balance', icon: 'fa fa-file-text-o', routerLink: 'trialbalance' },
|
||||||
|
{ moduleId: 'ELIT.3.3.8', label: 'Income & Expenditure', icon: 'fa fa-file-text-o', routerLink: 'incomeexpense' },
|
||||||
|
{ moduleId: 'ELIT.3.3.4', label: 'Day Book', icon: 'fa fa-file-text-o', routerLink: 'daybook' },
|
||||||
|
{ moduleId: 'ELIT.3.3.5', label: 'Bank/Cash Book', icon: 'fa fa-file-text-o', routerLink: 'bankcashbook' },
|
||||||
|
{ moduleId: 'ELIT.3.3.6', label: 'Schedule', icon: 'fa fa-file-text-o', routerLink: 'glschedule' },
|
||||||
|
{ moduleId: 'ELIT.3.3.7', label: 'Previous Final Reports', icon: 'fa fa-file-text-o', routerLink: 'prvfinalreports' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.4', label: 'Order To Cash', icon: 'fa fa-money',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.4.1', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.4.1.1', label: 'Income GL Codes', icon: 'fa fa-pencil-square-o', routerLink: 'incomeglcodes' },
|
||||||
|
{ moduleId: 'ELIT.4.1.2', label: 'VAT Liability GL Codes', icon: 'fa fa-pencil-square', routerLink: 'vatglcodes' },
|
||||||
|
{ moduleId: 'ELIT.4.1.3', label: 'AIT GL Codes', icon: 'fa fa-book', routerLink: 'aitglcodes' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.4.2', label: 'Regular Activities', icon: 'fa fa-building',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.4.2.1', label: 'Purchase Orders', icon: 'fa fa-smile-o', routerLink: 'purchaseorders' },
|
||||||
|
{ moduleId: 'ELIT.4.2.2', label: 'Invoices', icon: 'fa fa-share-square', routerLink: 'invoices' },
|
||||||
|
{ moduleId: 'ELIT.4.2.3', label: 'Payments', icon: 'fa fa-money', routerLink: 'payments' },
|
||||||
|
{ moduleId: 'ELIT.4.2.4', label: 'Freeze PO/Invoice', icon: 'fa fa-archive', routerLink: 'archivepoinvs' },
|
||||||
|
{ moduleId: 'ELIT.4.2.8', label: 'VAT Challan Update', icon: 'fa fa-sliders', routerLink: 'updvatchlano2c' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.4.3', label: 'Reports', icon: 'fa fa-newspaper-o',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.4.3.1', label: 'GL Vouchers', icon: 'fa fa-th-list', routerLink: 'glvouchers' },
|
||||||
|
{ moduleId: 'ELIT.4.3.2', label: 'Transactional Reports', icon: 'fa fa-file-text-o', routerLink: 'txnreports' },
|
||||||
|
{ moduleId: 'ELIT.4.3.3', label: 'Contract Expiry Report', icon: 'fa fa-file-text-o', routerLink: 'contexpryreports' },
|
||||||
|
{ moduleId: 'ELIT.4.3.4', label: 'Customized Report', icon: 'fa fa-file-text-o', routerLink: 'customreporto2c' },
|
||||||
|
{ moduleId: 'ELIT.4.3.5', label: 'Client Ledger', icon: 'fa fa-file-text-o', routerLink: 'clientledgero2c' },
|
||||||
|
{ moduleId: 'ELIT.4.3.6', label: 'Monthly Trends', icon: 'fa fa-file-text-o', routerLink: 'monthlytrendso2c' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.9', label: 'Sales System', icon: 'fa fa-sitemap',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.9.1', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.9.1.1', label: 'Market Hierarchies', icon: 'fa fa-pencil-square', routerLink: 'markethierarchies' },
|
||||||
|
{ moduleId: 'ELIT.9.1.2', label: 'Sales Points', icon: 'fa fa-pencil-square', routerLink: 'salespoints' },
|
||||||
|
{ moduleId: 'ELIT.9.1.3', label: 'Product Hierarchies', icon: 'fa fa-pencil-square', routerLink: 'producthierarchies' },
|
||||||
|
{ moduleId: 'ELIT.9.1.4', label: 'Brands', icon: 'fa fa-pencil-square', routerLink: 'brands' },
|
||||||
|
{ moduleId: 'ELIT.9.1.5', label: 'SKUs', icon: 'fa fa-pencil-square', routerLink: 'skus' },
|
||||||
|
{ moduleId: 'ELIT.9.1.6', label: 'Channel Hierarchies', icon: 'fa fa-pencil-square', routerLink: 'channelhierarchies' },
|
||||||
|
{ moduleId: 'ELIT.9.1.7', label: 'Customers', icon: 'fa fa-pencil-square', routerLink: 'customers' },
|
||||||
|
{ moduleId: 'ELIT.9.1.8', label: 'Sales Officers', icon: 'fa fa-pencil-square', routerLink: 'salesofficers' },
|
||||||
|
{ moduleId: 'ELIT.9.1.9', label: 'Product Prices', icon: 'fa fa-pencil-square', routerLink: 'skupricess' },
|
||||||
|
{ moduleId: 'ELIT.9.1.10', label: 'Product VAT-SD-Comm', icon: 'fa fa-pencil-square', routerLink: 'skuvattaxes' },
|
||||||
|
{ moduleId: 'ELIT.9.1.11', label: 'Customer Credit', icon: 'fa fa-pencil-square', routerLink: 'customercredit' },
|
||||||
|
{ moduleId: 'ELIT.9.1.12', label: 'External Products', icon: 'fa fa-pencil-square', routerLink: 'extnlproducts' },
|
||||||
|
{ moduleId: 'ELIT.9.1.13', label: 'Sales Promotions', icon: 'fa fa-pencil-square', routerLink: 'salespromotions' },
|
||||||
|
{ moduleId: 'ELIT.9.1.14', label: 'Order Authorization Limit', icon: 'fa fa-pencil-square', routerLink: 'ordrauthlimit' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.9.2', label: 'Regular Activities', icon: 'fa fa-building',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.9.2.1', label: 'Customer Opening Balance', icon: 'fa fa-puzzle-piece', routerLink: 'slscustsopnbal' },
|
||||||
|
{ moduleId: 'ELIT.9.2.2', label: 'Customer Adjustment', icon: 'fa fa-pencil-square', routerLink: 'slscustsadjustment' },
|
||||||
|
{ moduleId: 'ELIT.9.2.3', label: 'Initial Stock', icon: 'fa fa-puzzle-piece', routerLink: 'slsinitstocks' },
|
||||||
|
{ moduleId: 'ELIT.9.2.4', label: 'Receive Stocks', icon: 'fa fa-reply-all', routerLink: 'slsrcvstocks' },
|
||||||
|
{ moduleId: 'ELIT.9.2.5', label: 'Sales Orders', icon: 'fa fa-pencil-square', routerLink: 'slsorders' },
|
||||||
|
{ moduleId: 'ELIT.9.2.6', label: 'Spot Sales', icon: 'fa fa-pencil-square', routerLink: 'slsdirectinvoices' },
|
||||||
|
{ moduleId: 'ELIT.9.2.7', label: 'Sales Invoices', icon: 'fa fa-pencil-square', routerLink: 'slsinvoices' },
|
||||||
|
{ moduleId: 'ELIT.9.2.8', label: 'Payment Against Invoices', icon: 'fa fa-archive', routerLink: 'slsinvpayments' },
|
||||||
|
{ moduleId: 'ELIT.9.2.9', label: 'Stock Transfers', icon: 'fa fa-archive', routerLink: 'slsstockxfers' },
|
||||||
|
{ moduleId: 'ELIT.9.2.10', label: 'Receive Transferred Stocks', icon: 'fa fa-archive', routerLink: 'slsstockxferrcvs' },
|
||||||
|
{ moduleId: 'ELIT.9.2.11', label: 'Fix Transfer Anomalies', icon: 'fa fa-archive', routerLink: 'slsstockxferanmls' },
|
||||||
|
{ moduleId: 'ELIT.9.2.12', label: 'Sales Return', icon: 'fa fa-archive', routerLink: 'slsrtnstocks' },
|
||||||
|
{ moduleId: 'ELIT.9.2.13', label: 'Damage Stocks', icon: 'fa fa-archive', routerLink: 'slsdmgstocks' },
|
||||||
|
{ moduleId: 'ELIT.9.2.14', label: 'Stock Take', icon: 'fa fa-archive', routerLink: 'slsstocktakes' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.9.3', label: 'Reports', icon: 'fa fa-newspaper-o',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.9.3.1', label: 'Customer Balance', icon: 'fa fa-th-list', routerLink: 'salescustbalance' },
|
||||||
|
{ moduleId: 'ELIT.9.3.2', label: 'Customer Ledger', icon: 'fa fa-th-list', routerLink: 'salescustledger' },
|
||||||
|
{ moduleId: 'ELIT.9.3.3', label: 'Current Stock', icon: 'fa fa-file-text-o', routerLink: 'salescurrentstock' },
|
||||||
|
{ moduleId: 'ELIT.9.3.4', label: 'Stock Ledger', icon: 'fa fa-th-list', routerLink: 'salesstockledger' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.5', label: 'Purchase To Pay', icon: 'fa fa-shopping-cart',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.5.1', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.5.1.1', label: 'Product Types', icon: 'fa fa-address-card-o', routerLink: 'prodtypes' },
|
||||||
|
{ moduleId: 'ELIT.5.1.2', label: 'Products', icon: 'fa fa-university', routerLink: 'products' },
|
||||||
|
{ moduleId: 'ELIT.5.1.3', label: 'WO Terms & Conditions', icon: 'fa fa-pencil-square-o', routerLink: 'woterms' },
|
||||||
|
{ moduleId: 'ELIT.5.1.4', label: 'VAT & AIT Rates', icon: 'fa fa-user-circle-o', routerLink: 'aitvatratep2p' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.5.2', label: 'Regular Activities', icon: 'fa fa-building',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.5.2.0', label: 'Initial Stock', icon: 'fa fa-puzzle-piece', routerLink: 'initstocksp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.13', label: 'Purchase Requisitions', icon: 'fa fa-puzzle-piece', routerLink: 'purchrequisitionsp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.1', label: 'Issue Work Orders', icon: 'fa fa-smile-o', routerLink: 'workordersp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.12', label: 'Advance Payments', icon: 'fa fa-money', routerLink: 'advpaymntsp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.2', label: 'Receive Items at CS', icon: 'fa fa-reply-all', routerLink: 'stksrcvdatcsp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.3', label: 'Receive Invoices', icon: 'fa fa-money', routerLink: 'invoicesp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.4', label: 'Cash Purchase', icon: 'fa fa-archive', routerLink: 'cashpurchases' },
|
||||||
|
{ moduleId: 'ELIT.5.2.5', label: 'Payment Against Invoice', icon: 'fa fa-archive', routerLink: 'paymentsp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.6', label: 'Goods Transfer', icon: 'fa fa-archive', routerLink: 'gdstransfers' },
|
||||||
|
{ moduleId: 'ELIT.5.2.7', label: 'Receive Goods Transfer', icon: 'fa fa-archive', routerLink: 'gdsreceives' },
|
||||||
|
{ moduleId: 'ELIT.5.2.8', label: 'Fix Transfer Anomalies', icon: 'fa fa-archive', routerLink: 'transferanomalies' },
|
||||||
|
{ moduleId: 'ELIT.5.2.9', label: 'Consumption of Goods', icon: 'fa fa-archive', routerLink: 'gdscnsmpnsp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.10', label: 'Damage of Goods', icon: 'fa fa-archive', routerLink: 'gdsdamagesp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.2.11', label: 'Stock Take of Goods', icon: 'fa fa-archive', routerLink: 'stocktakes' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.5.3', label: 'Reports', icon: 'fa fa-newspaper-o',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.5.3.1', label: 'GL Vouchers', icon: 'fa fa-th-list', routerLink: 'glvouchersp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.3.2', label: 'Current Stock', icon: 'fa fa-file-text-o', routerLink: 'currentstockp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.3.3', label: 'Stock Ledger', icon: 'fa fa-file-text-o', routerLink: 'stockledgerp2p' },
|
||||||
|
{ moduleId: 'ELIT.5.3.4', label: 'Supplier Ledger', icon: 'fa fa-file-text-o', routerLink: 'supplierledgerp2p' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.6', label: 'Fixed Assets', icon: 'fa fa-sitemap',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.6.1', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.6.1.1', label: 'Asset Types', icon: 'fa fa-address-card-o', routerLink: 'assettypes' },
|
||||||
|
{ moduleId: 'ELIT.6.1.2', label: 'Asset Categories', icon: 'fa fa-university', routerLink: 'assetcategories' },
|
||||||
|
{ moduleId: 'ELIT.6.1.3', label: 'Asset Items', icon: 'fa fa-credit-card', routerLink: 'assetitems' },
|
||||||
|
{ moduleId: 'ELIT.6.1.6', label: 'Asset Hierarchies', icon: 'fa fa-credit-card', routerLink: 'assethierarchies' },
|
||||||
|
{ moduleId: 'ELIT.6.1.4', label: 'Locations', icon: 'fa fa-pencil-square', routerLink: 'locations' },
|
||||||
|
{ moduleId: 'ELIT.6.1.5', label: 'VAT & AIT Rates', icon: 'fa fa-user-circle-o', routerLink: 'aitvatratefa' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.6.2', label: 'Regular Activities', icon: 'fa fa-building',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.6.2.0', label: 'Initial Fixed Assets', icon: 'fa fa-puzzle-piece', routerLink: 'initstocksfa' },
|
||||||
|
{ moduleId: 'ELIT.6.2.15', label: 'Purchase Requisitions', icon: 'fa fa-puzzle-piece', routerLink: 'purchrequisitionsfa' },
|
||||||
|
{ moduleId: 'ELIT.6.2.1', label: 'Issue Work Orders', icon: 'fa fa-smile-o', routerLink: 'workordersfa' },
|
||||||
|
{ moduleId: 'ELIT.6.2.14', label: 'Advance Payments', icon: 'fa fa-money', routerLink: 'advpaymntsfa' },
|
||||||
|
{ moduleId: 'ELIT.6.2.2', label: 'Received Items At CS', icon: 'fa fa-reply-all', routerLink: 'stksrcvdatcsfa' },
|
||||||
|
{ moduleId: 'ELIT.6.2.3', label: 'Receive Invoices', icon: 'fa fa-money', routerLink: 'invoicesfa' },
|
||||||
|
{ moduleId: 'ELIT.6.2.4', label: 'Payment Against Invoice', icon: 'fa fa-archive', routerLink: 'paymentsfa' },
|
||||||
|
{ moduleId: 'ELIT.6.2.5', label: 'Item Acquisition', icon: 'fa fa-smile-o', routerLink: 'itemsacquisition' },
|
||||||
|
{ moduleId: 'ELIT.6.2.5A', label: 'Update Item Data', icon: 'fa fa-smile-o', routerLink: 'updfaitmdescription' },
|
||||||
|
{ moduleId: 'ELIT.6.2.6', label: 'Item Installation', icon: 'fa fa-share-square', routerLink: 'astinstalns' },
|
||||||
|
{ moduleId: 'ELIT.6.2.7', label: 'Transfer Fixed Asset', icon: 'fa fa-money', routerLink: 'assetxfers' },
|
||||||
|
{ moduleId: 'ELIT.6.2.8', label: 'Write Off', icon: 'fa fa-archive', routerLink: 'astwriteoffs' },
|
||||||
|
{ moduleId: 'ELIT.6.2.9', label: 'Asset Sales', icon: 'fa fa-archive', routerLink: 'astsales' },
|
||||||
|
{ moduleId: 'ELIT.6.2.10', label: 'Add Asset Value', icon: 'fa fa-archive', routerLink: 'astaddvalues' },
|
||||||
|
{ moduleId: 'ELIT.6.2.11', label: 'Reduce Asset Value', icon: 'fa fa-archive', routerLink: 'assetreducesvalue' },
|
||||||
|
{ moduleId: 'ELIT.6.2.12', label: 'No Depreciation Mark', icon: 'fa fa-user-circle-o', routerLink: 'nodeprnmark' },
|
||||||
|
{ moduleId: 'ELIT.6.2.13', label: 'Depreciation Calculation', icon: 'fa fa-user-circle-o', routerLink: 'calcdepreciation' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.6.3', label: 'Reports', icon: 'fa fa-newspaper-o',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.6.3.1', label: 'GL Vouchers', icon: 'fa fa-th-list', routerLink: 'glvouchersfa' },
|
||||||
|
{ moduleId: 'ELIT.6.3.2', label: 'Current Stock', icon: 'fa fa-file-text-o', routerLink: 'currentstockfa' },
|
||||||
|
{ moduleId: 'ELIT.6.3.3', label: 'Stock Ledger', icon: 'fa fa-file-text-o', routerLink: 'stockledgerfa' },
|
||||||
|
{ moduleId: 'ELIT.6.3.4', label: 'Item Details', icon: 'fa fa-file-text-o', routerLink: 'faitemdetail' },
|
||||||
|
{ moduleId: 'ELIT.6.3.5', label: 'Fixed Asset List', icon: 'fa fa-file-text-o', routerLink: 'faitemsatglance' },
|
||||||
|
{ moduleId: 'ELIT.6.3.6', label: 'Waiting Acquisition', icon: 'fa fa-file-text-o', routerLink: 'faitemswtngaqstn' },
|
||||||
|
{ moduleId: 'ELIT.6.3.7', label: 'Acquired Assets', icon: 'fa fa-file-text-o', routerLink: 'faitemsacquire' },
|
||||||
|
{ moduleId: 'ELIT.6.3.8', label: 'Waiting Installation', icon: 'fa fa-file-text-o', routerLink: 'faitemswtnginstall' },
|
||||||
|
{ moduleId: 'ELIT.6.3.9', label: 'No Depreciation Marked', icon: 'fa fa-file-text-o', routerLink: 'faitemsnodprn' },
|
||||||
|
{ moduleId: 'ELIT.6.3.10', label: 'Depreciation Report', icon: 'fa fa-file-text-o', routerLink: 'faitemsdprnrpt' },
|
||||||
|
{ moduleId: 'ELIT.6.3.11', label: 'Supplier Ledger', icon: 'fa fa-file-text-o', routerLink: 'fasupplierledger' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.7', label: 'Task Management', icon: 'fa fa-users',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.7.1', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.7.1.1', label: 'Developers', icon: 'fa fa-user-circle-o', routerLink: 'developers' },
|
||||||
|
{ moduleId: 'ELIT.7.1.2', label: 'Support Teams', icon: 'fa fa-user-circle-o', routerLink: 'supportteams' },
|
||||||
|
{ moduleId: 'ELIT.7.1.2A', label: 'QA Teams', icon: 'fa fa-user-circle-o', routerLink: 'qateams' },
|
||||||
|
{ moduleId: 'ELIT.7.1.3', label: 'Priorities', icon: 'fa fa-check-square-o', routerLink: 'priorities' },
|
||||||
|
{ moduleId: 'ELIT.7.1.4', label: 'Task Statuses', icon: 'fa fa-pencil-square', routerLink: 'taskstatuses' },
|
||||||
|
{ moduleId: 'ELIT.7.1.5', label: 'Task Categories', icon: 'fa fa-check-square-o', routerLink: 'taskcategories' },
|
||||||
|
{ moduleId: 'ELIT.7.1.6', label: 'Task Types', icon: 'fa fa-check-square-o', routerLink: 'tasktypes' },
|
||||||
|
{ moduleId: 'ELIT.7.1.7', label: 'Team Spaces', icon: 'fa fa-user-circle-o', routerLink: 'teamspaces' },
|
||||||
|
{ moduleId: 'ELIT.7.1.9', label: 'User Projects', icon: 'fa fa-product-hunt', routerLink: 'tsuserprojects' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.7.2', label: 'Regular Activities', icon: 'fa fa-building',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.7.2.1', label: 'Tasks', icon: 'fa fa-smile-o', routerLink: 'tasks' },
|
||||||
|
{ moduleId: 'ELIT.7.2.2', label: 'My Tasks', icon: 'fa fa-tasks', routerLink: 'mytasks' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.7.3', label: 'Reports', icon: 'fa fa-newspaper-o',
|
||||||
|
items: [{ moduleId: 'ELIT.7.3.1', label: 'Task Reports', icon: 'fa fa-file-text-o', routerLink: 'taskreport' }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.8', label: 'Attendance System', icon: 'fa fa-calendar',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.8.1', label: 'Basic Setup', icon: 'fa fa-wrench',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.8.1.1', label: 'Ip/Mac Entries', icon: 'fa fa-user-circle-o', routerLink: 'ipmacentries' },
|
||||||
|
{ moduleId: 'ELIT.8.1.2', label: 'Holiday Calendar', icon: 'fa fa-calendar', routerLink: 'calendar' },
|
||||||
|
{ moduleId: 'ELIT.8.1.3', label: 'Ramadan Calendar', icon: 'fa fa-calendar', routerLink: 'ramadan' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.8.2', label: 'Regular Activities', icon: 'fa fa-building',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.8.2.1', label: 'Employee Leaves', icon: 'fa fa-smile-o', routerLink: 'empleaves' },
|
||||||
|
{ moduleId: 'ELIT.8.2.2', label: 'Late Entries', icon: 'fa fa-tasks', routerLink: 'emplates' },
|
||||||
|
{ moduleId: 'ELIT.8.2.3', label: 'Client Visits', icon: 'fa fa-tasks', routerLink: 'empclntvsts' },
|
||||||
|
{ moduleId: 'ELIT.8.2.4', label: 'Home Offices', icon: 'fa fa-tasks', routerLink: 'emphmofcs' },
|
||||||
|
{ moduleId: 'ELIT.8.2.6', label: 'Asset Bookings', icon: 'fa fa-tasks', routerLink: 'assetbookings' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleId: 'ELIT.8.3', label: 'Reports', icon: 'fa fa-newspaper-o',
|
||||||
|
items:
|
||||||
|
[
|
||||||
|
{ moduleId: 'ELIT.8.3.1', label: 'Login History', icon: 'fa fa-tasks', routerLink: 'loginhistory' },
|
||||||
|
{ moduleId: 'ELIT.8.3.2', label: 'Attendance Reports', icon: 'fa fa-file-text-o', routerLink: 'atnreports' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps the nodes the user is permitted to see.
|
||||||
|
*
|
||||||
|
* A group is kept only when its own key is permitted and at least one of its children survives,
|
||||||
|
* a page is kept only when its key is permitted and the route is actually registered in the app,
|
||||||
|
* so a permitted but not yet implemented page never lands in the sidebar as a dead link.
|
||||||
|
*/
|
||||||
|
export function buildPermittedMenu(nodes: MenuNode[], moduleIds: string[], routeExists: (routerLink: string) => boolean): MenuNode[]
|
||||||
|
{
|
||||||
|
const permitted: MenuNode[] = [];
|
||||||
|
for (const node of nodes ?? [])
|
||||||
|
{
|
||||||
|
if (node.moduleId && !moduleIds?.includes(node.moduleId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (node.items?.length)
|
||||||
|
{
|
||||||
|
const items = buildPermittedMenu(node.items, moduleIds, routeExists);
|
||||||
|
if (items.length)
|
||||||
|
permitted.push({ moduleId: node.moduleId, label: node.label, icon: node.icon, items: items });
|
||||||
|
}
|
||||||
|
else if (node.routerLink && routeExists(node.routerLink))
|
||||||
|
{
|
||||||
|
permitted.push({ moduleId: node.moduleId, label: node.label, icon: node.icon, routerLink: node.routerLink });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return permitted;
|
||||||
|
}
|
||||||
|
|
@ -1,35 +1,39 @@
|
||||||
export class UserModel
|
export class UserModel
|
||||||
{
|
{
|
||||||
id: number;
|
id: number;
|
||||||
logId: number;
|
|
||||||
expires?: Date;
|
expires?: Date;
|
||||||
loginId: string;
|
loginId: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
systemDate: Date;
|
systemDate: Date;
|
||||||
idleTime: number;
|
|
||||||
pingTime: number;
|
|
||||||
loginTime: string;
|
loginTime: string;
|
||||||
logoutTime?: Date;
|
logoutTime?: Date;
|
||||||
validUser: boolean;
|
validUser: boolean;
|
||||||
employeeId: number;
|
|
||||||
timeoutTime: number;
|
|
||||||
loginStatus: number;
|
loginStatus: number;
|
||||||
bmProcessId: number;
|
authMethod: number;
|
||||||
prProcessId: number;
|
|
||||||
dbOnStartup: boolean;
|
|
||||||
batchEnabled: boolean;
|
|
||||||
viewOwnTaskOnly: boolean;
|
|
||||||
notificationCount: number;
|
notificationCount: number;
|
||||||
pwdChangeRequired: boolean;
|
pwdChangeRequired: boolean;
|
||||||
authenticationToken?: string;
|
authenticationToken?: string;
|
||||||
authRequiredAtLogin: boolean;
|
authRequiredAtLogin: boolean;
|
||||||
|
|
||||||
idsValue: string;
|
//Returned by the login endpoint since the token based authentication
|
||||||
moduleIds: any[] = [];
|
refreshToken?: string;
|
||||||
|
userPlatFormType?: number;
|
||||||
|
userRoleType?: string;
|
||||||
|
employeeNumber?: string;
|
||||||
|
|
||||||
|
//Permission keys of the logged in user, "<moduleId>" = select, "_1" = add, "_2" = edit, "_3" = delete
|
||||||
|
moduleIds: string[] = [];
|
||||||
returnStatus: number;
|
returnStatus: number;
|
||||||
returnMessage: any[] = [];
|
returnMessage: any[] = [];
|
||||||
validationErrors: any[] = [];
|
validationErrors: any[] = [];
|
||||||
|
|
||||||
|
//Not returned by the login endpoint anymore, defaults are applied on the client
|
||||||
|
logId?: number;
|
||||||
|
idleTime?: number;
|
||||||
|
pingTime?: number;
|
||||||
|
employeeId?: number;
|
||||||
|
timeoutTime?: number;
|
||||||
|
dbOnStartup?: boolean;
|
||||||
schemeName: string = 'dark';
|
schemeName: string = 'dark';
|
||||||
themeName: string = 'yellow';
|
themeName: string = 'yellow';
|
||||||
menuLayout: string = 'overlay';
|
menuLayout: string = 'overlay';
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,7 @@ export class LoginComponent implements OnInit
|
||||||
debugger;
|
debugger;
|
||||||
if (this.authService.currentUserValue?.id)
|
if (this.authService.currentUserValue?.id)
|
||||||
{
|
{
|
||||||
if (this.authService.currentUserValue.dbOnStartup)
|
this.router.navigate(['/home']);
|
||||||
this.router.navigate(['/dashboard']);
|
|
||||||
else
|
|
||||||
this.router.navigate(['/home']);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -270,110 +267,107 @@ export class LoginComponent implements OnInit
|
||||||
{
|
{
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.spinnerService.hide();
|
this.spinnerService.hide();
|
||||||
|
|
||||||
|
//The endpoint answers 200 only for a valid user, guard anyway so a partial
|
||||||
|
//response never leaves a half logged in session behind
|
||||||
|
if (!data?.validUser || !data.id || !data.authenticationToken)
|
||||||
|
{
|
||||||
|
this.abortLogin(this.parseReturnMessage(data) || 'Login failed, please try again.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.authRequiredAtLogin)
|
if (data.authRequiredAtLogin)
|
||||||
{
|
{
|
||||||
this.authService.loggedIn(data, false);
|
this.verifyOtp(data, sysDate, loginInf);
|
||||||
const modalOptions: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true, windowClass: 'misc-width' };
|
|
||||||
const modalRef = this.modalService.open(OtpComponent, modalOptions);
|
|
||||||
|
|
||||||
modalRef.componentInstance.fromParent = { userId: data.id, authMethod: data.authMethod };
|
|
||||||
modalRef.result.then((result) =>
|
|
||||||
{
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (data.pwdChangeRequired)
|
|
||||||
{
|
|
||||||
this.authService.loggedIn(data, false);
|
|
||||||
const modalOptions1: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true };
|
|
||||||
const modalRef1 = this.modalService.open(ChangePwdComponent, modalOptions1);
|
|
||||||
modalRef1.componentInstance.fromParent = { userId: data.id, loginId: data.loginId, userName: data.userName };
|
|
||||||
|
|
||||||
modalRef1.result.then(() =>
|
|
||||||
{
|
|
||||||
this.authService.loggedout();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.authService.refreshToken().subscribe(
|
|
||||||
{
|
|
||||||
next: () =>
|
|
||||||
{
|
|
||||||
localStorage.setItem('OnlineSalesAutoCrop.sysdate', sysDate);
|
|
||||||
if (this.f.remberMe.value)
|
|
||||||
localStorage.setItem('OnlineSalesAutoCrop.rlap', loginInf);
|
|
||||||
else
|
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.rlap');
|
|
||||||
|
|
||||||
this.idleSvc.startMonitor();
|
|
||||||
this.authService.raiseLoginEvent(data.id, true);
|
|
||||||
const returnUrl = this.authService.currentUserValue?.dbOnStartup ? this.route.snapshot.queryParams['returnUrl'] ?? '/dashboard' : this.route.snapshot.queryParams['returnUrl'] ?? '/home';
|
|
||||||
this.router.navigate([returnUrl]);
|
|
||||||
},
|
|
||||||
error: () =>
|
|
||||||
{
|
|
||||||
this.authService.loggedout();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.rlap');
|
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.sysdate');
|
|
||||||
|
|
||||||
this.authService.loggedout();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else if (data.pwdChangeRequired)
|
else if (data.pwdChangeRequired)
|
||||||
{
|
{
|
||||||
this.authService.loggedIn(data, false);
|
this.changePassword(data);
|
||||||
const modalOptions: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true };
|
|
||||||
const modalRef = this.modalService.open(ChangePwdComponent, modalOptions);
|
|
||||||
modalRef.componentInstance.fromParent = { userId: data.id, loginId: data.loginId, userName: data.userName };;
|
|
||||||
|
|
||||||
modalRef.result.then(() =>
|
|
||||||
{
|
|
||||||
this.authService.loggedout();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.authService.refreshToken().subscribe(
|
this.completeLogin(data, sysDate, loginInf);
|
||||||
{
|
|
||||||
next: () =>
|
|
||||||
{
|
|
||||||
localStorage.setItem('OnlineSalesAutoCrop.sysdate', sysDate);
|
|
||||||
if (this.f.remberMe.value)
|
|
||||||
localStorage.setItem('OnlineSalesAutoCrop.rlap', loginInf);
|
|
||||||
else
|
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.rlap');
|
|
||||||
|
|
||||||
this.idleSvc.startMonitor();
|
|
||||||
this.authService.raiseLoginEvent(data.id, true);
|
|
||||||
const returnUrl = this.authService.currentUserValue?.dbOnStartup ? this.route.snapshot.queryParams['returnUrl'] ?? '/dashboard' : this.route.snapshot.queryParams['returnUrl'] ?? '/home';
|
|
||||||
this.router.navigate([returnUrl]);
|
|
||||||
},
|
|
||||||
error: () =>
|
|
||||||
{
|
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.rlap');
|
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.sysdate');
|
|
||||||
|
|
||||||
this.authService.loggedout();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (errorMessage: string) =>
|
error: (errorMessage: string) =>
|
||||||
{
|
{
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.spinnerService.hide();
|
this.spinnerService.hide();
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.rlap');
|
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.sysdate');
|
|
||||||
|
|
||||||
this.alertService.error(errorMessage);
|
this.abortLogin(errorMessage);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Second factor, the user is cached already so the otp call travels with the token. */
|
||||||
|
private verifyOtp(data: any, sysDate: string, loginInf: string): void
|
||||||
|
{
|
||||||
|
this.authService.loggedIn(data, false);
|
||||||
|
const modalOptions: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true, windowClass: 'misc-width' };
|
||||||
|
const modalRef = this.modalService.open(OtpComponent, modalOptions);
|
||||||
|
|
||||||
|
modalRef.componentInstance.fromParent = { userId: data.id, authMethod: data.authMethod };
|
||||||
|
modalRef.result.then((result) =>
|
||||||
|
{
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
this.abortLogin('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.pwdChangeRequired)
|
||||||
|
this.changePassword(data);
|
||||||
|
else
|
||||||
|
this.completeLogin(data, sysDate, loginInf);
|
||||||
|
},
|
||||||
|
() => this.abortLogin(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Expired/first time password, the user has to sign in again with the new one. */
|
||||||
|
private changePassword(data: any): void
|
||||||
|
{
|
||||||
|
this.authService.loggedIn(data, false);
|
||||||
|
const modalOptions: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true };
|
||||||
|
const modalRef = this.modalService.open(ChangePwdComponent, modalOptions);
|
||||||
|
modalRef.componentInstance.fromParent = { userId: data.id, loginId: data.loginId, userName: data.userName };
|
||||||
|
|
||||||
|
modalRef.result.then(() => this.authService.loggedout(), () => this.authService.loggedout());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The login response already carries the authentication token, the refresh token and the
|
||||||
|
* permission keys (moduleIds), so nothing else has to be fetched before entering the app.
|
||||||
|
* Raising the login event makes the sidebar rebuild itself from those permission keys.
|
||||||
|
*/
|
||||||
|
private completeLogin(data: any, sysDate: string, loginInf: string): void
|
||||||
|
{
|
||||||
|
localStorage.setItem('OnlineSalesAutoCrop.sysdate', sysDate);
|
||||||
|
if (this.f.remberMe.value)
|
||||||
|
localStorage.setItem('OnlineSalesAutoCrop.rlap', loginInf);
|
||||||
|
else
|
||||||
|
localStorage.removeItem('OnlineSalesAutoCrop.rlap');
|
||||||
|
|
||||||
|
this.idleSvc.startMonitor();
|
||||||
|
this.authService.raiseLoginEvent(data.id, true);
|
||||||
|
|
||||||
|
const returnUrl = this.route.snapshot.queryParams['returnUrl'] ?? '/home';
|
||||||
|
this.router.navigate([returnUrl]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private abortLogin(errorMessage: string): void
|
||||||
|
{
|
||||||
|
this.loading = false;
|
||||||
|
this.spinnerService.hide();
|
||||||
|
localStorage.removeItem('OnlineSalesAutoCrop.rlap');
|
||||||
|
localStorage.removeItem('OnlineSalesAutoCrop.sysdate');
|
||||||
|
|
||||||
|
this.authService.loggedout();
|
||||||
|
if (errorMessage)
|
||||||
|
this.alertService.error(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseReturnMessage(data: any): string
|
||||||
|
{
|
||||||
|
return Array.isArray(data?.returnMessage) ? data.returnMessage.join('<br/>') : '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export class AuthGuard
|
||||||
let keys: string[] = permissionkey.split(',');
|
let keys: string[] = permissionkey.split(',');
|
||||||
for (const key of keys)
|
for (const key of keys)
|
||||||
{
|
{
|
||||||
found = currentUser.moduleIds.includes(key);
|
found = currentUser.moduleIds?.includes(key) === true;
|
||||||
if (found)
|
if (found)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ export class AuthGuard
|
||||||
if (found === false)
|
if (found === false)
|
||||||
this.router.navigate(['/accessdenied']);
|
this.router.navigate(['/accessdenied']);
|
||||||
|
|
||||||
return true;
|
return found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -59,12 +59,7 @@ export class AuthenticationService
|
||||||
return this.api.postAsync<any>('v1/users/login', params)
|
return this.api.postAsync<any>('v1/users/login', params)
|
||||||
.pipe(map(user =>
|
.pipe(map(user =>
|
||||||
{
|
{
|
||||||
user.moduleIds = JSON.parse(this.functionService.decipherData(user.idsValue));
|
this.storeCurrentUser(user);
|
||||||
user.idsValue = '';
|
|
||||||
const encString: string = this.functionService.encrypt(JSON.stringify(user));
|
|
||||||
localStorage.setItem('OnlineSalesAutoCrop.currentUser', encString);
|
|
||||||
|
|
||||||
this.currentUserSubject.next(user);
|
|
||||||
return user;
|
return user;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
@ -74,6 +69,31 @@ export class AuthenticationService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The login endpoint returns the permission keys in `moduleIds` and no longer returns the
|
||||||
|
* theme/idle settings, so the client defaults are applied here before the user is cached.
|
||||||
|
*/
|
||||||
|
public storeCurrentUser(user: any): void
|
||||||
|
{
|
||||||
|
user.moduleIds = user.moduleIds ?? [];
|
||||||
|
|
||||||
|
const defaults = new UserModel();
|
||||||
|
user.themeName = user.themeName || defaults.themeName;
|
||||||
|
user.schemeName = user.schemeName || defaults.schemeName;
|
||||||
|
user.menuLayout = user.menuLayout || defaults.menuLayout;
|
||||||
|
|
||||||
|
const encString: string = this.functionService.encrypt(JSON.stringify(user));
|
||||||
|
localStorage.setItem('OnlineSalesAutoCrop.currentUser', encString);
|
||||||
|
|
||||||
|
this.currentUserSubject.next(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** True when the permission key is granted, pass "<moduleId>_1|_2|_3" to check add/edit/delete. */
|
||||||
|
public hasPermission(moduleId: string): boolean
|
||||||
|
{
|
||||||
|
return this.currentUserValue?.moduleIds?.includes(moduleId) === true;
|
||||||
|
}
|
||||||
|
|
||||||
public refreshToken()
|
public refreshToken()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -99,13 +119,13 @@ export class AuthenticationService
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!this.currentUserValue?.logId)
|
if (!this.currentUserValue?.id)
|
||||||
{
|
{
|
||||||
localStorage.removeItem('OnlineSalesAutoCrop.currentUser');
|
localStorage.removeItem('OnlineSalesAutoCrop.currentUser');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params: any = { logId: this.currentUserValue.logId, attendanceLogout: attendanceLogout, ipAddress: ipAddress, macAddress: macAddress, hostName: hostName, logoutRemarks: logoutRemarks };
|
const params: any = { logId: this.currentUserValue.logId ?? 0, attendanceLogout: attendanceLogout, ipAddress: ipAddress, macAddress: macAddress, hostName: hostName, logoutRemarks: logoutRemarks };
|
||||||
return this.api.postAsync<any>('v1/users/logout', params)
|
return this.api.postAsync<any>('v1/users/logout', params)
|
||||||
.pipe(map(value =>
|
.pipe(map(value =>
|
||||||
{
|
{
|
||||||
|
|
@ -142,7 +162,7 @@ export class AuthenticationService
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const params: any = { logId: this.currentUserValue.logId };
|
const params: any = { logId: this.currentUserValue?.logId ?? 0 };
|
||||||
return this.api.postAsync<any>('v1/users/sessionExpired', params)
|
return this.api.postAsync<any>('v1/users/sessionExpired', params)
|
||||||
.pipe(map(value =>
|
.pipe(map(value =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user