update project file and add refresh token

This commit is contained in:
dibakor 2026-06-16 11:36:11 +06:00
parent 0d5b708044
commit 495f2df15d
11 changed files with 318 additions and 344 deletions

2
.gitignore vendored
View File

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

View File

@ -7,13 +7,14 @@ using System.Text;
namespace OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
public class IntegrstionLoginRequest
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
@ -33,6 +34,7 @@ public class RevokedRefreshTokenRequest
public class GenerateRefreshTokenRequest
{
public int UserId { get; set; }
public User User { get; set; }
public string IpAddress { get; set; }
public string RawRefreshToken { get; set; }
}

View File

@ -31,6 +31,7 @@ public class LoginRequest
public string LoginRemarks { get; set; }
}
public class OtpValidationRequest
{
public int UserId { get; set; }

View File

@ -21,6 +21,7 @@ public class RefreshTokenResponse
public DateTime ExpiredAt { get; set; }
public DateTime? RevokedAt { get; set; }
public string DeviceInfo { get; set; }
public bool IsActive { get; set; }
}
public class GenerateRefreshTokenResponse

View File

@ -48,30 +48,24 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems
public void Map(User source)
{
Id = source.Id;
LogId = source.LogId;
Id = source.UserId;
LoginId = source.LoginId;
IdleTime = source.IdleTime;
UserName = source.UserName;
PingTime = source.PingTime;
ThemeName = source.ThemeName;
//ModuleIds = source.ModuleIds;
LogoutTime = source.LogoutTime;
SchemeName = source.SchemeName;
AuthMethod = source.AuthMethod;
MenuLayout = source.MenuLayout;
SystemDate = source.SystemDate;
EmployeeId = source.EmployeeId;
LoginStatus = source.LoginStatus;
DbOnStartup = source.DbOnStartup;
TimeoutTime = source.TimeoutTime;
BmProcessId = source.BmProcessId;
PrProcessId = source.PrProcessId;
BatchEnabled = source.BatchEnabled;
ViewOwnTaskOnly = source.ViewOwnTaskOnly;
NotificationCount = source.NotificationCount;
AuthRequiredAtLogin = source.AuthRequiredAtLogin;
IdsValue = Newtonsoft.Json.JsonConvert.SerializeObject(source.ModuleIds);
//DbOnStartup = source.DbOnStartup;
//TimeoutTime = source.TimeoutTime;
//BmProcessId = source.BmProcessId;
//PrProcessId = source.PrProcessId;
//BatchEnabled = source.BatchEnabled;
//ViewOwnTaskOnly = source.ViewOwnTaskOnly;
//NotificationCount = source.NotificationCount;
//AuthRequiredAtLogin = source.AuthRequiredAtLogin;
//IdsValue = Newtonsoft.Json.JsonConvert.SerializeObject(source.ModuleIds);
}
}
@ -118,19 +112,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems
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
{

View File

@ -1,5 +1,6 @@
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Setups;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
using System;
@ -12,7 +13,9 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems
{
Task<bool> ValidateAuthValueAsync(string authValue, int userId);
Task<User> LoginAsync(LoginRequest 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<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> DeleteUserAsync(int userId, int deletedBy);
Task<bool> ForceLogoutNowAsync(List<int> userIds, string ipAddress);
@ -40,7 +43,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems
Task<UserBasicInfoResponse> GetAttendanceUsersAsync(int userId);
Task<UserForceLogoutResponse> GetForceLogoutUsersAsync(int createdBy);
Task<UserSearchResponse> GetUsersAsync(UserSearchRequest request, int userId);
Task<bool> SendPasswordAsync(int userId, string newPassword, string ipAddress);
Task<UserBasicInfoResponse> GetUsersByTeamSpaceAsync(string teamSpaceIds, int projectId, int userId);
Task<UserBasicInfoResponse> GetUsersBasicAsync(bool applyFilter, string teamSpaceIds, int projectId);

View File

@ -81,23 +81,7 @@ public class RefreshTokenService : IRefreshTokenService
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
try
{
SqlParameter[] p =
[
SqlHelperExtension.CreateInParam(pName: "@TokenHash", pType: SqlDbType.VarChar, pValue: tokenHash, size: 10)
];
using (IDataReader dr =await tc.ExecuteReaderSpAsync("dbo.GetRefreshTokenByTokenHash", parameterValues: p))
{
if (dr.Read())
{
response.UserId = dr.GetString(0);
response.TokenHash = dr.GetString(1);
response.IpAddress = dr.GetString(2);
response.ExpiredAt = dr.GetDateTime(3);
response.RevokedAt = dr.IsDBNull(4) ? null: dr.GetDateTime(4);
}
dr.Close();
}
await GetByTokenHashAsync(tc, tokenHash);
tc.End();
}
catch (Exception ie)
@ -115,6 +99,36 @@ public class RefreshTokenService : IRefreshTokenService
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;
@ -156,13 +170,7 @@ public class RefreshTokenService : IRefreshTokenService
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
try
{
SqlParameter[] p =
[
SqlHelperExtension.CreateInParam(pName: "@RefreshToken", pType: SqlDbType.NVarChar, pValue: token.RefreshToken)
];
_ = await tc.ExecuteNonQuerySpAsync(spName: "dbo.RevokedAllRefreshToken", parameterValues: p);
returnValue = true;
returnValue = await RevokeAsync(tc, token);
tc.End();
}
@ -181,20 +189,74 @@ public class RefreshTokenService : IRefreshTokenService
return returnValue;
}
public async Task<GenerateRefreshTokenResponse> GenerateRefreshToken()
private async Task<bool> RevokeAsync(TransactionContext tc, RevokedRefreshTokenRequest token)
{
throw new NotImplementedException();
bool returnValue = false;
try
{
SqlParameter[] p =
[
SqlHelperExtension.CreateInParam(pName: "@RefreshToken", pType: SqlDbType.NVarChar, pValue: token.RefreshToken)
];
_ = await tc.ExecuteNonQuerySpAsync(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.IsActive)
throw new UnauthorizedAccessException("Refresh token has expired or been revoked.");
// Rotate: revoke old token, issue new one
await 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<LoginResponse> IssueTokensAsync(TransactionContext tc, User user, string deviceInfo, string ipAddress)
private async Task<GenerateRefreshTokenResponse> IssueTokensAsync(TransactionContext tc, User user, string ipAddress)
{
string rawRefreshToken = GenerateRowToken();
var refreshToken = new InsertRefreshTokenRequest
{
UserId = user.UserId,
TokenHash = HashToken(GenerateRowToken()),
TokenHash = HashToken(rawRefreshToken),
IpAddress = ipAddress,
CreatedAt = DateTime.UtcNow,
ExpiresAt = DateTime.UtcNow.AddDays(_settings.RefreshTokenDuration)
@ -202,11 +264,10 @@ public class RefreshTokenService : IRefreshTokenService
await AddAsync(tc,refreshToken);
return new LoginResponse
return new GenerateRefreshTokenResponse
{
AccessToken = accessToken,
RefreshToken = rawRefreshToken,
AccessTokenExpiry = DateTime.UtcNow.AddMinutes(_settings.AccessTokenExpiryMinutes)
ExpireTime = DateTime.UtcNow.AddMinutes(_settings.RefreshTokenDuration)
};
}

View File

@ -17,7 +17,6 @@ using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
@ -351,7 +350,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
}
public async Task<User> IntegrationLoginAsync(IntegrstionLoginRequest request, string ipAddress, bool checkPwd)
public async Task<User> IntegrationLoginAsync(IntegrationLoginRequest request, string ipAddress, bool checkPwd)
{
User user = null;
try
@ -363,7 +362,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
{
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;
int maxTryCount = 5, lockTime = 1;
#region Read User data using authentication data
@ -1478,93 +1477,93 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
/// <param name="userId"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task<UserSearchResponse> GetUsersAsync(UserSearchRequest request, int userId)
{
UserSearchResponse response = new();
try
{
string andClause = string.Empty;
if (!string.IsNullOrEmpty(request.Criteria))
{
string criteria = request.Criteria.Replace("'", "''");
andClause = $" AND (LoginID='{criteria}' OR MobileNo='{criteria}' OR EmailAddress='{criteria}' OR UserName LIKE '%{criteria}%' OR Designation LIKE '%{criteria}%')";
}
//public async Task<UserSearchResponse> GetUsersAsync(UserSearchRequest request, int userId)
//{
// UserSearchResponse response = new();
// try
// {
// string andClause = string.Empty;
// if (!string.IsNullOrEmpty(request.Criteria))
// {
// string criteria = request.Criteria.Replace("'", "''");
// andClause = $" AND (LoginID='{criteria}' OR MobileNo='{criteria}' OR EmailAddress='{criteria}' OR UserName LIKE '%{criteria}%' OR Designation LIKE '%{criteria}%')";
// }
if (request.Status > 0)
andClause += SQLParser.MakeSQL(" AND Status=%n", request.Status);
// if (request.Status > 0)
// andClause += SQLParser.MakeSQL(" AND Status=%n", request.Status);
if (request.CheckOwner)
andClause += SQLParser.MakeSQL(" AND (CreatedBy=%n OR ViewToAll=1)", userId);
// if (request.CheckOwner)
// andClause += SQLParser.MakeSQL(" AND (CreatedBy=%n OR ViewToAll=1)", userId);
string sortField = request.SortField switch
{
"userName" => "UserName",
"designation" => "Designation",
"mobileNo" => "MobileNo",
"emailAddress" => "EmailAddress",
"statusDetail" => "Status",
"loginId" => "LoginId",
_ => "SeqId, LoginId"
};
// string sortField = request.SortField switch
// {
// "userName" => "UserName",
// "designation" => "Designation",
// "mobileNo" => "MobileNo",
// "emailAddress" => "EmailAddress",
// "statusDetail" => "Status",
// "loginId" => "LoginId",
// _ => "SeqId, LoginId"
// };
string sortOrder = request.SortOrder switch
{
"desc" => "DESC",
_ => "ASC",
};
// string sortOrder = request.SortOrder switch
// {
// "desc" => "DESC",
// _ => "ASC",
// };
string commandText = request.Skip + request.PageSize <= 0 ?
SQLParser.MakeSQL("SELECT UserId, LoginId, UserName, Designation, MobileNo, EmailAddress, Status, SeqId, IsLocked, CanUseAtnSys, Password,"
+ " COUNT(*) OVER() AS TotalRows FROM Users WHERE UserId!=-9%q ORDER BY %q %q", andClause, sortField, sortOrder)
: SQLParser.MakeSQL("SELECT A.UserId, A.LoginId, A.UserName, A.Designation, A.MobileNo, A.EmailAddress, A.Status, A.SeqId, A.IsLocked,"
+ " A.CanUseAtnSys, A.Password, A.TotalRows FROM(SELECT UserId, LoginId, UserName, Designation, MobileNo, EmailAddress, Status, SeqId,"
+ " IsLocked, CanUseAtnSys, Password, ROW_NUMBER() OVER(ORDER BY %q %q) AS RN, COUNT(*) OVER() AS TotalRows FROM Users WHERE UserId!=-9%q) A"
+ " WHERE A.RN>%n AND A.RN<=%n", sortField, sortOrder, andClause, request.Skip, request.Skip + request.PageSize);
// string commandText = request.Skip + request.PageSize <= 0 ?
// SQLParser.MakeSQL("SELECT UserId, LoginId, UserName, Designation, MobileNo, EmailAddress, Status, SeqId, IsLocked, CanUseAtnSys, Password,"
// + " COUNT(*) OVER() AS TotalRows FROM Users WHERE UserId!=-9%q ORDER BY %q %q", andClause, sortField, sortOrder)
// : SQLParser.MakeSQL("SELECT A.UserId, A.LoginId, A.UserName, A.Designation, A.MobileNo, A.EmailAddress, A.Status, A.SeqId, A.IsLocked,"
// + " A.CanUseAtnSys, A.Password, A.TotalRows FROM(SELECT UserId, LoginId, UserName, Designation, MobileNo, EmailAddress, Status, SeqId,"
// + " IsLocked, CanUseAtnSys, Password, ROW_NUMBER() OVER(ORDER BY %q %q) AS RN, COUNT(*) OVER() AS TotalRows FROM Users WHERE UserId!=-9%q) A"
// + " WHERE A.RN>%n AND A.RN<=%n", sortField, sortOrder, andClause, request.Skip, request.Skip + request.PageSize);
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
try
{
int totalRows = 0;
using IDataReader dr = tc.ExecuteReader(commandText: commandText);
while (dr.Read())
{
UserGetResponse item = new()
{
UserId = dr.GetInt32(0),
LoginId = dr.GetString(1),
UserName = dr.GetString(2),
Designation = dr.GetString(3),
MobileNo = dr.GetString(4),
EmailAddress = dr.GetString(5),
Status = (EnumStatus)dr.GetInt16(6),
SeqId = dr.GetInt16(7),
IsLocked = !dr.IsDBNull(8) && dr.GetInt16(8) != 0,
CanUseAttendanceSystem = !dr.IsDBNull(9) && dr.GetInt16(9) != 0,
};
totalRows = dr.GetInt32(11);
// using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode);
// try
// {
// int totalRows = 0;
// using IDataReader dr = tc.ExecuteReader(commandText: commandText);
// while (dr.Read())
// {
// UserGetResponse item = new()
// {
// UserId = dr.GetInt32(0),
// LoginId = dr.GetString(1),
// UserName = dr.GetString(2),
// Designation = dr.GetString(3),
// MobileNo = dr.GetString(4),
// EmailAddress = dr.GetString(5),
// Status = (EnumStatus)dr.GetInt16(6),
// SeqId = dr.GetInt16(7),
// IsLocked = !dr.IsDBNull(8) && dr.GetInt16(8) != 0,
// CanUseAttendanceSystem = !dr.IsDBNull(9) && dr.GetInt16(9) != 0,
// };
// totalRows = dr.GetInt32(11);
}
dr.Close();
// }
// dr.Close();
response.TotalRows = totalRows;
// response.TotalRows = totalRows;
tc.End();
response.ReturnStatus = 200;
}
catch (Exception ie)
{
tc?.HandleError();
// tc.End();
// response.ReturnStatus = 200;
// }
// catch (Exception ie)
// {
// tc?.HandleError();
throw DBCustomError.GenerateCustomError(ie);
}
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message, e);
}
// throw DBCustomError.GenerateCustomError(ie);
// }
// }
// catch (Exception e)
// {
// throw new InvalidOperationException(e.Message, e);
// }
return response;
}
// return response;
//}
/// <summary>
///
@ -2639,6 +2638,12 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
throw new NotImplementedException();
}
#endregion
}
internal class UserSearchResponse
{
}
}

View File

@ -1,22 +1,25 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using OnlineSalesAutoCrop.CoreAPI.Configurations;
using OnlineSalesAutoCrop.CoreAPI.Models;
using OnlineSalesAutoCrop.CoreAPI.Models.Global;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects;
using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Systems;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems;
using OnlineSalesAutoCrop.CoreAPI.SignalRHub;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.DirectoryServices;
@ -27,8 +30,6 @@ using System.Runtime.Versioning;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Auth;
namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
{
@ -70,7 +71,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
[AllowAnonymous]
[IgnoreAntiforgeryToken]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(LoginResponse))]
public async Task<IActionResult> Login([FromBody] LoginRequest request)
public async Task<IActionResult> Login([FromBody] IntegrationLoginRequest request)
{
ArgumentNullException.ThrowIfNull(request);
@ -89,12 +90,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
return StatusCode(StatusCodes.Status417ExpectationFailed, response);
}
if (string.IsNullOrEmpty(request.AppVersion))
{
response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
response.ReturnMessage.Add("Version is required.");
return StatusCode(StatusCodes.Status417ExpectationFailed, response);
}
string ipAddress = string.Empty;
try
@ -104,11 +99,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey);
request.LoginId = Helper.DecryptData(secret: cipherSecretKey, data: request.LoginId);
request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password);
request.AppId = Helper.DecryptData(secret: cipherSecretKey, data: request.AppId);
request.HostName = Helper.DecryptData(secret: cipherSecretKey, data: request.HostName);
request.IpAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.IpAddress);
request.MacAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.MacAddress);
if (request.LoginId.Equals("*Key/Data Error*") || request.Password.Equals("*Key/Data Error*") || request.AppId.Equals("*Key/Data Error*"))
if (request.LoginId.Equals("*Key/Data Error*") || request.Password.Equals("*Key/Data Error*") )
{
response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
response.ReturnMessage.Add("Key or Data Error...!");
@ -144,7 +135,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
#endregion
ipAddress = Request.HttpContext.GetIpAddress();
User user = await _service.LoginAsync(request: request, ipAddress: ipAddress, checkPwd: checkPwd);
User user = await _service.IntegrationLoginAsync(request: request, ipAddress: ipAddress, checkPwd: checkPwd);
if (user == null || user.UserId == 0)
{
@ -217,7 +208,14 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
string userToken = tokenHandler.WriteToken(token);
string refreshToken = _refreshTokenService.GenerateRefreshToken();
GenerateRefreshTokenRequest refreshTokenRequest = new GenerateRefreshTokenRequest()
{
User = user,
IpAddress = ipAddress,
RawRefreshToken = request.RefreshToken
};
var refreshToken =await _refreshTokenService.GenerateRefreshToken(refreshTokenRequest);
@ -566,7 +564,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
string ipAddress = Request.HttpContext.GetIpAddress();
int changedBy = HttpContext.User.GetClaimValue<int>(Constants.UserId);
response.Value = await _service.ResetPasswordAsync(userId: request.UserId, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: changedBy);
await _hub.Clients.All.NotifySubscriber(userId: request.UserId, msgType: 1, itemId: 0, ipAddress: ipAddress);
response.ReturnMessage.Add("Password Reset successfully, User must change password at next Login.");
_cache.Clear("User");
@ -643,7 +640,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
string ipAddress = Request.HttpContext.GetIpAddress();
int changedBy = HttpContext.User.GetClaimValue<int>(Constants.UserId);
response.Value = await _service.ChangePasswordAsync(userId: request.UserId, oldPassword: request.OldPassword, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: changedBy);
await _hub.Clients.All.NotifySubscriber(userId: request.UserId, msgType: 1, itemId: 0, ipAddress: ipAddress);
_cache.Clear("User");
return Ok(response);
@ -712,7 +708,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
string ipAddress = Request.HttpContext.GetIpAddress();
int userId = HttpContext.User.GetClaimValue<int>(Constants.UserId);
response.Value = await _service.ChangePasswordAsync(userId: userId, oldPassword: request.OldPassword, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: userId);
await _hub.Clients.All.NotifySubscriber(userId: userId, msgType: 1, itemId: 0, ipAddress: ipAddress);
response.ReturnMessage.Add("Password changed successfully.");
_cache.Clear("User");
@ -955,39 +950,39 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
/// </returns>
/// <response code="200">Top 50 users</response>
/// <response code="204">If the item is null.</response>
[ValidateSession]
[HttpPost("getUsers")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))]
[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))]
public async Task<IActionResult> GetUsers([FromBody] UserSearchRequest request)
{
ArgumentNullException.ThrowIfNull(request);
//[ValidateSession]
//[HttpPost("getUsers")]
//[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))]
//[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))]
//public async Task<IActionResult> GetUsers([FromBody] UserSearchRequest request)
//{
// ArgumentNullException.ThrowIfNull(request);
UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
try
{
int userId = HttpContext.User.GetClaimValue<int>(Constants.UserId);
request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id;
// UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
// try
// {
// int userId = HttpContext.User.GetClaimValue<int>(Constants.UserId);
// request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id;
string key = "Users";
string key2 = $"{request.Criteria}~{request.Status}~{request.SortField}~{request.SortOrder}~{request.Skip}~{request.PageSize}~{request.CheckOwner}~{userId}";
if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
{
response = await _service.GetUsersAsync(request: request, userId: userId);
_ = _cache.Set(key: key, key2: key2, value: response, options: _options);
}
// string key = "Users";
// string key2 = $"{request.Criteria}~{request.Status}~{request.SortField}~{request.SortOrder}~{request.Skip}~{request.PageSize}~{request.CheckOwner}~{userId}";
// if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
// {
// response = await _service.GetUsersAsync(request: request, userId: userId);
// _ = _cache.Set(key: key, key2: key2, value: response, options: _options);
// }
response.ReturnStatus = StatusCodes.Status200OK;
return Ok(response);
}
catch (Exception ex)
{
_logger.LogError(ex);
response.ReturnStatus = StatusCodes.Status500InternalServerError;
response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, response);
}
}
// 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>
///
@ -1140,10 +1135,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
{
string ipAddress = Request.HttpContext.GetIpAddress();
response.Value = await _service.ForceLogoutNowAsync(userIds: request.UserIds, ipAddress: ipAddress);
foreach (int userId in request.UserIds)
{
await _hub.Clients.All.NotifySubscriber(userId: userId, msgType: 1, itemId: 0, ipAddress: ipAddress);
}
response.ReturnMessage.Add("Process completed successfully...");
response.ReturnStatus = StatusCodes.Status200OK;
return Ok(response);
@ -1313,42 +1304,6 @@ 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>
@ -1892,10 +1847,6 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
_ = await HttpContext.ClearSessionAsync();
response.Value = true;
if (request.AttendanceLogout)
{
await _hub.Clients.All.NotifySubscriber(userId: userId, msgType: 6, itemId: 0, ipAddress: ipAddress);
}
return Ok(response);
}

View File

@ -146,7 +146,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
ipAddress = Request.HttpContext.GetIpAddress();
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.ReturnStatus = StatusCodes.Status403Forbidden;
@ -205,7 +205,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
response.Map(user);
response.ValidUser = true;
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 userPwd = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(privateKey: pwdSecretKey, publicKey: pwdSecretKey, data: request.Password);
@ -215,15 +215,15 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
{
Subject = new ClaimsIdentity(
[
Helper.CreateClaim("UserId", $"{user.Id}"),
Helper.CreateClaim("LoginId", user.LoginId),
Helper.CreateClaim("UserPwd", userPwd),
Helper.CreateClaim("AuthKey", $"{user.AuthKey}"),
Helper.CreateClaim("TeamSpaceIds", $"{string.Join(',',user.TeamSpaceIds)}"),
Helper.CreateClaim("BatchEnabled", user.BatchEnabled ? "1" : "0"),
Helper.CreateClaim("BmProcessId", $"{user.BmProcessId}"),
Helper.CreateClaim("PrProcessId", $"{user.PrProcessId}"),
Helper.CreateClaim("EmployeeId", $"{user.EmployeeCode}")
//Helper.CreateClaim("UserId", $"{user.Id}"),
//Helper.CreateClaim("LoginId", user.LoginId),
//Helper.CreateClaim("UserPwd", userPwd),
//Helper.CreateClaim("AuthKey", $"{user.AuthKey}"),
//Helper.CreateClaim("TeamSpaceIds", $"{string.Join(',',user.TeamSpaceIds)}"),
//Helper.CreateClaim("BatchEnabled", user.BatchEnabled ? "1" : "0"),
//Helper.CreateClaim("BmProcessId", $"{user.BmProcessId}"),
//Helper.CreateClaim("PrProcessId", $"{user.PrProcessId}"),
//Helper.CreateClaim("EmployeeId", $"{user.EmployeeCode}")
]),
Expires = DateTime.UtcNow.AddHours(12),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
@ -246,35 +246,35 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
response.AuthenticationToken = userToken;
response.LoginTime = $"{DateTime.Now:dd-MM-yy H:mm:ss}";
await HttpContext.Session.SetModulesToSession(key: userToken, value: user.ModuleIds);
if (user.LoginStatus == EnumLoginStatus.Success)
{
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)];
await MailHelper.SendMailMessageAsync(settings: _appSettings, to: to,
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));
}
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);
}
}
//await HttpContext.Session.SetModulesToSession(key: userToken, value: user.ModuleIds);
//if (user.LoginStatus == EnumLoginStatus.Success)
//{
// 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)];
// await MailHelper.SendMailMessageAsync(settings: _appSettings, to: to,
// 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));
// }
// 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);
// }
//}
if (user.DisallowMultiLogin)
{
await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 1, itemId: 0, ipAddress: ipAddress);
if (request.AttendanceLogin)
await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress);
}
else
{
await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 2, itemId: 0, ipAddress: ipAddress);
if (request.AttendanceLogin)
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);
//if (user.DisallowMultiLogin)
//{
// await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 1, itemId: 0, ipAddress: ipAddress);
// if (request.AttendanceLogin)
// await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 6, itemId: 0, ipAddress: ipAddress);
//}
//else
//{
// await _hub.Clients.All.NotifySubscriber(userId: user.Id, msgType: 2, itemId: 0, ipAddress: ipAddress);
// if (request.AttendanceLogin)
// 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);
return Ok(response);
}
@ -996,39 +996,39 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1
/// </returns>
/// <response code="200">Top 50 users</response>
/// <response code="204">If the item is null.</response>
[ValidateSession]
[HttpPost("getUsers")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))]
[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))]
public async Task<IActionResult> GetUsers([FromBody] UserSearchRequest request)
{
ArgumentNullException.ThrowIfNull(request);
//[ValidateSession]
//[HttpPost("getUsers")]
//[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))]
//[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))]
//public async Task<IActionResult> GetUsers([FromBody] UserSearchRequest request)
//{
// ArgumentNullException.ThrowIfNull(request);
UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
try
{
int userId = HttpContext.User.GetClaimValue<int>(Constants.UserId);
request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id;
// UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
// try
// {
// int userId = HttpContext.User.GetClaimValue<int>(Constants.UserId);
// request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id;
string key = "Users";
string key2 = $"{request.Criteria}~{request.Status}~{request.SortField}~{request.SortOrder}~{request.Skip}~{request.PageSize}~{request.CheckOwner}~{userId}";
if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
{
response = await _service.GetUsersAsync(request: request, userId: userId);
_ = _cache.Set(key: key, key2: key2, value: response, options: _options);
}
// string key = "Users";
// string key2 = $"{request.Criteria}~{request.Status}~{request.SortField}~{request.SortOrder}~{request.Skip}~{request.PageSize}~{request.CheckOwner}~{userId}";
// if (!_cache.TryGetValue(key: key, key2: key2, value: out response))
// {
// response = await _service.GetUsersAsync(request: request, userId: userId);
// _ = _cache.Set(key: key, key2: key2, value: response, options: _options);
// }
response.ReturnStatus = StatusCodes.Status200OK;
return Ok(response);
}
catch (Exception ex)
{
_logger.LogError(ex);
response.ReturnStatus = StatusCodes.Status500InternalServerError;
response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, response);
}
}
// 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>
///
@ -1354,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>
///

View File

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