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; using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations; namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems { public class UserService(IOptions settings, IOptions menuSettings) : IUserService { private readonly AppSettings _settings = settings?.Value; private readonly MenuSettings _menuSettings = menuSettings?.Value; /// /// /// /// /// /// /// /// public async Task 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 IntegrationLoginAsync(IntegrationLoginRequest 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; #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; } /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// public async Task 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 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; } /// /// /// /// /// /// /// public async Task 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 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; } /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// /// public async Task ChangePasswordAsync(int userId, string oldPassword, string newPassword, string ipAddress, int changedBy) { bool returnValue = false; try { bool loginIdCantPwd = false; DateTime? lastPassChgDate = null; List actPwdHistories = []; Queue 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; } /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// //public async Task 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; //} /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// public async Task ForceLogoutNowAsync(List 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; } /// /// /// /// /// public async Task 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; } /// /// /// /// /// public async Task 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; } /// /// /// /// /// public async Task 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 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 items = []; List fullMenu = GlobalFunctions.BuildMenu(); IEnumerable 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; } /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// /// public async Task 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; } /// /// /// /// /// /// /// /// /// public async Task 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 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 /// /// /// /// /// /// /// /// /// /// 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); } } /// /// /// /// /// /// /// /// /// /// /// /// private void CheckPasswordHistory(string password, short minLen, short maxLen, bool enfStgPwd, string reservedWords, int daLastPwds, Queue pwdHistories, List 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); } } /// /// Validates a password against specified policies, including length constraints, reserved words, and strong password requirements. /// /// 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. /// The password to validate. Cannot be null or empty. /// The minimum allowed length for the password. Must be greater than 0. /// The maximum allowed length for the password. Must be greater than 0. /// A value indicating whether strong password enforcement is enabled. If , the password /// must contain at least one uppercase letter, one lowercase letter, one number, and one special character (!, @, #, $, %, ^, &, *, ?). /// A comma-separated list of reserved words that cannot be included in the password. Cannot be null or empty. /// Thrown if the password violates any of the specified policies, including: /// Contains a reserved word. Does not meet the minimum length requirement. /// Exceeds the maximum length requirement. Fails strong password enforcement when is . private static void ValidatePwdPolicies(string password, short minLen, short maxLen, bool enfStgPwd, string reservedWords) { try { if (!string.IsNullOrEmpty(password) && !string.IsNullOrEmpty(reservedWords)) { List 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); } } /// /// /// /// /// 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); } } /// /// /// /// /// /// /// 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); } } /// /// /// /// /// /// /// 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); } } /// /// /// /// /// /// private static void MakeHierarchy(GroupPermission parent, List data, List pmns) { try { IEnumerable 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); } } /// /// /// /// /// 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); } } public Task SaveAttributesAsync(int userId, int clientType, string ipAddress, int attributeSetBy, List ukIds) { throw new NotImplementedException(); } #endregion } internal class UserSearchResponse { } }