2644 lines
120 KiB
C#
2644 lines
120 KiB
C#
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.Services.Contracts.Auth;
|
|
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
|
|
|
namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
public Task<bool> SaveAttributesAsync(int userId, int clientType, string ipAddress, int attributeSetBy, List<string> ukIds)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |