complete auth for mobile api
This commit is contained in:
parent
43efe23587
commit
1b738897d2
|
|
@ -718,4 +718,22 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models
|
|||
[Description("Percentage Based Discount")]
|
||||
ZDS2 = 3
|
||||
}
|
||||
|
||||
public enum UserPlatFormType : short
|
||||
{
|
||||
SAP=1,
|
||||
AppUser =2,
|
||||
}
|
||||
|
||||
public enum UserRoleTypeEnum
|
||||
{
|
||||
[Description("SAP User")]
|
||||
SapUser = 1,
|
||||
[Description("Order Collector")]
|
||||
OrderCollector = 2,
|
||||
[Description("OrderValidator")]
|
||||
OrderValidator = 3,
|
||||
[Description("OrderApprover")]
|
||||
OrderApprover =4
|
||||
}
|
||||
}
|
||||
|
|
@ -26,9 +26,14 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems
|
|||
public string SchemeName { get; set; }
|
||||
public string MenuLayout { get; set; }
|
||||
public bool IsLocked { get; set; }
|
||||
|
||||
public UserPlatFormType? UserPlatFormType { get; set; }
|
||||
public UserRoleTypeEnum? UserRoleType { get; set; }
|
||||
public string? EmployeeNumber { get; set; }
|
||||
public string? DesignationCode { get; set; }
|
||||
public string? DesignationName { get; set; }
|
||||
public EnumLoginStatus LoginStatus { get; set; }
|
||||
public DateTime? NextLoginTime { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class LoginHistory
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Common;
|
||||
|
||||
public class AuthLoginRequest
|
||||
{
|
||||
[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; }
|
||||
}
|
||||
|
|
@ -1,20 +1,14 @@
|
|||
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Common;
|
||||
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
|
||||
public class IntegrationLoginRequest
|
||||
public class IntegrationLoginRequest : AuthLoginRequest
|
||||
{
|
||||
[Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 3, ErrorMessage = "Login Id must be between 4 and 30 characters.")]
|
||||
public string LoginId { get; set; }
|
||||
|
||||
[Required, NotNull, StringLength(maximumLength: 150, MinimumLength = 5, ErrorMessage = "Password must be between 1 and 30 characters.")]
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class IntegrationRefreshTokenRequest
|
||||
{
|
||||
public string RefreshToken { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.MobileApp;
|
||||
|
||||
public class MobileAppAuthRequest : AuthLoginRequest
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class AuthLogoutRequest
|
||||
{
|
||||
[Required, NotNull, StringLength(maximumLength: 10, MinimumLength = 3, ErrorMessage = "Login Id must be between 3 and 10 characters.")]
|
||||
public string LoginId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class AppUserChangePasswordRequest
|
||||
{
|
||||
[Required, NotNull, StringLength(maximumLength: 10, MinimumLength = 3, ErrorMessage = "Login Id must be between 3 and 10 characters.")]
|
||||
public string LoginId { get; set; }
|
||||
|
||||
[Required, NotNull, StringLength(maximumLength: 20, MinimumLength = 5, ErrorMessage = "Password must be between 5 and 20 characters.")]
|
||||
public string Password { get; set; }
|
||||
|
||||
[Required, NotNull, StringLength(maximumLength: 20, MinimumLength = 5, ErrorMessage = "Password must be between 5 and 20 characters.")]
|
||||
public string NewPassword { get; set; }
|
||||
|
||||
[Required, NotNull, StringLength(maximumLength: 20, MinimumLength = 5, ErrorMessage = "Password must be between 5 and 20 characters.")]
|
||||
[Compare("NewPassword", ErrorMessage = "Password and Confirm Password do not match.")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(NewPassword) &&
|
||||
!string.IsNullOrWhiteSpace(ConfirmPassword) &&
|
||||
Password != ConfirmPassword)
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"Password and Confirm Password do not match.",
|
||||
[nameof(NewPassword), nameof(ConfirmPassword)]
|
||||
);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(LoginId) &&
|
||||
!string.IsNullOrWhiteSpace(NewPassword) &&
|
||||
Password.Equals(LoginId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"Password must not be the same as your Login ID.",
|
||||
[nameof(NewPassword)]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
|
||||
|
|
@ -219,3 +220,43 @@ public class PayslipRequest
|
|||
[Required, NotNull]
|
||||
public DateTime YearMonth { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class AppUserCreateRequest
|
||||
{
|
||||
[Required(ErrorMessage = "Login ID is required.")]
|
||||
[MaxLength(100, ErrorMessage = "Login ID cannot exceed 100 characters.")]
|
||||
public string LoginId { get; set; } = string.Empty;
|
||||
|
||||
[Required(ErrorMessage = "Username is required.")]
|
||||
[MaxLength(150, ErrorMessage = "Username cannot exceed 150 characters.")]
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public int Status { get; set; }
|
||||
|
||||
[Required]
|
||||
public int AccessStatus { get; set; }
|
||||
|
||||
[Phone(ErrorMessage = "Invalid mobile number format.")]
|
||||
[MaxLength(20, ErrorMessage = "Mobile number cannot exceed 20 characters.")]
|
||||
public string? MobileNo { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "Email address is required.")]
|
||||
[EmailAddress(ErrorMessage = "Invalid email address format.")]
|
||||
[MaxLength(200, ErrorMessage = "Email address cannot exceed 200 characters.")]
|
||||
public string EmailAddress { get; set; } = string.Empty;
|
||||
|
||||
public int IsLocked { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "Password is required.")]
|
||||
[MaxLength(500, ErrorMessage = "Password hash length cannot exceed 500 characters.")]
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
public int? UserPlatformId { get; set; }
|
||||
|
||||
public int? UserRoleType { get; set; }
|
||||
|
||||
[MaxLength(10,ErrorMessage = "EmployeeNumber hash length cannot exceed 10 characters")]
|
||||
public string? EmployeeNumber { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ public class IntegrationRrefreshTokenResponse : ResponseBase
|
|||
public string RefreshToken { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public class RefreshTokenResponse : ResponseBase
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
|
||||
using System;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.MobileApp;
|
||||
|
||||
public class AppAuthUserResponse : ResponseBase
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
public string LoginId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? MobileNumber { get; set; }
|
||||
public string EmployeeNumber { get; set; }
|
||||
public string DesignationCode { get; set; }
|
||||
public string DesignationName { get; set; }
|
||||
public bool IsLocked { get; set; }
|
||||
public UserRoleTypeEnum UserRole { get; set; }
|
||||
public string AccessToken { get; set; }
|
||||
public DateTime AccessTokenExpiryTime { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
public DateTime RefreshTokenExpiryTime { get; set; }
|
||||
public EnumLoginStatus LoginStatus { get; set; }
|
||||
public bool IsAuthorized { get; set; }
|
||||
public bool IsInitialPassword { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class AuthLogoutResponse : ResponseBase
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
public string LoginId { get; set; }
|
||||
public bool IsSuccess { get; set; }
|
||||
}
|
||||
|
||||
public class AppChangePasswordResponse : ResponseBase
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
public string LoginId { get; set; }
|
||||
public bool IsSuccess { get; set; }
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
using Ease.NetCore.DataAccess;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -9,4 +10,5 @@ public interface IRefreshTokenService
|
|||
Task<GenerateRefreshTokenResponse> GenerateRefreshTokenByUserAsync(GenerateRefreshTokenRequest request);
|
||||
Task<string> GenerateRefreshTokenAsync(string refreshToken, string ipAddress);
|
||||
Task<UserByRefreshTokenResponse> GetUserByRefreshTokenAsync(string refreshToken);
|
||||
Task<bool> InvalidRefreshTokenAsync(TransactionContext tc, int userId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Setups;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Common;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.MobileApp;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.MobileApp;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -13,10 +16,14 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems
|
|||
{
|
||||
Task<bool> ValidateAuthValueAsync(string authValue, int userId);
|
||||
Task<User> LoginAsync(LoginRequest request, string ipAddress, bool checkPwd);
|
||||
Task<AppAuthUserResponse> LoginAsync(MobileAppAuthRequest request, string ipAddress);
|
||||
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<AuthLogoutResponse> LogoutAsync(AuthLogoutRequest request, string ipAddress);
|
||||
Task<AppChangePasswordResponse> ChangePasswordAsync(AppUserChangePasswordRequest request, string ipAddress);
|
||||
|
||||
Task<bool> DeleteUserAsync(int userId, int deletedBy);
|
||||
Task<bool> ForceLogoutNowAsync(List<int> userIds, string ipAddress);
|
||||
Task<bool> UnlockUserAsync(int userId, string loginId, int unlockedBy);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ 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;
|
||||
|
|
@ -116,6 +117,22 @@ public class RefreshTokenService : IRefreshTokenService
|
|||
return refreshTokenResponse;
|
||||
}
|
||||
|
||||
public async Task<bool> InvalidRefreshTokenAsync( TransactionContext tc, int userId)
|
||||
{
|
||||
bool response = false;
|
||||
try
|
||||
{
|
||||
RevokeRefreshTokenByUserIdAsync(tc, userId);
|
||||
response = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException(e.Message, e);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
#region Private Methods
|
||||
// ----- private helpers -----
|
||||
|
||||
|
|
@ -145,7 +162,7 @@ public class RefreshTokenService : IRefreshTokenService
|
|||
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)),
|
||||
SqlHelperExtension.CreateInParam(pName: "@ExpiredAt", pType: SqlDbType.DateTime, pValue: refreshToken.ExpiresAt),
|
||||
];
|
||||
_ = tc.ExecuteNonQuerySp(spName: "dbo.InsertRefreshToken", parameterValues: p);
|
||||
|
||||
|
|
@ -259,7 +276,7 @@ public class RefreshTokenService : IRefreshTokenService
|
|||
return new GenerateRefreshTokenResponse
|
||||
{
|
||||
RefreshToken = tokenHash,
|
||||
ExpireTime = DateTime.UtcNow.AddMinutes(_settings.RefreshTokenDuration)
|
||||
ExpireTime = DateTime.UtcNow.AddDays(_settings.RefreshTokenDuration)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -277,5 +294,7 @@ public class RefreshTokenService : IRefreshTokenService
|
|||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
using Ease.NetCore.DataAccess;
|
||||
using Ease.NetCore.DataAccess.SQL;
|
||||
using Ease.NetCore.Utility;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Integrations;
|
||||
|
|
@ -16,10 +22,12 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Integrations;
|
|||
public class IntegrationService : IIntegrationService
|
||||
{
|
||||
private readonly AppSettings _settings;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public IntegrationService(IOptions<AppSettings> options)
|
||||
public IntegrationService(IOptions<AppSettings> options, IUserService userService)
|
||||
{
|
||||
_settings = options.Value;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -142,6 +150,28 @@ public class IntegrationService : IIntegrationService
|
|||
response.IsUpdated = false;
|
||||
}
|
||||
|
||||
bool isUserExist = await IsUserExistByEmployeeNumberAsync(tc, request.EmployeeVendorCode);
|
||||
|
||||
if (!isUserExist)
|
||||
{
|
||||
AppUserCreateRequest appUser = new()
|
||||
{
|
||||
LoginId = request.EmployeeVendorCode,
|
||||
UserName = request.EmployeeVendorCode,
|
||||
Status = (int)EnumStatus.Authorized,
|
||||
AccessStatus = (int)EnumAccessStatus.FirstTime,
|
||||
MobileNo = request.MobileNo,
|
||||
EmailAddress = request.Mail,
|
||||
IsLocked = 0,
|
||||
Password ="12345",
|
||||
UserRoleType = request.Designation == "01"? (int)UserRoleTypeEnum.OrderCollector : null,
|
||||
UserPlatformId = (int)UserPlatFormType.AppUser,
|
||||
EmployeeNumber = request.EmployeeVendorCode
|
||||
};
|
||||
|
||||
await AddUserAsync(tc, appUser);
|
||||
}
|
||||
|
||||
response.EmployeeVendorCode = request.EmployeeVendorCode;
|
||||
response.CompanyCode = request.CompanyCode;
|
||||
tc.End();
|
||||
|
|
@ -717,6 +747,93 @@ public class IntegrationService : IIntegrationService
|
|||
return response;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> AddUserAsync(TransactionContext tc, AppUserCreateRequest user)
|
||||
{
|
||||
bool returnValue;
|
||||
try
|
||||
{
|
||||
int userId = 0;
|
||||
user.Password = EncryptPassword(password: user.Password);
|
||||
|
||||
if (!string.IsNullOrEmpty(user.EmailAddress))
|
||||
user.EmailAddress = user.EmailAddress.Replace(" ", "");
|
||||
|
||||
|
||||
SqlParameter[] p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 100),
|
||||
SqlHelperExtension.CreateInParam(pName: "@UserName", pType: SqlDbType.VarChar, pValue: user.UserName, size: 150),
|
||||
SqlHelperExtension.CreateInParam(pName: "@Status", pType: SqlDbType.Int, pValue: user.Status),
|
||||
SqlHelperExtension.CreateInParam(pName: "@AccessStatus", pType: SqlDbType.Int, pValue: user.AccessStatus),
|
||||
SqlHelperExtension.CreateInParam(pName: "@MobileNo", pType: SqlDbType.VarChar, pValue: DataReader.GetNullValue(user.MobileNo), size: 20),
|
||||
SqlHelperExtension.CreateInParam(pName: "@EmailAddress", pType: SqlDbType.VarChar, pValue: user.EmailAddress, size: 200),
|
||||
SqlHelperExtension.CreateInParam(pName: "@IsLocked", pType: SqlDbType.Int, pValue: user.IsLocked),
|
||||
SqlHelperExtension.CreateInParam(pName: "@Password", pType: SqlDbType.NVarChar, pValue: user.Password, size: 500),
|
||||
SqlHelperExtension.CreateInParam(pName: "@UserPlatformId", pType: SqlDbType.Int, pValue: DataReader.GetNullValue(user.UserPlatformId)),
|
||||
SqlHelperExtension.CreateInParam(pName: "@UserRoleType", pType: SqlDbType.Int, pValue: DataReader.GetNullValue(user.UserRoleType)),
|
||||
SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.VarChar, pValue: DataReader.GetNullValue(user.EmployeeNumber), size: 10),
|
||||
SqlHelperExtension.CreateOutParam(pName: "@NewUserId", pType: SqlDbType.Int) // index 11 — output
|
||||
];
|
||||
|
||||
_ = tc.ExecuteNonQuerySp(spName: "dbo.InsertUser", parameterValues: p);
|
||||
userId = (p[11]?.Value != null && p[11]?.Value != DBNull.Value)
|
||||
? Convert.ToInt32(p[11].Value)
|
||||
: 0;
|
||||
|
||||
returnValue = userId > 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException(e.Message, e);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
private string EncryptPassword(string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
string pwdSecretKey = GlobalFunctions.ConvertFromBase64String(_settings.PwdSecretKey);
|
||||
return Global.CipherFunctions.EncryptByAES(privateKey: pwdSecretKey, publicKey: pwdSecretKey, data: password);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException(e.Message, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async Task<bool> IsUserExistByEmployeeNumberAsync(TransactionContext tc, string employeeNumber)
|
||||
{
|
||||
bool response = false;
|
||||
|
||||
try
|
||||
{
|
||||
SqlParameter[] p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@EmployeeNumber", pType: SqlDbType.NVarChar, pValue: employeeNumber)
|
||||
];
|
||||
|
||||
using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.IsUserExistByEmployeeNumber", parameterValues: p))
|
||||
{
|
||||
if (dr.Read())
|
||||
{
|
||||
response = dr.GetInt32(0) > 0 ? true: false;
|
||||
}
|
||||
dr.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw DBCustomError.GenerateCustomError(ex);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private bool InsertEmployee(TransactionContext tc, IntegrationEmployeeRequest request)
|
||||
{
|
||||
bool returnValue = false;
|
||||
|
|
|
|||
|
|
@ -1,28 +1,33 @@
|
|||
using Ease.NetCore.DataAccess;
|
||||
using Ease.NetCore.DataAccess.SQL;
|
||||
using Ease.NetCore.Utility;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Common;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.MobileApp;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.MobileApp;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
||||
{
|
||||
public class UserService(IOptions<AppSettings> settings, IOptions<MenuSettings> menuSettings) : IUserService
|
||||
public class UserService(IOptions<AppSettings> settings, IOptions<MenuSettings> menuSettings, IRefreshTokenService refreshTokenService) : IUserService
|
||||
{
|
||||
private readonly AppSettings _settings = settings?.Value;
|
||||
private readonly MenuSettings _menuSettings = menuSettings?.Value;
|
||||
private readonly IRefreshTokenService _refreshTokenService = refreshTokenService;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
|
@ -348,6 +353,192 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
|||
}
|
||||
|
||||
|
||||
public async Task<AppAuthUserResponse> LoginAsync(MobileAppAuthRequest request, string ipAddress)
|
||||
{
|
||||
AppAuthUserResponse response = null;
|
||||
try
|
||||
{
|
||||
string password = EncryptPassword(password: request.Password);
|
||||
User user = null;
|
||||
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
|
||||
try
|
||||
{
|
||||
DateTime sysDate = DateTime.Today.Date;
|
||||
string appVer = string.Empty, alParams = string.Empty;
|
||||
int maxTryCount = 5, lockTime = 1;
|
||||
|
||||
bool initialPassword = false;
|
||||
|
||||
#region Read User data using authentication data
|
||||
|
||||
SqlParameter[] p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.NVarChar, pValue: request.LoginId)
|
||||
];
|
||||
|
||||
using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetUserByLogin", parameterValues: p))
|
||||
{
|
||||
if (dr.Read())
|
||||
{
|
||||
user = new User();
|
||||
{
|
||||
user.UserId = dr.GetInt32(0);
|
||||
user.Password = dr.GetString(1);
|
||||
user.LoginId = dr.GetString(2);
|
||||
user.UserName = dr.GetString(3);
|
||||
user.Status = (EnumStatus)dr.GetInt32(4);
|
||||
user.MobileNo = dr.GetString(5);
|
||||
user.EmailAddress = dr.GetString(6);
|
||||
user.AuthKey = dr.GetString(7);
|
||||
user.AuthValue = dr.GetString(8);
|
||||
user.IsLocked = dr.GetBoolean(9);
|
||||
user.LoginStatus = EnumLoginStatus.Success;
|
||||
user.UserRoleType = (UserRoleTypeEnum)dr.GetInt32(10);
|
||||
user.EmployeeNumber = dr.GetString(11);
|
||||
user.DesignationCode = dr.GetString(12);
|
||||
user.DesignationName = dr.GetString(13);
|
||||
};
|
||||
|
||||
initialPassword = dr.GetInt32(14) > 0;
|
||||
}
|
||||
dr.Close();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#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;
|
||||
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";
|
||||
p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: request.LoginId, size: 30),
|
||||
SqlHelperExtension.CreateInParam(pName: "@TryLoginInfo", pType: SqlDbType.VarChar, pValue: tryLoginInfo, size: 100),
|
||||
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
||||
SqlHelperExtension.CreateInParam(pName: "@MaxTryCount", pType: SqlDbType.SmallInt, pValue: maxTryCount),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LockTime", pType: SqlDbType.Int, pValue: lockTime),
|
||||
SqlHelperExtension.CreateOutParam(pName: "@RemainingTry", pType: SqlDbType.SmallInt, pValue: remainsTry),
|
||||
SqlHelperExtension.CreateOutParam(pName: "@NextLoginTime", pType: SqlDbType.DateTime, pValue: nextLoginTime),
|
||||
];
|
||||
_ = tc.ExecuteNonQuerySp(spName: "dbo.LogUnauthorizeAccess", parameterValues: p);
|
||||
if (p[5] != null && p[5].Value != null && p[5].Value != DBNull.Value)
|
||||
remainsTry = Convert.ToInt32(p[5].Value);
|
||||
|
||||
if (p[6] != null && p[6].Value != null && p[6].Value != DBNull.Value)
|
||||
nextLoginTime = Convert.ToDateTime(p[6].Value);
|
||||
|
||||
if (remainsTry <= 0)
|
||||
{
|
||||
user.IsLocked = true;
|
||||
if (lockTime <= 0)
|
||||
{
|
||||
user.NextLoginTime = nextLoginTime;
|
||||
user.UnsuccessfulMsg = "Please contact with Head office to Unlock";
|
||||
}
|
||||
else
|
||||
{
|
||||
user.NextLoginTime = nextLoginTime;
|
||||
user.UnsuccessfulMsg = $"You can Login after {user.NextLoginTime:dd-MMM-yyyy H:mm:ss}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
user.UnsuccessfulMsg = $"{remainsTry} More attempt{(remainsTry > 1 ? "s" : "")} remaining";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region If login successful and user is active read module id for this user
|
||||
|
||||
if (user.LoginStatus == EnumLoginStatus.Success && user.Status == EnumStatus.Authorized && !user.IsLocked)
|
||||
{
|
||||
p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.UserId),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30),
|
||||
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginTime", pType: SqlDbType.DateTime, pValue: DateTime.Now),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LogoutTime", pType: SqlDbType.DateTime, pValue: null)
|
||||
];
|
||||
|
||||
_ = tc.ExecuteNonQuerySp(spName: "dbo.SaveAccessLog", parameterValues: p);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
response = new()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
Name = user.UserName,
|
||||
LoginId = user.LoginId,
|
||||
Email = user.EmailAddress,
|
||||
MobileNumber = user.MobileNo,
|
||||
IsLocked = user.IsLocked,
|
||||
UserRole = user.UserRoleType.Value,
|
||||
LoginStatus = user.LoginStatus,
|
||||
IsAuthorized = EnumStatus.Authorized == user.Status,
|
||||
EmployeeNumber = user.EmployeeNumber,
|
||||
DesignationCode = user.DesignationCode,
|
||||
DesignationName = user.DesignationName,
|
||||
IsInitialPassword = initialPassword
|
||||
};
|
||||
|
||||
tc.End();
|
||||
}
|
||||
catch (Exception ie)
|
||||
{
|
||||
tc?.HandleError();
|
||||
|
||||
throw DBCustomError.GenerateCustomError(ie);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException(e.Message, e);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public async Task<User> IntegrationLoginAsync(IntegrationLoginRequest request, string ipAddress, bool checkPwd)
|
||||
{
|
||||
User user = null;
|
||||
|
|
@ -365,7 +556,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
|||
#region Read User data using authentication data
|
||||
|
||||
string commandText = SQLParser.MakeSQL("SELECT UserId,Password,LoginId, UserName, Status, ISNULL(MobileNo,'')MobileNo ,ISNULL( EmailAddress,'')EmailAddress,"
|
||||
+ " ISNULL(AuthKey,'') AuthKey, ISNULL(AuthValue,'')AuthValue, IsLocked FROM Users WHERE LoginID=%s", request.LoginId);
|
||||
+ " ISNULL(AuthKey,'') AuthKey, ISNULL(AuthValue,'')AuthValue, IsLocked FROM Users WHERE LoginID=%s and UserPlatformId=1 ", request.LoginId);
|
||||
|
||||
using (IDataReader dr = tc.ExecuteReader(commandText: commandText))
|
||||
{
|
||||
|
|
@ -505,6 +696,8 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
|||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
|
@ -2231,6 +2424,206 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
|||
return returnValue;
|
||||
}
|
||||
|
||||
public async Task<AuthLogoutResponse> LogoutAsync(AuthLogoutRequest request, string ipAddress)
|
||||
{
|
||||
AuthLogoutResponse response = null;
|
||||
try
|
||||
{
|
||||
User user = null;
|
||||
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
|
||||
try
|
||||
{
|
||||
DateTime sysDate = DateTime.Today.Date;
|
||||
string appVer = string.Empty, alParams = string.Empty;
|
||||
|
||||
#region Read User data using authentication data
|
||||
|
||||
SqlParameter[] p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.NVarChar, pValue: request.LoginId)
|
||||
];
|
||||
|
||||
using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetUserByLogin", parameterValues: p))
|
||||
{
|
||||
if (dr.Read())
|
||||
{
|
||||
user = new User();
|
||||
{
|
||||
user.UserId = dr.GetInt32(0);
|
||||
user.Password = dr.GetString(1);
|
||||
user.LoginId = dr.GetString(2);
|
||||
user.UserName = dr.GetString(3);
|
||||
user.Status = (EnumStatus)dr.GetInt32(4);
|
||||
user.MobileNo = dr.GetString(5);
|
||||
user.EmailAddress = dr.GetString(6);
|
||||
user.AuthKey = dr.GetString(7);
|
||||
user.AuthValue = dr.GetString(8);
|
||||
user.IsLocked = dr.GetBoolean(9);
|
||||
user.LoginStatus = EnumLoginStatus.Success;
|
||||
user.UserRoleType = (UserRoleTypeEnum)dr.GetInt32(10);
|
||||
user.EmployeeNumber = dr.GetString(11);
|
||||
user.DesignationCode = dr.GetString(12);
|
||||
user.DesignationName = dr.GetString(13);
|
||||
}
|
||||
;
|
||||
}
|
||||
dr.Close();
|
||||
}
|
||||
|
||||
if (user is null)
|
||||
{
|
||||
tc.End();
|
||||
throw new InvalidOperationException($"User not found with login: {request.LoginId}");
|
||||
}
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.UserId),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.VarChar, pValue: user.LoginId, size: 30),
|
||||
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginTime", pType: SqlDbType.DateTime, pValue: null),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LogoutTime", pType: SqlDbType.DateTime, pValue: DateTime.Now)
|
||||
];
|
||||
|
||||
_ = tc.ExecuteNonQuerySp(spName: "dbo.SaveAccessLog", parameterValues: p);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
await _refreshTokenService.InvalidRefreshTokenAsync(tc, user.UserId);
|
||||
|
||||
response = new()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
LoginId = user.LoginId,
|
||||
IsSuccess = true
|
||||
};
|
||||
|
||||
tc.End();
|
||||
}
|
||||
catch (Exception ie)
|
||||
{
|
||||
tc?.HandleError();
|
||||
|
||||
throw DBCustomError.GenerateCustomError(ie);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException(e.Message, e);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public async Task<AppChangePasswordResponse> ChangePasswordAsync(AppUserChangePasswordRequest request, string ipAddress)
|
||||
{
|
||||
AppChangePasswordResponse response = null;
|
||||
try
|
||||
{
|
||||
string password = EncryptPassword(password: request.Password);
|
||||
User user = null;
|
||||
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
|
||||
try
|
||||
{
|
||||
DateTime sysDate = DateTime.Today.Date;
|
||||
string appVer = string.Empty, alParams = string.Empty;
|
||||
|
||||
#region Read User data using authentication data
|
||||
|
||||
SqlParameter[] p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@LoginId", pType: SqlDbType.NVarChar, pValue: request.LoginId)
|
||||
];
|
||||
|
||||
using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetUserByLogin", parameterValues: p))
|
||||
{
|
||||
if (dr.Read())
|
||||
{
|
||||
user = new User();
|
||||
{
|
||||
user.UserId = dr.GetInt32(0);
|
||||
user.Password = dr.GetString(1);
|
||||
user.LoginId = dr.GetString(2);
|
||||
user.UserName = dr.GetString(3);
|
||||
user.Status = (EnumStatus)dr.GetInt32(4);
|
||||
user.MobileNo = dr.GetString(5);
|
||||
user.EmailAddress = dr.GetString(6);
|
||||
user.AuthKey = dr.GetString(7);
|
||||
user.AuthValue = dr.GetString(8);
|
||||
user.IsLocked = dr.GetBoolean(9);
|
||||
user.LoginStatus = EnumLoginStatus.Success;
|
||||
user.UserRoleType = (UserRoleTypeEnum)dr.GetInt32(10);
|
||||
user.EmployeeNumber = dr.GetString(11);
|
||||
user.DesignationCode = dr.GetString(12);
|
||||
user.DesignationName = dr.GetString(13);
|
||||
}
|
||||
;
|
||||
}
|
||||
dr.Close();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
string newPassword = EncryptPassword(request.ConfirmPassword);
|
||||
|
||||
|
||||
p =
|
||||
[
|
||||
SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: user.UserId),
|
||||
SqlHelperExtension.CreateInParam(pName: "@Password", pType: SqlDbType.VarChar, pValue: newPassword, size: 30),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LastPassword", pType: SqlDbType.VarChar, pValue: password, size: 20),
|
||||
SqlHelperExtension.CreateInParam(pName: "@LastPasswordChnageDate", pType: SqlDbType.DateTime, pValue: DateTime.Now)
|
||||
];
|
||||
|
||||
_ = tc.ExecuteNonQuerySp(spName: "dbo.ChangePassword", parameterValues: p);
|
||||
|
||||
response = new()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
LoginId = user.LoginId,
|
||||
IsSuccess = true
|
||||
};
|
||||
|
||||
tc.End();
|
||||
}
|
||||
catch (Exception ie)
|
||||
{
|
||||
tc?.HandleError();
|
||||
|
||||
throw DBCustomError.GenerateCustomError(ie);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException(e.Message, e);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
|
@ -2636,11 +3029,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
|||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class UserSearchResponse
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -230,7 +230,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers
|
|||
loginReponse.AccessToken = userToken;
|
||||
loginReponse.RefreshToken = refreshToken.RefreshToken;
|
||||
loginReponse.AccessTokenExpiry = refreshToken.ExpireTime;
|
||||
return StatusCode(StatusCodes.Status431RequestHeaderFieldsTooLarge, loginReponse);
|
||||
return StatusCode(StatusCodes.Status200OK, loginReponse);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -295,7 +295,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers
|
|||
response.AccessToken = userToken;
|
||||
response.RefreshToken = refreshToken;
|
||||
|
||||
return StatusCode(StatusCodes.Status431RequestHeaderFieldsTooLarge, response);
|
||||
return StatusCode(StatusCodes.Status200OK, response);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -10,7 +10,7 @@ using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Controllers.IntegretionApi
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
|
|
@ -0,0 +1,334 @@
|
|||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using OnlineSalesAutoCrop.CoreAPI;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Common;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.MobileApp;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.MobileApp;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
|
||||
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
|
||||
using System;
|
||||
using System.DirectoryServices;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OnlineSalesAutoCrop.CoreAPI.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// </remarks>
|
||||
/// <param name="service"></param>
|
||||
/// <param name="appSettings"></param>
|
||||
/// <param name="cache"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="refreshTokenService"></param>
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[ValidateAntiForgeryToken]
|
||||
[Route("api/mobile/v{version:apiVersion}/auth")]
|
||||
public class MobileAuthController(IUserService service, IOptions<AppSettings> appSettings, IEaseCache cache, ILogger<IntegrationAuthController> logger,
|
||||
IRefreshTokenService refreshTokenService) : ControllerBase
|
||||
{
|
||||
private readonly ILogger _logger = logger;
|
||||
private readonly IEaseCache _cache = cache;
|
||||
private readonly IUserService _service = service;
|
||||
private readonly IRefreshTokenService _refreshTokenService = refreshTokenService;
|
||||
private readonly AppSettings _appSettings = appSettings?.Value;
|
||||
private readonly DateTimeOffset _options = Helper.CreateEaseCacheOptions();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Login using your credential data retrieve from SqlServer
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>If login successful ValidUser: true</returns>
|
||||
/// <response code="200">If login successful Return ValidUser: true and UserName: not empty</response>
|
||||
[HttpPost("Login")]
|
||||
[AllowAnonymous]
|
||||
[IgnoreAntiforgeryToken]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(MobileAppAuthRequest))]
|
||||
public async Task<IActionResult> Login([FromBody] MobileAppAuthRequest request)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
AppAuthUserResponse loginReponse = new();
|
||||
|
||||
if (string.IsNullOrEmpty(request.LoginId))
|
||||
{
|
||||
loginReponse.ReturnStatus = StatusCodes.Status417ExpectationFailed;
|
||||
loginReponse.ReturnMessage.Add("Login ID is required.");
|
||||
return StatusCode(StatusCodes.Status417ExpectationFailed, loginReponse);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(request.Password))
|
||||
{
|
||||
loginReponse.ReturnStatus = StatusCodes.Status417ExpectationFailed;
|
||||
loginReponse.ReturnMessage.Add("Password is required.");
|
||||
return StatusCode(StatusCodes.Status417ExpectationFailed, loginReponse);
|
||||
}
|
||||
|
||||
|
||||
string ipAddress = string.Empty;
|
||||
try
|
||||
{
|
||||
#region Decrypt LoginID
|
||||
|
||||
string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
bool checkPwd = true;
|
||||
|
||||
ipAddress = Request.HttpContext.GetIpAddress();
|
||||
loginReponse = await _service.LoginAsync(request: request, ipAddress: ipAddress);
|
||||
|
||||
if (loginReponse == null || loginReponse.UserId == 0)
|
||||
{
|
||||
loginReponse.LoginStatus = EnumLoginStatus.Error;
|
||||
loginReponse.ReturnStatus = StatusCodes.Status403Forbidden;
|
||||
loginReponse.ReturnMessage.Add(checkPwd ? "Login ID/Password is invalid." : "You are not Authorized to login into the System");
|
||||
return StatusCode(StatusCodes.Status417ExpectationFailed, loginReponse);
|
||||
}
|
||||
|
||||
if (loginReponse.LoginStatus == EnumLoginStatus.Unsuccessful)
|
||||
{
|
||||
loginReponse.LoginStatus = loginReponse.LoginStatus;
|
||||
loginReponse.ReturnStatus = StatusCodes.Status403Forbidden;
|
||||
loginReponse.ReturnMessage.Add(checkPwd ? $"Login ID/Password is invalid for {request.LoginId}." : "You are not Authorized to login into the System");
|
||||
return StatusCode(StatusCodes.Status417ExpectationFailed, loginReponse);
|
||||
}
|
||||
|
||||
|
||||
if (loginReponse.IsLocked)
|
||||
{
|
||||
loginReponse.LoginStatus = loginReponse.LoginStatus;
|
||||
loginReponse.ReturnStatus = StatusCodes.Status403Forbidden;
|
||||
loginReponse.ReturnMessage.Add($"Your Account is locked . Please try again after few minutes");
|
||||
return StatusCode(StatusCodes.Status417ExpectationFailed, loginReponse);
|
||||
}
|
||||
|
||||
if (!loginReponse.IsAuthorized )
|
||||
{
|
||||
loginReponse.LoginStatus = loginReponse.LoginStatus;
|
||||
loginReponse.ReturnStatus = StatusCodes.Status403Forbidden;
|
||||
loginReponse.ReturnMessage.Add("You are not Authorized to Login into the System, Please contact with System Administrator.");
|
||||
return StatusCode(StatusCodes.Status417ExpectationFailed, loginReponse);
|
||||
}
|
||||
|
||||
loginReponse.ReturnStatus = StatusCodes.Status200OK;
|
||||
string pwdSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.PwdSecretKey);
|
||||
string userPwd = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(privateKey: pwdSecretKey, publicKey: pwdSecretKey, data: request.Password);
|
||||
byte[] key = Encoding.ASCII.GetBytes(_appSettings.JwtCryptoKey);
|
||||
JwtSecurityTokenHandler tokenHandler = new();
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
Subject = new ClaimsIdentity(
|
||||
[
|
||||
Helper.CreateClaim("LoginId", loginReponse.LoginId),
|
||||
Helper.CreateClaim("Email", loginReponse.Email),
|
||||
Helper.CreateClaim("Mobile", $"{loginReponse.MobileNumber}"),
|
||||
Helper.CreateClaim("HashKey", Guid.NewGuid().ToString())
|
||||
]),
|
||||
Expires = DateTime.UtcNow.AddHours(12),
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
|
||||
};
|
||||
|
||||
SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
|
||||
string userToken = tokenHandler.WriteToken(token);
|
||||
GenerateRefreshTokenRequest refreshTokenRequest = new GenerateRefreshTokenRequest()
|
||||
{
|
||||
UserId = loginReponse.UserId,
|
||||
IpAddress = ipAddress,
|
||||
RawRefreshToken = string.Empty
|
||||
};
|
||||
|
||||
var refreshToken = await _refreshTokenService.GenerateRefreshTokenByUserAsync(refreshTokenRequest);
|
||||
|
||||
//If token length is greater than or equal to 4096 (4KB) then return error
|
||||
//because cookie can not store more than 4KB data and we are storing this token in cookie for authentication
|
||||
if (userToken.Length >= 4096) //4Kb
|
||||
{
|
||||
loginReponse.LoginStatus = loginReponse.LoginStatus;
|
||||
loginReponse.ReturnStatus = StatusCodes.Status431RequestHeaderFieldsTooLarge;
|
||||
loginReponse.ReturnMessage.Add("Authentication Token is too large for cookie.");
|
||||
return StatusCode(StatusCodes.Status431RequestHeaderFieldsTooLarge, loginReponse);
|
||||
}
|
||||
|
||||
loginReponse.ReturnStatus = loginReponse.ReturnStatus;
|
||||
loginReponse.ReturnMessage = loginReponse.ReturnMessage;
|
||||
loginReponse.LoginId = loginReponse.LoginId;
|
||||
loginReponse.AccessToken = userToken;
|
||||
loginReponse.RefreshToken = refreshToken.RefreshToken;
|
||||
loginReponse.AccessTokenExpiryTime = DateTime.UtcNow.AddHours(12);
|
||||
loginReponse.RefreshTokenExpiryTime = refreshToken.ExpireTime;
|
||||
return StatusCode(StatusCodes.Status200OK, loginReponse);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = $"{request?.LoginId}~{ipAddress}";
|
||||
_logger.LogError(exception: ex, message: msg);
|
||||
loginReponse.ReturnStatus = StatusCodes.Status500InternalServerError;
|
||||
loginReponse.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, loginReponse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Login using your credential data retrieve from SqlServer
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>If login successful ValidUser: true</returns>
|
||||
/// <response code="200">If login successful Return ValidUser: true and UserName: not empty</response>
|
||||
[HttpPost("RefreshToken")]
|
||||
[AllowAnonymous]
|
||||
[IgnoreAntiforgeryToken]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IntegrationLoginResponse))]
|
||||
public async Task<IActionResult> GetRefreshToken([FromBody] IntegrationRefreshTokenRequest request)
|
||||
{
|
||||
IntegrationRrefreshTokenResponse response = new();
|
||||
try
|
||||
{
|
||||
var userRefreshToken = await _refreshTokenService.GetUserByRefreshTokenAsync(request.RefreshToken);
|
||||
if (!userRefreshToken.IsActive)
|
||||
{
|
||||
string msg = $"Refresh Token is not active: {request?.RefreshToken}";
|
||||
_logger.LogError(message: msg);
|
||||
response.ReturnStatus = StatusCodes.Status401Unauthorized;
|
||||
response.ReturnMessage.Add(msg);
|
||||
return StatusCode(StatusCodes.Status401Unauthorized, response);
|
||||
}
|
||||
|
||||
byte[] key = Encoding.ASCII.GetBytes(_appSettings.JwtCryptoKey);
|
||||
JwtSecurityTokenHandler tokenHandler = new();
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
Subject = new ClaimsIdentity(
|
||||
[
|
||||
Helper.CreateClaim("LoginId", userRefreshToken.LoginId),
|
||||
Helper.CreateClaim("Email", userRefreshToken.EmailAddress),
|
||||
Helper.CreateClaim("AuthKey", $"{userRefreshToken.AuthKey}"),
|
||||
Helper.CreateClaim("HashKey", Guid.NewGuid().ToString())
|
||||
]),
|
||||
Expires = DateTime.UtcNow.AddHours(12),
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
|
||||
};
|
||||
|
||||
SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
|
||||
string userToken = tokenHandler.WriteToken(token);
|
||||
|
||||
string ipAddress = Request.HttpContext.GetIpAddress();
|
||||
var refreshToken = await _refreshTokenService.GenerateRefreshTokenAsync(request.RefreshToken, ipAddress);
|
||||
|
||||
response.AccessToken = userToken;
|
||||
response.RefreshToken = refreshToken;
|
||||
|
||||
return StatusCode(StatusCodes.Status200OK, response);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = $"{request?.RefreshToken}";
|
||||
_logger.LogError(exception: ex, message: msg);
|
||||
response.ReturnStatus = StatusCodes.Status500InternalServerError;
|
||||
response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Login using your credential data retrieve from SqlServer
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>If login successful ValidUser: true</returns>
|
||||
/// <response code="200">If login successful Return ValidUser: true and UserName: not empty</response>
|
||||
[HttpPost("Logout")]
|
||||
[Authorize]
|
||||
[IgnoreAntiforgeryToken]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AuthLogoutResponse))]
|
||||
public async Task<IActionResult> Logout([FromBody] AuthLogoutRequest request)
|
||||
{
|
||||
AuthLogoutResponse response = new();
|
||||
try
|
||||
{
|
||||
string ipAddress = Request.HttpContext.GetIpAddress();
|
||||
response = await _service.LogoutAsync(request, ipAddress);
|
||||
|
||||
response.ReturnStatus = StatusCodes.Status200OK;
|
||||
response.ReturnMessage.Add("Successfully Logout");
|
||||
return StatusCode(StatusCodes.Status200OK, response);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = $"Exception occur on logout {request?.LoginId}";
|
||||
_logger.LogError(exception: ex, message: msg);
|
||||
response.ReturnStatus = StatusCodes.Status500InternalServerError;
|
||||
response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Login using your credential data retrieve from SqlServer
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>If login successful ValidUser: true</returns>
|
||||
/// <response code="200">If login successful Return ValidUser: true and UserName: not empty</response>
|
||||
[HttpPost("ChangePassword")]
|
||||
[Authorize]
|
||||
[IgnoreAntiforgeryToken]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AppChangePasswordResponse))]
|
||||
public async Task<IActionResult> ChangePassword([FromBody] AppUserChangePasswordRequest request)
|
||||
{
|
||||
AppChangePasswordResponse response = new();
|
||||
try
|
||||
{
|
||||
string ipAddress = Request.HttpContext.GetIpAddress();
|
||||
response = await _service.ChangePasswordAsync(request, ipAddress);
|
||||
|
||||
response.ReturnStatus = StatusCodes.Status200OK;
|
||||
response.ReturnMessage.Add("Successfully Changed the Password");
|
||||
return StatusCode(StatusCodes.Status200OK, response);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = $"Exception occur on logout {request?.LoginId}";
|
||||
_logger.LogError(exception: ex, message: msg);
|
||||
response.ReturnStatus = StatusCodes.Status500InternalServerError;
|
||||
response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user