This commit is contained in:
nadira 2026-06-16 17:31:08 +06:00
commit b71003f000
25 changed files with 5848 additions and 3095 deletions

1
.gitignore vendored
View File

@ -17,4 +17,5 @@ obj
/UpgradeLog5.htm /UpgradeLog5.htm
/UpgradeLog7.htm /UpgradeLog7.htm
/OnlineSalesAutoCrop/App_Data/RadUploadTemp /OnlineSalesAutoCrop/App_Data/RadUploadTemp
/OnlineSalesAutoCrop/App/ClientApp/node_modules
/App/ClientApp/node_modules /App/ClientApp/node_modules

View File

@ -53,6 +53,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Global
public string JwtAudience { get; set; } public string JwtAudience { get; set; }
public bool JwtValidateIssuer { get; set; } public bool JwtValidateIssuer { get; set; }
public bool JwtValidateAudience { get; set; } public bool JwtValidateAudience { get; set; }
public int RefreshTokenDuration { get; set; }
/// <summary> /// <summary>
/// Folder management /// Folder management
@ -85,6 +86,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Global
public string EmailSenderIp { get; set; } public string EmailSenderIp { get; set; }
public string EmailSenderId { get; set; } public string EmailSenderId { get; set; }
private string _emailSenderPwd; private string _emailSenderPwd;
public string EmailSenderPwd public string EmailSenderPwd
{ {

View File

@ -0,0 +1,57 @@
namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Integrations;
public class CustomerIntegration
{
public int CustomerId { get; set; }
public string CustomerNumber { get; set; }
public string CustomerName { get; set; }
public string AccountGroup { get; set; }
public string AccountGroupDescription { get; set; }
public string CompanyCode { get; set; }
public string CompanyCodeDescription { get; set; }
public string SalesOrganization { get; set; }
public string SalesOrganizationDescription { get; set; }
public string DistributionChannel { get; set; }
public string DistributionChannelDescription { get; set; }
public string Division { get; set; }
public string DivisionDescription { get; set; }
public string MobileNumber { get; set; }
public string EmailAddress { get; set; }
public string BusinessTaxNumber { get; set; }
public decimal? CreditLimit { get; set; }
public string SalesOffice { get; set; }
public string SalesOfficeDescription { get; set; }
public string SalesGroup { get; set; }
public string CustomerGroup { get; set; }
public string Status { get; set; }
public string PaymentTerms { get; set; }
public string SearchTerm { get; set; }
public string Region { get; set; }
public string RegionName { get; set; }
public string Area { get; set; }
public string AreaName { get; set; }
public string SalesUnit { get; set; }
public string SalesUnitName { get; set; }
public string Territory { get; set; }
public string TerritoryName { get; set; }
public string Plant { get; set; }
public string PlantName { get; set; }
}

View File

@ -0,0 +1,16 @@
using System;
namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
public class RefreshToken
{
public int Id { get; set; }
public int UserId { get; set; }
public string TokenHash { get; set; } = string.Empty;
public string DeviceInfo { get; set; } = string.Empty;
public string IpAddress { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
public DateTime ExpiresAt { get; set; }
public DateTime? RevokedAt { get; set; }
public bool IsActive => RevokedAt == null && ExpiresAt > DateTime.UtcNow;
}

View File

@ -1,6 +1,4 @@
using OnlineSalesAutoCrop.CoreAPI.Models.Global; using System;
using System;
using System.Collections.Generic;
namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
{ {
@ -9,9 +7,9 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public const int SuperUser_Id = -9; public const int SuperUser_Id = -9;
public const string SuperUser_LoginId = "superuser"; public const string SuperUser_LoginId = "superuser";
public int Id { get; set; } public int UserId { get; set; }
public string LoginId { get; set; } public string LoginId { get; set; }
public int LogId { get; set; } public string Password { get; set; }
public DateTime? LogoutTime { get; set; } public DateTime? LogoutTime { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public EnumStatus Status { get; set; } public EnumStatus Status { get; set; }
@ -19,17 +17,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public bool NeverExpires { get; set; } public bool NeverExpires { get; set; }
public string LastPasswords { get; set; } public string LastPasswords { get; set; }
public DateTime? LastPassChgDate { get; set; } public DateTime? LastPassChgDate { get; set; }
public DateTime? ExpireDate { get; set; }
public DateTime? NextLoginTime { get; set; }
public DateTime SystemDate { get; set; }
public bool DbOnStartup { get; set; }
public bool ViewOwnTaskOnly { get; set; }
public int? EmployeeId { get; set; }
public string EmployeeCode { get; set; }
public EnumLoginStatus LoginStatus { get; set; }
public EnumAuthenticationMethod AuthMethod { get; set; }
public bool AuthRequiredAtLogin { get; set; }
public List<string> ModuleIds { get; set; }
public string EmailAddress { get; set; } public string EmailAddress { get; set; }
public string AuthKey { get; set; } public string AuthKey { get; set; }
public string AuthValue { get; set; } public string AuthValue { get; set; }
@ -39,17 +26,9 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public string SchemeName { get; set; } public string SchemeName { get; set; }
public string MenuLayout { get; set; } public string MenuLayout { get; set; }
public bool IsLocked { get; set; } public bool IsLocked { get; set; }
public DateTime MinReportDate { get; set; } public EnumLoginStatus LoginStatus { get; set; }
public string AppId { get; set; } public DateTime? NextLoginTime { get; set; }
public bool DisallowMultiLogin { get; set; }
public bool BatchEnabled { get; set; }
public int BmProcessId { get; set; }
public int PrProcessId { get; set; }
public int IdleTime { get; set; }
public int PingTime { get; set; }
public int TimeoutTime { get; set; }
public int NotificationCount { get; set; }
public List<int> TeamSpaceIds { get; set; }
} }
public class LoginHistory public class LoginHistory
@ -63,38 +42,14 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public class AccessLog public class AccessLog
{ {
public int AccessLogId { get; set; }
public int UserId { get; set; }
public string LoginId { get; set; } public string LoginId { get; set; }
public DateTime LoginTime { get; set; } public DateTime LoginTime { get; set; }
public string LoginIp { get; set; } public string LoginIp { get; set; }
public DateTime? LogoutTime { get; set; } public DateTime? LogoutTime { get; set; }
public string LogoutIp { get; set; } public string LogoutIp { get; set; }
public string LoginStatus { get; set; } public EnumLoginStatus LoginStatus { get; set; }
}
public class DashboardItem
{
public string DivStyleCss { get; set; }
public string Title { get; set; }
public string TitleCss { get; set; }
public string Value { get; set; }
public string ValueCss { get; set; }
public int Id { get; set; }
public string Href { get; set; }
}
public class Dashboard2Item
{
public string Title { get; set; }
public decimal Value { get; set; }
public string TitleStyle { get; set; }
public string ValueStyle { get; set; }
public string ValueFormat { get; set; }
}
public class Dashboard2Data
{
public string GroupName { get; set; }
public List<Dashboard2Item> Items { get; set; }
} }
public class UserForceLogout public class UserForceLogout
@ -104,20 +59,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
public string UserName { get; set; } public string UserName { get; set; }
} }
public class UserSearch : UserForceLogout
{
public string Designation { get; set; }
public string MobileNo { get; set; }
public string EmailAddress { get; set; }
public EnumStatus Status { get; set; }
public short SeqId { get; set; }
public bool CanUseAttendanceSystem { get; set; }
public bool IsLocked { get; set; }
public string AuthId { get; set; }
public string StatusDetail => Status.GetDescription();
}
public class UserBasicInfo public class UserBasicInfo
{ {
public int UserId { get; set; } public int UserId { get; set; }

View File

@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
public class CustomerIntegrationRequest
{
[Required(ErrorMessage = "Customer Number is required")]
[StringLength(10, MinimumLength = 1, ErrorMessage = "Customer Number must be between 1 and 10 characters")]
public string CustomerNumber { get; set; } = string.Empty;
[Required(ErrorMessage = "Customer Name is required")]
[StringLength(35, MinimumLength = 1, ErrorMessage = "Customer Name must be between 1 and 35 characters")]
public string CustomerName { get; set; } = string.Empty;
[Required(ErrorMessage = "Account Group is required")]
[StringLength(3, MinimumLength = 1, ErrorMessage = "Account Group must be between 1 and 3 characters")]
public string AccountGroup { get; set; } = string.Empty;
[Required(ErrorMessage = "Account Group Description is required")]
[StringLength(30, ErrorMessage = "Account Group Description cannot exceed 30 characters")]
public string AccountGroupDescription { get; set; } = string.Empty;
[Required(ErrorMessage = "Company Code is required")]
[StringLength(4, MinimumLength = 1, ErrorMessage = "Company Code must be between 1 and 4 characters")]
public string CompanyCode { get; set; } = string.Empty;
[Required(ErrorMessage = "Company Code Description is required")]
[StringLength(25, ErrorMessage = "Company Code Description cannot exceed 25 characters")]
public string CompanyCodeDescription { get; set; } = string.Empty;
[Required(ErrorMessage = "Sales Organization is required")]
[StringLength(4, MinimumLength = 1, ErrorMessage = "Sales Organization must be between 1 and 4 characters")]
public string SalesOrganization { get; set; } = string.Empty;
[Required(ErrorMessage = "Sales Organization Description is required")]
[StringLength(40, ErrorMessage = "Sales Organization Description cannot exceed 40 characters")]
public string SalesOrganizationDescription { get; set; } = string.Empty;
[Required(ErrorMessage = "Distribution Channel is required")]
[StringLength(2, MinimumLength = 1, ErrorMessage = "Distribution Channel must be between 1 and 2 characters")]
public string DistributionChannel { get; set; } = string.Empty;
[Required(ErrorMessage = "Distribution Channel Description is required")]
[StringLength(20, ErrorMessage = "Distribution Channel Description cannot exceed 20 characters")]
public string DistributionChannelDescription { get; set; } = string.Empty;
[Required(ErrorMessage = "Division is required")]
[StringLength(2, MinimumLength = 1, ErrorMessage = "Division must be between 1 and 2 characters")]
public string Division { get; set; } = string.Empty;
[Required(ErrorMessage = "Division Description is required")]
[StringLength(20, ErrorMessage = "Division Description cannot exceed 20 characters")]
public string DivisionDescription { get; set; } = string.Empty;
[Required(ErrorMessage = "Mobile Number is required")]
[StringLength(31, ErrorMessage = "Mobile Number cannot exceed 31 characters")]
[Phone(ErrorMessage = "Invalid mobile number format")]
public string MobileNumber { get; set; } = string.Empty;
[Required(ErrorMessage = "Email Address is required")]
[StringLength(241, ErrorMessage = "Email Address cannot exceed 241 characters")]
[EmailAddress(ErrorMessage = "Invalid email address format")]
public string EmailAddress { get; set; } = string.Empty;
[Required(ErrorMessage = "Business/Tax Number is required")]
[StringLength(16, ErrorMessage = "Business/Tax Number cannot exceed 16 characters")]
public string BusinessTaxNumber { get; set; } = string.Empty;
[Required(ErrorMessage = "Credit Limit is required")]
[Range(0, 9999999999999, ErrorMessage = "Credit Limit must be a valid number")]
public decimal CreditLimit { get; set; }
[Required(ErrorMessage = "Sales Office is required")]
[StringLength(4, MinimumLength = 1, ErrorMessage = "Sales Office must be between 1 and 4 characters")]
public string SalesOffice { get; set; } = string.Empty;
[StringLength(255, ErrorMessage = "Sales Office Description cannot exceed 255 characters")]
public string? SalesOfficeDescription { get; set; }
[Required(ErrorMessage = "Sales Group is required")]
[StringLength(3, MinimumLength = 1, ErrorMessage = "Sales Group must be between 1 and 3 characters")]
public string SalesGroup { get; set; } = string.Empty;
[Required(ErrorMessage = "Customer Group is required")]
[StringLength(2, MinimumLength = 1, ErrorMessage = "Customer Group must be between 1 and 2 characters")]
public string CustomerGroup { get; set; } = string.Empty;
[Required(ErrorMessage = "Status is required")]
[StringLength(1, MinimumLength = 1, ErrorMessage = "Status must be exactly 1 character")]
public string Status { get; set; } = string.Empty;
[Required(ErrorMessage = "Payment Terms are required")]
[StringLength(4, MinimumLength = 1, ErrorMessage = "Payment Terms must be between 1 and 4 characters")]
public string PaymentTerms { get; set; } = string.Empty;
[Required(ErrorMessage = "Search Term is required")]
[StringLength(20, ErrorMessage = "Search Term cannot exceed 20 characters")]
public string SearchTerm { get; set; } = string.Empty;
[Required(ErrorMessage = "Region is required")]
[StringLength(3, MinimumLength = 1, ErrorMessage = "Region must be between 1 and 3 characters")]
public string Region { get; set; } = string.Empty;
[Required(ErrorMessage = "Region Name is required")]
[StringLength(40, ErrorMessage = "Region Name cannot exceed 40 characters")]
public string RegionName { get; set; } = string.Empty;
[Required(ErrorMessage = "Area is required")]
[StringLength(10, MinimumLength = 1, ErrorMessage = "Area must be between 1 and 10 characters")]
public string Area { get; set; } = string.Empty;
[Required(ErrorMessage = "Area Name is required")]
[StringLength(40, ErrorMessage = "Area Name cannot exceed 40 characters")]
public string AreaName { get; set; } = string.Empty;
[Required(ErrorMessage = "Sales Unit is required")]
[StringLength(3, MinimumLength = 1, ErrorMessage = "Sales Unit must be between 1 and 3 characters")]
public string SalesUnit { get; set; } = string.Empty;
[Required(ErrorMessage = "Sales Unit Name is required")]
[StringLength(30, ErrorMessage = "Sales Unit Name cannot exceed 30 characters")]
public string SalesUnitName { get; set; } = string.Empty;
[Required(ErrorMessage = "Territory is required")]
[StringLength(3, MinimumLength = 1, ErrorMessage = "Territory must be between 1 and 3 characters")]
public string Territory { get; set; } = string.Empty;
[Required(ErrorMessage = "Territory Name is required")]
[StringLength(20, ErrorMessage = "Territory Name cannot exceed 20 characters")]
public string TerritoryName { get; set; } = string.Empty;
[Required(ErrorMessage = "Plant is required")]
[StringLength(4, MinimumLength = 1, ErrorMessage = "Plant must be between 1 and 4 characters")]
public string Plant { get; set; } = string.Empty;
[Required(ErrorMessage = "Plant Name is required")]
[StringLength(30, ErrorMessage = "Plant Name cannot exceed 30 characters")]
public string PlantName { get; set; } = string.Empty;
}
public class CustomerByCompanyCodeRequest
{
[Required(ErrorMessage = "Customer Number is required")]
[StringLength(10, MinimumLength = 1, ErrorMessage = "Customer Number must be between 1 and 10 characters")]
public string CustomerNumber { get; set; } = string.Empty;
[Required(ErrorMessage = "Company Code is required")]
[StringLength(4, MinimumLength = 1, ErrorMessage = "Company Code must be between 1 and 4 characters")]
public string CompanyCode { get; set; } = string.Empty;
}

View File

@ -0,0 +1,41 @@
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 IntegrationLoginRequest
{
[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 string RefreshToken { 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 int UserId { get; set; }
}
public class GenerateRefreshTokenRequest
{
public User User { get; set; }
public string IpAddress { get; set; }
public string RawRefreshToken { get; set; }
}

View File

@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis; 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.")] [Required, NotNull, StringLength(maximumLength: 200, MinimumLength = 4, ErrorMessage = "Login Id or Email address or Mobile number must be between 4 and 100 characters.")]
@ -31,6 +31,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems
public string LoginRemarks { get; set; } public string LoginRemarks { get; set; }
} }
public class OtpValidationRequest public class OtpValidationRequest
{ {
public int UserId { get; set; } public int UserId { get; set; }
@ -218,4 +219,3 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems
[Required, NotNull] [Required, NotNull]
public DateTime YearMonth { get; set; } public DateTime YearMonth { get; set; }
} }
}

View File

@ -0,0 +1,62 @@
namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
public class CustomerIntegrationResponse : ResponseBase
{
}
public class CustomerByCompanyCodeResponse : ResponseBase
{
public int CustomerId { get; set; }
public string CustomerNumber { get; set; }
public string CustomerName { get; set; }
public string AccountGroup { get; set; }
public string AccountGroupDescription { get; set; }
public string CompanyCode { get; set; }
public string CompanyCodeDescription { get; set; }
public string SalesOrganization { get; set; }
public string SalesOrganizationDescription { get; set; }
public string DistributionChannel { get; set; }
public string DistributionChannelDescription { get; set; }
public string Division { get; set; }
public string DivisionDescription { get; set; }
public string MobileNumber { get; set; }
public string EmailAddress { get; set; }
public string BusinessTaxNumber { get; set; }
public decimal? CreditLimit { get; set; }
public string SalesOffice { get; set; }
public string SalesOfficeDescription { get; set; }
public string SalesGroup { get; set; }
public string CustomerGroup { get; set; }
public string Status { get; set; }
public string PaymentTerms { get; set; }
public string SearchTerm { get; set; }
public string Region { get; set; }
public string RegionName { get; set; }
public string Area { get; set; }
public string AreaName { get; set; }
public string SalesUnit { get; set; }
public string SalesUnitName { get; set; }
public string Territory { get; set; }
public string TerritoryName { get; set; }
public string Plant { get; set; }
public string PlantName { get; set; }
}

View File

@ -0,0 +1,33 @@
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
using System;
using System.Collections.Generic;
using System.Text;
namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
public class IntegrationLoginResponse : ResponseBase
{
public string LoginId { get; set; }
public string AccessToken { get; set; } = string.Empty;
public string RefreshToken { get; set; } = string.Empty;
public EnumLoginStatus LoginStatus { get; set; }
public DateTime AccessTokenExpiry { get; set; }
}
public class RefreshTokenResponse : ResponseBase
{
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 bool IsActive { get; set; }
}
public class GenerateRefreshTokenResponse : ResponseBase
{
public string RefreshToken { get; set; }
public DateTime ExpireTime { get; set; }
}

View File

@ -48,30 +48,24 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems
public void Map(User source) public void Map(User source)
{ {
Id = source.Id; Id = source.UserId;
LogId = source.LogId;
LoginId = source.LoginId; LoginId = source.LoginId;
IdleTime = source.IdleTime;
UserName = source.UserName; UserName = source.UserName;
PingTime = source.PingTime;
ThemeName = source.ThemeName; ThemeName = source.ThemeName;
//ModuleIds = source.ModuleIds; //ModuleIds = source.ModuleIds;
LogoutTime = source.LogoutTime; LogoutTime = source.LogoutTime;
SchemeName = source.SchemeName; SchemeName = source.SchemeName;
AuthMethod = source.AuthMethod;
MenuLayout = source.MenuLayout; MenuLayout = source.MenuLayout;
SystemDate = source.SystemDate;
EmployeeId = source.EmployeeId;
LoginStatus = source.LoginStatus; LoginStatus = source.LoginStatus;
DbOnStartup = source.DbOnStartup; //DbOnStartup = source.DbOnStartup;
TimeoutTime = source.TimeoutTime; //TimeoutTime = source.TimeoutTime;
BmProcessId = source.BmProcessId; //BmProcessId = source.BmProcessId;
PrProcessId = source.PrProcessId; //PrProcessId = source.PrProcessId;
BatchEnabled = source.BatchEnabled; //BatchEnabled = source.BatchEnabled;
ViewOwnTaskOnly = source.ViewOwnTaskOnly; //ViewOwnTaskOnly = source.ViewOwnTaskOnly;
NotificationCount = source.NotificationCount; //NotificationCount = source.NotificationCount;
AuthRequiredAtLogin = source.AuthRequiredAtLogin; //AuthRequiredAtLogin = source.AuthRequiredAtLogin;
IdsValue = Newtonsoft.Json.JsonConvert.SerializeObject(source.ModuleIds); //IdsValue = Newtonsoft.Json.JsonConvert.SerializeObject(source.ModuleIds);
} }
} }
@ -118,19 +112,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems
public List<LoginHistory> LoginHistories { get; set; } public List<LoginHistory> LoginHistories { get; set; }
} }
public class DashboardDataResponse : ResponseBase
{
public List<DashboardItem> GroupData { get; set; } = [];
public Dashboard2Data Group1Data { get; set; }
public Dashboard2Data Group2Data { get; set; }
public Dashboard2Data Group3Data { get; set; }
public Dashboard2Data Group4Data { get; set; }
}
public class UserSearchResponse : TotalRowsResponseBase
{
public List<UserSearch> Value { get; set; } = [];
}
public class UserForceLogoutResponse : ResponseBase public class UserForceLogoutResponse : ResponseBase
{ {

View File

@ -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<RefreshTokenResponse?> GetByTokenHashAsync(string tokenHash);
Task<bool> AddAsync(InsertRefreshTokenRequest refreshToken);
Task<bool> RevokeAsync(RevokedRefreshTokenRequest token);
Task<bool> RevokeAllForUserAsync(int userId);
Task<GenerateRefreshTokenResponse> GenerateRefreshToken(GenerateRefreshTokenRequest request);
}

View File

@ -0,0 +1,12 @@

using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
using System.Threading.Tasks;
namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
public interface IIntegrationService
{
Task<bool> UpsertCustomerAsync(CustomerIntegrationRequest request);
Task<CustomerByCompanyCodeResponse> GetCustomerByCompanyCodeAsync(CustomerByCompanyCodeRequest request);
}

View File

@ -1,5 +1,6 @@
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Setups; using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Setups;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems; using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems; using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems; using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
using System; using System;
@ -12,6 +13,8 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems
{ {
Task<bool> ValidateAuthValueAsync(string authValue, int userId); Task<bool> ValidateAuthValueAsync(string authValue, int userId);
Task<User> LoginAsync(LoginRequest request, string ipAddress, bool checkPwd); Task<User> LoginAsync(LoginRequest request, string ipAddress, bool checkPwd);
Task<User> IntegrationLoginAsync(IntegrationLoginRequest request, string ipAddress, bool checkPwd);
Task<bool> LogoutAsync(string ipAddress, int userId, int logId, bool attendanceLogout, string loginId, string localIp, string macAddress, string hostName, string logoutRemarks); Task<bool> LogoutAsync(string ipAddress, int userId, int logId, bool attendanceLogout, string loginId, string localIp, string macAddress, string hostName, string logoutRemarks);
Task<bool> DeleteUserAsync(int userId, int deletedBy); Task<bool> DeleteUserAsync(int userId, int deletedBy);
@ -34,14 +37,12 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems
Task<FindAccountResponse> FindAccountAsync(string accountId); Task<FindAccountResponse> FindAccountAsync(string accountId);
Task<UserAuthorizeLimitResponse> GetAuthorizeLimitAsync(int userId); Task<UserAuthorizeLimitResponse> GetAuthorizeLimitAsync(int userId);
Task<UserAttributesResponse> GetAttributesAsync(int userId, int clientType); Task<UserAttributesResponse> GetAttributesAsync(int userId, int clientType);
Task<DashboardDataResponse> GetDashboardData(int userId, bool canViewLeave, bool canViewLate, bool canViewClientVisit, bool canViewHomeOffice, bool viewAll);
Task<int> LoadNotificationCountAsync(int userId); Task<int> LoadNotificationCountAsync(int userId);
Task<UserBasicInfoResponse> GetAttendanceUsersAsync(int userId); Task<UserBasicInfoResponse> GetAttendanceUsersAsync(int userId);
Task<UserForceLogoutResponse> GetForceLogoutUsersAsync(int createdBy); Task<UserForceLogoutResponse> GetForceLogoutUsersAsync(int createdBy);
Task<UserSearchResponse> GetUsersAsync(UserSearchRequest request, int userId);
Task<bool> SendPasswordAsync(int userId, string newPassword, string ipAddress); Task<bool> SendPasswordAsync(int userId, string newPassword, string ipAddress);
Task<UserBasicInfoResponse> GetUsersByTeamSpaceAsync(string teamSpaceIds, int projectId, int userId); Task<UserBasicInfoResponse> GetUsersByTeamSpaceAsync(string teamSpaceIds, int projectId, int userId);
Task<UserBasicInfoResponse> GetUsersBasicAsync(bool applyFilter, string teamSpaceIds, int projectId); Task<UserBasicInfoResponse> GetUsersBasicAsync(bool applyFilter, string teamSpaceIds, int projectId);

View File

@ -0,0 +1,283 @@
using Ease.NetCore.DataAccess;
using Ease.NetCore.DataAccess.SQL;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Options;
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.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<AppSettings> settings)
{
_settings = settings.Value;
}
public async Task<bool> AddAsync(InsertRefreshTokenRequest refreshToken)
{
bool returnValue = false;
try
{
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
AddAsync(tc, refreshToken);
tc.End();
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
return returnValue;
}
private bool 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)),
];
_ = tc.ExecuteNonQuerySp(spName: "dbo.InsertRefreshToken", parameterValues: p);
returnValue = true;
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
return returnValue;
}
public async Task<RefreshTokenResponse> GetByTokenHashAsync(string tokenHash)
{
RefreshTokenResponse response = new();
try
{
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
try
{
await GetByTokenHashAsync(tc, tokenHash);
tc.End();
}
catch (Exception ie)
{
tc?.HandleError();
throw DBCustomError.GenerateCustomError(ie);
}
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
return response;
}
private async Task<RefreshTokenResponse> GetByTokenHashAsync(TransactionContext tc, string tokenHash)
{
RefreshTokenResponse response = new();
try
{
SqlParameter[] p =
[
SqlHelperExtension.CreateInParam(pName: "@RefreshToken", pType: SqlDbType.VarChar, pValue: tokenHash),
];
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();
}
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
return response;
}
public async Task<bool> 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<bool> RevokeAsync(RevokedRefreshTokenRequest token)
{
bool returnValue = false;
try
{
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
try
{
returnValue = RevokeAsync(tc, token);
tc.End();
}
catch (Exception ie)
{
tc?.HandleError();
throw DBCustomError.GenerateCustomError(ie);
}
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
return returnValue;
}
private bool RevokeAsync(TransactionContext tc, RevokedRefreshTokenRequest token)
{
bool returnValue = false;
try
{
SqlParameter[] p =
[
SqlHelperExtension.CreateInParam(pName: "@RefreshToken", pType: SqlDbType.NVarChar, pValue: token.RefreshToken)
];
_ = tc.ExecuteNonQuerySp(spName: "dbo.RevokedAllRefreshToken", parameterValues: p);
returnValue = true;
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
return returnValue;
}
public async Task<GenerateRefreshTokenResponse> GenerateRefreshToken(GenerateRefreshTokenRequest request)
{
GenerateRefreshTokenResponse refreshTokenResponse = new();
try
{
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
try
{
var tokenHash = HashToken(request.RawRefreshToken);
var storedToken = await GetByTokenHashAsync(tc, tokenHash);
if (storedToken.UserId is not null && !storedToken.IsActive)
throw new UnauthorizedAccessException("Refresh token has expired or been revoked.");
// Rotate: revoke old token, issue new one
RevokeAsync(tc,new RevokedRefreshTokenRequest() { RefreshToken = storedToken.TokenHash });
refreshTokenResponse= await IssueTokensAsync(tc,request.User, request.IpAddress);
tc.End();
}
catch (Exception ie)
{
tc?.HandleError();
throw DBCustomError.GenerateCustomError(ie);
}
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
return refreshTokenResponse;
}
// ----- private helpers -----
private async Task<GenerateRefreshTokenResponse> IssueTokensAsync(TransactionContext tc, User user, string ipAddress)
{
string rawRefreshToken = GenerateRowToken();
var refreshToken = new InsertRefreshTokenRequest
{
UserId = user.UserId,
TokenHash = HashToken(rawRefreshToken),
IpAddress = ipAddress,
CreatedAt = DateTime.UtcNow,
ExpiresAt = DateTime.UtcNow.AddDays(_settings.RefreshTokenDuration)
};
AddAsync(tc,refreshToken);
return new GenerateRefreshTokenResponse
{
RefreshToken = rawRefreshToken,
ExpireTime = DateTime.UtcNow.AddMinutes(_settings.RefreshTokenDuration)
};
}
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);
}
}

View File

@ -0,0 +1,152 @@
using Ease.NetCore.DataAccess;
using Ease.NetCore.DataAccess.SQL;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Options;
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
using System;
using System.Data;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Integrations;
public class IntegrationService : IIntegrationService
{
private readonly AppSettings _settings;
public IntegrationService(IOptions<AppSettings> options)
{
_settings = options.Value;
}
public async Task<CustomerByCompanyCodeResponse> GetCustomerByCompanyCodeAsync(CustomerByCompanyCodeRequest request)
{
CustomerByCompanyCodeResponse response = new();
try
{
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
try
{
await GetCustomerByCompanyCodeAsync(tc, request);
tc.End();
}
catch (Exception ie)
{
tc?.HandleError();
throw DBCustomError.GenerateCustomError(ie);
}
}
catch (Exception ex)
{
throw;
}
return response;
}
public async Task<bool> UpsertCustomerAsync(CustomerIntegrationRequest request)
{
bool response = false;
try
{
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
try
{
var customer = await GetCustomerByCompanyCodeAsync(tc, new CustomerByCompanyCodeRequest() { CompanyCode = request.CompanyCode, CustomerNumber = request.CustomerNumber });
if( customer != null && customer.CustomerId>0)
{
//Update Here
}
else
{
//Insert Here
}
tc.End();
}
catch (Exception ie)
{
tc?.HandleError();
throw DBCustomError.GenerateCustomError(ie);
}
}
catch (Exception ex)
{
throw;
}
return response;
}
private async Task<CustomerByCompanyCodeResponse> GetCustomerByCompanyCodeAsync(TransactionContext tc, CustomerByCompanyCodeRequest request)
{
CustomerByCompanyCodeResponse response = new CustomerByCompanyCodeResponse();
try
{
SqlParameter[] p =
[
SqlHelperExtension.CreateInParam(pName: "@CustomerNumber", pType: SqlDbType.NVarChar,pValue: request.CustomerNumber ),
SqlHelperExtension.CreateInParam(pName: "@CompanyCode", pType: SqlDbType.NVarChar,pValue: request.CompanyCode ),
];
using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetCustomerByCompanyCode", parameterValues: p))
{
if (dr.Read())
{
response = new CustomerByCompanyCodeResponse()
{
CustomerNumber = dr["CustomerNumber"].ToString(),
CustomerName = dr["CustomerName"].ToString(),
AccountGroup = dr["AccountGroup"].ToString(),
AccountGroupDescription = dr["AccountGroupDescription"].ToString(),
CompanyCode = dr["CompanyCode"].ToString(),
CompanyCodeDescription = dr["CompanyCodeDescription"].ToString(),
SalesOrganization = dr["SalesOrganization"].ToString(),
SalesOrganizationDescription = dr["SalesOrganizationDescription"].ToString(),
DistributionChannel = dr["DistributionChannel"].ToString(),
DistributionChannelDescription = dr["DistributionChannelDescription"].ToString(),
Division = dr["Division"].ToString(),
DivisionDescription = dr["DivisionDescription"].ToString(),
MobileNumber = dr["MobileNumber"].ToString(),
EmailAddress = dr["EmailAddress"].ToString(),
BusinessTaxNumber = dr["BusinessTaxNumber"].ToString(),
CreditLimit = dr["CreditLimit"] == DBNull.Value ? 0 : Convert.ToDecimal(dr["CreditLimit"]),
SalesOffice = dr["SalesOffice"].ToString(),
SalesOfficeDescription = dr["SalesOfficeDescription"].ToString(),
SalesGroup = dr["SalesGroup"].ToString(),
CustomerGroup = dr["CustomerGroup"].ToString(),
Status = dr["Status"].ToString(),
PaymentTerms = dr["PaymentTerms"].ToString(),
SearchTerm = dr["SearchTerm"].ToString(),
Region = dr["Region"].ToString(),
RegionName = dr["RegionName"].ToString(),
Area = dr["Area"].ToString(),
AreaName = dr["AreaName"].ToString(),
SalesUnit = dr["SalesUnit"].ToString(),
SalesUnitName = dr["SalesUnitName"].ToString(),
Territory = dr["Territory"].ToString(),
TerritoryName = dr["TerritoryName"].ToString(),
Plant = dr["Plant"].ToString(),
PlantName = dr["PlantName"].ToString()
};
}
dr.Close();
}
}
catch(Exception ex)
{
throw;
}
return response;
}
}

View File

@ -17,6 +17,7 @@ using System.Data;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
{ {
@ -36,6 +37,322 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
public async Task<User> LoginAsync(LoginRequest request, string ipAddress, bool checkPwd) public async Task<User> LoginAsync(LoginRequest request, string ipAddress, bool checkPwd)
{ {
User user = new() { LoginId = request.LoginId, LoginStatus = EnumLoginStatus.Unsuccessful }; User user = new() { LoginId = request.LoginId, LoginStatus = EnumLoginStatus.Unsuccessful };
//try
//{
// string password = EncryptPassword(password: request.Password);
// using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
// try
// {
// #region Attendance Login and Valid Ip Address
// if (request.AttendanceLogin && !request.LoginId.ToLower().Equals(User.SuperUser_LoginId))
// {
// string errMsg = string.Empty;
// SqlParameter[] p =
// [
// SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: request.IpAddress, size: 20),
// SqlHelperExtension.CreateInParam(pName: "@MacAddress", pType: SqlDbType.VarChar, pValue: request.MacAddress, size: 30),
// SqlHelperExtension.CreateInParam(pName: "@HostName", pType: SqlDbType.VarChar, pValue: request.HostName, size: 100),
// SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 50),
// SqlHelperExtension.CreateOutParam(pName: "@ErrMsg", pType: SqlDbType.VarChar, pValue: errMsg, size: 300)
// ];
// _ = tc.ExecuteNonQuerySp(spName: "dbo.IsValidIpOrMacAddress", parameterValues: p);
// errMsg = (p[4] == null || p[4].Value == null || p[4].Value == DBNull.Value) ? string.Empty : Convert.ToString(p[4].Value);
// if (!string.IsNullOrEmpty(errMsg))
// {
// tc.End();
// throw new InvalidOperationException(errMsg);
// }
// }
// #endregion
// bool batchEnabled = false;
// DateTime sysDate = DateTime.Today.Date;
// string appVer = string.Empty, alParams = string.Empty;
// int maxTryCount = 5, lockTime = 1, marMonths = 24, idleTime = 0, timeoutTime = 0, pingTime = 0, bmProcessId = 0, prProcessId = 0;
// #region Read Params from ThisSystem
// using (IDataReader dr = tc.ExecuteReader("SELECT MaxTryCount, LockTime, MarMonths, CAST(GETDATE() as date), AppVersion, AutoLogoutParams, BatchEnabled, BmProcessId, PrProcessId FROM ThisSystem"))
// {
// if (dr.Read())
// {
// maxTryCount = dr.GetInt16(0);
// lockTime = dr.GetInt16(1);
// marMonths = dr.GetInt16(2);
// sysDate = dr.GetDateTime(3);
// appVer = dr.GetString(4);
// alParams = dr.IsDBNull(5) ? string.Empty : dr.GetString(5);
// batchEnabled = !dr.IsDBNull(6) && dr.GetInt16(6) != 0;
// bmProcessId = dr.IsDBNull(7) ? 0 : dr.GetInt16(7);
// prProcessId = dr.IsDBNull(8) ? 0 : dr.GetInt16(8);
// }
// dr.Close();
// }
// if (!string.IsNullOrEmpty(alParams))
// {
// string[] times = alParams.Split(separator: ',', options: StringSplitOptions.RemoveEmptyEntries);
// if (times.Length == 3)
// {
// if (!int.TryParse(times[0], out idleTime))
// idleTime = 0;
// if (!int.TryParse(times[1], out timeoutTime))
// timeoutTime = 0;
// if (!int.TryParse(times[2], out pingTime))
// pingTime = 0;
// }
// }
// if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && !request.AppVersion.Equals(appVer))
// {
// user.UnsuccessfulMsg = appVer;
// user.LoginStatus = EnumLoginStatus.VersionMismatch;
// }
// #endregion
// if (user.LoginStatus != EnumLoginStatus.VersionMismatch)
// {
// #region Read User data using authentication data
// string commandText;
// if (!checkPwd)
// {
// commandText = SQLParser.MakeSQL("SELECT UserId, UserName, Status, MobileNo, EmailAddress, AuthReqAtlogin, AuthMethod,"
// + " AuthKey, AppId, AccessStatus, NeverExpire, LastPasswords, LastPassChgDate, ExpireDate, ThemeName, SchemeName, MenuLayout,"
// + " IsLocked, NextLoginTime, DBOnStartup, DAMultiLogin, ViewOwnTaskOnly, EmployeeId, LoginID, EmployeeCode FROM Users WHERE LoginID=%s", request.LoginId);
// }
// else
// {
// commandText = SQLParser.MakeSQL("SELECT UserId, UserName, Status, MobileNo, EmailAddress, AuthReqAtlogin, AuthMethod,"
// + " AuthKey, AppId, AccessStatus, NeverExpire, LastPasswords, LastPassChgDate, ExpireDate, ThemeName, SchemeName, MenuLayout,"
// + " IsLocked, NextLoginTime, DBOnStartup, DAMultiLogin, ViewOwnTaskOnly, EmployeeId, LoginID, EmployeeCode FROM Users"
// + " WHERE (LoginID=%s OR MobileNo=%s OR EmailAddress=%s) AND Password=%s", request.LoginId, request.LoginId, request.LoginId, password);
// }
// using (IDataReader dr = tc.ExecuteReader(commandText: commandText))
// {
// if (dr.Read())
// {
// user = new User
// {
// Id = dr.GetInt32(0),
// UserName = dr.GetString(1),
// Status = (EnumStatus)dr.GetInt16(2),
// MobileNo = dr.GetString(3),
// EmailAddress = dr.GetString(4),
// AuthRequiredAtLogin = !dr.IsDBNull(5) && dr.GetInt16(5) > 0,
// AuthMethod = (EnumAuthenticationMethod)dr.GetInt16(6),
// AuthKey = dr.IsDBNull(7) ? string.Empty : dr.GetString(7),
// AppId = dr.IsDBNull(8) ? string.Empty : dr.GetString(8),
// AccessStatus = (EnumAccessStatus)dr.GetInt16(9),
// NeverExpires = !dr.IsDBNull(10) && dr.GetInt16(10) > 0,
// LastPasswords = dr.IsDBNull(11) ? string.Empty : dr.GetString(11),
// LastPassChgDate = dr.IsDBNull(12) ? null : dr.GetDateTime(12),
// ExpireDate = dr.IsDBNull(13) ? null : dr.GetDateTime(13),
// ThemeName = dr.IsDBNull(14) ? "yellow" : dr.GetString(14),
// SchemeName = dr.IsDBNull(15) ? "dark" : dr.GetString(15),
// MenuLayout = dr.IsDBNull(16) ? "static" : dr.GetString(16),
// IsLocked = !dr.IsDBNull(17) && dr.GetInt16(17) > 0,
// NextLoginTime = dr.IsDBNull(18) ? null : dr.GetDateTime(18),
// DbOnStartup = dr.GetInt16(19) != 0,
// DisallowMultiLogin = dr.GetInt16(20) != 0,
// ViewOwnTaskOnly = dr.GetInt16(21) != 0,
// EmployeeId = dr.IsDBNull(22) ? null : dr.GetInt32(22),
// LoginId = dr.GetString(23),
// EmployeeCode = dr.IsDBNull(24) ? string.Empty : dr.GetString(24),
// TeamSpaceIds = [],
// IdleTime = idleTime,
// PingTime = pingTime,
// SystemDate = sysDate,
// TimeoutTime = timeoutTime,
// PrProcessId = prProcessId,
// BmProcessId = bmProcessId,
// BatchEnabled = batchEnabled,
// LoginStatus = EnumLoginStatus.Success
// };
// }
// dr.Close();
// user.MinReportDate = marMonths <= 0 ? new DateTime(year: 2015, month: 1, day: 1, hour: 0, minute: 0, second: 0, kind: DateTimeKind.Local) : sysDate.AddMonths(-1 * marMonths);
// }
// #endregion
// #region If the user was locked, try set set unlock if Time expired
// if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && user.IsLocked)
// {
// int isSuccessful = 0;
// SqlParameter[] p =
// [
// SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 30),
// SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
// SqlHelperExtension.CreateOutParam(pName: "@IsSuccessful", pType: SqlDbType.Int, pValue: isSuccessful),
// ];
// _ = tc.ExecuteNonQuerySp(spName: "dbo.DoUnlockUser", parameterValues: p);
// if (p[2] != null && p[2].Value != null && p[2].Value != DBNull.Value)
// isSuccessful = Convert.ToInt32(p[2].Value);
// if (isSuccessful == 1)
// user.IsLocked = false;
// }
// #endregion
// #region Keep log for unauthrise access and Set user lock if exceeds max try
// if (!request.LoginId.ToLower().Equals(User.SuperUser_LoginId) && maxTryCount > 0 && user.LoginStatus == EnumLoginStatus.Unsuccessful)
// {
// int remainsTry = 0;
// DateTime? nextLoginTime = null;
// string tryLoginInfo = $"{request.LoginId}~{password}~13";
// SqlParameter[] p =
// [
// SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 30),
// SqlHelperExtension.CreateInParam(pName: "@TryLoginInfo", pType: SqlDbType.VarChar, pValue: tryLoginInfo, size: 100),
// SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
// SqlHelperExtension.CreateInParam(pName: "@MaxTryCount", pType: SqlDbType.SmallInt, pValue: maxTryCount),
// SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
// SqlHelperExtension.CreateOutParam(pName: "@RemainingTry", pType: SqlDbType.SmallInt, pValue: remainsTry),
// SqlHelperExtension.CreateOutParam(pName: "@NextLoginTime", pType: SqlDbType.DateTime, pValue: nextLoginTime),
// ];
// _ = tc.ExecuteNonQuerySp(spName: "dbo.LogUnauthorizeAccess", parameterValues: p);
// if (p[5] != null && p[5].Value != null && p[5].Value != DBNull.Value)
// remainsTry = Convert.ToInt32(p[5].Value);
// if (p[6] != null && p[6].Value != null && p[6].Value != DBNull.Value)
// nextLoginTime = Convert.ToDateTime(p[6].Value);
// if (remainsTry <= 0)
// {
// user.IsLocked = true;
// if (lockTime <= 0)
// {
// user.NextLoginTime = nextLoginTime;
// user.UnsuccessfulMsg = "Please contact with Head office to Unlock";
// }
// else
// {
// user.NextLoginTime = nextLoginTime;
// user.UnsuccessfulMsg = $"You can Login after {user.NextLoginTime:dd-MMM-yyyy H:mm:ss}";
// }
// }
// else
// {
// user.UnsuccessfulMsg = $"{remainsTry} More attempt{(remainsTry > 1 ? "s" : "")} remaining";
// }
// }
// #endregion
// #region Generate and Save Otp if Otp is enabled and send thru SMS/Email
// if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && (user.AuthMethod == EnumAuthenticationMethod.Email || user.AuthMethod == EnumAuthenticationMethod.MobileSMS))
// {
// string secretKey = $"{user.Id}~{user.LoginId}";
// secretKey = secretKey.EncodeAsBase32String(addPadding: false);
// user.AuthValue = TOtpService.GetCurrentPIN(secretKey: secretKey);
// SetAuthValue(tc: tc, authValue: user.AuthValue, validMinutes: 5, userId: user.Id);
// }
// #endregion
// #region If login successful and user is active read module id for this user
// if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && !user.IsLocked)
// {
// int logId = 0;
// DateTime? logoutTime = null;
// SqlParameter[] p =
// [
// SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.Id),
// SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
// SqlHelperExtension.CreateInParam(pName: "@AppId", pType: SqlDbType.VarChar, pValue: request.AppId, size: 250),
// SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30),
// SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
// SqlHelperExtension.CreateInParam(pName: "@AttendanceLogin", pType: SqlDbType.Int, pValue: request.AttendanceLogin? 1:0),
// SqlHelperExtension.CreateInParam(pName: "@LocalIp", pType: SqlDbType.VarChar, pValue: request.IpAddress, size: 20),
// SqlHelperExtension.CreateInParam(pName: "@MacAddress", pType: SqlDbType.VarChar, pValue: request.MacAddress, size: 30),
// SqlHelperExtension.CreateInParam(pName: "@HostName", pType: SqlDbType.VarChar, pValue: request.HostName, size: 100),
// SqlHelperExtension.CreateInParam(pName: "@LoginRemarks", pType: SqlDbType.VarChar, pValue: request.LoginRemarks, size: 50)
// ];
// using (IDataReader dr = tc.ExecuteReaderSp(spName: "dbo.GetPermissionKeys", parameterValues: p))
// {
// user.ModuleIds = [];
// while (dr.Read())
// {
// string moduleId = dr.GetString(0);
// user.ModuleIds.Add(moduleId);
// logId = dr.GetInt32(1);
// if (dr.GetInt16(2) != 0) //Alow add
// {
// user.ModuleIds.Add($"{moduleId}_1");
// }
// if (dr.GetInt16(3) != 0) //Alow edit
// {
// user.ModuleIds.Add($"{moduleId}_2");
// }
// if (dr.GetInt16(4) != 0) //Allow Delete
// {
// user.ModuleIds.Add($"{moduleId}_3");
// }
// logoutTime = dr.IsDBNull(5) ? null : dr.GetDateTime(5);
// }
// dr.Close();
// }
// user.LogId = logId;
// user.LogoutTime = logoutTime;
// //Read User TeamSpace Ids
// using (IDataReader dr = tc.ExecuteReader("SELECT TeamSpaceId FROM TeamSpaceUsers WHERE UserId=%n", user.Id))
// {
// while (dr.Read())
// {
// user.TeamSpaceIds.Add(dr.GetInt32(0));
// }
// dr.Close();
// }
// //Pending Notification count
// user.NotificationCount = GetPendingNotifCount(tc: tc, userId: user.Id);
// }
// #endregion
// }
// tc.End();
// }
// catch (Exception ie)
// {
// tc?.HandleError();
// throw DBCustomError.GenerateCustomError(ie);
// }
//}
//catch (Exception e)
//{
// throw new InvalidOperationException(e.Message, e);
//}
return user;
}
public async Task<User> IntegrationLoginAsync(IntegrationLoginRequest request, string ipAddress, bool checkPwd)
{
User user = null;
try try
{ {
string password = EncryptPassword(password: request.Password); string password = EncryptPassword(password: request.Password);
@ -43,97 +360,14 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true); using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
try 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; DateTime sysDate = DateTime.Today.Date;
string appVer = string.Empty, alParams = string.Empty; string appVer = string.Empty, alParams = string.Empty;
int maxTryCount = 5, lockTime = 1, marMonths = 24, idleTime = 0, timeoutTime = 0, pingTime = 0, bmProcessId = 0, prProcessId = 0; int maxTryCount = 5, lockTime = 1;
#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 #region Read User data using authentication data
string commandText; string commandText = SQLParser.MakeSQL("SELECT UserId,Password,LoginId, UserName, Status, ISNULL(MobileNo,'')MobileNo ,ISNULL( EmailAddress,'')EmailAddress,"
if (!checkPwd) + " ISNULL(AuthKey,'') AuthKey, ISNULL(AuthValue,'')AuthValue, IsLocked FROM Users WHERE LoginID=%s", request.LoginId);
{
commandText = SQLParser.MakeSQL("SELECT UserId, UserName, Status, MobileNo, EmailAddress, AuthReqAtlogin, AuthMethod,"
+ " AuthKey, AppId, AccessStatus, NeverExpire, LastPasswords, LastPassChgDate, ExpireDate, ThemeName, SchemeName, MenuLayout,"
+ " IsLocked, NextLoginTime, DBOnStartup, DAMultiLogin, ViewOwnTaskOnly, EmployeeId, LoginID, EmployeeCode FROM Users WHERE LoginID=%s", request.LoginId);
}
else
{
commandText = SQLParser.MakeSQL("SELECT UserId, UserName, Status, MobileNo, EmailAddress, AuthReqAtlogin, AuthMethod,"
+ " AuthKey, AppId, AccessStatus, NeverExpire, LastPasswords, LastPassChgDate, ExpireDate, ThemeName, SchemeName, MenuLayout,"
+ " IsLocked, NextLoginTime, DBOnStartup, DAMultiLogin, ViewOwnTaskOnly, EmployeeId, LoginID, EmployeeCode FROM Users"
+ " WHERE (LoginID=%s OR MobileNo=%s OR EmailAddress=%s) AND Password=%s", request.LoginId, request.LoginId, request.LoginId, password);
}
using (IDataReader dr = tc.ExecuteReader(commandText: commandText)) using (IDataReader dr = tc.ExecuteReader(commandText: commandText))
{ {
@ -141,48 +375,35 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
{ {
user = new User user = new User
{ {
Id = dr.GetInt32(0), UserId = dr.GetInt32(0),
UserName = dr.GetString(1), Password = dr.GetString(1),
Status = (EnumStatus)dr.GetInt16(2), LoginId = dr.GetString(2),
MobileNo = dr.GetString(3), UserName = dr.GetString(3),
EmailAddress = dr.GetString(4), Status = (EnumStatus)dr.GetInt32(4),
AuthRequiredAtLogin = !dr.IsDBNull(5) && dr.GetInt16(5) > 0, MobileNo = dr.GetString(5),
AuthMethod = (EnumAuthenticationMethod)dr.GetInt16(6), EmailAddress = dr.GetString(6),
AuthKey = dr.IsDBNull(7) ? string.Empty : dr.GetString(7), AuthKey = dr.GetString(7),
AppId = dr.IsDBNull(8) ? string.Empty : dr.GetString(8), AuthValue = dr.GetString(8),
AccessStatus = (EnumAccessStatus)dr.GetInt16(9), IsLocked = dr.GetBoolean(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 LoginStatus = EnumLoginStatus.Success
}; };
} }
dr.Close(); 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);
} }
if (user is null)
{
tc.End();
throw new InvalidOperationException($"User not found with login: {request.LoginId}");
}
if (!password.Equals(user.Password))
{
tc.End();
throw new InvalidOperationException($"Password mismatch for login: {request.LoginId}");
}
#endregion #endregion
#region If the user was locked, try set set unlock if Time expired #region If the user was locked, try set set unlock if Time expired
@ -252,84 +473,23 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
#endregion #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 #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) if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && !user.IsLocked)
{ {
int logId = 0;
DateTime? logoutTime = null;
SqlParameter[] p = SqlParameter[] p =
[ [
SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.Id), SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.UserId),
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
SqlHelperExtension.CreateInParam(pName: "@AppId", pType: SqlDbType.VarChar, pValue: request.AppId, size: 250),
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30), SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30),
SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime), SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
SqlHelperExtension.CreateInParam(pName: "@AttendanceLogin", pType: SqlDbType.Int, pValue: request.AttendanceLogin? 1:0), SqlHelperExtension.CreateInParam(pName: "@LoginTime", pType: SqlDbType.DateTime, pValue: DateTime.Now)
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); _ = tc.ExecuteNonQuerySp(spName: "dbo.SaveAccessLog", parameterValues: p);
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 #endregion
}
tc.End(); tc.End();
} }
@ -347,7 +507,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
return user; return user;
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -1317,95 +1476,93 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
/// <param name="userId"></param> /// <param name="userId"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public async Task<UserSearchResponse> GetUsersAsync(UserSearchRequest request, int userId) //public async Task<UserSearchResponse> GetUsersAsync(UserSearchRequest request, int userId)
{ //{
UserSearchResponse response = new(); // UserSearchResponse response = new();
try // try
{ // {
string andClause = string.Empty; // string andClause = string.Empty;
if (!string.IsNullOrEmpty(request.Criteria)) // if (!string.IsNullOrEmpty(request.Criteria))
{ // {
string criteria = request.Criteria.Replace("'", "''"); // string criteria = request.Criteria.Replace("'", "''");
andClause = $" AND (LoginID='{criteria}' OR MobileNo='{criteria}' OR EmailAddress='{criteria}' OR UserName LIKE '%{criteria}%' OR Designation LIKE '%{criteria}%')"; // andClause = $" AND (LoginID='{criteria}' OR MobileNo='{criteria}' OR EmailAddress='{criteria}' OR UserName LIKE '%{criteria}%' OR Designation LIKE '%{criteria}%')";
} // }
if (request.Status > 0) // if (request.Status > 0)
andClause += SQLParser.MakeSQL(" AND Status=%n", request.Status); // andClause += SQLParser.MakeSQL(" AND Status=%n", request.Status);
if (request.CheckOwner) // if (request.CheckOwner)
andClause += SQLParser.MakeSQL(" AND (CreatedBy=%n OR ViewToAll=1)", userId); // andClause += SQLParser.MakeSQL(" AND (CreatedBy=%n OR ViewToAll=1)", userId);
string sortField = request.SortField switch // string sortField = request.SortField switch
{ // {
"userName" => "UserName", // "userName" => "UserName",
"designation" => "Designation", // "designation" => "Designation",
"mobileNo" => "MobileNo", // "mobileNo" => "MobileNo",
"emailAddress" => "EmailAddress", // "emailAddress" => "EmailAddress",
"statusDetail" => "Status", // "statusDetail" => "Status",
"loginId" => "LoginId", // "loginId" => "LoginId",
_ => "SeqId, LoginId" // _ => "SeqId, LoginId"
}; // };
string sortOrder = request.SortOrder switch // string sortOrder = request.SortOrder switch
{ // {
"desc" => "DESC", // "desc" => "DESC",
_ => "ASC", // _ => "ASC",
}; // };
string commandText = request.Skip + request.PageSize <= 0 ? // string commandText = request.Skip + request.PageSize <= 0 ?
SQLParser.MakeSQL("SELECT UserId, LoginId, UserName, Designation, MobileNo, EmailAddress, Status, SeqId, IsLocked, CanUseAtnSys, Password," // 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) // + " 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," // : 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," // + " 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" // + " 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); // + " 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); // using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
try // try
{ // {
int totalRows = 0; // int totalRows = 0;
using IDataReader dr = tc.ExecuteReader(commandText: commandText); // using IDataReader dr = tc.ExecuteReader(commandText: commandText);
while (dr.Read()) // while (dr.Read())
{ // {
UserSearch item = new() // UserGetResponse item = new()
{ // {
UserId = dr.GetInt32(0), // UserId = dr.GetInt32(0),
LoginId = dr.GetString(1), // LoginId = dr.GetString(1),
UserName = dr.GetString(2), // UserName = dr.GetString(2),
Designation = dr.GetString(3), // Designation = dr.GetString(3),
MobileNo = dr.GetString(4), // MobileNo = dr.GetString(4),
EmailAddress = dr.GetString(5), // EmailAddress = dr.GetString(5),
Status = (EnumStatus)dr.GetInt16(6), // Status = (EnumStatus)dr.GetInt16(6),
SeqId = dr.GetInt16(7), // SeqId = dr.GetInt16(7),
IsLocked = !dr.IsDBNull(8) && dr.GetInt16(8) != 0, // IsLocked = !dr.IsDBNull(8) && dr.GetInt16(8) != 0,
CanUseAttendanceSystem = !dr.IsDBNull(9) && dr.GetInt16(9) != 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);
totalRows = dr.GetInt32(11);
response.Value.Add(item); // }
} // dr.Close();
dr.Close();
response.TotalRows = totalRows; // response.TotalRows = totalRows;
tc.End(); // tc.End();
response.ReturnStatus = 200; // response.ReturnStatus = 200;
} // }
catch (Exception ie) // catch (Exception ie)
{ // {
tc?.HandleError(); // tc?.HandleError();
throw DBCustomError.GenerateCustomError(ie); // throw DBCustomError.GenerateCustomError(ie);
} // }
} // }
catch (Exception e) // catch (Exception e)
{ // {
throw new InvalidOperationException(e.Message, e); // throw new InvalidOperationException(e.Message, e);
} // }
return response; // return response;
} //}
/// <summary> /// <summary>
/// ///
@ -1946,137 +2103,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
/// <param name="viewAll"></param> /// <param name="viewAll"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="InvalidOperationException"></exception> /// <exception cref="InvalidOperationException"></exception>
public async Task<DashboardDataResponse> 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 ? $"<a class=\"hand-cursor\" href=\"#/emphmofcs\">Home Office: {dr.GetInt32(1)}</a>" : $"Home Office: {dr.GetInt32(1)}");
else if (dr.GetInt16(0) == 3)
sb.Append(canViewClientVisit && viewAll ? $"<a class=\"hand-cursor\" href=\"#/empclntvsts\">Client Visit: {dr.GetInt32(1)}</a>" : $"Client Visit: {dr.GetInt32(1)}");
else if (dr.GetInt16(0) == 2)
sb.Append(canViewLate && viewAll ? $"<a class=\"hand-cursor\" href=\"#/emplates\">Late: {dr.GetInt32(1)}</a>" : $"Late: {dr.GetInt32(1)}");
else
sb.Append(canViewLeave && viewAll ? $"<a class=\"hand-cursor\" href=\"#/empleaves\">Leave: {dr.GetInt32(1)}</a>" : $"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;
}
/// <summary> /// <summary>
/// ///
@ -2240,8 +2266,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
LoginTime = dr.GetDateTime(1), LoginTime = dr.GetDateTime(1),
LoginIp = dr.GetString(2), LoginIp = dr.GetString(2),
LogoutTime = dr.IsDBNull(3) ? null : dr.GetDateTime(3), LogoutTime = dr.IsDBNull(3) ? null : dr.GetDateTime(3),
LogoutIp = dr.IsDBNull(4) ? null : dr.GetString(4), LogoutIp = dr.IsDBNull(4) ? null : dr.GetString(4)
LoginStatus = dr.GetString(5),
}; };
response.Value.Add(item); response.Value.Add(item);
@ -2612,6 +2637,12 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
} }
internal class UserSearchResponse
{
}
} }

View File

@ -1,8 +1,12 @@
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Setups; using Microsoft.Extensions.DependencyInjection;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Setups;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems; using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
using OnlineSalesAutoCrop.CoreAPI.Services.Services.Auth;
using OnlineSalesAutoCrop.CoreAPI.Services.Services.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Services.Setups; using OnlineSalesAutoCrop.CoreAPI.Services.Services.Setups;
using OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems; using OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems;
using Microsoft.Extensions.DependencyInjection;
namespace OnlineSalesAutoCrop.CoreAPI.Configuration.DI namespace OnlineSalesAutoCrop.CoreAPI.Configuration.DI
{ {
@ -25,7 +29,8 @@ namespace OnlineSalesAutoCrop.CoreAPI.Configuration.DI
services.AddTransient<IParamTypeService, ParamTypeService>(); services.AddTransient<IParamTypeService, ParamTypeService>();
services.AddTransient<IThisSystemService, ThisSystemService>(); services.AddTransient<IThisSystemService, ThisSystemService>();
services.AddTransient<IAuthModulesService, AuthModulesService>(); services.AddTransient<IAuthModulesService, AuthModulesService>();
services.AddTransient<IRefreshTokenService, RefreshTokenService>();
services.AddScoped<IIntegrationService, IntegrationService>();
} }
} }
} }

View File

@ -0,0 +1,74 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Services.Integrations;
using System;
using System.Threading.Tasks;
namespace OnlineSalesAutoCrop.CoreAPI.Controllers.IntegretionApi
{
/// <summary>
///
/// </summary>
/// <remarks>
///
/// </remarks>
/// <param name="logger"></param>
/// <param name="integrationService"></param>
[Authorize]
[ApiController]
[ApiVersion("1.0")]
[ValidateAntiForgeryToken]
[Route("api/v{version:apiVersion}/Integration")]
public class IntegrationController(ILogger<IntegrationAuthController> logger, IIntegrationService integrationService) : ControllerBase
{
private readonly ILogger _logger = logger;
private readonly IIntegrationService _integrationService = integrationService;
/// <summary>
/// Insert or Update Customers for SAP
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="request"></param>
/// <returns>if created return 201 or if updated return 204 true</returns>
[HttpGet("Customers")]
[IgnoreAntiforgeryToken]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IntegrationLoginResponse))]
public async Task<IActionResult> UpsertCustomers(CustomerIntegrationRequest request)
{
CustomerIntegrationResponse response = new CustomerIntegrationResponse();
try
{
bool result = await _integrationService.UpsertCustomerAsync(request);
if (result)
{
response.ReturnMessage.Add($"Customer Created Successfully for CustomerNumber :{request.CustomerNumber} & CompanyCode:{request.CompanyCode}");
response.ReturnStatus = StatusCodes.Status201Created;
return StatusCode(StatusCodes.Status201Created, response);
}
else
{
response.ReturnMessage.Add($"Customer Updated Successfully for CustomerNumber :{request.CustomerNumber} & CompanyCode:{request.CompanyCode}");
response.ReturnStatus = StatusCodes.Status204NoContent;
return StatusCode(StatusCodes.Status204NoContent, response);
}
}
catch (Exception ex)
{
string msg = $"Exception Occur in Customer Operation {request?.CustomerName}~{request?.CompanyCode}";
_logger.LogError(exception: ex, msg);
response.ReturnStatus = StatusCodes.Status500InternalServerError;
response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, response);
}
}
}
}

View File

@ -3,7 +3,6 @@ using OnlineSalesAutoCrop.CoreAPI.Configurations;
using OnlineSalesAutoCrop.CoreAPI.Models; using OnlineSalesAutoCrop.CoreAPI.Models;
using OnlineSalesAutoCrop.CoreAPI.Models.Global; using OnlineSalesAutoCrop.CoreAPI.Models.Global;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects; using OnlineSalesAutoCrop.CoreAPI.Models.Objects;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Setups;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems; using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests; using OnlineSalesAutoCrop.CoreAPI.Models.Requests;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups; using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups;
@ -19,7 +18,6 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.Reporting.NETCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.DirectoryServices; using System.DirectoryServices;
@ -51,7 +49,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
[Route("api/v{version:apiVersion}/users")] [Route("api/v{version:apiVersion}/users")]
public class UserController(IUserService service, IOptions<AppSettings> appSettings, IEaseCache cache, ILogger<UserController> logger, IHubContext<NotificationHub, INotificationHub> hub) : ControllerBase public class UserController(IUserService service, IOptions<AppSettings> appSettings, IEaseCache cache, ILogger<IntegrationAuthController> logger, IHubContext<NotificationHub, INotificationHub> hub) : ControllerBase
{ {
private readonly ILogger _logger = logger; private readonly ILogger _logger = logger;
private readonly IEaseCache _cache = cache; private readonly IEaseCache _cache = cache;
@ -148,7 +146,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
ipAddress = Request.HttpContext.GetIpAddress(); ipAddress = Request.HttpContext.GetIpAddress();
User user = await _service.LoginAsync(request: request, ipAddress: ipAddress, checkPwd: checkPwd); User user = await _service.LoginAsync(request: request, ipAddress: ipAddress, checkPwd: checkPwd);
if (user == null || user.Id == 0) if (user == null || user.UserId == 0)
{ {
response.LoginStatus = EnumLoginStatus.Error; response.LoginStatus = EnumLoginStatus.Error;
response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnStatus = StatusCodes.Status403Forbidden;
@ -207,7 +205,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
response.Map(user); response.Map(user);
response.ValidUser = true; response.ValidUser = true;
response.ReturnStatus = StatusCodes.Status200OK; response.ReturnStatus = StatusCodes.Status200OK;
response.PwdChangeRequired = (user.AccessStatus == EnumAccessStatus.FirstTime) || (user.ExpireDate.HasValue && user.ExpireDate.Value.Date < DateTime.Today.Date); //response.PwdChangeRequired = (user.AccessStatus == EnumAccessStatus.FirstTime) || (user.ExpireDate.HasValue && user.ExpireDate.Value.Date < DateTime.Today.Date);
string pwdSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.PwdSecretKey); string pwdSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.PwdSecretKey);
string userPwd = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(privateKey: pwdSecretKey, publicKey: pwdSecretKey, data: request.Password); string userPwd = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(privateKey: pwdSecretKey, publicKey: pwdSecretKey, data: request.Password);
@ -217,15 +215,15 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
{ {
Subject = new ClaimsIdentity( Subject = new ClaimsIdentity(
[ [
Helper.CreateClaim("UserId", $"{user.Id}"), //Helper.CreateClaim("UserId", $"{user.Id}"),
Helper.CreateClaim("LoginId", user.LoginId), //Helper.CreateClaim("LoginId", user.LoginId),
Helper.CreateClaim("UserPwd", userPwd), //Helper.CreateClaim("UserPwd", userPwd),
Helper.CreateClaim("AuthKey", $"{user.AuthKey}"), //Helper.CreateClaim("AuthKey", $"{user.AuthKey}"),
Helper.CreateClaim("TeamSpaceIds", $"{string.Join(',',user.TeamSpaceIds)}"), //Helper.CreateClaim("TeamSpaceIds", $"{string.Join(',',user.TeamSpaceIds)}"),
Helper.CreateClaim("BatchEnabled", user.BatchEnabled ? "1" : "0"), //Helper.CreateClaim("BatchEnabled", user.BatchEnabled ? "1" : "0"),
Helper.CreateClaim("BmProcessId", $"{user.BmProcessId}"), //Helper.CreateClaim("BmProcessId", $"{user.BmProcessId}"),
Helper.CreateClaim("PrProcessId", $"{user.PrProcessId}"), //Helper.CreateClaim("PrProcessId", $"{user.PrProcessId}"),
Helper.CreateClaim("EmployeeId", $"{user.EmployeeCode}") //Helper.CreateClaim("EmployeeId", $"{user.EmployeeCode}")
]), ]),
Expires = DateTime.UtcNow.AddHours(12), Expires = DateTime.UtcNow.AddHours(12),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature) SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
@ -248,35 +246,35 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
response.AuthenticationToken = userToken; response.AuthenticationToken = userToken;
response.LoginTime = $"{DateTime.Now:dd-MM-yy H:mm:ss}"; response.LoginTime = $"{DateTime.Now:dd-MM-yy H:mm:ss}";
await HttpContext.Session.SetModulesToSession(key: userToken, value: user.ModuleIds); //await HttpContext.Session.SetModulesToSession(key: userToken, value: user.ModuleIds);
if (user.LoginStatus == EnumLoginStatus.Success) //if (user.LoginStatus == EnumLoginStatus.Success)
{ //{
if (user.AuthMethod == EnumAuthenticationMethod.Email && !string.IsNullOrEmpty(user.EmailAddress) && !string.IsNullOrWhiteSpace(user.EmailAddress) && !string.IsNullOrWhiteSpace(user.AuthValue)) // if (user.AuthMethod == EnumAuthenticationMethod.Email && !string.IsNullOrEmpty(user.EmailAddress) && !string.IsNullOrWhiteSpace(user.EmailAddress) && !string.IsNullOrWhiteSpace(user.AuthValue))
{ // {
List<string> to = [.. user.EmailAddress.Split(separator: ';', options: StringSplitOptions.RemoveEmptyEntries)]; // List<string> to = [.. user.EmailAddress.Split(separator: ';', options: StringSplitOptions.RemoveEmptyEntries)];
await MailHelper.SendMailMessageAsync(settings: _appSettings, to: to, // await MailHelper.SendMailMessageAsync(settings: _appSettings, to: to,
cc: null, bcc: null, attachments: null, embeddedImages: null, isHtmlBody: false, priority: System.Net.Mail.MailPriority.Normal, // cc: null, bcc: null, attachments: null, embeddedImages: null, isHtmlBody: false, priority: System.Net.Mail.MailPriority.Normal,
subject: "Your OTP", messageBody: string.Format("Your OTP: {0} and is valid for 5 minutes only", user.AuthValue)); // subject: "Your OTP", messageBody: string.Format("Your OTP: {0} and is valid for 5 minutes only", user.AuthValue));
} // }
else if (user.AuthMethod == EnumAuthenticationMethod.MobileSMS && !string.IsNullOrEmpty(user.MobileNo) && !string.IsNullOrWhiteSpace(user.MobileNo) && !string.IsNullOrWhiteSpace(user.AuthValue)) // else if (user.AuthMethod == EnumAuthenticationMethod.MobileSMS && !string.IsNullOrEmpty(user.MobileNo) && !string.IsNullOrWhiteSpace(user.MobileNo) && !string.IsNullOrWhiteSpace(user.AuthValue))
{ // {
MailHelper.SendSMSOrWhatsAppMessage(settings: _appSettings, whatsAppMsg: false, msg: string.Format("Your OTP: {0} and is valid for 5 minutes only", user.AuthValue), mobileNumber: user.MobileNo); // MailHelper.SendSMSOrWhatsAppMessage(settings: _appSettings, whatsAppMsg: false, msg: string.Format("Your OTP: {0} and is valid for 5 minutes only", user.AuthValue), mobileNumber: user.MobileNo);
} // }
} //}
if (user.DisallowMultiLogin) //if (user.DisallowMultiLogin)
{ //{
await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 1, itemId: 0, ipAddress: ipAddress); // await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 1, itemId: 0, ipAddress: ipAddress);
if (request.AttendanceLogin) // if (request.AttendanceLogin)
await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress); // await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress);
} //}
else //else
{ //{
await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 2, itemId: 0, ipAddress: ipAddress); // await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 2, itemId: 0, ipAddress: ipAddress);
if (request.AttendanceLogin) // if (request.AttendanceLogin)
await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress); // await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress);
} //}
response.IdsValue = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(data: Newtonsoft.Json.JsonConvert.SerializeObject(user.ModuleIds), privateKey: cipherSecretKey, publicKey: cipherSecretKey, output: 2); //response.IdsValue = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(data: Newtonsoft.Json.JsonConvert.SerializeObject(user.ModuleIds), privateKey: cipherSecretKey, publicKey: cipherSecretKey, output: 2);
return Ok(response); return Ok(response);
} }
@ -998,39 +996,39 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
/// </returns> /// </returns>
/// <response code="200">Top 50 users</response> /// <response code="200">Top 50 users</response>
/// <response code="204">If the item is null.</response> /// <response code="204">If the item is null.</response>
[ValidateSession] //[ValidateSession]
[HttpPost("getUsers")] //[HttpPost("getUsers")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))] //[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))]
[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))] //[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))]
public async Task<IActionResult> GetUsers([FromBody] UserSearchRequest request) //public async Task<IActionResult> GetUsers([FromBody] UserSearchRequest request)
{ //{
ArgumentNullException.ThrowIfNull(request); // ArgumentNullException.ThrowIfNull(request);
UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; // UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
try // try
{ // {
int userId = HttpContext.User.GetClaimValue<int>(Constants.UserId); // int userId = HttpContext.User.GetClaimValue<int>(Constants.UserId);
request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id; // request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id;
string key = "Users"; // string key = "Users";
string key2 = $"{request.Criteria}~{request.Status}~{request.SortField}~{request.SortOrder}~{request.Skip}~{request.PageSize}~{request.CheckOwner}~{userId}"; // 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)) // if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
{ // {
response = await _service.GetUsersAsync(request: request, userId: userId); // response = await _service.GetUsersAsync(request: request, userId: userId);
_ = _cache.Set(key: key, key2: key2, value: response, options: _options); // _ = _cache.Set(key: key, key2: key2, value: response, options: _options);
} // }
response.ReturnStatus = StatusCodes.Status200OK; // response.ReturnStatus = StatusCodes.Status200OK;
return Ok(response); // return Ok(response);
} // }
catch (Exception ex) // catch (Exception ex)
{ // {
_logger.LogError(ex); // _logger.LogError(ex);
response.ReturnStatus = StatusCodes.Status500InternalServerError; // response.ReturnStatus = StatusCodes.Status500InternalServerError;
response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); // response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, response); // return StatusCode(StatusCodes.Status500InternalServerError, response);
} // }
} //}
/// <summary> /// <summary>
/// ///
@ -1356,41 +1354,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
} }
} }
/// <summary>
///
/// </summary>
/// <returns></returns>
[ValidateSession]
[HttpPost("getDashboardData")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(DashboardDataResponse))]
[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(DashboardDataResponse))]
public async Task<IActionResult> 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<int>(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);
}
}
/// <summary> /// <summary>
/// ///

View File

@ -1,33 +0,0 @@
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
# Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
# For more information, please see https://aka.ms/containercompat
# This stage is used when running from VS in fast mode (Default for Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:9.0-nanoserver-1809 AS base
WORKDIR /app
EXPOSE 8080
# This stage is used to build the service project
FROM mcr.microsoft.com/dotnet/sdk:9.0-nanoserver-1809 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["Api/OnlineSalesAutoCrop.CoreAPI/OnlineSalesAutoCrop.CoreAPI.csproj", "Api/OnlineSalesAutoCrop.CoreAPI/"]
COPY ["Api/OnlineSalesAutoCrop.CoreAPI.Models/OnlineSalesAutoCrop.CoreAPI.Models.csproj", "Api/OnlineSalesAutoCrop.CoreAPI.Models/"]
COPY ["Api/OnlineSalesAutoCrop.CoreAPI.Services/OnlineSalesAutoCrop.CoreAPI.Services.csproj", "Api/OnlineSalesAutoCrop.CoreAPI.Services/"]
RUN dotnet restore "./Api/OnlineSalesAutoCrop.CoreAPI/OnlineSalesAutoCrop.CoreAPI.csproj"
COPY . .
WORKDIR "/src/Api/OnlineSalesAutoCrop.CoreAPI"
RUN dotnet build "./OnlineSalesAutoCrop.CoreAPI.csproj" -c %BUILD_CONFIGURATION% -o /app/build
# This stage is used to publish the service project to be copied to the final stage
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./OnlineSalesAutoCrop.CoreAPI.csproj" -c %BUILD_CONFIGURATION% -o /app/publish /p:UseAppHost=false
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "OnlineSalesAutoCrop.CoreAPI.dll"]

View File

@ -3,6 +3,8 @@
<PropertyGroup> <PropertyGroup>
<NameOfLastUsedPublishProfile>D:\Local\EaseBilling\Api\EaseO2C.CoreAPI\Properties\PublishProfiles\Windows.Publish.pubxml</NameOfLastUsedPublishProfile> <NameOfLastUsedPublishProfile>D:\Local\EaseBilling\Api\EaseO2C.CoreAPI\Properties\PublishProfiles\Windows.Publish.pubxml</NameOfLastUsedPublishProfile>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile> <ActiveDebugProfile>IIS Express</ActiveDebugProfile>
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor> <DebuggerFlavor>ProjectDebugger</DebuggerFlavor>

View File

@ -57,6 +57,7 @@ namespace OnlineSalesAutoCrop.CoreAPI
_appSettings = Configuration.GetSection("AppSettings").Get<AppSettings>(); _appSettings = Configuration.GetSection("AppSettings").Get<AppSettings>();
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>

View File

@ -29,54 +29,9 @@
"DbConfig": [ "DbConfig": [
{ {
"ConnectionNode": { "ConnectionNode": {
"ConnectionString": "Data Source=103.197.204.162,3341;Initial Catalog=OnlineSalesAutoCrop;User ID=OnlineSalesAutoCropSysUser;Password=OnlineSalesAutoCrop;Encrypt=false;", "ConnectionString": "Data Source=210.4.65.222,3341;Initial Catalog=AutoCropDB;User ID=dmsuser;Password=dMsu@er;Encrypt=false;",
"EncryptKey": "",
"Key": "spadb1", "Key": "spadb1",
"Provider": "sql", "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;",
"Key": "spadb7",
"Provider": "sql",
"SqlSyntax": "SQL", "SqlSyntax": "SQL",
"EncryptKey": "" "EncryptKey": ""
} }
@ -128,7 +83,8 @@
"WaAccountSid": "AC0138ad79a532f653c35072dad10e52b9", "WaAccountSid": "AC0138ad79a532f653c35072dad10e52b9",
"WaAuthToken": "024a6897584671d9f9fa588d7c94aa96", "WaAuthToken": "024a6897584671d9f9fa588d7c94aa96",
"WaMsgSvcSid": "MG8401d33a9a3b2aea95619bda3e5757b5", "WaMsgSvcSid": "MG8401d33a9a3b2aea95619bda3e5757b5",
"WaSenderId": "+8801326755660" "WaSenderId": "+8801326755660",
"RefreshTokenDuration": "15"
}, },
"MenuSettings": { "MenuSettings": {