2026-06-14 12:46:29 +06:00
using Ease.NetCore.DataAccess ;
using Ease.NetCore.DataAccess.SQL ;
using Ease.NetCore.Utility ;
using OnlineSalesAutoCrop.CoreAPI.Models ;
using OnlineSalesAutoCrop.CoreAPI.Models.Global ;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects ;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Setups ;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems ;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems ;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems ;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems ;
using Microsoft.Data.SqlClient ;
using Microsoft.Extensions.Options ;
using System ;
using System.Collections.Generic ;
using System.Data ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
2026-06-15 18:26:58 +06:00
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth ;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations ;
2026-06-14 12:46:29 +06:00
namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
{
2026-06-15 18:26:58 +06:00
public class UserService ( IOptions < AppSettings > settings , IOptions < MenuSettings > menuSettings ) : IUserService
{
private readonly AppSettings _settings = settings ? . Value ;
private readonly MenuSettings _menuSettings = menuSettings ? . Value ;
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="ipAddress"></param>
/// <param name="checkPwd"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < User > LoginAsync ( LoginRequest request , string ipAddress , bool checkPwd )
{
User user = new ( ) { LoginId = request . LoginId , LoginStatus = EnumLoginStatus . Unsuccessful } ;
//try
//{
// string password = EncryptPassword(password: request.Password);
// using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
// try
// {
// #region Attendance Login and Valid Ip Address
// if (request.AttendanceLogin && !request.LoginId.ToLower().Equals(User.SuperUser_LoginId))
// {
// string errMsg = string.Empty;
// SqlParameter[] p =
// [
// SqlHelperExtension.CreateInParam(pName: "@IpAddress", 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: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 50),
// SqlHelperExtension.CreateOutParam(pName: "@ErrMsg", pType: SqlDbType.VarChar, pValue: errMsg, size: 300)
// ];
// _ = tc.ExecuteNonQuerySp(spName: "dbo.IsValidIpOrMacAddress", parameterValues: p);
// errMsg = (p[4] == null || p[4].Value == null || p[4].Value == DBNull.Value) ? string.Empty : Convert.ToString(p[4].Value);
// if (!string.IsNullOrEmpty(errMsg))
// {
// tc.End();
// throw new InvalidOperationException(errMsg);
// }
// }
// #endregion
// bool batchEnabled = false;
// DateTime sysDate = DateTime.Today.Date;
// string appVer = string.Empty, alParams = string.Empty;
// int maxTryCount = 5, lockTime = 1, marMonths = 24, idleTime = 0, timeoutTime = 0, pingTime = 0, bmProcessId = 0, prProcessId = 0;
// #region Read Params from ThisSystem
// using (IDataReader dr = tc.ExecuteReader("SELECT MaxTryCount, LockTime, MarMonths, CAST(GETDATE() as date), AppVersion, AutoLogoutParams, BatchEnabled, BmProcessId, PrProcessId FROM ThisSystem"))
// {
// if (dr.Read())
// {
// maxTryCount = dr.GetInt16(0);
// lockTime = dr.GetInt16(1);
// marMonths = dr.GetInt16(2);
// sysDate = dr.GetDateTime(3);
// appVer = dr.GetString(4);
// alParams = dr.IsDBNull(5) ? string.Empty : dr.GetString(5);
// batchEnabled = !dr.IsDBNull(6) && dr.GetInt16(6) != 0;
// bmProcessId = dr.IsDBNull(7) ? 0 : dr.GetInt16(7);
// prProcessId = dr.IsDBNull(8) ? 0 : dr.GetInt16(8);
// }
// dr.Close();
// }
// if (!string.IsNullOrEmpty(alParams))
// {
// string[] times = alParams.Split(separator: ',', options: StringSplitOptions.RemoveEmptyEntries);
// if (times.Length == 3)
// {
// if (!int.TryParse(times[0], out idleTime))
// idleTime = 0;
// if (!int.TryParse(times[1], out timeoutTime))
// timeoutTime = 0;
// if (!int.TryParse(times[2], out pingTime))
// pingTime = 0;
// }
// }
// if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && !request.AppVersion.Equals(appVer))
// {
// user.UnsuccessfulMsg = appVer;
// user.LoginStatus = EnumLoginStatus.VersionMismatch;
// }
// #endregion
// if (user.LoginStatus != EnumLoginStatus.VersionMismatch)
// {
// #region Read User data using authentication data
// string commandText;
// if (!checkPwd)
// {
// 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))
// {
// if (dr.Read())
// {
// user = new User
// {
// Id = dr.GetInt32(0),
// UserName = dr.GetString(1),
// Status = (EnumStatus)dr.GetInt16(2),
// MobileNo = dr.GetString(3),
// EmailAddress = dr.GetString(4),
// AuthRequiredAtLogin = !dr.IsDBNull(5) && dr.GetInt16(5) > 0,
// AuthMethod = (EnumAuthenticationMethod)dr.GetInt16(6),
// AuthKey = dr.IsDBNull(7) ? string.Empty : dr.GetString(7),
// AppId = dr.IsDBNull(8) ? string.Empty : dr.GetString(8),
// AccessStatus = (EnumAccessStatus)dr.GetInt16(9),
// NeverExpires = !dr.IsDBNull(10) && dr.GetInt16(10) > 0,
// LastPasswords = dr.IsDBNull(11) ? string.Empty : dr.GetString(11),
// LastPassChgDate = dr.IsDBNull(12) ? null : dr.GetDateTime(12),
// ExpireDate = dr.IsDBNull(13) ? null : dr.GetDateTime(13),
// ThemeName = dr.IsDBNull(14) ? "yellow" : dr.GetString(14),
// SchemeName = dr.IsDBNull(15) ? "dark" : dr.GetString(15),
// 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 = [],
// 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);
// }
// #endregion
// #region If the user was locked, try set set unlock if Time expired
// 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);
// if (isSuccessful == 1)
// user.IsLocked = false;
// }
// #endregion
// #region Keep log for unauthrise access and Set user lock if exceeds max try
// 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);
// if (p[6] != null && p[6].Value != null && p[6].Value != DBNull.Value)
// 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 Generate and Save Otp if Otp is enabled and send thru SMS/Email
// if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && (user.AuthMethod == EnumAuthenticationMethod.Email || user.AuthMethod == EnumAuthenticationMethod.MobileSMS))
// {
// 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
// #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)
// {
// 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 (dr.GetInt16(2) != 0) //Alow add
// {
// user.ModuleIds.Add($"{moduleId}_1");
// }
// if (dr.GetInt16(3) != 0) //Alow edit
// {
// user.ModuleIds.Add($"{moduleId}_2");
// }
// if (dr.GetInt16(4) != 0) //Allow Delete
// {
// user.ModuleIds.Add($"{moduleId}_3");
// }
// logoutTime = dr.IsDBNull(5) ? null : dr.GetDateTime(5);
// }
// dr.Close();
// }
// user.LogId = logId;
// user.LogoutTime = logoutTime;
// //Read User TeamSpace Ids
// using (IDataReader dr = tc.ExecuteReader("SELECT TeamSpaceId FROM TeamSpaceUsers WHERE UserId=%n", user.Id))
// {
// while (dr.Read())
// {
// user.TeamSpaceIds.Add(dr.GetInt32(0));
// }
// dr.Close();
// }
// //Pending Notification count
// user.NotificationCount = GetPendingNotifCount(tc: tc, userId: user.Id);
// }
// #endregion
// }
// tc.End();
// }
// catch (Exception ie)
// {
// tc?.HandleError();
// throw DBCustomError.GenerateCustomError(ie);
// }
//}
//catch (Exception e)
//{
// throw new InvalidOperationException(e.Message, e);
//}
return user ;
}
public async Task < User > IntegrationLoginAsync ( IntegrstionLoginRequest request , string ipAddress , bool checkPwd )
{
User user = null ;
try
{
string password = EncryptPassword ( password : request . Password ) ;
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
DateTime sysDate = DateTime . Today . Date ;
string appVer = string . Empty , alParams = string . Empty ;
int maxTryCount = 5 , lockTime = 1 , marMonths = 24 , idleTime = 0 , timeoutTime = 0 , pingTime = 0 , bmProcessId = 0 , prProcessId = 0 ;
#region Read User data using authentication data
string commandText = SQLParser . MakeSQL ( "SELECT UserId,Password,LoginId, UserName, Status, MobileNo, EmailAddress,"
+ " AuthKey, AuthValue, IsLocked FROM Users WHERE LoginID=%s" , request . LoginId ) ;
using ( IDataReader dr = tc . ExecuteReader ( commandText : commandText ) )
{
if ( dr . Read ( ) )
{
user = new User
{
UserId = dr . GetInt32 ( 0 ) ,
Password = dr . GetString ( 1 ) ,
LoginId = dr . GetString ( 2 ) ,
UserName = dr . GetString ( 3 ) ,
Status = ( EnumStatus ) dr . GetInt32 ( 4 ) ,
MobileNo = dr . GetString ( 5 ) ,
EmailAddress = dr . GetString ( 6 ) ,
AuthKey = dr . GetString ( 7 ) ,
AuthValue = dr . GetString ( 8 ) ,
IsLocked = dr . GetBoolean ( 9 ) ,
LoginStatus = EnumLoginStatus . Success
} ;
}
dr . Close ( ) ;
}
if ( user is null )
{
tc . End ( ) ;
throw new InvalidOperationException ( $"User not found with login: {request.LoginId}" ) ;
}
if ( ! request . Password . Equals ( user . Password ) )
{
tc . End ( ) ;
throw new InvalidOperationException ( $"Password mismatch for login: {request.LoginId}" ) ;
}
#endregion
#region If the user was locked , try set set unlock if Time expired
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 ) ;
if ( isSuccessful = = 1 )
user . IsLocked = false ;
}
#endregion
#region Keep log for unauthrise access and Set user lock if exceeds max try
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 ) ;
if ( p [ 6 ] ! = null & & p [ 6 ] . Value ! = null & & p [ 6 ] . Value ! = DBNull . Value )
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
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 : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LoginId" , pType : SqlDbType . VarChar , pValue : user . LoginId , size : 30 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LockTime" , pType : SqlDbType . Int , pValue : lockTime ) ,
SqlHelperExtension . CreateInParam ( pName : "@LoginTime" , pType : SqlDbType . DateTime , pValue : DateTime . Now )
] ;
_ = await tc . ExecuteNonQuerySpAsync ( spName : "dbo.SaveAccessLog" , parameterValues : p ) ;
}
#endregion
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return user ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < int > LoadNotificationCountAsync ( int userId )
{
int value = 0 ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
value = GetPendingNotifCount ( tc : tc , userId : userId ) ;
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return value ;
}
/// <summary>
///
/// </summary>
/// <param name="accountId"></param>
/// <returns></returns>
public async Task < FindAccountResponse > FindAccountAsync ( string accountId )
{
FindAccountResponse response = new ( ) ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
using ( IDataReader dr = tc . ExecuteReader ( "SELECT UserID, EmailAddress, MobileNo FROM Users WHERE LoginID=%s OR EmailAddress=%s OR MobileNo=%s" , accountId , accountId , accountId ) )
{
if ( dr . Read ( ) )
{
response . UserId = dr . GetInt32 ( 0 ) ;
response . EmailAddress = dr . GetString ( 1 ) ;
response . PhoneNo = dr . GetString ( 2 ) ;
response . Value = true ;
}
dr . Close ( ) ;
}
tc . End ( ) ;
if ( ! response . Value )
{
response . ReturnMessage . Add ( $"[{accountId}] is not a valid Login Id/Email address/Mobile number." ) ;
}
else
{
if ( response . PhoneNo . Length > 8 )
response . PhoneNoMasked = string . Concat ( response . PhoneNo . AsSpan ( 0 , response . PhoneNo . Length - 8 ) , "*****" , response . PhoneNo . AsSpan ( response . PhoneNo . Length - 3 , 3 ) ) ;
int idx = response . EmailAddress . IndexOf ( '@' ) ;
if ( idx ! = - 1 )
{
string firstPart = response . EmailAddress [ . . idx ] ;
if ( firstPart . Length > = 5 )
firstPart = string . Concat ( firstPart . AsSpan ( 0 , firstPart . Length - 5 ) , "*****" ) ;
response . EmailAddressMasked = string . Concat ( firstPart , response . EmailAddress . AsSpan ( idx , response . EmailAddress . Length - idx ) ) ;
}
}
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="authValue"></param>
/// <param name="userId"></param>
/// <returns></returns>
public async Task < bool > ValidateAuthValueAsync ( string authValue , int userId )
{
bool returnValue = false ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@AuthValue" , pType : SqlDbType . VarChar , pValue : authValue , size : 10 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateOutParam ( pName : "@Valid" , pType : SqlDbType . SmallInt , pValue : 0 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.ValidateAuthValue" , parameterValues : p ) ;
if ( p [ 2 ] . Value ! = null & & p [ 2 ] . Value ! = DBNull . Value )
returnValue = Convert . ToInt16 ( p [ 2 ] . Value ) > 0 ;
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="user"></param>
/// <param name="ipAddress"></param>
/// <param name="createdBy"></param>
/// <returns></returns>
public async Task < bool > AddUserAsync ( NewUserRequest user , string ipAddress , int createdBy )
{
bool returnValue ;
try
{
#region Password Policy if Does not change password on next login
if ( user . AccessStatus ! = EnumAccessStatus . FirstTime )
{
ReadPwdParams ( userId : 0 , loginId : user . LoginId , enfStgPwd : out bool enfStgPwd , minLen : out short minLen , maxLen : out short maxLen , reservedWords : out string reservedWords ) ;
ValidatePwdPolicies ( password : user . Password , minLen : minLen , maxLen : maxLen , enfStgPwd : enfStgPwd , reservedWords : reservedWords ) ;
}
#endregion
int userId = 0 ;
user . Password = EncryptPassword ( password : user . Password ) ;
if ( ! string . IsNullOrEmpty ( user . EmailAddress ) )
user . EmailAddress = user . EmailAddress . Replace ( " " , "" ) ;
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@LoginId" , pType : SqlDbType . VarChar , pValue : user . LoginId , size : 30 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserName" , pType : SqlDbType . VarChar , pValue : user . UserName , size : 75 ) ,
SqlHelperExtension . CreateInParam ( pName : "@Designation" , pType : SqlDbType . VarChar , pValue : user . Designation , size : 50 ) ,
SqlHelperExtension . CreateInParam ( pName : "@Password" , pType : SqlDbType . VarChar , pValue : user . Password , size : 75 ) ,
SqlHelperExtension . CreateInParam ( pName : "@MobileNo" , pType : SqlDbType . VarChar , pValue : user . MobileNo , size : 15 ) ,
SqlHelperExtension . CreateInParam ( pName : "@EmailAddress" , pType : SqlDbType . VarChar , pValue : user . EmailAddress , size : 100 ) ,
SqlHelperExtension . CreateInParam ( pName : "@EmployeeId" , pType : SqlDbType . Int , pValue : DataReader . GetNullValue ( user . EmployeeId ) ) ,
SqlHelperExtension . CreateInParam ( pName : "@EmployeeCode" , pType : SqlDbType . VarChar , pValue : DataReader . GetNullValue ( user . EmployeeCode ) , size : 15 ) ,
SqlHelperExtension . CreateInParam ( pName : "@AuthReqAtlogin" , pType : SqlDbType . SmallInt , pValue : user . AuthReqAtlogin ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@AuthMethod" , pType : SqlDbType . SmallInt , pValue : user . AuthMethod ) ,
SqlHelperExtension . CreateInParam ( pName : "@DBOnStartup" , pType : SqlDbType . SmallInt , pValue : user . DbOnStartup ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@Status" , pType : SqlDbType . SmallInt , pValue : user . Status ) ,
SqlHelperExtension . CreateInParam ( pName : "@SeqId" , pType : SqlDbType . SmallInt , pValue : user . SeqId ) ,
SqlHelperExtension . CreateInParam ( pName : "@CanUseAtnSys" , pType : SqlDbType . SmallInt , pValue : user . CanUseAttendanceSystem ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@ViewToAll" , pType : SqlDbType . SmallInt , pValue : user . ViewToAll ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@AccessStatus" , pType : SqlDbType . SmallInt , pValue : user . AccessStatus ) ,
SqlHelperExtension . CreateInParam ( pName : "@NeverExpire" , pType : SqlDbType . SmallInt , pValue : user . NeverExpire ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@DAMultiLogin" , pType : SqlDbType . SmallInt , pValue : user . DisallowMultiLogin ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@CreatedBy" , pType : SqlDbType . Int , pValue : createdBy ) ,
SqlHelperExtension . CreateOutParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.InsertUser" , parameterValues : p ) ;
userId = ( p [ 20 ] ? . Value ! = null & & p [ 20 ] ? . Value ! = DBNull . Value ) ? Convert . ToInt32 ( p [ 20 ] . Value ) : 0 ;
if ( user . GroupIds ! = null & & user . GroupIds . Count > 0 & & userId > 0 )
{
List < int > ownerGroupsIds = [ ] ;
if ( createdBy = = User . SuperUser_Id )
{
ownerGroupsIds . AddRange ( user . GroupIds ) ;
}
else
{
using IDataReader dr = tc . ExecuteReader ( "SELECT GroupId FROM Groups WHERE (CreatedBy=%n OR ViewToAll=1)" , createdBy ) ;
while ( dr . Read ( ) )
{
ownerGroupsIds . Add ( dr . GetInt32 ( 0 ) ) ;
}
dr . Close ( ) ;
}
StringBuilder sb = new ( ) ;
foreach ( int groupId in user . GroupIds )
{
if ( ! ownerGroupsIds . Contains ( groupId ) )
continue ;
sb . Append ( $"INSERT INTO UserGroups(UserId,GroupId) VALUES({userId},{groupId});" ) ;
}
_ = tc . ExecuteNonQuery ( commandText : sb . ToString ( ) ) ;
}
tc . End ( ) ;
#region Copy File
try
{
string destFileName = System . IO . Path . Combine ( _settings . ProfileImageFolder , $"{userId}.png" ) ;
string sourceFileName = System . IO . Path . Combine ( _settings . ProfileImageFolder , "default-user.png" ) ;
if ( System . IO . File . Exists ( path : sourceFileName ) )
{
System . IO . File . Copy ( sourceFileName : sourceFileName , destFileName : destFileName ) ;
}
}
catch
{
//Do nothing
}
#endregion
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="user"></param>
/// <param name="ipAddress"></param>
/// <param name="modifiedBy"></param>
/// <returns></returns>
public async Task < bool > EditUserAsync ( UserRequest user , string ipAddress , int modifiedBy )
{
bool returnValue = false ;
try
{
if ( ! string . IsNullOrEmpty ( user . EmailAddress ) )
user . EmailAddress = user . EmailAddress . Replace ( " " , "" ) ;
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@LoginId" , pType : SqlDbType . VarChar , pValue : user . LoginId , size : 30 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserName" , pType : SqlDbType . VarChar , pValue : user . UserName , size : 75 ) ,
SqlHelperExtension . CreateInParam ( pName : "@Designation" , pType : SqlDbType . VarChar , pValue : user . Designation , size : 50 ) ,
SqlHelperExtension . CreateInParam ( pName : "@MobileNo" , pType : SqlDbType . VarChar , pValue : user . MobileNo , size : 15 ) ,
SqlHelperExtension . CreateInParam ( pName : "@EmailAddress" , pType : SqlDbType . VarChar , pValue : user . EmailAddress ? ? string . Empty , size : 100 ) ,
SqlHelperExtension . CreateInParam ( pName : "@AuthReqAtlogin" , pType : SqlDbType . SmallInt , pValue : user . AuthReqAtlogin ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@AuthMethod" , pType : SqlDbType . SmallInt , pValue : user . AuthMethod ) ,
SqlHelperExtension . CreateInParam ( pName : "@AuthKey" , pType : SqlDbType . VarChar , pValue : user . AuthKey , size : 100 ) ,
SqlHelperExtension . CreateInParam ( pName : "@DBOnStartup" , pType : SqlDbType . SmallInt , pValue : user . DbOnStartup ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@Status" , pType : SqlDbType . SmallInt , pValue : user . Status ) ,
SqlHelperExtension . CreateInParam ( pName : "@SeqId" , pType : SqlDbType . SmallInt , pValue : user . SeqId ) ,
SqlHelperExtension . CreateInParam ( pName : "@CanUseAtnSys" , pType : SqlDbType . SmallInt , pValue : user . CanUseAttendanceSystem ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@ViewToAll" , pType : SqlDbType . SmallInt , pValue : user . ViewToAll ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@AccessStatus" , pType : SqlDbType . SmallInt , pValue : user . AccessStatus ) ,
SqlHelperExtension . CreateInParam ( pName : "@NeverExpire" , pType : SqlDbType . SmallInt , pValue : user . NeverExpire ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@DAMultiLogin" , pType : SqlDbType . SmallInt , pValue : user . DisallowMultiLogin ? 1 : 0 ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@ModifiedBy" , pType : SqlDbType . Int , pValue : modifiedBy ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : user . UserId )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UpdateUser" , parameterValues : p ) ;
if ( user . GroupIds ! = null & & user . GroupIds . Count > 0 & & user . UserId > 0 )
{
List < int > ownerGroupsIds = [ ] ;
if ( modifiedBy = = User . SuperUser_Id )
{
ownerGroupsIds . AddRange ( user . GroupIds ) ;
}
else
{
using IDataReader dr = tc . ExecuteReader ( "SELECT GroupId FROM Groups WHERE (CreatedBy=%n OR ViewToAll=1)" , modifiedBy ) ;
while ( dr . Read ( ) )
{
ownerGroupsIds . Add ( dr . GetInt32 ( 0 ) ) ;
}
dr . Close ( ) ;
}
StringBuilder sb = new ( ) ;
foreach ( int groupId in user . GroupIds )
{
if ( ! ownerGroupsIds . Contains ( groupId ) )
continue ;
sb . Append ( $"INSERT INTO UserGroups(UserId,GroupId) VALUES({user.UserId},{groupId});" ) ;
}
_ = tc . ExecuteNonQuery ( commandText : sb . ToString ( ) ) ;
}
tc . End ( ) ;
#region Copy File
try
{
string destFileName = System . IO . Path . Combine ( _settings . ProfileImageFolder , $"{user.UserId}.png" ) ;
string sourceFileName = System . IO . Path . Combine ( _settings . ProfileImageFolder , "default-user.png" ) ;
if ( System . IO . File . Exists ( path : sourceFileName ) & & ! System . IO . File . Exists ( path : destFileName ) )
{
System . IO . File . Copy ( sourceFileName : sourceFileName , destFileName : destFileName ) ;
}
}
catch
{
//Do nothing
}
#endregion
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="deletedBy"></param>
/// <returns></returns>
public async Task < bool > DeleteUserAsync ( int userId , int deletedBy )
{
bool returnValue ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@DeletedBy" , pType : SqlDbType . Int , pValue : deletedBy ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.DeleteUser" , parameterValues : p ) ;
tc . End ( ) ;
#region Delete File
try
{
string fileSpec = System . IO . Path . Combine ( _settings . ProfileImageFolder , $"{userId}.png" ) ;
if ( System . IO . File . Exists ( path : fileSpec ) )
System . IO . File . Delete ( path : fileSpec ) ;
}
catch
{
//Do nothing
}
#endregion
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="loginId"></param>
/// <param name="unlockedBy"></param>
/// <returns></returns>
public async Task < bool > UnlockUserAsync ( int userId , string loginId , int unlockedBy )
{
bool returnValue ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@LoginId" , pType : SqlDbType . VarChar , pValue : loginId , size : 30 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UnlockedBy" , pType : SqlDbType . Int , pValue : unlockedBy )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UnlockUser" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="newPassword"></param>
/// <param name="ipAddress"></param>
/// <param name="changedBy"></param>
/// <returns></returns>
public async Task < bool > ResetPasswordAsync ( int userId , string newPassword , string ipAddress , int changedBy )
{
bool returnValue = false ;
try
{
try
{
newPassword = EncryptPassword ( password : newPassword ) ;
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@NewPwd" , pType : SqlDbType . VarChar , pValue : newPassword , size : 75 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LastPwds" , pType : SqlDbType . VarChar , pValue : string . Empty , size : 700 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LastPwdChgDate" , pType : SqlDbType . DateTime , pValue : DateTime . Now ) ,
SqlHelperExtension . CreateInParam ( pName : "@PwdExpireDate" , pType : SqlDbType . DateTime , pValue : DateTime . Now ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@ChangedBy" , pType : SqlDbType . Int , pValue : changedBy ) ,
SqlHelperExtension . CreateInParam ( pName : "@ResetPwd" , pType : SqlDbType . SmallInt , pValue : 1 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UpdateUserPassword" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="newPassword"></param>
/// <param name="ipAddress"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task < bool > SendPasswordAsync ( int userId , string newPassword , string ipAddress )
{
bool returnValue = false ;
try
{
newPassword = EncryptPassword ( password : newPassword ) ;
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@NewPwd" , pType : SqlDbType . VarChar , pValue : newPassword , size : 75 ) ,
SqlHelperExtension . CreateInParam ( pName : "LastPwds" , pType : SqlDbType . VarChar , pValue : string . Empty , size : 700 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LastPwdChgDate" , pType : SqlDbType . DateTime , pValue : DateTime . Now ) ,
SqlHelperExtension . CreateInParam ( pName : "@PwdExpireDate" , pType : SqlDbType . DateTime , pValue : DateTime . Now ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@ChangedBy" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@ResetPwd" , pType : SqlDbType . SmallInt , pValue : 1 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UpdateUserPassword" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="newPassword"></param>
/// <param name="oldPassword"></param>
/// <param name="ipAddress"></param>
/// <param name="changedBy"></param>
/// <returns></returns>
public async Task < bool > ChangePasswordAsync ( int userId , string oldPassword , string newPassword , string ipAddress , int changedBy )
{
bool returnValue = false ;
try
{
bool loginIdCantPwd = false ;
DateTime ? lastPassChgDate = null ;
List < string > actPwdHistories = [ ] ;
Queue < string > pwdHistories = new ( ) ;
EnumAccessStatus accessStatus = EnumAccessStatus . LoggedOut ;
short pwdMinLen = 0 , pwdMaxLen = 0 , daLastPwds = 0 , expiryDays = 0 ;
bool neverExpire = false , enfStgPwd = false , prvntAtckPwdReuse = false ;
string loginId = string . Empty , password = string . Empty , lastPasswords = string . Empty , reservedWords = string . Empty ;
#region Reading Data from DB
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
using IDataReader dr = tc . ExecuteReader ( "SELECT A.LoginId, A.Password, A.LastPasswords, A.LastPassChgDate, A.NeverExpire, A.AccessStatus,"
+ " B.EnfStgPwd, B.PwdMinLen, B.PwdMaxLen, B.ExpiryDays, B.DALastPwds, B.PwdRsvdWords, B.loginIdCantPwd, B.PrvntAtckPwdReuse"
+ " FROM Users A LEFT OUTER JOIN ThisSystem B ON A.UserID=A.UserID WHERE A.UserID=%n" , userId ) ;
if ( dr . Read ( ) )
{
loginId = dr . GetString ( 0 ) ;
password = dr . GetString ( 1 ) ;
lastPasswords = dr . IsDBNull ( 2 ) ? string . Empty : dr . GetString ( 2 ) ;
lastPassChgDate = dr . IsDBNull ( 3 ) ? null : dr . GetDateTime ( 3 ) ;
neverExpire = ! dr . IsDBNull ( 4 ) & & dr . GetInt16 ( 4 ) > 0 ;
accessStatus = ( EnumAccessStatus ) dr . GetInt16 ( 5 ) ;
enfStgPwd = ! dr . IsDBNull ( 6 ) & & dr . GetInt16 ( 6 ) > 0 ;
pwdMinLen = dr . IsDBNull ( 7 ) ? Convert . ToInt16 ( 0 ) : dr . GetInt16 ( 7 ) ;
pwdMaxLen = dr . IsDBNull ( 8 ) ? Convert . ToInt16 ( 30 ) : dr . GetInt16 ( 8 ) ;
expiryDays = dr . IsDBNull ( 9 ) ? Convert . ToInt16 ( 0 ) : dr . GetInt16 ( 9 ) ;
daLastPwds = dr . IsDBNull ( 10 ) ? Convert . ToInt16 ( 0 ) : dr . GetInt16 ( 10 ) ;
reservedWords = dr . IsDBNull ( 11 ) ? string . Empty : dr . GetString ( 11 ) ;
loginIdCantPwd = ! dr . IsDBNull ( 12 ) & & dr . GetInt16 ( 12 ) ! = 0 ;
prvntAtckPwdReuse = ! dr . IsDBNull ( 13 ) & & dr . GetInt16 ( 13 ) ! = 0 ;
}
dr . Close ( ) ;
tc . End ( ) ;
if ( loginIdCantPwd & & ! string . IsNullOrEmpty ( loginId ) )
{
reservedWords = string . IsNullOrEmpty ( reservedWords ) ? loginId : $"{reservedWords},{loginId}" ;
}
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
#endregion
#region Validation
oldPassword = EncryptPassword ( password : oldPassword ) ;
if ( ! oldPassword . Equals ( password ) )
throw new InvalidOperationException ( "Old Password does not match with system." ) ;
#region Password Histories
if ( ! string . IsNullOrEmpty ( lastPasswords ) & & ! string . IsNullOrWhiteSpace ( lastPasswords ) )
{
string [ ] pwds = lastPasswords . Split ( ',' ) ;
foreach ( string pwd in pwds )
{
pwdHistories . Enqueue ( pwd ) ;
}
}
#endregion
#region Actual Password Histories
string [ ] pwdsHists = [ . . pwdHistories ] ;
if ( daLastPwds > 0 & & pwdsHists . Length > 0 )
{
for ( int idx = pwdsHists . Length - 1 ; idx > = 0 ; idx - - )
{
if ( ! actPwdHistories . Contains ( pwdsHists [ idx ] ) & & actPwdHistories . Count < = daLastPwds )
actPwdHistories . Add ( pwdsHists [ idx ] ) ;
}
}
#endregion
if ( lastPassChgDate . HasValue & & prvntAtckPwdReuse & & accessStatus ! = EnumAccessStatus . FirstTime & & lastPassChgDate . Value . Date > = DateTime . Today . Date )
{
throw new InvalidOperationException ( "Password should be at least one day old to change again." ) ;
}
CheckPasswordHistory ( password : newPassword , minLen : pwdMinLen , maxLen : pwdMaxLen , enfStgPwd : enfStgPwd , reservedWords : reservedWords , daLastPwds : daLastPwds , pwdHistories : pwdHistories , actPwdHistories : actPwdHistories ) ;
#endregion
#region Updateing Data
if ( pwdHistories . ToArray ( ) . Length > 0 )
lastPasswords = string . Join ( "," , [ . . pwdHistories ] ) ;
DateTime ? expireDate = null ;
lastPassChgDate = DateTime . Now ;
if ( ! neverExpire & & expiryDays > 0 )
expireDate = DateTime . Now . AddDays ( expiryDays ) ;
try
{
newPassword = EncryptPassword ( password : newPassword ) ;
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@NewPwd" , pType : SqlDbType . VarChar , pValue : newPassword , size : 75 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LastPwds" , pType : SqlDbType . VarChar , pValue : lastPasswords , size : 700 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LastPwdChgDate" , pType : SqlDbType . DateTime , pValue : lastPassChgDate ) ,
SqlHelperExtension . CreateInParam ( pName : "@PwdExpireDate" , pType : SqlDbType . DateTime , pValue : expireDate ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@ChangedBy" , pType : SqlDbType . Int , pValue : changedBy ) ,
SqlHelperExtension . CreateInParam ( pName : "@ResetPwd" , pType : SqlDbType . SmallInt , pValue : 0 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UpdateUserPassword" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
#endregion
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="menuLayout"></param>
/// <param name="themeName"></param>
/// <param name="schemeName"></param>
/// <returns></returns>
public async Task < bool > UpdateMyThemeAsync ( int userId , string menuLayout , string themeName , string schemeName )
{
bool returnValue = false ;
try
{
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@MenuLayout" , pType : SqlDbType . VarChar , pValue : menuLayout , size : 15 ) ,
SqlHelperExtension . CreateInParam ( pName : "@ThemeName" , pType : SqlDbType . VarChar , pValue : themeName , size : 15 ) ,
SqlHelperExtension . CreateInParam ( pName : "@SchemeName" , pType : SqlDbType . VarChar , pValue : schemeName , size : 10 ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UpdateMyTheme" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <param name="contactNo"></param>
/// <param name="modifiedBy"></param>
/// <param name="emplyeeId"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < bool > UpdateMyInfoAsync ( string address , string contactNo , int modifiedBy , int emplyeeId )
{
bool returnValue = false ;
try
{
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@Address" , pType : SqlDbType . VarChar , pValue : address , size : 120 ) ,
SqlHelperExtension . CreateInParam ( pName : "@ContactNo" , pType : SqlDbType . VarChar , pValue : contactNo , size : 25 ) ,
SqlHelperExtension . CreateInParam ( pName : "@ModifiedBy" , pType : SqlDbType . Int , pValue : modifiedBy ) ,
SqlHelperExtension . CreateInParam ( pName : "@EmployeeId" , pType : SqlDbType . Int , pValue : emplyeeId )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UpdateMyInfo" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="clientType"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < UserAttributesResponse > GetAttributesAsync ( int userId , int clientType )
{
UserAttributesResponse response = new ( ) { ReturnStatus = 200 } ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
using ( IDataReader dr = tc . ExecuteReader ( "SELECT LoginId FROM Users WHERE UserId=%n" , userId ) )
{
if ( dr . Read ( ) )
{
response = new UserAttributesResponse
{
UserId = userId ,
LoginId = dr . GetString ( 0 ) ,
ReturnStatus = 200 ,
UkIds = [ ] ,
} ;
}
dr . Close ( ) ;
}
#region Client & Projects
if ( response . UserId > 0 )
{
using IDataReader dr = tc . ExecuteReader ( $"SELECT ProjectId, ClientId FROM UserClients WHERE UserId=%n AND ProjectId IS {(clientType == 1 ? " NOT " : " ")}NULL" , response . UserId ) ;
while ( dr . Read ( ) )
{
string ukId = $"{(dr.IsDBNull(0) ? 0 : dr.GetInt32(0))}|{dr.GetInt32(1)}" ;
response . UkIds . Add ( ukId ) ;
}
dr . Close ( ) ;
}
response . HasSetup = response . UkIds . Count > 0 ;
#endregion
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="clientType"></param>
/// <param name="ipAddress"></param>
/// <param name="attributeSetBy"></param>
/// <param name="ukIds"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="clientType"></param>
/// <param name="deletedBy"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < bool > DeleteAttributesAsync ( int userId , int clientType , int deletedBy )
{
bool returnValue ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@ClientType" , pType : SqlDbType . SmallInt , pValue : clientType ) ,
SqlHelperExtension . CreateInParam ( pName : "@DeletedBy" , pType : SqlDbType . Int , pValue : deletedBy )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.DeleteUserAttributes" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="userId"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task < UserSearchResponse > GetUsersAsync ( UserSearchRequest request , int userId )
{
UserSearchResponse response = new ( ) ;
try
{
string andClause = string . Empty ;
if ( ! string . IsNullOrEmpty ( request . Criteria ) )
{
string criteria = request . Criteria . Replace ( "'" , "''" ) ;
andClause = $" AND (LoginID='{criteria}' OR MobileNo='{criteria}' OR EmailAddress='{criteria}' OR UserName LIKE '%{criteria}%' OR Designation LIKE '%{criteria}%')" ;
}
if ( request . Status > 0 )
andClause + = SQLParser . MakeSQL ( " AND Status=%n" , request . Status ) ;
if ( request . CheckOwner )
andClause + = SQLParser . MakeSQL ( " AND (CreatedBy=%n OR ViewToAll=1)" , userId ) ;
string sortField = request . SortField switch
{
"userName" = > "UserName" ,
"designation" = > "Designation" ,
"mobileNo" = > "MobileNo" ,
"emailAddress" = > "EmailAddress" ,
"statusDetail" = > "Status" ,
"loginId" = > "LoginId" ,
_ = > "SeqId, LoginId"
} ;
string sortOrder = request . SortOrder switch
{
"desc" = > "DESC" ,
_ = > "ASC" ,
} ;
string commandText = request . Skip + request . PageSize < = 0 ?
SQLParser . MakeSQL ( "SELECT UserId, LoginId, UserName, Designation, MobileNo, EmailAddress, Status, SeqId, IsLocked, CanUseAtnSys, Password,"
+ " COUNT(*) OVER() AS TotalRows FROM Users WHERE UserId!=-9%q ORDER BY %q %q" , andClause , sortField , sortOrder )
: SQLParser . MakeSQL ( "SELECT A.UserId, A.LoginId, A.UserName, A.Designation, A.MobileNo, A.EmailAddress, A.Status, A.SeqId, A.IsLocked,"
+ " A.CanUseAtnSys, A.Password, A.TotalRows FROM(SELECT UserId, LoginId, UserName, Designation, MobileNo, EmailAddress, Status, SeqId,"
+ " IsLocked, CanUseAtnSys, Password, ROW_NUMBER() OVER(ORDER BY %q %q) AS RN, COUNT(*) OVER() AS TotalRows FROM Users WHERE UserId!=-9%q) A"
+ " WHERE A.RN>%n AND A.RN<=%n" , sortField , sortOrder , andClause , request . Skip , request . Skip + request . PageSize ) ;
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
int totalRows = 0 ;
using IDataReader dr = tc . ExecuteReader ( commandText : commandText ) ;
while ( dr . Read ( ) )
{
UserGetResponse item = new ( )
{
UserId = dr . GetInt32 ( 0 ) ,
LoginId = dr . GetString ( 1 ) ,
UserName = dr . GetString ( 2 ) ,
Designation = dr . GetString ( 3 ) ,
MobileNo = dr . GetString ( 4 ) ,
EmailAddress = dr . GetString ( 5 ) ,
Status = ( EnumStatus ) dr . GetInt16 ( 6 ) ,
SeqId = dr . GetInt16 ( 7 ) ,
IsLocked = ! dr . IsDBNull ( 8 ) & & dr . GetInt16 ( 8 ) ! = 0 ,
CanUseAttendanceSystem = ! dr . IsDBNull ( 9 ) & & dr . GetInt16 ( 9 ) ! = 0 ,
} ;
totalRows = dr . GetInt32 ( 11 ) ;
}
dr . Close ( ) ;
response . TotalRows = totalRows ;
tc . End ( ) ;
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="teamSpaceIds"></param>
/// <param name="projectId"></param>
/// <param name="userId"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < UserBasicInfoResponse > GetUsersByTeamSpaceAsync ( string teamSpaceIds , int projectId , int userId )
{
UserBasicInfoResponse response = new ( ) ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
string andClause = string . Empty ;
if ( userId > 0 )
{
andClause = $" AND UserID={userId}" ;
}
else
{
if ( ! string . IsNullOrEmpty ( teamSpaceIds ) )
{
andClause = $" AND UserID IN(SELECT UserId FROM TeamSpaceUsers WHERE TeamSpaceId IN({teamSpaceIds}))" ;
}
if ( projectId > 0 )
{
andClause + = $" AND UserID IN(SELECT UserId FROM TeamSpaceUserProjects WHERE ProjectId={projectId})" ;
}
}
string commandText = $"SELECT UserID, LoginID, UserName, Designation FROM Users WHERE UserID!={User.SuperUser_Id} AND Status=8{andClause} ORDER BY SeqId, UserName" ;
using IDataReader dr = tc . ExecuteReader ( commandText : commandText ) ;
while ( dr . Read ( ) )
{
UserBasicInfo item = new ( )
{
UserId = dr . GetInt32 ( 0 ) ,
LoginId = dr . GetString ( 1 ) ,
UserName = dr . GetString ( 2 ) ,
Designation = dr . GetString ( 3 ) ,
} ;
response . Value . Add ( item ) ;
}
dr . Close ( ) ;
tc . End ( ) ;
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="applyFilter"></param>
/// <param name="teamSpaceIds"></param>
/// <param name="projectId"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < UserBasicInfoResponse > GetUsersBasicAsync ( bool applyFilter , string teamSpaceIds , int projectId )
{
UserBasicInfoResponse response = new ( ) ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
string commandText ;
if ( applyFilter )
{
if ( ! string . IsNullOrEmpty ( teamSpaceIds ) )
{
commandText = $"SELECT UserID, LoginID, UserName, Designation FROM Users WHERE UserID!={User.SuperUser_Id}"
+ $" AND Status=8 AND UserID IN(SELECT UserId FROM TeamSpaceUsers WHERE TeamSpaceId IN({teamSpaceIds}))" ;
}
else
{
commandText = $"SELECT UserID, LoginID, UserName, Designation FROM Users WHERE UserID!={User.SuperUser_Id} AND Status=8" ;
}
if ( projectId > 0 )
{
commandText + = $" AND UserID IN(SELECT UserId FROM UserClients WHERE ProjectID={projectId})" ;
}
}
else
{
commandText = $"SELECT UserID, LoginID, UserName, Designation FROM Users WHERE UserID!={User.SuperUser_Id} AND Status=8" ;
}
commandText + = " ORDER BY SeqId, UserName" ;
using IDataReader dr = tc . ExecuteReader ( commandText : commandText ) ;
while ( dr . Read ( ) )
{
UserBasicInfo item = new ( )
{
UserId = dr . GetInt32 ( 0 ) ,
LoginId = dr . GetString ( 1 ) ,
UserName = dr . GetString ( 2 ) ,
Designation = dr . GetString ( 3 ) ,
} ;
response . Value . Add ( item ) ;
}
dr . Close ( ) ;
tc . End ( ) ;
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="createdBy"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task < UserForceLogoutResponse > GetForceLogoutUsersAsync ( int createdBy )
{
UserForceLogoutResponse response = new ( ) ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
string commandText ;
if ( createdBy = = User . SuperUser_Id )
commandText = $"SELECT UserID, LoginID, UserName FROM Users WHERE UserID!={User.SuperUser_Id} AND Status=8 ORDER BY LoginID" ;
else
commandText = $"SELECT UserID, LoginID, UserName FROM Users WHERE (CreatedBy={createdBy} OR ViewToAll=1) AND Status=8 ORDER BY LoginID" ;
using IDataReader dr = tc . ExecuteReader ( commandText : commandText ) ;
while ( dr . Read ( ) )
{
UserForceLogout item = new ( )
{
UserId = dr . GetInt32 ( 0 ) ,
LoginId = dr . GetString ( 1 ) ,
UserName = dr . GetString ( 2 )
} ;
response . Value . Add ( item ) ;
}
dr . Close ( ) ;
tc . End ( ) ;
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < UserBasicInfoResponse > GetAttendanceUsersAsync ( int userId )
{
UserBasicInfoResponse response = new ( ) ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
string andClause = userId > 0 ? $" AND UserID={userId}" : string . Empty ;
using IDataReader dr = tc . ExecuteReader ( commandText : $"SELECT UserID, LoginID, UserName, Designation FROM Users WHERE EmployeeId IS NOT NULL AND Status=8{andClause} ORDER BY SeqId, UserName" ) ;
while ( dr . Read ( ) )
{
UserBasicInfo item = new ( )
{
UserId = dr . GetInt32 ( 0 ) ,
LoginId = dr . GetString ( 1 ) ,
UserName = dr . GetString ( 2 ) ,
Designation = dr . GetString ( 3 ) ,
} ;
response . Value . Add ( item ) ;
}
dr . Close ( ) ;
tc . End ( ) ;
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="userIds"></param>
/// <param name="ipAddress"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task < bool > ForceLogoutNowAsync ( List < int > userIds , string ipAddress )
{
bool returnValue ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@UserIDs" , pType : SqlDbType . VarChar , pValue : string . Join ( "," , userIds . ToArray ( ) ) , size : 8000 ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.DoForceLogout" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task < UserGetResponse > GetUserAsync ( int userId )
{
UserGetResponse response = new ( ) { ReturnStatus = 200 } ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
using ( IDataReader dr = tc . ExecuteReader ( "SELECT LoginId, UserName, Designation, MobileNo, EmailAddress, IsLocked, Status,"
+ " AccessStatus, NeverExpire, AuthReqAtlogin, AuthMethod, DBOnStartup, DAMultiLogin, EmployeeCode, SeqId, CanUseAtnSys, ViewToAll"
+ " FROM Users WHERE UserId=%n" , userId ) )
{
if ( dr . Read ( ) )
{
response = new UserGetResponse
{
UserId = userId ,
LoginId = dr . GetString ( 0 ) ,
UserName = dr . GetString ( 1 ) ,
Designation = dr . GetString ( 2 ) ,
MobileNo = dr . GetString ( 3 ) ,
EmailAddress = dr . GetString ( 4 ) ,
IsLocked = ! dr . IsDBNull ( 5 ) & & dr . GetInt16 ( 5 ) > 0 ,
Status = ( EnumStatus ) dr . GetInt16 ( 6 ) ,
AccessStatus = ( EnumAccessStatus ) dr . GetInt16 ( 7 ) ,
NeverExpire = ! dr . IsDBNull ( 8 ) & & dr . GetInt16 ( 8 ) ! = 0 ,
AuthRequiredAtLogin = ! dr . IsDBNull ( 9 ) & & dr . GetInt16 ( 9 ) ! = 0 ,
AuthMethod = ( EnumAuthenticationMethod ) dr . GetInt16 ( 10 ) ,
DbOnStartup = ! dr . IsDBNull ( 11 ) & & dr . GetInt16 ( 11 ) ! = 0 ,
DisallowMultiLogin = ! dr . IsDBNull ( 12 ) & & dr . GetInt16 ( 12 ) ! = 0 ,
EmployeeCode = dr . IsDBNull ( 13 ) ? string . Empty : dr . GetString ( 13 ) ,
SeqId = dr . GetInt16 ( 14 ) ,
CanUseAttendanceSystem = ! dr . IsDBNull ( 15 ) & & dr . GetInt16 ( 15 ) ! = 0 ,
ViewToAll = ! dr . IsDBNull ( 16 ) & & dr . GetInt16 ( 16 ) ! = 0 ,
ReturnStatus = 200
} ;
}
dr . Close ( ) ;
}
response . GroupIds = [ ] ;
using ( IDataReader dr = tc . ExecuteReader ( "SELECT GroupId FROM UserGroups WHERE UserID=%n" , userId ) )
{
while ( dr . Read ( ) )
{
response . GroupIds . Add ( dr . GetInt32 ( 0 ) ) ;
}
dr . Close ( ) ;
}
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task < UserProfileResponse > GetUserProfileAsync ( int userId )
{
UserProfileResponse response = new ( ) { ReturnStatus = 200 } ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
int employeeId = 0 ;
using ( IDataReader dr = tc . ExecuteReader ( "SELECT LoginId, UserName, Designation, LastPassChgDate, ExpireDate, EmployeeId FROM Users WHERE UserId=%n" , userId ) )
{
if ( dr . Read ( ) )
{
response = new UserProfileResponse
{
UserId = userId ,
LoginId = dr . GetString ( 0 ) ,
UserName = dr . GetString ( 1 ) ,
Designation = dr . GetString ( 2 ) ,
PwdLastChangedTime = dr . IsDBNull ( 3 ) ? null : dr . GetDateTime ( 3 ) ,
NextPwdDate = dr . IsDBNull ( 4 ) ? null : dr . GetDateTime ( 4 ) ,
ReturnStatus = 200
} ;
employeeId = dr . IsDBNull ( 5 ) ? 0 : dr . GetInt32 ( 5 ) ;
}
dr . Close ( ) ;
}
if ( employeeId > 0 )
{
using IDataReader dr = tc . ExecuteReader ( "SELECT Address, ContactNo FROM Employees WHERE EmployeeId=%n" , employeeId ) ;
if ( dr . Read ( ) )
{
response . Address = dr . GetString ( 0 ) ;
response . ContactNo = dr . GetString ( 1 ) ;
}
dr . Close ( ) ;
}
response . LoginHistories = [ ] ;
using ( IDataReader dr = tc . ExecuteReader ( "SELECT TOP 10 LoginIPAddress, LoginTime, LogoutIPAddress, LogoutTime"
+ " FROM AccessLog WHERE UserID=%n ORDER BY LoginTime DESC" , userId ) )
{
int slNo = 0 ;
while ( dr . Read ( ) )
{
slNo + + ;
LoginHistory item = new ( )
{
SlNo = slNo ,
LoginIp = dr . GetString ( 0 ) ,
LoginTime = dr . GetDateTime ( 1 ) ,
LogoutIp = dr . IsDBNull ( 2 ) ? string . Empty : dr . GetString ( 2 ) ,
LogoutTime = dr . IsDBNull ( 3 ) ? null : dr . GetDateTime ( 3 ) ,
} ;
response . LoginHistories . Add ( item : item ) ;
}
dr . Close ( ) ;
}
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task < MenuResponse > GetUserPermissionsAsync ( int userId )
{
MenuResponse response = new ( ) { Item = new ( ) { Items = [ ] } } ;
MenuItem pi = new ( ) { Label = "User Profile" , Icon = "fa fa-user-md" , RouterLink = string . Empty , Items = [ ] } ;
pi . Items . Add ( new ( ) { Label = "My Profile" , Icon = "fa fa-user" , RouterLink = "/myprofile" } ) ;
pi . Items . Add ( new ( ) { Label = "Change My Password" , Icon = "fa fa-unlock" , RouterLink = "/changemypwd" } ) ;
pi . Items . Add ( new ( ) { Label = "Change My Theme" , Icon = "fa fa-user" , RouterLink = "/changemytheme" } ) ;
pi . Items . Add ( new ( ) { Label = "WhatsApp Message" , Icon = "fa fa-whatsapp" , RouterLink = "/sendwhatsappmsg" } ) ;
pi . Items . Add ( new ( ) { Label = "Access Log" , Icon = "fa fa-list-alt" , RouterLink = "/accesslog" } ) ;
response . Item . Items . Add ( pi ) ;
List < GroupPermission > pmns = [ ] ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
SqlParameter [ ] p = [ SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ] ;
using IDataReader dr = tc . ExecuteReaderSp ( spName : "dbo.GetUserPermissions" , parameterValues : p ) ;
while ( dr . Read ( ) )
{
GroupPermission item = new ( )
{
ModuleId = dr . GetString ( 0 ) ,
AllowSelect = dr . GetInt16 ( 1 ) ! = 0 ,
AllowAdd = dr . GetInt16 ( 2 ) ! = 0 ,
AllowEdit = dr . GetInt16 ( 3 ) ! = 0 ,
AllowDelete = dr . GetInt16 ( 4 ) ! = 0
} ;
pmns . Add ( item ) ;
}
dr . Close ( ) ;
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
#region Making Hierarchy
List < GroupPermission > items = [ ] ;
List < GroupPermission > fullMenu = GlobalFunctions . BuildMenu ( ) ;
IEnumerable < GroupPermission > data = fullMenu . Where ( x = > ( string . IsNullOrEmpty ( x . ParentId ) | | string . IsNullOrWhiteSpace ( x . ParentId ) ) & & x . Visible & & pmns . Where ( y = > y . AllowSelect ) . Select ( z = > z . ModuleId ) . Contains ( x . ModuleId ) ) ;
foreach ( GroupPermission datum in data )
{
MakeHierarchy ( parent : datum , data : fullMenu , pmns : pmns ) ;
}
items . AddRange ( data ) ;
if ( _menuSettings ? . MenuItems ? . Count > 0 )
{
foreach ( GroupPermission src in items )
{
MenuItem dst = src . Copy ( ) ;
dst . Label = _menuSettings . GetItem ( src . ModuleId , src . ModuleName ) . Value ;
response . Item . Items . Add ( dst ) ;
CopyHierarchy ( src : src , dst : dst ) ;
}
}
else
{
foreach ( GroupPermission src in items )
{
MenuItem dst = src . Copy ( ) ;
response . Item . Items . Add ( dst ) ;
CopyHierarchy ( src : src , dst : dst ) ;
}
}
items . Clear ( ) ;
#endregion
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="canViewLeave"></param>
/// <param name="canViewLate"></param>
/// <param name="canViewClientVisit"></param>
/// <param name="canViewHomeOffice"></param>
/// <param name="viewAll"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
/// <summary>
///
/// </summary>
/// <param name="poId"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="id"></param>
/// <param name="documentOf"></param>
/// <param name="orgFileName"></param>
/// <param name="fileName"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task < bool > UploadDocumentAsync ( int userId , int id , int documentOf , string orgFileName , string fileName )
{
bool returnValue = false ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@UserID" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@Id" , pType : SqlDbType . Int , pValue : id ) ,
SqlHelperExtension . CreateInParam ( pName : "@DocumentOf" , pType : SqlDbType . SmallInt , pValue : documentOf ) ,
SqlHelperExtension . CreateInParam ( pName : "@OrgFileName" , pType : SqlDbType . VarChar , pValue : orgFileName , size : 200 ) ,
SqlHelperExtension . CreateInParam ( pName : "@FileName" , pType : SqlDbType . VarChar , pValue : fileName , size : 100 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.UploadDocument" , parameterValues : p ) ;
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="userId"></param>
/// <param name="logId"></param>
/// <param name="attendanceLogout"></param>
/// <param name="loginId"></param>
/// <param name="localIp"></param>
/// <param name="macAddress"></param>
/// <param name="hostName"></param>
/// <param name="logoutRemarks"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < bool > LogoutAsync ( string ipAddress , int userId , int logId , bool attendanceLogout , string loginId , string localIp , string macAddress , string hostName , string logoutRemarks )
{
bool returnValue = false ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p ;
#region Attendance Logout and Valid Ip Address
if ( attendanceLogout & & userId ! = User . SuperUser_Id )
{
string errMsg = string . Empty ;
p =
[
SqlHelperExtension . CreateInParam ( pName : "@UserID" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@LoginId" , pType : SqlDbType . VarChar , pValue : loginId , size : 30 ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : localIp , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@MacAddress" , pType : SqlDbType . VarChar , pValue : macAddress , size : 30 ) ,
SqlHelperExtension . CreateInParam ( pName : "@HostName" , pType : SqlDbType . VarChar , pValue : hostName , size : 100 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LogoutRemarks" , pType : SqlDbType . VarChar , pValue : logoutRemarks , size : 50 ) ,
SqlHelperExtension . CreateOutParam ( pName : "@ErrMsg" , pType : SqlDbType . VarChar , pValue : errMsg , size : 300 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.LogoutFromAttendance" , parameterValues : p ) ;
errMsg = ( p [ 6 ] = = null | | p [ 6 ] . Value = = null | | p [ 6 ] . Value = = DBNull . Value ) ? string . Empty : Convert . ToString ( p [ 6 ] . Value ) ;
if ( ! string . IsNullOrEmpty ( errMsg ) )
{
throw new InvalidOperationException ( errMsg ) ;
}
}
#endregion
//Keep access history
p =
[
SqlHelperExtension . CreateInParam ( pName : "@UserID" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@Status" , pType : SqlDbType . TinyInt , pValue : 3 ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@LogID" , pType : SqlDbType . Int , pValue : logId ) ,
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.CreateAccessLog" , parameterValues : p ) ;
tc . End ( ) ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
/// <summary>
///
/// </summary>
/// <param name="accessType"></param>
/// <param name="loginId"></param>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task < AccessLogResponse > GetAccessLogAsync ( int accessType , string loginId , DateTime startDate , DateTime endDate )
{
AccessLogResponse response = new ( ) { Value = [ ] } ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@AccessType" , pType : SqlDbType . SmallInt , pValue : accessType ) ,
SqlHelperExtension . CreateInParam ( pName : "@LoginID" , pType : SqlDbType . VarChar , pValue : loginId , size : 30 ) ,
SqlHelperExtension . CreateInParam ( pName : "@StartDate" , pType : SqlDbType . DateTime , pValue : startDate ) ,
SqlHelperExtension . CreateInParam ( pName : "@EndDate" , pType : SqlDbType . DateTime , pValue : endDate ) ,
] ;
using IDataReader dr = tc . ExecuteReaderSp ( spName : "dbo.GetAccessLogData" , parameterValues : p ) ;
while ( dr . Read ( ) )
{
AccessLog item = new ( )
{
LoginId = dr . GetString ( 0 ) ,
LoginTime = dr . GetDateTime ( 1 ) ,
LoginIp = dr . GetString ( 2 ) ,
LogoutTime = dr . IsDBNull ( 3 ) ? null : dr . GetDateTime ( 3 ) ,
LogoutIp = dr . IsDBNull ( 4 ) ? null : dr . GetString ( 4 )
} ;
response . Value . Add ( item ) ;
}
dr . Close ( ) ;
tc . End ( ) ;
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
/// <summary>
///
/// </summary>
/// <param name="maxAuthLimit"></param>
/// <param name="userId"></param>
/// <param name="ipAddress"></param>
/// <param name="savedBy"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task < bool > SaveAuthorizeLimitAsync ( decimal maxAuthLimit , int userId , string ipAddress , string savedBy )
{
bool returnValue ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode , true ) ;
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@MaxAuthLimit" , pType : SqlDbType . Decimal , pValue : maxAuthLimit ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateInParam ( pName : "@IpAddress" , pType : SqlDbType . VarChar , pValue : ipAddress , size : 20 ) ,
SqlHelperExtension . CreateInParam ( pName : "@SavedBy" , pType : SqlDbType . VarChar , pValue : savedBy , size : 30 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.SaveAuthorizeLimit" , parameterValues : p ) ;
tc . End ( ) ;
returnValue = true ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return returnValue ;
}
public async Task < UserAuthorizeLimitResponse > GetAuthorizeLimitAsync ( int userId )
{
UserAuthorizeLimitResponse response = new ( ) { Value = 0 } ;
try
{
using TransactionContext tc = await TransactionContext . BeginAsync ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
using IDataReader dr = tc . ExecuteReader ( commandText : "SELECT LoginId, MaxAuthLimit FROM dbo.Users WHERE UserId=%n" , args : userId ) ;
if ( dr . Read ( ) )
{
response . LoginId = dr . GetString ( 0 ) ;
response . Value = dr . IsDBNull ( 1 ) ? 0 : dr . GetDecimal ( 1 ) ;
}
dr . Close ( ) ;
tc . End ( ) ;
response . ReturnStatus = 200 ;
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
return response ;
}
#region Private functions
/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="loginId"></param>
/// <param name="enfStgPwd"></param>
/// <param name="minLen"></param>
/// <param name="maxLen"></param>
/// <param name="reservedWords"></param>
/// <exception cref="Exception"></exception>
private void ReadPwdParams ( int userId , string loginId , out bool enfStgPwd , out short minLen , out short maxLen , out string reservedWords )
{
try
{
enfStgPwd = false ;
minLen = maxLen = 0 ;
reservedWords = string . Empty ;
using TransactionContext tc = TransactionContext . Begin ( _settings . DefaultConnection . ConnectionNode ) ;
try
{
bool loginIdCantPwd = false ;
using ( IDataReader dr = tc . ExecuteReader ( "SELECT EnfStgPwd, PwdMinLen, PwdMaxLen, PwdRsvdWords, LoginIdCantPwd FROM ThisSystem" ) )
{
if ( dr . Read ( ) )
{
enfStgPwd = Convert . ToBoolean ( dr . GetInt16 ( 0 ) ) ;
minLen = dr . GetInt16 ( 1 ) ;
maxLen = dr . GetInt16 ( 2 ) ;
reservedWords = dr . IsDBNull ( 3 ) ? string . Empty : dr . GetString ( 3 ) ;
loginIdCantPwd = ! dr . IsDBNull ( 4 ) & & dr . GetInt16 ( 4 ) ! = 0 ;
}
dr . Close ( ) ;
}
if ( string . IsNullOrEmpty ( loginId ) & & loginIdCantPwd & & userId > 0 )
{
using IDataReader dr = tc . ExecuteReader ( "SELECT LoginId FROM Users WHERE UserId=%n" , userId ) ;
if ( dr . Read ( ) )
{
loginId = dr . IsDBNull ( 0 ) ? string . Empty : dr . GetString ( 0 ) ;
}
dr . Close ( ) ;
}
tc . End ( ) ;
if ( loginIdCantPwd & & ! string . IsNullOrEmpty ( loginId ) )
{
reservedWords = string . IsNullOrEmpty ( reservedWords ) ? loginId : $"{reservedWords},{loginId}" ;
}
}
catch ( Exception ie )
{
tc ? . HandleError ( ) ;
throw DBCustomError . GenerateCustomError ( ie ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
/// <summary>
///
/// </summary>
/// <param name="password"></param>
/// <param name="minLen"></param>
/// <param name="maxLen"></param>
/// <param name="enfStgPwd"></param>
/// <param name="reservedWords"></param>
/// <param name="daLastPwds"></param>
/// <param name="pwdHistories"></param>
/// <param name="actPwdHistories"></param>
/// <exception cref="Exception"></exception>
private void CheckPasswordHistory ( string password , short minLen , short maxLen , bool enfStgPwd , string reservedWords , int daLastPwds , Queue < string > pwdHistories , List < string > actPwdHistories )
{
try
{
ValidatePwdPolicies ( password : password , minLen : minLen , maxLen : maxLen , enfStgPwd : enfStgPwd , reservedWords : reservedWords ) ;
password = EncryptPassword ( password : password ) ;
if ( daLastPwds > 0 & & actPwdHistories . Contains ( password ) )
throw new InvalidOperationException ( $"You cannot use this password, because it was used in last {daLastPwds} passwords." ) ;
if ( pwdHistories . Count > = 5 )
pwdHistories . Dequeue ( ) ;
pwdHistories . Enqueue ( password ) ;
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
/// <summary>
/// Validates a password against specified policies, including length constraints, reserved words, and strong password requirements.
/// </summary>
/// <remarks>This method performs validation based on the provided policies and throws an exception if the password does not comply.
/// Ensure that all parameters are correctly configured before calling this method.</remarks>
/// <param name="password">The password to validate. Cannot be null or empty.</param>
/// <param name="minLen">The minimum allowed length for the password. Must be greater than 0.</param>
/// <param name="maxLen">The maximum allowed length for the password. Must be greater than 0.</param>
/// <param name="enfStgPwd">A value indicating whether strong password enforcement is enabled. If <see langword="true"/>, the password
/// must contain at least one uppercase letter, one lowercase letter, one number, and one special character (!, @, #, $, %, ^, &, *, ?).</param>
/// <param name="reservedWords">A comma-separated list of reserved words that cannot be included in the password. Cannot be null or empty.</param>
/// <exception cref="InvalidOperationException">Thrown if the password violates any of the specified policies, including: <list type="bullet">
/// <item><description>Contains a reserved word.</description></item> <item><description>Does not meet the minimum length requirement.</description></item> <item>
/// <description>Exceeds the maximum length requirement.</description></item> <item><description>Fails strong password enforcement when <paramref
/// name="enfStgPwd"/> is <see langword="true"/>.</description></item> </list></exception>
private static void ValidatePwdPolicies ( string password , short minLen , short maxLen , bool enfStgPwd , string reservedWords )
{
try
{
if ( ! string . IsNullOrEmpty ( password ) & & ! string . IsNullOrEmpty ( reservedWords ) )
{
List < string > words = [ . . reservedWords . Split ( ',' ) ] ;
foreach ( string word in words )
{
if ( password . Contains ( word , StringComparison . InvariantCultureIgnoreCase ) )
throw new InvalidOperationException ( $"[{word}] can not be used in password." ) ;
}
}
if ( minLen > 0 & & password . Length < minLen )
throw new InvalidOperationException ( $"Minimum length of Password is {minLen}" ) ;
if ( maxLen > 0 & & password . Length > maxLen )
throw new InvalidOperationException ( $"Maximum length of Password is {maxLen}" ) ;
if ( enfStgPwd & & ! Global . StringFunctions . IsStrongPassword ( password ) )
throw new InvalidOperationException ( "Must have Upper & Lower case character, a Number and a Special character (!, @, #, $, %, ^, &, *, ?)." ) ;
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
/// <summary>
///
/// </summary>
/// <param name="password"></param>
/// <returns></returns>
private string EncryptPassword ( string password )
{
try
{
string pwdSecretKey = GlobalFunctions . ConvertFromBase64String ( _settings . PwdSecretKey ) ;
return Global . CipherFunctions . EncryptByAES ( privateKey : pwdSecretKey , publicKey : pwdSecretKey , data : password ) ;
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
/// <summary>
///
/// </summary>
/// <param name="tc"></param>
/// <param name="authValue"></param>
/// <param name="validMinutes"></param>
/// <param name="userId"></param>
private static void SetAuthValue ( TransactionContext tc , string authValue , int validMinutes , int userId )
{
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@AuthValue" , pType : SqlDbType . VarChar , pValue : authValue , size : 10 ) ,
SqlHelperExtension . CreateInParam ( pName : "@ValidMinutes" , pType : SqlDbType . Int , pValue : validMinutes ) ,
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.SetAuthValue" , parameterValues : p ) ;
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
/// <summary>
///
/// </summary>
/// <param name="tc"></param>
/// <param name="userId"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
private static int GetPendingNotifCount ( TransactionContext tc , int userId )
{
try
{
SqlParameter [ ] p =
[
SqlHelperExtension . CreateInParam ( pName : "@UserId" , pType : SqlDbType . Int , pValue : userId ) ,
SqlHelperExtension . CreateOutParam ( pName : "@NotifCount" , pType : SqlDbType . Int , pValue : 0 )
] ;
_ = tc . ExecuteNonQuerySp ( spName : "dbo.GetPendingAuthCountByUser" , parameterValues : p ) ;
return ( p [ 1 ] . Value ! = null & & p [ 1 ] . Value ! = DBNull . Value ) ? Convert . ToInt32 ( p [ 1 ] . Value ) : 0 ;
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
/// <summary>
///
/// </summary>
/// <param name="parent"></param>
/// <param name="data"></param>
/// <param name="pmns"></param>
private static void MakeHierarchy ( GroupPermission parent , List < GroupPermission > data , List < GroupPermission > pmns )
{
try
{
IEnumerable < GroupPermission > children = data . Where ( x = > x . ParentId = = parent . ModuleId & & x . Visible & & pmns . Where ( y = > y . AllowSelect ) . Select ( z = > z . ModuleId ) . Contains ( x . ModuleId ) ) ;
parent . Children . AddRange ( children ) ;
foreach ( GroupPermission child in parent . Children )
{
MakeHierarchy ( parent : child , data : data , pmns : pmns ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
/// <summary>
///
/// </summary>
/// <param name="src"></param>
/// <param name="dst"></param>
private void CopyHierarchy ( GroupPermission src , MenuItem dst )
{
try
{
if ( src . Children ? . Count > 0 )
dst . Items = [ ] ;
foreach ( GroupPermission srcChild in src . Children )
{
MenuItem dstChild = srcChild . Copy ( ) ;
dstChild . Label = _menuSettings ? . GetItem ( dstChild . ModuleId , dstChild . Label ) . Value ;
dst . Items . Add ( dstChild ) ;
CopyHierarchy ( src : srcChild , dst : dstChild ) ;
}
}
catch ( Exception e )
{
throw new InvalidOperationException ( e . Message , e ) ;
}
}
2026-06-14 12:46:29 +06:00
public Task < bool > SaveAttributesAsync ( int userId , int clientType , string ipAddress , int attributeSetBy , List < string > ukIds )
{
throw new NotImplementedException ( ) ;
}
#endregion
}
}