diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Global/AppSettings.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Global/AppSettings.cs
index 7769ee2..c58dd84 100644
--- a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Global/AppSettings.cs
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Global/AppSettings.cs
@@ -53,11 +53,12 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Global
public string JwtAudience { get; set; }
public bool JwtValidateIssuer { get; set; }
public bool JwtValidateAudience { get; set; }
-
- ///
- /// Folder management
- ///
- public string UploadFolder { get; set; }
+ public int RefreshTokenDuration { get; set; }
+
+ ///
+ /// Folder management
+ ///
+ public string UploadFolder { get; set; }
public string ProfileImageFolder { get; set; }
public string ReportFolder { get; set; }
public string FileProcessFolder { get; set; }
@@ -85,6 +86,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Global
public string EmailSenderIp { get; set; }
public string EmailSenderId { get; set; }
+
private string _emailSenderPwd;
public string EmailSenderPwd
{
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Objects/Systems/User.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Objects/Systems/User.cs
index 615923c..2155064 100644
--- a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Objects/Systems/User.cs
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Objects/Systems/User.cs
@@ -7,8 +7,9 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public const int SuperUser_Id = -9;
public const string SuperUser_LoginId = "superuser";
- public int Id { get; set; }
+ public int UserId { get; set; }
public string LoginId { get; set; }
+ public string Password { get; set; }
public DateTime? LogoutTime { get; set; }
public string UserName { get; set; }
public EnumStatus Status { get; set; }
@@ -25,7 +26,10 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public string SchemeName { get; set; }
public string MenuLayout { get; set; }
public bool IsLocked { get; set; }
- }
+ public EnumLoginStatus LoginStatus { get; set; }
+ public DateTime? NextLoginTime { get; set; }
+
+ }
public class LoginHistory
{
@@ -38,13 +42,15 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public class AccessLog
{
+ public int AccessLogId { get; set; }
+ public int UserId { get; set; }
public string LoginId { get; set; }
public DateTime LoginTime { get; set; }
public string LoginIp { get; set; }
public DateTime? LogoutTime { get; set; }
public string LogoutIp { get; set; }
- public string LoginStatus { get; set; }
- }
+ public EnumLoginStatus LoginStatus { get; set; }
+ }
public class UserForceLogout
{
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Requests/Integrations/IntegrationAuthRequest.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Requests/Integrations/IntegrationAuthRequest.cs
new file mode 100644
index 0000000..06d73c9
--- /dev/null
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Requests/Integrations/IntegrationAuthRequest.cs
@@ -0,0 +1,38 @@
+using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+
+namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
+
+public class IntegrstionLoginRequest
+{
+ [Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 3, ErrorMessage = "Login Id must be between 4 and 30 characters.")]
+ public string LoginId { get; set; }
+
+ [Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 5, ErrorMessage = "Password must be between 1 and 30 characters.")]
+ public string Password { get; set; }
+}
+
+public class IntegrationRefreshTokenRequest
+{
+ public string RefreshToken { get; set; }
+}
+
+public class InsertRefreshTokenRequest : RefreshToken
+{
+ public string RefreshToken { get; set; }
+}
+
+public class RevokedRefreshTokenRequest
+{
+ public string RefreshToken { get; set; }
+}
+
+public class GenerateRefreshTokenRequest
+{
+ public int UserId { get; set; }
+ public string IpAddress { get; set; }
+}
\ No newline at end of file
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Requests/Systems/UserRequest.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Requests/Systems/UserRequest.cs
index 303cd6a..29958b3 100644
--- a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Requests/Systems/UserRequest.cs
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Requests/Systems/UserRequest.cs
@@ -3,219 +3,218 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
-namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems
+namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
+
+public class FindAccountRequest
{
- public class FindAccountRequest
- {
- [Required, NotNull, StringLength(maximumLength: 200, MinimumLength = 4, ErrorMessage = "Login Id or Email address or Mobile number must be between 4 and 100 characters.")]
- public string AccountId { get; set; }
- }
-
- public class LoginRequest
- {
- [Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 4, ErrorMessage = "Login Id must be between 4 and 30 characters.")]
- public string LoginId { get; set; }
-
- [Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 1, ErrorMessage = "Password must be between 1 and 30 characters.")]
- public string Password { get; set; }
-
- public string AppId { get; set; }
-
- [Required, NotNull, StringLength(maximumLength: 8, MinimumLength = 5, ErrorMessage = "Version must be 5 and 8 digits (Example: 0.0.0 or 99.99.99)")]
- public string AppVersion { get; set; }
-
- public bool AttendanceLogin { get; set; }
- public string HostName { get; set; }
- public string IpAddress { get; set; }
- public string MacAddress { get; set; }
- public string LoginRemarks { get; set; }
- }
-
- public class OtpValidationRequest
- {
- public int UserId { get; set; }
-
- public EnumAuthenticationMethod AuthMethod { get; set; }
-
- [Required, NotNull, StringLength(6, MinimumLength = 6, ErrorMessage = "Otp must be 6 digit number.")]
- public string OtpCode { get; set; }
- }
-
- public class ByUserIdRequest
- {
- public int UserId { get; set; }
- }
-
- public class SendPasswordRequest
- {
- [Required, NotNull, StringLength(maximumLength: 300, MinimumLength = 1, ErrorMessage = "User Id is required.")]
- public string UserId { get; set; }
- public string MobileNo { get; set; }
- public string EmailAddress { get; set; }
- }
-
- public class UserUnlockRequest : ByUserIdRequest
- {
- [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Login Id must be between 1 and 30 characters.")]
- public string LoginId { get; set; }
- }
-
- public class ResetPasswordRequest : ByUserIdRequest
- {
- [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Password must be between 1 and 30 characters.")]
- public string Password { get; set; }
-
- [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Confirm Password must be between 1 and 30 characters.")]
- public string ConfirmPassword { get; set; }
- }
-
- public class PasswordChangeRequest : ResetPasswordRequest
- {
- [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Old Password must be between 1 and 30 characters.")]
- public string OldPassword { get; set; }
- }
-
- public class LogoutRequest
- {
- public int LogId { get; set; }
- public bool AttendanceLogout { get; set; }
- public string IpAddress { get; set; }
- public string MacAddress { get; set; }
- public string HostName { get; set; }
- public string LogoutRemarks { get; set; }
- }
-
- public class UserThemeRequest
- {
- [Required, NotNull, StringLength(15, MinimumLength = 1, ErrorMessage = "Menu Layout must be between 1 to 15 characters.")]
- public string MenuLayout { get; set; }
-
- [Required, NotNull, StringLength(15, MinimumLength = 1, ErrorMessage = "Theme Name must be between 1 to 15 characters.")]
- public string ThemeName { get; set; }
-
- [Required, NotNull, StringLength(10, MinimumLength = 1, ErrorMessage = "Scheme Name must be between 1 to 10 characters.")]
- public string SchemeName { get; set; }
- }
-
- public class UserRequestBase
- {
- [Required, NotNull, StringLength(30, MinimumLength = 3, ErrorMessage = "Login Id must be between 3 to 30 characters.")]
- public string LoginId { get; set; }
-
- [Required, NotNull, StringLength(75, MinimumLength = 3, ErrorMessage = "User Name must be between 3 to 75 characters.")]
- public string UserName { get; set; }
-
- [Required, NotNull, StringLength(50, MinimumLength = 0, ErrorMessage = "Designation must be between 0 to 50 characters.")]
- public string Designation { get; set; }
-
- [StringLength(15, MinimumLength = 11, ErrorMessage = "Mobile number must be 11 characters.")]
- [RegularExpression(@"^[01]{2}[123456789]{1}[0-9]{8}$", ErrorMessage = "Mobile number is invalid.")]
- public string MobileNo { get; set; }
-
- [Required, NotNull, StringLength(100, MinimumLength = 5, ErrorMessage = "Email address must be between 5 to 100 characters.")]
- [RegularExpression(@"^(([a-zA-Z0-9_\-\.]+)\@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)(\s*;\s*|\s*$))*$", ErrorMessage = "Email address is invalid.")]
- public string EmailAddress { get; set; } = string.Empty;
- public bool AuthReqAtlogin { get; set; }
- public bool NeverExpire { get; set; }
- public bool DbOnStartup { get; set; }
- public bool DisallowMultiLogin { get; set; }
- public EnumStatus Status { get; set; }
- public short SeqId { get; set; }
- public bool ViewToAll { get; set; }
- public bool CanUseAttendanceSystem { get; set; }
- public EnumAuthenticationMethod AuthMethod { get; set; }
- public EnumAccessStatus AccessStatus { get; set; }
- public List GroupIds { get; set; }
- }
-
- public class UserRequest : UserRequestBase
- {
- [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Select valid user (1 to 99999999).")]
- public int UserId { get; set; }
-
- public string AuthKey { get; set; }
- }
-
- public class NewUserRequest : UserRequestBase
- {
- public int? EmployeeId { get; set; }
- public string EmployeeCode { get; set; }
-
- [Required, NotNull, StringLength(30, MinimumLength = 1, ErrorMessage = "User Name must be between 1 to 30 characters.")]
- public string Password { get; set; }
- }
-
- public class UserSearchRequest : ValueStatusAndPageAndSortSearchRequest
- {
- public bool CheckOwner { get; set; }
- }
-
- public class ForceUserLogoutRequest
- {
- public List UserIds { get; set; }
- }
-
- public class ByUserAttributesRequest : ByUserIdRequest
- {
- [Required, Range(minimum: 1, maximum: 3, ConvertValueInInvariantCulture = true, ErrorMessage = "Client type must be 1 to 3")]
- public int ClientType { get; set; }
- }
-
- public class UpdateMyInfoRequest
- {
- [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Employee Id must be 1 to 2147483647")]
- public int EmployeeId { get; set; }
-
- [NotNull, StringLength(120, MinimumLength = 0, ErrorMessage = "Address be between 0 to 120 characters.")]
- public string Address { get; set; }
-
- public string ContactNo { get; set; }
- }
-
- public class UserAttributesRequest
- {
- [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Select valid user")]
- public int UserId { get; set; }
-
- [Required, Range(minimum: 1, maximum: 3, ConvertValueInInvariantCulture = true, ErrorMessage = "Client type must be 1 to 3")]
- public int ClientType { get; set; }
- public List UkIds { get; set; }
- }
- public class AccessLogSearchRequest
- {
- public int AccessType { get; set; }
- public string LoginId { get; set; }
- public DateTime StartDate { get; set; }
- public DateTime EndDate { get; set; }
- }
-
- public class ByTeamSpaceAndBasicUserRequest
- {
- public int TeamSpaceId { get; set; }
- public int ProjectId { get; set; }
- }
-
- public class BasicUserByTeamSpaceRequest : ByTeamSpaceAndBasicUserRequest
- {
- public int UserId { get; set; }
- }
-
- public class BasicUserSearchRequest : BasicUserByTeamSpaceRequest
- {
- public bool ApplyFilter { get; set; }
- }
-
- public class UserLimitAuthorizeRequest
- {
- [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Select valid user (1 to 99999999).")]
- public int UserId { get; set; }
-
- public decimal MaxAuthorizeAmount { get; set; }
- }
-
- public class PayslipRequest
- {
- [Required, NotNull]
- public DateTime YearMonth { get; set; }
- }
+ [Required, NotNull, StringLength(maximumLength: 200, MinimumLength = 4, ErrorMessage = "Login Id or Email address or Mobile number must be between 4 and 100 characters.")]
+ public string AccountId { get; set; }
+}
+
+public class LoginRequest
+{
+ [Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 4, ErrorMessage = "Login Id must be between 4 and 30 characters.")]
+ public string LoginId { get; set; }
+
+ [Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 1, ErrorMessage = "Password must be between 1 and 30 characters.")]
+ public string Password { get; set; }
+
+ public string AppId { get; set; }
+
+ [Required, NotNull, StringLength(maximumLength: 8, MinimumLength = 5, ErrorMessage = "Version must be 5 and 8 digits (Example: 0.0.0 or 99.99.99)")]
+ public string AppVersion { get; set; }
+
+ public bool AttendanceLogin { get; set; }
+ public string HostName { get; set; }
+ public string IpAddress { get; set; }
+ public string MacAddress { get; set; }
+ public string LoginRemarks { get; set; }
+}
+
+public class OtpValidationRequest
+{
+ public int UserId { get; set; }
+
+ public EnumAuthenticationMethod AuthMethod { get; set; }
+
+ [Required, NotNull, StringLength(6, MinimumLength = 6, ErrorMessage = "Otp must be 6 digit number.")]
+ public string OtpCode { get; set; }
+}
+
+public class ByUserIdRequest
+{
+ public int UserId { get; set; }
+}
+
+public class SendPasswordRequest
+{
+ [Required, NotNull, StringLength(maximumLength: 300, MinimumLength = 1, ErrorMessage = "User Id is required.")]
+ public string UserId { get; set; }
+ public string MobileNo { get; set; }
+ public string EmailAddress { get; set; }
+}
+
+public class UserUnlockRequest : ByUserIdRequest
+{
+ [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Login Id must be between 1 and 30 characters.")]
+ public string LoginId { get; set; }
+}
+
+public class ResetPasswordRequest : ByUserIdRequest
+{
+ [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Password must be between 1 and 30 characters.")]
+ public string Password { get; set; }
+
+ [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Confirm Password must be between 1 and 30 characters.")]
+ public string ConfirmPassword { get; set; }
+}
+
+public class PasswordChangeRequest : ResetPasswordRequest
+{
+ [Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Old Password must be between 1 and 30 characters.")]
+ public string OldPassword { get; set; }
+}
+
+public class LogoutRequest
+{
+ public int LogId { get; set; }
+ public bool AttendanceLogout { get; set; }
+ public string IpAddress { get; set; }
+ public string MacAddress { get; set; }
+ public string HostName { get; set; }
+ public string LogoutRemarks { get; set; }
+}
+
+public class UserThemeRequest
+{
+ [Required, NotNull, StringLength(15, MinimumLength = 1, ErrorMessage = "Menu Layout must be between 1 to 15 characters.")]
+ public string MenuLayout { get; set; }
+
+ [Required, NotNull, StringLength(15, MinimumLength = 1, ErrorMessage = "Theme Name must be between 1 to 15 characters.")]
+ public string ThemeName { get; set; }
+
+ [Required, NotNull, StringLength(10, MinimumLength = 1, ErrorMessage = "Scheme Name must be between 1 to 10 characters.")]
+ public string SchemeName { get; set; }
+}
+
+public class UserRequestBase
+{
+ [Required, NotNull, StringLength(30, MinimumLength = 3, ErrorMessage = "Login Id must be between 3 to 30 characters.")]
+ public string LoginId { get; set; }
+
+ [Required, NotNull, StringLength(75, MinimumLength = 3, ErrorMessage = "User Name must be between 3 to 75 characters.")]
+ public string UserName { get; set; }
+
+ [Required, NotNull, StringLength(50, MinimumLength = 0, ErrorMessage = "Designation must be between 0 to 50 characters.")]
+ public string Designation { get; set; }
+
+ [StringLength(15, MinimumLength = 11, ErrorMessage = "Mobile number must be 11 characters.")]
+ [RegularExpression(@"^[01]{2}[123456789]{1}[0-9]{8}$", ErrorMessage = "Mobile number is invalid.")]
+ public string MobileNo { get; set; }
+
+ [Required, NotNull, StringLength(100, MinimumLength = 5, ErrorMessage = "Email address must be between 5 to 100 characters.")]
+ [RegularExpression(@"^(([a-zA-Z0-9_\-\.]+)\@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)(\s*;\s*|\s*$))*$", ErrorMessage = "Email address is invalid.")]
+ public string EmailAddress { get; set; } = string.Empty;
+ public bool AuthReqAtlogin { get; set; }
+ public bool NeverExpire { get; set; }
+ public bool DbOnStartup { get; set; }
+ public bool DisallowMultiLogin { get; set; }
+ public EnumStatus Status { get; set; }
+ public short SeqId { get; set; }
+ public bool ViewToAll { get; set; }
+ public bool CanUseAttendanceSystem { get; set; }
+ public EnumAuthenticationMethod AuthMethod { get; set; }
+ public EnumAccessStatus AccessStatus { get; set; }
+ public List GroupIds { get; set; }
+}
+
+public class UserRequest : UserRequestBase
+{
+ [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Select valid user (1 to 99999999).")]
+ public int UserId { get; set; }
+
+ public string AuthKey { get; set; }
+}
+
+public class NewUserRequest : UserRequestBase
+{
+ public int? EmployeeId { get; set; }
+ public string EmployeeCode { get; set; }
+
+ [Required, NotNull, StringLength(30, MinimumLength = 1, ErrorMessage = "User Name must be between 1 to 30 characters.")]
+ public string Password { get; set; }
+}
+
+public class UserSearchRequest : ValueStatusAndPageAndSortSearchRequest
+{
+ public bool CheckOwner { get; set; }
+}
+
+public class ForceUserLogoutRequest
+{
+ public List UserIds { get; set; }
+}
+
+public class ByUserAttributesRequest : ByUserIdRequest
+{
+ [Required, Range(minimum: 1, maximum: 3, ConvertValueInInvariantCulture = true, ErrorMessage = "Client type must be 1 to 3")]
+ public int ClientType { get; set; }
+}
+
+public class UpdateMyInfoRequest
+{
+ [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Employee Id must be 1 to 2147483647")]
+ public int EmployeeId { get; set; }
+
+ [NotNull, StringLength(120, MinimumLength = 0, ErrorMessage = "Address be between 0 to 120 characters.")]
+ public string Address { get; set; }
+
+ public string ContactNo { get; set; }
+}
+
+public class UserAttributesRequest
+{
+ [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Select valid user")]
+ public int UserId { get; set; }
+
+ [Required, Range(minimum: 1, maximum: 3, ConvertValueInInvariantCulture = true, ErrorMessage = "Client type must be 1 to 3")]
+ public int ClientType { get; set; }
+ public List UkIds { get; set; }
+}
+public class AccessLogSearchRequest
+{
+ public int AccessType { get; set; }
+ public string LoginId { get; set; }
+ public DateTime StartDate { get; set; }
+ public DateTime EndDate { get; set; }
+}
+
+public class ByTeamSpaceAndBasicUserRequest
+{
+ public int TeamSpaceId { get; set; }
+ public int ProjectId { get; set; }
+}
+
+public class BasicUserByTeamSpaceRequest : ByTeamSpaceAndBasicUserRequest
+{
+ public int UserId { get; set; }
+}
+
+public class BasicUserSearchRequest : BasicUserByTeamSpaceRequest
+{
+ public bool ApplyFilter { get; set; }
+}
+
+public class UserLimitAuthorizeRequest
+{
+ [Required, Range(minimum: 1, maximum: int.MaxValue, ConvertValueInInvariantCulture = true, ErrorMessage = "Select valid user (1 to 99999999).")]
+ public int UserId { get; set; }
+
+ public decimal MaxAuthorizeAmount { get; set; }
+}
+
+public class PayslipRequest
+{
+ [Required, NotNull]
+ public DateTime YearMonth { get; set; }
}
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Models/Responses/Integrations/IntegrationAuthResponse.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Responses/Integrations/IntegrationAuthResponse.cs
new file mode 100644
index 0000000..357301c
--- /dev/null
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Models/Responses/Integrations/IntegrationAuthResponse.cs
@@ -0,0 +1,30 @@
+using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
+
+public class IntegrationLoginResponse
+{
+ public string LoginId { get; set; }
+ public string AccessToken { get; set; } = string.Empty;
+ public string RefreshToken { get; set; } = string.Empty;
+ public DateTime AccessTokenExpiry { get; set; }
+}
+
+public class RefreshTokenResponse
+{
+ public string UserId { get; set; }
+ public string TokenHash { get; set; }
+ public string IpAddress { get; set; }
+ public DateTime ExpiredAt { get; set; }
+ public DateTime? RevokedAt { get; set; }
+ public string DeviceInfo { get; set; }
+}
+
+public class GenerateRefreshTokenResponse
+{
+ public string RefreshToken { get; set; }
+ public DateTime ExpireTime { get; set; }
+}
\ No newline at end of file
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Services/Contracts/Auth/IRefreshTokenService.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Contracts/Auth/IRefreshTokenService.cs
new file mode 100644
index 0000000..c83520f
--- /dev/null
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Contracts/Auth/IRefreshTokenService.cs
@@ -0,0 +1,14 @@
+using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
+using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
+using System.Threading.Tasks;
+
+namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
+
+public interface IRefreshTokenService
+{
+ Task GetByTokenHashAsync(string tokenHash);
+ Task AddAsync(InsertRefreshTokenRequest refreshToken);
+ Task RevokeAsync(RevokedRefreshTokenRequest token);
+ Task RevokeAllForUserAsync(int userId);
+ Task GenerateRefreshToken(GenerateRefreshTokenRequest request);
+}
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Services/Contracts/Systems/IUserService.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Contracts/Systems/IUserService.cs
index cb15bc5..197e0de 100644
--- a/Api/OnlineSalesAutoCrop.CoreAPI.Services/Contracts/Systems/IUserService.cs
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Contracts/Systems/IUserService.cs
@@ -34,7 +34,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems
Task FindAccountAsync(string accountId);
Task GetAuthorizeLimitAsync(int userId);
Task GetAttributesAsync(int userId, int clientType);
- Task GetDashboardData(int userId, bool canViewLeave, bool canViewLate, bool canViewClientVisit, bool canViewHomeOffice, bool viewAll);
Task LoadNotificationCountAsync(int userId);
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Services/Services/Auth/RefreshTokenService.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Services/Auth/RefreshTokenService.cs
new file mode 100644
index 0000000..0aabbdb
--- /dev/null
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Services/Auth/RefreshTokenService.cs
@@ -0,0 +1,226 @@
+using DocumentFormat.OpenXml.Spreadsheet;
+using DocumentFormat.OpenXml.VariantTypes;
+using Ease.NetCore.DataAccess;
+using Ease.NetCore.DataAccess.SQL;
+using Microsoft.Data.SqlClient;
+using Microsoft.Extensions.Options;
+using MySqlX.XDevAPI.Common;
+using OnlineSalesAutoCrop.CoreAPI.Models.Global;
+using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
+using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
+using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
+using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
+using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
+using System;
+using System.Data;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Auth;
+
+public class RefreshTokenService : IRefreshTokenService
+{
+ private readonly AppSettings _settings;
+ public RefreshTokenService(IOptions settings)
+ {
+ _settings = settings.Value;
+ }
+
+
+ public async Task AddAsync(InsertRefreshTokenRequest refreshToken)
+ {
+ bool returnValue = false;
+ try
+ {
+ using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
+ await AddAsync(tc, refreshToken);
+
+ tc.End();
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(e.Message, e);
+ }
+
+ return returnValue;
+ }
+
+ private async Task AddAsync( TransactionContext tc, InsertRefreshTokenRequest refreshToken)
+ {
+ bool returnValue = false;
+
+ try
+ {
+ SqlParameter[] p =
+ [
+ SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.VarChar, pValue: refreshToken.UserId),
+ SqlHelperExtension.CreateInParam(pName: "@TokenHash", pType: SqlDbType.VarChar, pValue: refreshToken.TokenHash),
+ SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: refreshToken.IpAddress),
+ SqlHelperExtension.CreateInParam(pName: "@CreatedAt", pType: SqlDbType.DateTime, pValue: DateTime.Now),
+ SqlHelperExtension.CreateInParam(pName: "@ExpiredAt", pType: SqlDbType.DateTime, pValue: DateTime.Now.AddMinutes(_settings.RefreshTokenDuration)),
+ ];
+ _ = await tc.ExecuteNonQuerySpAsync(spName: "dbo.InsertRefreshToken", parameterValues: p);
+
+ returnValue = true;
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(e.Message, e);
+ }
+
+ return returnValue;
+ }
+
+
+ public async Task GetByTokenHashAsync(string tokenHash)
+ {
+ RefreshTokenResponse response = new();
+ try
+ {
+ using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
+ try
+ {
+ SqlParameter[] p =
+ [
+ SqlHelperExtension.CreateInParam(pName: "@TokenHash", pType: SqlDbType.VarChar, pValue: tokenHash, size: 10)
+ ];
+
+ using (IDataReader dr =await tc.ExecuteReaderSpAsync("dbo.GetRefreshTokenByTokenHash", parameterValues: p))
+ {
+ if (dr.Read())
+ {
+ response.UserId = dr.GetString(0);
+ response.TokenHash = dr.GetString(1);
+ response.IpAddress = dr.GetString(2);
+ response.ExpiredAt = dr.GetDateTime(3);
+ response.RevokedAt = dr.IsDBNull(4) ? null: dr.GetDateTime(4);
+ }
+ 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 RevokeAllForUserAsync(int userId)
+ {
+ 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)
+ ];
+ _ = await tc.ExecuteNonQuerySpAsync(spName: "dbo.RevokedAllRefreshToken", parameterValues: p);
+
+ returnValue = true;
+
+ 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 RevokeAsync(RevokedRefreshTokenRequest token)
+ {
+ bool returnValue = false;
+ try
+ {
+ using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
+ try
+ {
+ SqlParameter[] p =
+ [
+ SqlHelperExtension.CreateInParam(pName: "@RefreshToken", pType: SqlDbType.NVarChar, pValue: token.RefreshToken)
+ ];
+ _ = await tc.ExecuteNonQuerySpAsync(spName: "dbo.RevokedAllRefreshToken", parameterValues: p);
+
+ returnValue = true;
+
+ 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 GenerateRefreshToken()
+ {
+ throw new NotImplementedException();
+ }
+
+
+ // ----- private helpers -----
+
+ private async Task IssueTokensAsync(TransactionContext tc, User user, string deviceInfo, string ipAddress)
+ {
+ var refreshToken = new InsertRefreshTokenRequest
+ {
+ UserId = user.UserId,
+ TokenHash = HashToken(GenerateRowToken()),
+ IpAddress = ipAddress,
+ CreatedAt = DateTime.UtcNow,
+ ExpiresAt = DateTime.UtcNow.AddDays(_settings.RefreshTokenDuration)
+ };
+
+ await AddAsync(tc,refreshToken);
+
+ return new LoginResponse
+ {
+ AccessToken = accessToken,
+ RefreshToken = rawRefreshToken,
+ AccessTokenExpiry = DateTime.UtcNow.AddMinutes(_settings.AccessTokenExpiryMinutes)
+ };
+ }
+
+ private static string HashToken(string token)
+ {
+ var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(token));
+ return Convert.ToBase64String(bytes);
+ }
+
+ private string GenerateRowToken()
+ {
+ var bytes = new byte[64];
+ using var rng = RandomNumberGenerator.Create();
+ rng.GetBytes(bytes);
+ return Convert.ToBase64String(bytes);
+ }
+}
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI.Services/Services/Systems/UserService.cs b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Services/Systems/UserService.cs
index bf38091..b9b000b 100644
--- a/Api/OnlineSalesAutoCrop.CoreAPI.Services/Services/Systems/UserService.cs
+++ b/Api/OnlineSalesAutoCrop.CoreAPI.Services/Services/Systems/UserService.cs
@@ -17,2595 +17,2622 @@ 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 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 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())
- {
- UserSearch 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,
- };
- item.AuthId = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{item.LoginId}~{dr.GetString(10)}"));
- totalRows = dr.GetInt32(11);
-
- response.Value.Add(item);
- }
- 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 GetDashboardData(int userId, bool canViewLeave, bool canViewLate, bool canViewClientVisit, bool canViewHomeOffice, bool viewAll)
- {
- DashboardDataResponse response = new()
- {
- GroupData = [],
- ReturnStatus = 200,
- Group1Data = new() { Items = [] },
- Group2Data = new() { Items = [] },
- Group3Data = new() { Items = [] },
- Group4Data = new() { Items = [] },
- };
-
- 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.GetDashBoard", parameterValues: p);
-
- #region Dashboard1 (Project, PO, Invoice, payment)
-
- while (dr.Read())
- {
- DashboardItem item = new()
- {
- DivStyleCss = dr.GetString(0),
- Title = dr.GetString(1),
- TitleCss = dr.GetString(2),
- Value = $"{dr.GetInt32(3)}",
- ValueCss = dr.GetString(4),
- Id = dr.GetInt32(5),
- Href = dr.GetString(6),
- };
- response.GroupData.Add(item);
- }
- dr.NextResult();
-
- #endregion
-
- #region Dashboard2 (Sales, Acounting, Purchase to Pay, Fixed Assests)
-
- while (dr.Read())
- {
- int groupId = dr.GetInt16(0);
- string groupName = dr.GetString(1);
- Dashboard2Item item = new()
- {
- Title = dr.GetString(2),
- Value = dr.GetDecimal(3),
- TitleStyle = dr.GetString(4),
- ValueStyle = dr.GetString(5),
- ValueFormat = dr.GetString(6),
- };
- if (groupId == 1)
- {
- response.Group1Data.GroupName = groupName;
- response.Group1Data.Items.Add(item);
- }
- else if (groupId == 2)
- {
- response.Group2Data.GroupName = groupName;
- response.Group2Data.Items.Add(item);
- }
- else if (groupId == 3)
- {
- response.Group3Data.GroupName = groupName;
- response.Group3Data.Items.Add(item);
- }
- else if (groupId == 4)
- {
- response.Group4Data.GroupName = groupName;
- response.Group4Data.Items.Add(item);
- }
- }
- dr.NextResult();
-
- #endregion
-
- #region Dashboard1 (Today's Attendance)
-
- StringBuilder sb = new();
- while (dr.Read())
- {
- if (sb.Length > 0)
- sb.Append(" | ");
-
- if (dr.GetInt16(0) == 4)
- sb.Append(canViewHomeOffice && viewAll ? $"Home Office: {dr.GetInt32(1)}" : $"Home Office: {dr.GetInt32(1)}");
- else if (dr.GetInt16(0) == 3)
- sb.Append(canViewClientVisit && viewAll ? $"Client Visit: {dr.GetInt32(1)}" : $"Client Visit: {dr.GetInt32(1)}");
- else if (dr.GetInt16(0) == 2)
- sb.Append(canViewLate && viewAll ? $"Late: {dr.GetInt32(1)}" : $"Late: {dr.GetInt32(1)}");
- else
- sb.Append(canViewLeave && viewAll ? $"Leave: {dr.GetInt32(1)}" : $"Leave: {dr.GetInt32(1)}");
- }
- dr.Close();
-
- if (sb.Length > 0)
- {
- int rmndr = (response.GroupData.Count + 1) % 2;
- DashboardItem item = new()
- {
- Id = 999,
- Href = "",
- Value = sb.ToString(),
- Title = "No-shows Today",
- TitleCss = "db-style title",
- DivStyleCss = rmndr == 1 ? "db-style default" : "db-style alternate",
- ValueCss = rmndr == 1 ? "default-detail attendance" : "alternate-detail attendance"
- };
- response.GroupData.Add(item);
- }
-
- #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 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),
- LoginStatus = dr.GetString(5),
- };
-
- 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 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(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;
+ }
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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)
{
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI/Controllers/IntegretionApi/AuthController.cs b/Api/OnlineSalesAutoCrop.CoreAPI/Controllers/IntegretionApi/AuthController.cs
new file mode 100644
index 0000000..b3f75d2
--- /dev/null
+++ b/Api/OnlineSalesAutoCrop.CoreAPI/Controllers/IntegretionApi/AuthController.cs
@@ -0,0 +1,2042 @@
+using Asp.Versioning;
+using OnlineSalesAutoCrop.CoreAPI.Configurations;
+using OnlineSalesAutoCrop.CoreAPI.Models;
+using OnlineSalesAutoCrop.CoreAPI.Models.Global;
+using OnlineSalesAutoCrop.CoreAPI.Models.Objects;
+using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
+using OnlineSalesAutoCrop.CoreAPI.Models.Requests;
+using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups;
+using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
+using OnlineSalesAutoCrop.CoreAPI.Models.Responses;
+using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
+using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
+using OnlineSalesAutoCrop.CoreAPI.SignalRHub;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.SignalR;
+using Microsoft.Extensions.Logging;
+using Microsoft.IdentityModel.Tokens;
+using System;
+using System.Collections.Generic;
+using System.DirectoryServices;
+using System.IdentityModel.Tokens.Jwt;
+using System.IO;
+using System.Linq;
+using System.Runtime.Versioning;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Options;
+using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
+
+namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [Authorize]
+ [ApiController]
+ [ApiVersion("1.0")]
+ [ValidateAntiForgeryToken]
+ [Route("api/v{version:apiVersion}/users")]
+
+ public class AuthController(IUserService service, IOptions appSettings, IEaseCache cache, ILogger logger, IRefreshTokenService refreshTokenService) : ControllerBase
+ {
+ private readonly ILogger _logger = logger;
+ private readonly IEaseCache _cache = cache;
+ private readonly IUserService _service = service;
+ private readonly IRefreshTokenService _refreshTokenService = refreshTokenService;
+ private readonly AppSettings _appSettings = appSettings?.Value;
+ private readonly DateTimeOffset _options = Helper.CreateEaseCacheOptions();
+
+ ///
+ /// Login using your credential data retrieve from SqlServer
+ ///
+ ///
+ ///
+ ///
+ /// If login successful ValidUser: true
+ /// If login successful Return ValidUser: true and UserName: not empty
+ [HttpPost("login")]
+ [AllowAnonymous]
+ [IgnoreAntiforgeryToken]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(LoginResponse))]
+ public async Task Login([FromBody] LoginRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ LoginResponse response = new();
+ if (string.IsNullOrEmpty(request.LoginId))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Login ID is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.Password))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Password is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.AppVersion))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Version is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ string ipAddress = string.Empty;
+ try
+ {
+ #region Decrypt LoginID
+
+ string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
+ request.LoginId = Helper.DecryptData(secret: cipherSecretKey, data: request.LoginId);
+ request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password);
+ request.AppId = Helper.DecryptData(secret: cipherSecretKey, data: request.AppId);
+ request.HostName = Helper.DecryptData(secret: cipherSecretKey, data: request.HostName);
+ request.IpAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.IpAddress);
+ request.MacAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.MacAddress);
+ if (request.LoginId.Equals("*Key/Data Error*") || request.Password.Equals("*Key/Data Error*") || request.AppId.Equals("*Key/Data Error*"))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Key or Data Error...!");
+ return BadRequest(response);
+ }
+
+ #endregion
+
+ bool checkPwd = true;
+ #region If AD (Active Directory) authentication is enabled do validate
+
+ if (_appSettings.ADConfig.Enabled)
+ {
+ checkPwd = false;
+ #pragma warning disable CA1416 // Validate platform compatibility
+ int adLoginStatus = GetADLoginStatus(loginId: request.LoginId, password: request.Password);
+ #pragma warning restore CA1416 // Validate platform compatibility
+ if (adLoginStatus != 1)
+ {
+ response.LoginStatus = EnumLoginStatus.Unsuccessful;
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ if (adLoginStatus == 2)
+ response.ReturnMessage.Add("Active Directory User is DISABLED.");
+ else if (adLoginStatus == 3)
+ response.ReturnMessage.Add("Active Directory User's Password has EXPIRED.");
+ else
+ response.ReturnMessage.Add("Active Directory User/Password is INVALID.");
+
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+ }
+
+ #endregion
+
+ ipAddress = Request.HttpContext.GetIpAddress();
+ User user = await _service.LoginAsync(request: request, ipAddress: ipAddress, checkPwd: checkPwd);
+
+ if (user == null || user.UserId == 0)
+ {
+ response.LoginStatus = EnumLoginStatus.Error;
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add(checkPwd ? "Login ID/Password is invalid." : "You are not Authorized to login into the System");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (user.LoginStatus == EnumLoginStatus.Unsuccessful)
+ {
+ string usm = string.Empty;
+ if (user != null && !string.IsNullOrEmpty(user.UnsuccessfulMsg))
+ usm = $" ({user.UnsuccessfulMsg})";
+
+ response.LoginStatus = user.LoginStatus;
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add(checkPwd ? $"Login ID/Password is invalid{usm}." : "You are not Authorized to login into the System");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+
+ if (user.IsLocked)
+ {
+ response.LoginStatus = user.LoginStatus;
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ if (!user.NextLoginTime.HasValue)
+ response.ReturnMessage.Add("You are locked, please contact Head office.");
+ else
+ response.ReturnMessage.Add($"You can Login after {user.NextLoginTime:dd-MMM-yyyy H:mm:ss}");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (user.Status != EnumStatus.Authorized)
+ {
+ response.LoginStatus = user.LoginStatus;
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not Authorized to Login into the System, Please contact with System Administrator.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ response.ValidUser = user.LoginStatus == EnumLoginStatus.Success;
+ if (!response.ValidUser)
+ {
+ response.LoginStatus = user.LoginStatus;
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("Unknown error.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ response.Map(user);
+ response.ValidUser = true;
+ response.ReturnStatus = StatusCodes.Status200OK;
+ string pwdSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.PwdSecretKey);
+ string userPwd = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(privateKey: pwdSecretKey, publicKey: pwdSecretKey, data: request.Password);
+ byte[] key = Encoding.ASCII.GetBytes(_appSettings.JwtCryptoKey);
+ JwtSecurityTokenHandler tokenHandler = new();
+ var tokenDescriptor = new SecurityTokenDescriptor
+ {
+ Subject = new ClaimsIdentity(
+ [
+ Helper.CreateClaim("LoginId", user.LoginId),
+ Helper.CreateClaim("Email", user.EmailAddress),
+ Helper.CreateClaim("AuthKey", $"{user.AuthKey}"),
+ Helper.CreateClaim("HashKey", Guid.NewGuid().ToString())
+ ]),
+ Expires = DateTime.UtcNow.AddHours(12),
+ SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
+ };
+
+ SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
+ string userToken = tokenHandler.WriteToken(token);
+ string refreshToken = _refreshTokenService.GenerateRefreshToken();
+
+
+
+ //If token length is greater than or equal to 4096 (4KB) then return error
+ //because cookie can not store more than 4KB data and we are storing this token in cookie for authentication
+ if (userToken.Length >= 4096) //4Kb
+ {
+ response.LoginStatus = user.LoginStatus;
+ response.ReturnStatus = StatusCodes.Status431RequestHeaderFieldsTooLarge;
+ response.ReturnMessage.Add("Authentication Token is too large for cookie.");
+ return StatusCode(StatusCodes.Status431RequestHeaderFieldsTooLarge, response);
+ }
+
+ response.Expires = tokenDescriptor.Expires;
+ response.AuthenticationToken = userToken;
+ response.LoginTime = $"{DateTime.Now:dd-MM-yy H:mm:ss}";
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ string msg = $"{request?.LoginId}~{ipAddress}";
+ _logger.LogError(exception: ex, message: msg);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("loadMenu")]
+ public async Task LoadMenu([FromBody] ByUserIdRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ try
+ {
+ MenuResponse response = await _service.GetUserPermissionsAsync(userId: request.UserId);
+ return Ok(response.Item);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ return StatusCode(StatusCodes.Status500InternalServerError, (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [IgnoreAntiforgeryToken]
+ [HttpPost("validateOtp")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task ValidateOtp([FromBody] OtpValidationRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { Value = false, ReturnStatus = StatusCodes.Status200OK };
+ if (string.IsNullOrEmpty(request.OtpCode) || request.OtpCode.Length != 6)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Otp must be 6 digit.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ if (request.AuthMethod == EnumAuthenticationMethod.ThirdPartyAuthenticator)
+ {
+ string secretKey = HttpContext.User.GetClaimValue("AuthKey");
+ if (string.IsNullOrEmpty(secretKey))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Authentication key is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ TOtpService otp = new();
+ DateTime now = DateTime.UtcNow;
+ response.Value = otp.ValidateTwoFactorPIN(secretKey, request.OtpCode, now);
+ }
+ else
+ {
+ response.Value = await _service.ValidateAuthValueAsync(request.OtpCode, request.UserId);
+ }
+
+ if (!response.Value)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("This is not a valid Otp.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+ else
+ {
+ return Ok(response);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status406NotAcceptable;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("addUser")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task AddUser([FromBody] NewUserRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_1");
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not authorize to Add User.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ int createdBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.AddUserAsync(user: request, ipAddress: ipAddress, createdBy: createdBy);
+ response.ReturnMessage.Add("User added successfully...");
+
+ //Cache
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("editUser")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task EditUser([FromBody] UserRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_2");
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not authorize to Update User.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (request.AuthMethod == EnumAuthenticationMethod.ThirdPartyAuthenticator && (string.IsNullOrEmpty(request.AuthKey) || string.IsNullOrWhiteSpace(request.AuthKey) || request.AuthKey.Length <= 0))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("For third party Authenticator, Authentication key is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ int modifiedBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.EditUserAsync(user: request, ipAddress: ipAddress, modifiedBy: modifiedBy);
+ response.ReturnMessage.Add("User edited successfully...");
+
+ //Cache
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("deleteUser")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task DeleteUser([FromBody] ByUserIdRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_3");
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not authorize to Delete User.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ int deletedBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.DeleteUserAsync(userId: request.UserId, deletedBy: deletedBy);
+ response.ReturnMessage.Add("User deleted successfully...");
+
+ //Cache
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("unlockUser")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task UnlockUser([FromBody] UserUnlockRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_2");
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not authorize to Unlock User.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ int unlockedBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.UnlockUserAsync(userId: request.UserId, loginId: request.LoginId, unlockedBy: unlockedBy);
+ response.ReturnMessage.Add("User Unlocked successfully...");
+
+ //Cache
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("resetPassword")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task ResetPassword([FromBody] ResetPasswordRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ if (request.UserId == 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("User is not valid.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.Password) || string.IsNullOrWhiteSpace(request.Password))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.ConfirmPassword) || string.IsNullOrWhiteSpace(request.ConfirmPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Confirm Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ #region Decrypt Password
+
+ string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
+ request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password);
+ request.ConfirmPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.ConfirmPassword);
+
+ #endregion
+
+ if (!request.Password.Equals(request.ConfirmPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("New password and confirm password are not same.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ bool permitted = await HttpContext.IsPermitted("ELIT.1.2.3_2");
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not authorize to Reset Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ int changedBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.ResetPasswordAsync(userId: request.UserId, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: changedBy);
+ await _hub.Clients.All.NotifySubscriber(userId: request.UserId, msgType: 1, itemId: 0, ipAddress: ipAddress);
+ response.ReturnMessage.Add("Password Reset successfully, User must change password at next Login.");
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [IgnoreAntiforgeryToken]
+ [HttpPost("changePassword")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task ChangePassword([FromBody] PasswordChangeRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ if (request.UserId == 0)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("Your not a valid user.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.OldPassword) || string.IsNullOrWhiteSpace(request.OldPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Old Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.Password) || string.IsNullOrWhiteSpace(request.Password))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.ConfirmPassword) || string.IsNullOrWhiteSpace(request.ConfirmPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Confirm Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ #region Decrypt Password
+
+ string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
+ request.OldPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.OldPassword);
+ request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password);
+ request.ConfirmPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.ConfirmPassword);
+
+ #endregion
+
+ if (!request.Password.Equals(request.ConfirmPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("New password and confirm password are not same.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ int changedBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.ChangePasswordAsync(userId: request.UserId, oldPassword: request.OldPassword, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: changedBy);
+ await _hub.Clients.All.NotifySubscriber(userId: request.UserId, msgType: 1, itemId: 0, ipAddress: ipAddress);
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("updateMyPassword")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task UpdateMyPassword([FromBody] PasswordChangeRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ if (string.IsNullOrEmpty(request.OldPassword) || string.IsNullOrWhiteSpace(request.OldPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Old Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.Password) || string.IsNullOrWhiteSpace(request.Password))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.ConfirmPassword) || string.IsNullOrWhiteSpace(request.ConfirmPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Invalid parameter value Confirm Password.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ #region Decrypt Password
+
+ string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
+ request.OldPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.OldPassword);
+ request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password);
+ request.ConfirmPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.ConfirmPassword);
+
+ #endregion
+
+ if (!request.Password.Equals(request.ConfirmPassword))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("New password and confirm password are not same.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.ChangePasswordAsync(userId: userId, oldPassword: request.OldPassword, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: userId);
+ await _hub.Clients.All.NotifySubscriber(userId: userId, msgType: 1, itemId: 0, ipAddress: ipAddress);
+ response.ReturnMessage.Add("Password changed successfully.");
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("updateMyTheme")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task UpdateMyTheme([FromBody] UserThemeRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.UpdateMyThemeAsync(userId: userId, menuLayout: request.MenuLayout, themeName: request.ThemeName, schemeName: request.SchemeName);
+ response.ReturnMessage.Add("Your theme set successfully. Need re-login to see the effect.");
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("updateMyInfo")]
+ [AllowAnonymous, IgnoreAntiforgeryToken]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task UpdateMyInfo([FromBody] UpdateMyInfoRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ if (request.EmployeeId < 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("System allow to update only Your Information.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ int modifiedBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.UpdateMyInfoAsync(address: request.Address, contactNo: request.ContactNo, modifiedBy: modifiedBy, emplyeeId: request.EmployeeId);
+ response.ReturnMessage.Add("Your Information updated successfully.");
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getAttributes")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserAttributesResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserAttributesResponse))]
+ public async Task GetAttributes([FromBody] ByUserAttributesRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserAttributesResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ string key = "UserAttributes";
+ string key2 = $"{request.UserId}~{request.ClientType}";
+ if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
+ {
+ response = await _service.GetAttributesAsync(userId: request.UserId, clientType: request.ClientType);
+
+ //Cache
+ _ = _cache.Set(key: key, key2: key2, value: response, options: _options);
+ }
+ response.ReturnStatus = StatusCodes.Status200OK;
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("saveAttributes")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task SaveAttributes([FromBody] UserAttributesRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ if (request.UkIds == null || request.UkIds.Count <= 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no data to save.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ string msg, key;
+ if (request.ClientType == 2)
+ {
+ key = "ELIT.1.5.12_2";
+ msg = "Supplier(s) to user";
+ }
+ else
+ {
+ key = "ELIT.1.5.11_2";
+ msg = "Project(s) to user";
+ }
+
+ bool permitted = await HttpContext.IsPermitted(key);
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add($"You are not authorize to Assign {msg}.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ int attributeSetBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.SaveAttributesAsync(userId: request.UserId, clientType: request.ClientType, ipAddress: ipAddress, attributeSetBy: attributeSetBy, ukIds: request.UkIds);
+ response.ReturnMessage.Add($"{msg} Assigned successfully...");
+
+ //Cache
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("deleteAttributes")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task DeleteAttributes([FromBody] ByUserAttributesRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ string msg, key;
+ if (request.ClientType == 2)
+ {
+ key = "ELIT.1.5.12_3";
+ msg = "Supplier(s) from user";
+ }
+ else
+ {
+ key = "ELIT.1.5.11_3";
+ msg = "Project(s) from user";
+ }
+
+ bool permitted = await HttpContext.IsPermitted(key);
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add($"You are not authorize to Unassign {msg}.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ int deletedBy = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.DeleteAttributesAsync(userId: request.UserId, clientType: request.ClientType, deletedBy: deletedBy);
+ response.ReturnMessage.Add($"{msg} Unassigned successfully...");
+
+ //Cache
+ _cache.Clear("User");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ /// Returns users according to search criteria.
+ ///
+ ///
+ /// top 50 users
+ ///
+ /// Top 50 users
+ /// If the item is null.
+ [ValidateSession]
+ [HttpPost("getUsers")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))]
+ public async Task GetUsers([FromBody] UserSearchRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id;
+
+ string key = "Users";
+ string key2 = $"{request.Criteria}~{request.Status}~{request.SortField}~{request.SortOrder}~{request.Skip}~{request.PageSize}~{request.CheckOwner}~{userId}";
+ if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
+ {
+ response = await _service.GetUsersAsync(request: request, userId: userId);
+ _ = _cache.Set(key: key, key2: key2, value: response, options: _options);
+ }
+
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getUsersBasic")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserBasicInfoResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserBasicInfoResponse))]
+ public async Task GetUsersBasic([FromBody] BasicUserSearchRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserBasicInfoResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ string teamSpaceIds = request.TeamSpaceId > 0 ? $"{request.TeamSpaceId}" : HttpContext.User.GetClaimValue("TeamSpaceIds");
+ response = await _service.GetUsersBasicAsync(applyFilter: request.ApplyFilter, teamSpaceIds: teamSpaceIds, projectId: request.ProjectId);
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getUsersByTeamSpace")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserBasicInfoResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserBasicInfoResponse))]
+ public async Task GetUsersByTeamSpace([FromBody] BasicUserByTeamSpaceRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserBasicInfoResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ string teamSpaceIds = request.TeamSpaceId > 0 ? $"{request.TeamSpaceId}" : HttpContext.User.GetClaimValue("TeamSpaceIds");
+ response = await _service.GetUsersByTeamSpaceAsync(teamSpaceIds: teamSpaceIds, projectId: request.ProjectId, userId: request.UserId);
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getAttendanceUsers")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserBasicInfoResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserBasicInfoResponse))]
+ public async Task GetAttendanceUsers([FromBody] ByUserIdRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserBasicInfoResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ response = await _service.GetAttendanceUsersAsync(userId: request.UserId);
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getUsersForForceLogout")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserForceLogoutResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserForceLogoutResponse))]
+ public async Task GetForceLogoutUsers([FromBody] NoContentRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserForceLogoutResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ response = await _service.GetForceLogoutUsersAsync(createdBy: userId);
+
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("forceLogoutNow")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(BooleanResponse))]
+ public async Task ForceLogoutNow([FromBody] ForceUserLogoutRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ if (request.UserIds == null || request.UserIds.Count <= 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Parameter value is null/no User was selected.");
+ return BadRequest(response);
+ }
+
+ bool permitted = await HttpContext.IsPermitted("ELIT.1.2.4_2");
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not authorize to Do Force Logout.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ response.Value = await _service.ForceLogoutNowAsync(userIds: request.UserIds, ipAddress: ipAddress);
+ foreach (int userId in request.UserIds)
+ {
+ await _hub.Clients.All.NotifySubscriber(userId: userId, msgType: 1, itemId: 0, ipAddress: ipAddress);
+ }
+ response.ReturnMessage.Add("Process completed successfully...");
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getUser")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserGetResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserGetResponse))]
+ public async Task GetUser([FromBody] ByUserIdRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserGetResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ string key = "User";
+ string key2 = $"{request.UserId}";
+ if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
+ {
+ response = await _service.GetUserAsync(userId: request.UserId);
+ _ = _cache.Set(key: key, key2: key2, value: response, options: _options);
+ }
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getCurrentUser")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserGetResponse))]
+ public async Task GetCurrentUser([FromBody] NoContentRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserGetResponse response;
+ try
+ {
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+
+ string key = "UserCurrent";
+ string key2 = $"{userId}";
+ if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
+ {
+ response = await _service.GetUserAsync(userId: userId);
+ response.ReturnStatus = StatusCodes.Status200OK;
+ _ = _cache.Set(key: key, key2: key2, value: response, options: _options);
+ }
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response = new UserGetResponse() { ReturnStatus = StatusCodes.Status500InternalServerError };
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getMyProfile")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserProfileResponse))]
+ public async Task GetMyProfile([FromBody] NoContentRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserProfileResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ response = await _service.GetUserProfileAsync(userId: userId);
+ response.HasPayslipPath = !string.IsNullOrEmpty(_appSettings.PayslipPath);
+ response.HasAIApiKey = !string.IsNullOrEmpty(_appSettings.ApiKeyOpenAI) || !string.IsNullOrEmpty(_appSettings.ApiKeyGoogle);
+ response.ReturnStatus = StatusCodes.Status200OK;
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getMyPayslip")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StringResponse))]
+ public IActionResult GetMyPayslip([FromBody] PayslipRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ StringResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ if (string.IsNullOrEmpty(_appSettings.PayslipPath))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Payslip path is not in the system.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ string employeeId = HttpContext.User.GetClaimValue("EmployeeId");
+ if (string.IsNullOrEmpty(employeeId))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("You are not a valid Employee to view payslip.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string path = $"{employeeId}_{request.YearMonth:yyyy}_{request.YearMonth:MM}.pdf";
+ path = Path.Combine(_appSettings.PayslipPath, path);
+ if (System.IO.File.Exists(path))
+ {
+ response.Value = Convert.ToBase64String(System.IO.File.ReadAllBytes(path: path));
+ return Ok(response);
+ }
+ else
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add($"Payslip does not exists for the Month: {request.YearMonth:MMMM, yyyy}");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getDashboardData")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(DashboardDataResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(DashboardDataResponse))]
+ public async Task GetDashboardData([FromBody] NoContentRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ DashboardDataResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ bool viewAll = await HttpContext.IsPermitted("ELIT.8.2.5_2");
+ bool canViewLate = await HttpContext.IsPermitted("ELIT.8.2.2");
+ bool canViewLeave = await HttpContext.IsPermitted("ELIT.8.2.1");
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ bool canViewHomeOffice = await HttpContext.IsPermitted("ELIT.8.2.4");
+ bool canViewClientVisit = await HttpContext.IsPermitted("ELIT.8.2.3");
+
+ response = await _service.GetDashboardData(userId: userId, canViewLeave: canViewLeave, canViewLate: canViewLate,
+ canViewClientVisit: canViewClientVisit, canViewHomeOffice: canViewHomeOffice, viewAll: viewAll);
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("sendQrCodeViaEmail")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public IActionResult SendQrCodeViaEmail([FromForm] QRCodeUploadRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ if (string.IsNullOrEmpty(request.EmailAddress))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no email address to send mail.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.FileName))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no image to send to send mail.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (request.FileData.Length <= 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no image to send to send mail.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ Result result = ImageFileValidator.Validate(request.FileData);
+ if (!result.Acceptable)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("This is not a valid image file.");
+ return BadRequest(response);
+ }
+
+ var fileSpec = Path.Combine(_appSettings.UploadFolder, request.FileName);
+ if (System.IO.File.Exists(fileSpec))
+ System.IO.File.Delete(fileSpec);
+
+ using (var stream = new FileStream(fileSpec, FileMode.Create))
+ {
+ request.FileData.CopyTo(stream);
+ }
+
+ bool sent = MailHelper.SendMailMessage(settings: _appSettings, to: [request.EmailAddress],
+ cc: null, bcc: null, attachments: [fileSpec], embeddedImages: null, isHtmlBody: false,
+ priority: System.Net.Mail.MailPriority.High, subject: "QR Code", messageBody: "Scan image");
+
+ if (sent)
+ {
+ if (System.IO.File.Exists(fileSpec))
+ System.IO.File.Delete(fileSpec);
+
+ response.Value = sent;
+ response.ReturnMessage.Add($"Successfully mail sent to {request.EmailAddress}");
+ return Ok(response);
+ }
+ else
+ {
+ response.Value = sent;
+ response.ReturnMessage.Add($"Cannot send mail to {request.EmailAddress}");
+ return StatusCode(StatusCodes.Status422UnprocessableEntity, response);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("uploadProfileImage")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public IActionResult UploadProfileImage([FromForm] FileUploadRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ if (string.IsNullOrEmpty(request.FileName))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no Image to set Profile image.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (request.FileData.Length <= 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no image to set Profile image.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ Result result = ImageFileValidator.Validate(request.FileData);
+ if (!result.Acceptable)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("This is not a valid image file.");
+ return BadRequest(response);
+ }
+
+ long maxSz = 20 * 1024;
+ if (request.FileData.Length > maxSz)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Maximum size allowed is 20 Kb");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ var fileSpec = Path.Combine(_appSettings.ProfileImageFolder, request.FileName);
+ if (System.IO.File.Exists(fileSpec))
+ System.IO.File.Delete(fileSpec);
+
+ using (var stream = new FileStream(fileSpec, FileMode.Create))
+ {
+ request.FileData.CopyTo(stream);
+ }
+ response.Value = true;
+ response.ReturnMessage.Add("Refresh page to view your profile image.");
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("uploadDocument")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task UploadDocument([FromForm] UploadDocumentRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ if (string.IsNullOrEmpty(request.FileName))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no valid file to process.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (request.FileData.Length <= 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no valid data to process.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ string fileName, fileSpec;
+ if (request.DocumentOf == 6)
+ {
+ string[] allowedExtensions = [".xlsx", ".xls"];
+ string fileExtension = Path.GetExtension(request.FileName).ToLowerInvariant();
+ if (!allowedExtensions.Contains(fileExtension))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Only excel file is allowed to process.");
+ return BadRequest(response);
+ }
+
+ if (fileExtension.EndsWith(".xls"))
+ {
+ Result result = ExcelFileValidator.Validate(request.FileData);
+ if (!result.Acceptable)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("This is not a valid Excel file.");
+ return BadRequest(response);
+ }
+ }
+ else
+ {
+ Result result = ExcelxFileValidator.Validate(request.FileData);
+ if (!result.Acceptable)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("This is not a valid Excel file.");
+ return BadRequest(response);
+ }
+ }
+
+ fileName = request.FileName;
+ fileSpec = Path.Combine(_appSettings.UploadFolder, fileName);
+ if (System.IO.File.Exists(fileSpec))
+ System.IO.File.Delete(fileSpec);
+ }
+ else if (request.DocumentOf == 2)
+ {
+ if (!request.FileName.ToLower().EndsWith(".csv"))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Only csv file is allowed to process.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ fileName = request.FileName;
+ fileSpec = Path.Combine(_appSettings.UploadFolder, fileName);
+ if (System.IO.File.Exists(fileSpec))
+ System.IO.File.Delete(fileSpec);
+ }
+ else
+ {
+ if (!request.FileName.ToLower().EndsWith(".pdf"))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Only pdf file is allowed to Process.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ long maxSz = 10 * 1024 * 1024;
+ if (request.FileData.Length > maxSz)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Maximum allowable size is 10 MB");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ fileName = $"{request.Id}_{request.DocumentOf}.pdf";
+ fileSpec = Path.Combine(_appSettings.UploadFolder, fileName);
+ if (System.IO.File.Exists(fileSpec))
+ System.IO.File.Delete(fileSpec);
+ }
+
+ using (var stream = new FileStream(fileSpec, FileMode.Create))
+ {
+ request.FileData.CopyTo(stream);
+ }
+
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ response.Value = await _service.UploadDocumentAsync(userId: userId, id: request.Id, documentOf: request.DocumentOf, orgFileName: request.FileName, fileName: fileName);
+ response.ReturnMessage.Add("File Uploaded successfully.");
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getDocument")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StringResponse))]
+ public IActionResult GetDocument([FromBody] FileViewRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ StringResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ if (string.IsNullOrEmpty(request.FileName))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("There is no Image to set Profile image.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ string path = Path.Combine(_appSettings.UploadFolder, request.FileName);
+ if (System.IO.File.Exists(path))
+ {
+ response.Value = Convert.ToBase64String(System.IO.File.ReadAllBytes(path: path));
+ }
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("findAccount")]
+ [AllowAnonymous, IgnoreAntiforgeryToken]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(FindAccountResponse))]
+ public async Task FindAccount([FromBody] FindAccountRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ FindAccountResponse response = new();
+ if (string.IsNullOrEmpty(request.AccountId))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Login Id or Email address or Mobile number is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string key = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
+ request.AccountId = Helper.DecryptData(secret: key, data: request.AccountId);
+ response = await _service.FindAccountAsync(accountId: request.AccountId);
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("sendPassword")]
+ [AllowAnonymous, IgnoreAntiforgeryToken]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task SendPassword([FromBody] SendPasswordRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ if (string.IsNullOrEmpty(request.UserId))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("User Id is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.MobileNo))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Mobile number is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ if (string.IsNullOrEmpty(request.EmailAddress))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Email address is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string key = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
+ string decipherValue = Helper.DecryptData(secret: key, data: request.UserId);
+ if (string.IsNullOrEmpty(decipherValue))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("User Id is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+ if (!int.TryParse(decipherValue, out int userId))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("User Id is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+ if (userId == 0)
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("User Id is required.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ request.MobileNo = Helper.DecryptData(secret: key, data: request.MobileNo);
+ request.EmailAddress = Helper.DecryptData(secret: key, data: request.EmailAddress);
+ if (string.IsNullOrEmpty(request.MobileNo) && string.IsNullOrEmpty(request.EmailAddress))
+ {
+ response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
+ response.ReturnMessage.Add("Mobile number and Email address both cannot be empty.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ //Do reset password
+ string newPassword = $"{new Random().Next(100000, 999999)}";
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ response.Value = await _service.SendPasswordAsync(userId: userId, newPassword: newPassword, ipAddress: ipAddress);
+ if (response.Value)
+ {
+ if (!string.IsNullOrEmpty(request.EmailAddress) && !string.IsNullOrWhiteSpace(request.EmailAddress))
+ {
+ List to = [.. request.EmailAddress.Split(separator: ';', options: StringSplitOptions.RemoveEmptyEntries)];
+ await MailHelper.SendMailMessageAsync(settings: _appSettings, to: to, cc: null, bcc: null, attachments: null, embeddedImages: null, isHtmlBody: false, priority: System.Net.Mail.MailPriority.Normal,
+ subject: "One Time Password", messageBody: $"Your one time password (use as Old password): {newPassword} and must change password at next Login.");
+ }
+ if (!string.IsNullOrEmpty(request.MobileNo) && !string.IsNullOrWhiteSpace(request.MobileNo))
+ {
+ MailHelper.SendSMSOrWhatsAppMessage(settings: _appSettings, whatsAppMsg: false, msg: $"Your one time password (use as Old password): {newPassword} and must change password at next Login.", mobileNumber: request.MobileNo);
+ }
+
+ response.ReturnMessage.Add("Password sent to your Email address and/or Mobile number, User must change password at next Login.");
+ }
+ else
+ {
+ response.ReturnMessage.Add("Cannot do action on your request.");
+ }
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("saveAuthorizeLimit")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(BooleanResponse))]
+ public async Task SaveAuthorizeLimit([FromBody] UserLimitAuthorizeRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ bool permitted = await HttpContext.IsPermitted("ELIT.9.1.14_1") || await HttpContext.IsPermitted("ELIT.9.1.14_2");
+ if (!permitted)
+ {
+ response.ReturnStatus = StatusCodes.Status403Forbidden;
+ response.ReturnMessage.Add("You are not authorize to Update Authorization Limit.");
+ return StatusCode(StatusCodes.Status417ExpectationFailed, response);
+ }
+
+ try
+ {
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ string loginId = HttpContext.User.GetClaimValue(Constants.LoginId);
+ response.Value = await _service.SaveAuthorizeLimitAsync(maxAuthLimit: request.MaxAuthorizeAmount, userId: request.UserId, ipAddress: ipAddress, savedBy: loginId);
+ response.ReturnMessage.Add("Process completed successfully...");
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getAuthorizeLimit")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserAuthorizeLimitResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserAuthorizeLimitResponse))]
+ public async Task GetAuthorizeLimit([FromBody] ByUserIdRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ UserAuthorizeLimitResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ response = await _service.GetAuthorizeLimitAsync(userId: request.UserId);
+ response.ReturnStatus = StatusCodes.Status200OK;
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ [HttpPost("logOut")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))]
+ public async Task LogOut([FromBody] LogoutRequest request)
+ {
+ BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ string key = HttpContext.GetAuthenticationToken();
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ string loginId = HttpContext.User.GetClaimValue(Constants.LoginId);
+
+ if (request.AttendanceLogout)
+ {
+ string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
+ request.IpAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.IpAddress);
+ request.MacAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.MacAddress);
+ request.HostName = Helper.DecryptData(secret: cipherSecretKey, data: request.HostName);
+ }
+ _ = await _service.LogoutAsync(ipAddress: ipAddress, userId: userId, logId: request.LogId, attendanceLogout: request.AttendanceLogout, loginId: loginId, localIp: request.IpAddress, macAddress: request.MacAddress, hostName: request.HostName, logoutRemarks: request.LogoutRemarks);
+ _cache.Clear(pattern: key);
+ _ = await HttpContext.ClearSessionAsync();
+
+ response.Value = true;
+ if (request.AttendanceLogout)
+ {
+ await _hub.Clients.All.NotifySubscriber(userId: userId, msgType: 6, itemId: 0, ipAddress: ipAddress);
+ }
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// 0
+ [AllowAnonymous]
+ [IgnoreAntiforgeryToken]
+ [HttpPost("sessionExpired")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ public async Task SessionExpired([FromBody] LogoutRequest request)
+ {
+ try
+ {
+ int userId = HttpContext.User.GetClaimValue(Constants.UserId);
+ string ipAddress = Request.HttpContext.GetIpAddress();
+ _ = await _service.LogoutAsync(ipAddress: ipAddress, userId: userId, logId: request.LogId, attendanceLogout: false, loginId: string.Empty, localIp: string.Empty, macAddress: string.Empty, hostName: string.Empty, logoutRemarks: string.Empty);
+ _ = await HttpContext.ClearSessionAsync();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [SupportedOSPlatform("windows")]
+ private int GetADLoginStatus(string loginId, string password)
+ {
+ try
+ {
+ const string displayNameAttribute = "DisplayName";
+ const string samAccountNameAttribute = "SAMAccountName";
+ const string userAccountControlAttribute = "useraccountcontrol";
+
+ string username = (string.IsNullOrEmpty(_appSettings.ADConfig.Domain) || string.IsNullOrWhiteSpace(_appSettings.ADConfig.Domain)) ? loginId : $"{loginId}@{_appSettings.ADConfig.Domain}";
+ using DirectoryEntry entry = new(path: _appSettings.ADConfig.Path, username: username, password: password);
+ using DirectorySearcher searcher = new(searchRoot: entry);
+ searcher.Filter = $"({samAccountNameAttribute}={loginId})";
+ searcher.PropertiesToLoad.Add(value: displayNameAttribute);
+ searcher.PropertiesToLoad.Add(value: samAccountNameAttribute);
+ searcher.PropertiesToLoad.Add(value: userAccountControlAttribute);
+ var result = searcher.FindOne();
+ if (result == null)
+ return 0;
+
+ ResultPropertyValueCollection displayName = result.Properties[name: displayNameAttribute];
+ ResultPropertyValueCollection samAccountName = result.Properties[name: samAccountNameAttribute];
+ ResultPropertyValueCollection userAccountControl = result.Properties[name: userAccountControlAttribute];
+ int uacFlag = (userAccountControl != null && userAccountControl.Count > 0) ? Convert.ToInt32(userAccountControl[0]) : 0;
+ if ((uacFlag & 0x000002) == 0x000002) //Disabled
+ return 2;
+ else if ((uacFlag & 0x800000) == 0x800000) //Password expired
+ return 3;
+
+ if (displayName != null && displayName.Count > 0 && samAccountName != null && samAccountName.Count > 0)
+ return 1;
+ else
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ return 0;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("getAccessLog")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AccessLogResponse))]
+ [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(AccessLogResponse))]
+ public async Task GetAccessLog([FromBody] AccessLogSearchRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ AccessLogResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
+ try
+ {
+ string loginId = HttpContext.User.GetClaimValue(Constants.LoginId);
+ bool permitted = await HttpContext.IsPermitted("ELIT.1.2.5_2");
+ if (!(permitted || loginId.Equals(value: Models.Objects.Systems.User.SuperUser_LoginId, comparisonType: StringComparison.OrdinalIgnoreCase)))
+ {
+ request.LoginId = loginId;
+ }
+ response = await _service.GetAccessLogAsync(accessType: request.AccessType, loginId: request.LoginId, startDate: request.StartDate, endDate: request.EndDate);
+ response.ReturnStatus = StatusCodes.Status200OK;
+
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ response.ReturnStatus = StatusCodes.Status500InternalServerError;
+ response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ return StatusCode(StatusCodes.Status500InternalServerError, response);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ValidateSession]
+ [HttpPost("loadNotificationCount")]
+ [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))]
+ public async Task LoadNotificationCount([FromBody] NoContentRequest request)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+ try
+ {
+ int value = HttpContext.User.GetClaimValue(Constants.UserId);
+ value = await _service.LoadNotificationCountAsync(userId: value);
+
+ return Ok(value);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex);
+ return StatusCode(StatusCodes.Status500InternalServerError);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI/Controllers/V1/UserController.cs b/Api/OnlineSalesAutoCrop.CoreAPI/Controllers/V1/UserController.cs
index 94d2267..d5f9c9c 100644
--- a/Api/OnlineSalesAutoCrop.CoreAPI/Controllers/V1/UserController.cs
+++ b/Api/OnlineSalesAutoCrop.CoreAPI/Controllers/V1/UserController.cs
@@ -3,7 +3,6 @@ using OnlineSalesAutoCrop.CoreAPI.Configurations;
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;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups;
@@ -19,7 +18,6 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
-using Microsoft.Reporting.NETCore;
using System;
using System.Collections.Generic;
using System.DirectoryServices;
@@ -51,7 +49,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
[ValidateAntiForgeryToken]
[Route("api/v{version:apiVersion}/users")]
- public class UserController(IUserService service, IOptions appSettings, IEaseCache cache, ILogger logger, IHubContext hub) : ControllerBase
+ public class UserController(IUserService service, IOptions appSettings, IEaseCache cache, ILogger logger, IHubContext hub) : ControllerBase
{
private readonly ILogger _logger = logger;
private readonly IEaseCache _cache = cache;
diff --git a/Api/OnlineSalesAutoCrop.CoreAPI/appsettings.json b/Api/OnlineSalesAutoCrop.CoreAPI/appsettings.json
index ce97578..b8d9626 100644
--- a/Api/OnlineSalesAutoCrop.CoreAPI/appsettings.json
+++ b/Api/OnlineSalesAutoCrop.CoreAPI/appsettings.json
@@ -27,51 +27,6 @@
"CorsMethods": "POST",
"CorsOrigins": "http://localhost:4200,http://localhost:5050,http://localhost:7777",
"DbConfig": [
- {
- "ConnectionNode": {
- "ConnectionString": "Data Source=103.197.204.162,3341;Initial Catalog=OnlineSalesAutoCrop;User ID=OnlineSalesAutoCropSysUser;Password=OnlineSalesAutoCrop;Encrypt=false;",
- "EncryptKey": "",
- "Key": "spadb1",
- "Provider": "sql",
- "SqlSyntax": "SQL"
- }
- },
- {
- "ConnectionNode": {
- "ConnectionString": "V3DJ2Y3A4Tzp9y3WKGINJWSjQdvo7QxL+U4VfYkfrfbZB8b4sNPPgJM5J17wFLAmaOzvDmGBK0hN5TX8iOYEdntndR1isy1SqPZgoyEshX+87OQYsKVKrl85foY49BJGB75CdAuVXoizsLsDrKcNzw==",
- "Key": "spadb2",
- "Provider": "sql",
- "SqlSyntax": "SQL",
- "EncryptKey": "RWFzZURoMTk5MlRvMjAyMw=="
- }
- },
- {
- "ConnectionNode": {
- "ConnectionString": "M6aE4Nur0oHi9ddFe/IC/VlXYQTfJSafpWzjFeSHfNrozfGF/ZJMBLEMLe9SwVt0SUisTwL+5v5l1TYsYkpn9Dgo+K2H2X+OMsql1pf1vww=",
- "Key": "spadb3",
- "Provider": "sql",
- "SqlSyntax": "SQL",
- "EncryptKey": "RWFzZURoMTk5MlRvMjAyMw=="
- }
- },
- {
- "ConnectionNode": {
- "ConnectionString": "Server=Russel;Initial Catalog=OnlineSalesAutoCrop;Integrated Security=True;TrustServerCertificate=True;Encrypt=true;",
- "Key": "spadb4",
- "Provider": "sql",
- "SqlSyntax": "SQL",
- "EncryptKey": ""
- }
- },
- {
- "ConnectionNode": {
- "ConnectionString": "Data Source=100.100.100.80;Initial Catalog=OnlineSalesAutoCrop;User ID=OnlineSalesAutoCropSysuser;Password=[password];Encrypt=false;",
- "Key": "spadb6",
- "Provider": "sql",
- "SqlSyntax": "SQL",
- "EncryptKey": ""
- }
- },
{
"ConnectionNode": {
"ConnectionString": "Data Source=210.4.65.222,3341;Initial Catalog=OnlineSalesAutoCrop;User ID=OnlineSalesAutoCropSysUser;Password=OnlineSalesAutoCrop;Encrypt=false;",
@@ -128,7 +83,8 @@
"WaAccountSid": "AC0138ad79a532f653c35072dad10e52b9",
"WaAuthToken": "024a6897584671d9f9fa588d7c94aa96",
"WaMsgSvcSid": "MG8401d33a9a3b2aea95619bda3e5757b5",
- "WaSenderId": "+8801326755660"
+ "WaSenderId": "+8801326755660",
+ "RefreshTokenDuration": "15"
},
"MenuSettings": {