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 System; using System.Collections.Generic; using System.DirectoryServices; using System.IdentityModel.Tokens.Jwt; using System.IO; using System.Linq; using System.Runtime.Versioning; using System.Security.Claims; using System.Text; using System.Threading.Tasks; namespace OnlineSalesAutoCrop.CoreAPI.Controllers.V1 { /// /// /// /// /// /// /// /// /// /// /// [Authorize] [ApiController] [ApiVersion("1.0")] [ValidateAntiForgeryToken] [Route("api/v{version:apiVersion}/users")] public class AuthController(IUserService service, IOptions appSettings, IEaseCache cache, ILogger logger, IRefreshTokenService refreshTokenService) : ControllerBase { private readonly ILogger _logger = logger; private readonly IEaseCache _cache = cache; private readonly IUserService _service = service; private readonly IRefreshTokenService _refreshTokenService = refreshTokenService; private readonly AppSettings _appSettings = appSettings?.Value; private readonly DateTimeOffset _options = Helper.CreateEaseCacheOptions(); /// /// Login using your credential data retrieve from SqlServer /// /// /// /// /// If login successful ValidUser: true /// If login successful Return ValidUser: true and UserName: not empty [HttpPost("login")] [AllowAnonymous] [IgnoreAntiforgeryToken] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(LoginResponse))] public async Task Login([FromBody] IntegrationLoginRequest request) { ArgumentNullException.ThrowIfNull(request); LoginResponse response = new(); if (string.IsNullOrEmpty(request.LoginId)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Login ID is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.Password)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Password is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } string ipAddress = string.Empty; try { #region Decrypt LoginID string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey); request.LoginId = Helper.DecryptData(secret: cipherSecretKey, data: request.LoginId); request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password); if (request.LoginId.Equals("*Key/Data Error*") || request.Password.Equals("*Key/Data Error*") ) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Key or Data Error...!"); return BadRequest(response); } #endregion bool checkPwd = true; #region If AD (Active Directory) authentication is enabled do validate if (_appSettings.ADConfig.Enabled) { checkPwd = false; #pragma warning disable CA1416 // Validate platform compatibility int adLoginStatus = GetADLoginStatus(loginId: request.LoginId, password: request.Password); #pragma warning restore CA1416 // Validate platform compatibility if (adLoginStatus != 1) { response.LoginStatus = EnumLoginStatus.Unsuccessful; response.ReturnStatus = StatusCodes.Status403Forbidden; if (adLoginStatus == 2) response.ReturnMessage.Add("Active Directory User is DISABLED."); else if (adLoginStatus == 3) response.ReturnMessage.Add("Active Directory User's Password has EXPIRED."); else response.ReturnMessage.Add("Active Directory User/Password is INVALID."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } } #endregion ipAddress = Request.HttpContext.GetIpAddress(); User user = await _service.IntegrationLoginAsync(request: request, ipAddress: ipAddress, checkPwd: checkPwd); if (user == null || user.UserId == 0) { response.LoginStatus = EnumLoginStatus.Error; response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add(checkPwd ? "Login ID/Password is invalid." : "You are not Authorized to login into the System"); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (user.LoginStatus == EnumLoginStatus.Unsuccessful) { string usm = string.Empty; if (user != null && !string.IsNullOrEmpty(user.UnsuccessfulMsg)) usm = $" ({user.UnsuccessfulMsg})"; response.LoginStatus = user.LoginStatus; response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add(checkPwd ? $"Login ID/Password is invalid{usm}." : "You are not Authorized to login into the System"); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (user.IsLocked) { response.LoginStatus = user.LoginStatus; response.ReturnStatus = StatusCodes.Status403Forbidden; if (!user.NextLoginTime.HasValue) response.ReturnMessage.Add("You are locked, please contact Head office."); else response.ReturnMessage.Add($"You can Login after {user.NextLoginTime:dd-MMM-yyyy H:mm:ss}"); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (user.Status != EnumStatus.Authorized) { response.LoginStatus = user.LoginStatus; response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not Authorized to Login into the System, Please contact with System Administrator."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } response.ValidUser = user.LoginStatus == EnumLoginStatus.Success; if (!response.ValidUser) { response.LoginStatus = user.LoginStatus; response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("Unknown error."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } response.Map(user); response.ValidUser = true; response.ReturnStatus = StatusCodes.Status200OK; string pwdSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.PwdSecretKey); string userPwd = Ease.NetCore.Utility.Global.CipherFunctions.EncryptByAES(privateKey: pwdSecretKey, publicKey: pwdSecretKey, data: request.Password); byte[] key = Encoding.ASCII.GetBytes(_appSettings.JwtCryptoKey); JwtSecurityTokenHandler tokenHandler = new(); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity( [ Helper.CreateClaim("LoginId", user.LoginId), Helper.CreateClaim("Email", user.EmailAddress), Helper.CreateClaim("AuthKey", $"{user.AuthKey}"), Helper.CreateClaim("HashKey", Guid.NewGuid().ToString()) ]), Expires = DateTime.UtcNow.AddHours(12), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature) }; SecurityToken token = tokenHandler.CreateToken(tokenDescriptor); string userToken = tokenHandler.WriteToken(token); GenerateRefreshTokenRequest refreshTokenRequest = new GenerateRefreshTokenRequest() { User = user, IpAddress = ipAddress, RawRefreshToken = request.RefreshToken }; var refreshToken =await _refreshTokenService.GenerateRefreshToken(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 { response.LoginStatus = user.LoginStatus; response.ReturnStatus = StatusCodes.Status431RequestHeaderFieldsTooLarge; response.ReturnMessage.Add("Authentication Token is too large for cookie."); return StatusCode(StatusCodes.Status431RequestHeaderFieldsTooLarge, response); } response.Expires = tokenDescriptor.Expires; response.AuthenticationToken = userToken; response.LoginTime = $"{DateTime.Now:dd-MM-yy H:mm:ss}"; return Ok(response); } catch (Exception ex) { string msg = $"{request?.LoginId}~{ipAddress}"; _logger.LogError(exception: ex, message: msg); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("loadMenu")] public async Task LoadMenu([FromBody] ByUserIdRequest request) { ArgumentNullException.ThrowIfNull(request); try { MenuResponse response = await _service.GetUserPermissionsAsync(userId: request.UserId); return Ok(response.Item); } catch (Exception ex) { _logger.LogError(ex); return StatusCode(StatusCodes.Status500InternalServerError, (ex.InnerException != null ? ex.InnerException.Message : ex.Message)); } } /// /// /// /// /// [IgnoreAntiforgeryToken] [HttpPost("validateOtp")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task ValidateOtp([FromBody] OtpValidationRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { Value = false, ReturnStatus = StatusCodes.Status200OK }; if (string.IsNullOrEmpty(request.OtpCode) || request.OtpCode.Length != 6) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Otp must be 6 digit."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { if (request.AuthMethod == EnumAuthenticationMethod.ThirdPartyAuthenticator) { string secretKey = HttpContext.User.GetClaimValue("AuthKey"); if (string.IsNullOrEmpty(secretKey)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Authentication key is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } TOtpService otp = new(); DateTime now = DateTime.UtcNow; response.Value = otp.ValidateTwoFactorPIN(secretKey, request.OtpCode, now); } else { response.Value = await _service.ValidateAuthValueAsync(request.OtpCode, request.UserId); } if (!response.Value) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("This is not a valid Otp."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } else { return Ok(response); } } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status406NotAcceptable; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("addUser")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task AddUser([FromBody] NewUserRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_1"); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not authorize to Add User."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); int createdBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.AddUserAsync(user: request, ipAddress: ipAddress, createdBy: createdBy); response.ReturnMessage.Add("User added successfully..."); //Cache _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("editUser")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task EditUser([FromBody] UserRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_2"); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not authorize to Update User."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (request.AuthMethod == EnumAuthenticationMethod.ThirdPartyAuthenticator && (string.IsNullOrEmpty(request.AuthKey) || string.IsNullOrWhiteSpace(request.AuthKey) || request.AuthKey.Length <= 0)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("For third party Authenticator, Authentication key is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); int modifiedBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.EditUserAsync(user: request, ipAddress: ipAddress, modifiedBy: modifiedBy); response.ReturnMessage.Add("User edited successfully..."); //Cache _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("deleteUser")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task DeleteUser([FromBody] ByUserIdRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_3"); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not authorize to Delete User."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { int deletedBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.DeleteUserAsync(userId: request.UserId, deletedBy: deletedBy); response.ReturnMessage.Add("User deleted successfully..."); //Cache _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("unlockUser")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task UnlockUser([FromBody] UserUnlockRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; bool permitted = await HttpContext.IsPermitted("ELIT.1.2.2_2"); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not authorize to Unlock User."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { int unlockedBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.UnlockUserAsync(userId: request.UserId, loginId: request.LoginId, unlockedBy: unlockedBy); response.ReturnMessage.Add("User Unlocked successfully..."); //Cache _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("resetPassword")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task ResetPassword([FromBody] ResetPasswordRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; if (request.UserId == 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("User is not valid."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.Password) || string.IsNullOrWhiteSpace(request.Password)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.ConfirmPassword) || string.IsNullOrWhiteSpace(request.ConfirmPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Confirm Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } #region Decrypt Password string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey); request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password); request.ConfirmPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.ConfirmPassword); #endregion if (!request.Password.Equals(request.ConfirmPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("New password and confirm password are not same."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } bool permitted = await HttpContext.IsPermitted("ELIT.1.2.3_2"); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not authorize to Reset Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); int changedBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.ResetPasswordAsync(userId: request.UserId, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: changedBy); response.ReturnMessage.Add("Password Reset successfully, User must change password at next Login."); _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [IgnoreAntiforgeryToken] [HttpPost("changePassword")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task ChangePassword([FromBody] PasswordChangeRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; if (request.UserId == 0) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("Your not a valid user."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.OldPassword) || string.IsNullOrWhiteSpace(request.OldPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Old Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.Password) || string.IsNullOrWhiteSpace(request.Password)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.ConfirmPassword) || string.IsNullOrWhiteSpace(request.ConfirmPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Confirm Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } #region Decrypt Password string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey); request.OldPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.OldPassword); request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password); request.ConfirmPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.ConfirmPassword); #endregion if (!request.Password.Equals(request.ConfirmPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("New password and confirm password are not same."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); int changedBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.ChangePasswordAsync(userId: request.UserId, oldPassword: request.OldPassword, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: changedBy); _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("updateMyPassword")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task UpdateMyPassword([FromBody] PasswordChangeRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; if (string.IsNullOrEmpty(request.OldPassword) || string.IsNullOrWhiteSpace(request.OldPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Old Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.Password) || string.IsNullOrWhiteSpace(request.Password)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.ConfirmPassword) || string.IsNullOrWhiteSpace(request.ConfirmPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Invalid parameter value Confirm Password."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } #region Decrypt Password string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey); request.OldPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.OldPassword); request.Password = Helper.DecryptData(secret: cipherSecretKey, data: request.Password); request.ConfirmPassword = Helper.DecryptData(secret: cipherSecretKey, data: request.ConfirmPassword); #endregion if (!request.Password.Equals(request.ConfirmPassword)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("New password and confirm password are not same."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); int userId = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.ChangePasswordAsync(userId: userId, oldPassword: request.OldPassword, newPassword: request.ConfirmPassword, ipAddress: ipAddress, changedBy: userId); response.ReturnMessage.Add("Password changed successfully."); _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("updateMyTheme")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task UpdateMyTheme([FromBody] UserThemeRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { int userId = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.UpdateMyThemeAsync(userId: userId, menuLayout: request.MenuLayout, themeName: request.ThemeName, schemeName: request.SchemeName); response.ReturnMessage.Add("Your theme set successfully. Need re-login to see the effect."); _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("updateMyInfo")] [AllowAnonymous, IgnoreAntiforgeryToken] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task UpdateMyInfo([FromBody] UpdateMyInfoRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { if (request.EmployeeId < 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("System allow to update only Your Information."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } int modifiedBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.UpdateMyInfoAsync(address: request.Address, contactNo: request.ContactNo, modifiedBy: modifiedBy, emplyeeId: request.EmployeeId); response.ReturnMessage.Add("Your Information updated successfully."); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("getAttributes")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserAttributesResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserAttributesResponse))] public async Task GetAttributes([FromBody] ByUserAttributesRequest request) { ArgumentNullException.ThrowIfNull(request); UserAttributesResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { string key = "UserAttributes"; string key2 = $"{request.UserId}~{request.ClientType}"; if (!_cache.TryGetValue(key: key, key2: key2, value: out response)) { response = await _service.GetAttributesAsync(userId: request.UserId, clientType: request.ClientType); //Cache _ = _cache.Set(key: key, key2: key2, value: response, options: _options); } response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("saveAttributes")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task SaveAttributes([FromBody] UserAttributesRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; if (request.UkIds == null || request.UkIds.Count <= 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no data to save."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } string msg, key; if (request.ClientType == 2) { key = "ELIT.1.5.12_2"; msg = "Supplier(s) to user"; } else { key = "ELIT.1.5.11_2"; msg = "Project(s) to user"; } bool permitted = await HttpContext.IsPermitted(key); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add($"You are not authorize to Assign {msg}."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); int attributeSetBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.SaveAttributesAsync(userId: request.UserId, clientType: request.ClientType, ipAddress: ipAddress, attributeSetBy: attributeSetBy, ukIds: request.UkIds); response.ReturnMessage.Add($"{msg} Assigned successfully..."); //Cache _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("deleteAttributes")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task DeleteAttributes([FromBody] ByUserAttributesRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; string msg, key; if (request.ClientType == 2) { key = "ELIT.1.5.12_3"; msg = "Supplier(s) from user"; } else { key = "ELIT.1.5.11_3"; msg = "Project(s) from user"; } bool permitted = await HttpContext.IsPermitted(key); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add($"You are not authorize to Unassign {msg}."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { int deletedBy = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.DeleteAttributesAsync(userId: request.UserId, clientType: request.ClientType, deletedBy: deletedBy); response.ReturnMessage.Add($"{msg} Unassigned successfully..."); //Cache _cache.Clear("User"); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// Returns users according to search criteria. /// /// /// top 50 users /// /// Top 50 users /// If the item is null. //[ValidateSession] //[HttpPost("getUsers")] //[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserSearchResponse))] //[ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserSearchResponse))] //public async Task GetUsers([FromBody] UserSearchRequest request) //{ // ArgumentNullException.ThrowIfNull(request); // UserSearchResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; // try // { // int userId = HttpContext.User.GetClaimValue(Constants.UserId); // request.CheckOwner = userId != Models.Objects.Systems.User.SuperUser_Id; // string key = "Users"; // string key2 = $"{request.Criteria}~{request.Status}~{request.SortField}~{request.SortOrder}~{request.Skip}~{request.PageSize}~{request.CheckOwner}~{userId}"; // if (!_cache.TryGetValue(key: key, key2: key2, value: out response)) // { // response = await _service.GetUsersAsync(request: request, userId: userId); // _ = _cache.Set(key: key, key2: key2, value: response, options: _options); // } // response.ReturnStatus = StatusCodes.Status200OK; // return Ok(response); // } // catch (Exception ex) // { // _logger.LogError(ex); // response.ReturnStatus = StatusCodes.Status500InternalServerError; // response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); // return StatusCode(StatusCodes.Status500InternalServerError, response); // } //} /// /// /// /// /// [ValidateSession] [HttpPost("getUsersBasic")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserBasicInfoResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserBasicInfoResponse))] public async Task GetUsersBasic([FromBody] BasicUserSearchRequest request) { ArgumentNullException.ThrowIfNull(request); UserBasicInfoResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { string teamSpaceIds = request.TeamSpaceId > 0 ? $"{request.TeamSpaceId}" : HttpContext.User.GetClaimValue("TeamSpaceIds"); response = await _service.GetUsersBasicAsync(applyFilter: request.ApplyFilter, teamSpaceIds: teamSpaceIds, projectId: request.ProjectId); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("getUsersByTeamSpace")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserBasicInfoResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserBasicInfoResponse))] public async Task GetUsersByTeamSpace([FromBody] BasicUserByTeamSpaceRequest request) { ArgumentNullException.ThrowIfNull(request); UserBasicInfoResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { string teamSpaceIds = request.TeamSpaceId > 0 ? $"{request.TeamSpaceId}" : HttpContext.User.GetClaimValue("TeamSpaceIds"); response = await _service.GetUsersByTeamSpaceAsync(teamSpaceIds: teamSpaceIds, projectId: request.ProjectId, userId: request.UserId); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("getAttendanceUsers")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserBasicInfoResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserBasicInfoResponse))] public async Task GetAttendanceUsers([FromBody] ByUserIdRequest request) { ArgumentNullException.ThrowIfNull(request); UserBasicInfoResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { response = await _service.GetAttendanceUsersAsync(userId: request.UserId); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// [ValidateSession] [HttpPost("getUsersForForceLogout")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserForceLogoutResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserForceLogoutResponse))] public async Task GetForceLogoutUsers([FromBody] NoContentRequest request) { ArgumentNullException.ThrowIfNull(request); UserForceLogoutResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { int userId = HttpContext.User.GetClaimValue(Constants.UserId); response = await _service.GetForceLogoutUsersAsync(createdBy: userId); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// [ValidateSession] [HttpPost("forceLogoutNow")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(BooleanResponse))] public async Task ForceLogoutNow([FromBody] ForceUserLogoutRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; if (request.UserIds == null || request.UserIds.Count <= 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Parameter value is null/no User was selected."); return BadRequest(response); } bool permitted = await HttpContext.IsPermitted("ELIT.1.2.4_2"); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not authorize to Do Force Logout."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); response.Value = await _service.ForceLogoutNowAsync(userIds: request.UserIds, ipAddress: ipAddress); response.ReturnMessage.Add("Process completed successfully..."); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("getUser")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserGetResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserGetResponse))] public async Task GetUser([FromBody] ByUserIdRequest request) { ArgumentNullException.ThrowIfNull(request); UserGetResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { string key = "User"; string key2 = $"{request.UserId}"; if (!_cache.TryGetValue(key: key, key2: key2, value: out response)) { response = await _service.GetUserAsync(userId: request.UserId); _ = _cache.Set(key: key, key2: key2, value: response, options: _options); } response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// [ValidateSession] [HttpPost("getCurrentUser")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserGetResponse))] public async Task GetCurrentUser([FromBody] NoContentRequest request) { ArgumentNullException.ThrowIfNull(request); UserGetResponse response; try { int userId = HttpContext.User.GetClaimValue(Constants.UserId); string key = "UserCurrent"; string key2 = $"{userId}"; if (!_cache.TryGetValue(key: key, key2: key2, value: out response)) { response = await _service.GetUserAsync(userId: userId); response.ReturnStatus = StatusCodes.Status200OK; _ = _cache.Set(key: key, key2: key2, value: response, options: _options); } return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response = new UserGetResponse() { ReturnStatus = StatusCodes.Status500InternalServerError }; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// [ValidateSession] [HttpPost("getMyProfile")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserProfileResponse))] public async Task GetMyProfile([FromBody] NoContentRequest request) { ArgumentNullException.ThrowIfNull(request); UserProfileResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { int userId = HttpContext.User.GetClaimValue(Constants.UserId); response = await _service.GetUserProfileAsync(userId: userId); response.HasPayslipPath = !string.IsNullOrEmpty(_appSettings.PayslipPath); response.HasAIApiKey = !string.IsNullOrEmpty(_appSettings.ApiKeyOpenAI) || !string.IsNullOrEmpty(_appSettings.ApiKeyGoogle); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("getMyPayslip")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StringResponse))] public IActionResult GetMyPayslip([FromBody] PayslipRequest request) { ArgumentNullException.ThrowIfNull(request); StringResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; if (string.IsNullOrEmpty(_appSettings.PayslipPath)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Payslip path is not in the system."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } string employeeId = HttpContext.User.GetClaimValue("EmployeeId"); if (string.IsNullOrEmpty(employeeId)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("You are not a valid Employee to view payslip."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string path = $"{employeeId}_{request.YearMonth:yyyy}_{request.YearMonth:MM}.pdf"; path = Path.Combine(_appSettings.PayslipPath, path); if (System.IO.File.Exists(path)) { response.Value = Convert.ToBase64String(System.IO.File.ReadAllBytes(path: path)); return Ok(response); } else { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add($"Payslip does not exists for the Month: {request.YearMonth:MMMM, yyyy}"); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("sendQrCodeViaEmail")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public IActionResult SendQrCodeViaEmail([FromForm] QRCodeUploadRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { if (string.IsNullOrEmpty(request.EmailAddress)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no email address to send mail."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.FileName)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no image to send to send mail."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (request.FileData.Length <= 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no image to send to send mail."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } Result result = ImageFileValidator.Validate(request.FileData); if (!result.Acceptable) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("This is not a valid image file."); return BadRequest(response); } var fileSpec = Path.Combine(_appSettings.UploadFolder, request.FileName); if (System.IO.File.Exists(fileSpec)) System.IO.File.Delete(fileSpec); using (var stream = new FileStream(fileSpec, FileMode.Create)) { request.FileData.CopyTo(stream); } bool sent = MailHelper.SendMailMessage(settings: _appSettings, to: [request.EmailAddress], cc: null, bcc: null, attachments: [fileSpec], embeddedImages: null, isHtmlBody: false, priority: System.Net.Mail.MailPriority.High, subject: "QR Code", messageBody: "Scan image"); if (sent) { if (System.IO.File.Exists(fileSpec)) System.IO.File.Delete(fileSpec); response.Value = sent; response.ReturnMessage.Add($"Successfully mail sent to {request.EmailAddress}"); return Ok(response); } else { response.Value = sent; response.ReturnMessage.Add($"Cannot send mail to {request.EmailAddress}"); return StatusCode(StatusCodes.Status422UnprocessableEntity, response); } } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("uploadProfileImage")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public IActionResult UploadProfileImage([FromForm] FileUploadRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { if (string.IsNullOrEmpty(request.FileName)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no Image to set Profile image."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (request.FileData.Length <= 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no image to set Profile image."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } Result result = ImageFileValidator.Validate(request.FileData); if (!result.Acceptable) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("This is not a valid image file."); return BadRequest(response); } long maxSz = 20 * 1024; if (request.FileData.Length > maxSz) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Maximum size allowed is 20 Kb"); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } var fileSpec = Path.Combine(_appSettings.ProfileImageFolder, request.FileName); if (System.IO.File.Exists(fileSpec)) System.IO.File.Delete(fileSpec); using (var stream = new FileStream(fileSpec, FileMode.Create)) { request.FileData.CopyTo(stream); } response.Value = true; response.ReturnMessage.Add("Refresh page to view your profile image."); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("uploadDocument")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task UploadDocument([FromForm] UploadDocumentRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { if (string.IsNullOrEmpty(request.FileName)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no valid file to process."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (request.FileData.Length <= 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no valid data to process."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } string fileName, fileSpec; if (request.DocumentOf == 6) { string[] allowedExtensions = [".xlsx", ".xls"]; string fileExtension = Path.GetExtension(request.FileName).ToLowerInvariant(); if (!allowedExtensions.Contains(fileExtension)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Only excel file is allowed to process."); return BadRequest(response); } if (fileExtension.EndsWith(".xls")) { Result result = ExcelFileValidator.Validate(request.FileData); if (!result.Acceptable) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("This is not a valid Excel file."); return BadRequest(response); } } else { Result result = ExcelxFileValidator.Validate(request.FileData); if (!result.Acceptable) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("This is not a valid Excel file."); return BadRequest(response); } } fileName = request.FileName; fileSpec = Path.Combine(_appSettings.UploadFolder, fileName); if (System.IO.File.Exists(fileSpec)) System.IO.File.Delete(fileSpec); } else if (request.DocumentOf == 2) { if (!request.FileName.ToLower().EndsWith(".csv")) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Only csv file is allowed to process."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } fileName = request.FileName; fileSpec = Path.Combine(_appSettings.UploadFolder, fileName); if (System.IO.File.Exists(fileSpec)) System.IO.File.Delete(fileSpec); } else { if (!request.FileName.ToLower().EndsWith(".pdf")) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Only pdf file is allowed to Process."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } long maxSz = 10 * 1024 * 1024; if (request.FileData.Length > maxSz) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Maximum allowable size is 10 MB"); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } fileName = $"{request.Id}_{request.DocumentOf}.pdf"; fileSpec = Path.Combine(_appSettings.UploadFolder, fileName); if (System.IO.File.Exists(fileSpec)) System.IO.File.Delete(fileSpec); } using (var stream = new FileStream(fileSpec, FileMode.Create)) { request.FileData.CopyTo(stream); } int userId = HttpContext.User.GetClaimValue(Constants.UserId); response.Value = await _service.UploadDocumentAsync(userId: userId, id: request.Id, documentOf: request.DocumentOf, orgFileName: request.FileName, fileName: fileName); response.ReturnMessage.Add("File Uploaded successfully."); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("getDocument")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StringResponse))] public IActionResult GetDocument([FromBody] FileViewRequest request) { ArgumentNullException.ThrowIfNull(request); StringResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { if (string.IsNullOrEmpty(request.FileName)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("There is no Image to set Profile image."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } string path = Path.Combine(_appSettings.UploadFolder, request.FileName); if (System.IO.File.Exists(path)) { response.Value = Convert.ToBase64String(System.IO.File.ReadAllBytes(path: path)); } return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [HttpPost("findAccount")] [AllowAnonymous, IgnoreAntiforgeryToken] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(FindAccountResponse))] public async Task FindAccount([FromBody] FindAccountRequest request) { ArgumentNullException.ThrowIfNull(request); FindAccountResponse response = new(); if (string.IsNullOrEmpty(request.AccountId)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Login Id or Email address or Mobile number is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string key = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey); request.AccountId = Helper.DecryptData(secret: key, data: request.AccountId); response = await _service.FindAccountAsync(accountId: request.AccountId); return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [HttpPost("sendPassword")] [AllowAnonymous, IgnoreAntiforgeryToken] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task SendPassword([FromBody] SendPasswordRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; if (string.IsNullOrEmpty(request.UserId)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("User Id is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.MobileNo)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Mobile number is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (string.IsNullOrEmpty(request.EmailAddress)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Email address is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string key = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey); string decipherValue = Helper.DecryptData(secret: key, data: request.UserId); if (string.IsNullOrEmpty(decipherValue)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("User Id is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (!int.TryParse(decipherValue, out int userId)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("User Id is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } if (userId == 0) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("User Id is required."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } request.MobileNo = Helper.DecryptData(secret: key, data: request.MobileNo); request.EmailAddress = Helper.DecryptData(secret: key, data: request.EmailAddress); if (string.IsNullOrEmpty(request.MobileNo) && string.IsNullOrEmpty(request.EmailAddress)) { response.ReturnStatus = StatusCodes.Status417ExpectationFailed; response.ReturnMessage.Add("Mobile number and Email address both cannot be empty."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } //Do reset password string newPassword = $"{new Random().Next(100000, 999999)}"; string ipAddress = Request.HttpContext.GetIpAddress(); response.Value = await _service.SendPasswordAsync(userId: userId, newPassword: newPassword, ipAddress: ipAddress); if (response.Value) { if (!string.IsNullOrEmpty(request.EmailAddress) && !string.IsNullOrWhiteSpace(request.EmailAddress)) { List to = [.. request.EmailAddress.Split(separator: ';', options: StringSplitOptions.RemoveEmptyEntries)]; await MailHelper.SendMailMessageAsync(settings: _appSettings, to: to, cc: null, bcc: null, attachments: null, embeddedImages: null, isHtmlBody: false, priority: System.Net.Mail.MailPriority.Normal, subject: "One Time Password", messageBody: $"Your one time password (use as Old password): {newPassword} and must change password at next Login."); } if (!string.IsNullOrEmpty(request.MobileNo) && !string.IsNullOrWhiteSpace(request.MobileNo)) { MailHelper.SendSMSOrWhatsAppMessage(settings: _appSettings, whatsAppMsg: false, msg: $"Your one time password (use as Old password): {newPassword} and must change password at next Login.", mobileNumber: request.MobileNo); } response.ReturnMessage.Add("Password sent to your Email address and/or Mobile number, User must change password at next Login."); } else { response.ReturnMessage.Add("Cannot do action on your request."); } return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("saveAuthorizeLimit")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(BooleanResponse))] public async Task SaveAuthorizeLimit([FromBody] UserLimitAuthorizeRequest request) { ArgumentNullException.ThrowIfNull(request); BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; bool permitted = await HttpContext.IsPermitted("ELIT.9.1.14_1") || await HttpContext.IsPermitted("ELIT.9.1.14_2"); if (!permitted) { response.ReturnStatus = StatusCodes.Status403Forbidden; response.ReturnMessage.Add("You are not authorize to Update Authorization Limit."); return StatusCode(StatusCodes.Status417ExpectationFailed, response); } try { string ipAddress = Request.HttpContext.GetIpAddress(); string loginId = HttpContext.User.GetClaimValue(Constants.LoginId); response.Value = await _service.SaveAuthorizeLimitAsync(maxAuthLimit: request.MaxAuthorizeAmount, userId: request.UserId, ipAddress: ipAddress, savedBy: loginId); response.ReturnMessage.Add("Process completed successfully..."); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("getAuthorizeLimit")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserAuthorizeLimitResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(UserAuthorizeLimitResponse))] public async Task GetAuthorizeLimit([FromBody] ByUserIdRequest request) { ArgumentNullException.ThrowIfNull(request); UserAuthorizeLimitResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { response = await _service.GetAuthorizeLimitAsync(userId: request.UserId); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// [HttpPost("logOut")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BooleanResponse))] public async Task LogOut([FromBody] LogoutRequest request) { BooleanResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { string key = HttpContext.GetAuthenticationToken(); string ipAddress = Request.HttpContext.GetIpAddress(); int userId = HttpContext.User.GetClaimValue(Constants.UserId); string loginId = HttpContext.User.GetClaimValue(Constants.LoginId); if (request.AttendanceLogout) { string cipherSecretKey = GlobalFunctions.ConvertFromBase64String(_appSettings.CipherSecretKey); request.IpAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.IpAddress); request.MacAddress = Helper.DecryptData(secret: cipherSecretKey, data: request.MacAddress); request.HostName = Helper.DecryptData(secret: cipherSecretKey, data: request.HostName); } _ = await _service.LogoutAsync(ipAddress: ipAddress, userId: userId, logId: request.LogId, attendanceLogout: request.AttendanceLogout, loginId: loginId, localIp: request.IpAddress, macAddress: request.MacAddress, hostName: request.HostName, logoutRemarks: request.LogoutRemarks); _cache.Clear(pattern: key); _ = await HttpContext.ClearSessionAsync(); response.Value = true; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// 0 [AllowAnonymous] [IgnoreAntiforgeryToken] [HttpPost("sessionExpired")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task SessionExpired([FromBody] LogoutRequest request) { try { int userId = HttpContext.User.GetClaimValue(Constants.UserId); string ipAddress = Request.HttpContext.GetIpAddress(); _ = await _service.LogoutAsync(ipAddress: ipAddress, userId: userId, logId: request.LogId, attendanceLogout: false, loginId: string.Empty, localIp: string.Empty, macAddress: string.Empty, hostName: string.Empty, logoutRemarks: string.Empty); _ = await HttpContext.ClearSessionAsync(); } catch (Exception ex) { _logger.LogError(ex); } } /// /// /// /// /// /// [SupportedOSPlatform("windows")] private int GetADLoginStatus(string loginId, string password) { try { const string displayNameAttribute = "DisplayName"; const string samAccountNameAttribute = "SAMAccountName"; const string userAccountControlAttribute = "useraccountcontrol"; string username = (string.IsNullOrEmpty(_appSettings.ADConfig.Domain) || string.IsNullOrWhiteSpace(_appSettings.ADConfig.Domain)) ? loginId : $"{loginId}@{_appSettings.ADConfig.Domain}"; using DirectoryEntry entry = new(path: _appSettings.ADConfig.Path, username: username, password: password); using DirectorySearcher searcher = new(searchRoot: entry); searcher.Filter = $"({samAccountNameAttribute}={loginId})"; searcher.PropertiesToLoad.Add(value: displayNameAttribute); searcher.PropertiesToLoad.Add(value: samAccountNameAttribute); searcher.PropertiesToLoad.Add(value: userAccountControlAttribute); var result = searcher.FindOne(); if (result == null) return 0; ResultPropertyValueCollection displayName = result.Properties[name: displayNameAttribute]; ResultPropertyValueCollection samAccountName = result.Properties[name: samAccountNameAttribute]; ResultPropertyValueCollection userAccountControl = result.Properties[name: userAccountControlAttribute]; int uacFlag = (userAccountControl != null && userAccountControl.Count > 0) ? Convert.ToInt32(userAccountControl[0]) : 0; if ((uacFlag & 0x000002) == 0x000002) //Disabled return 2; else if ((uacFlag & 0x800000) == 0x800000) //Password expired return 3; if (displayName != null && displayName.Count > 0 && samAccountName != null && samAccountName.Count > 0) return 1; else return 0; } catch (Exception ex) { _logger.LogError(ex); return 0; } } /// /// /// /// /// [ValidateSession] [HttpPost("getAccessLog")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AccessLogResponse))] [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(AccessLogResponse))] public async Task GetAccessLog([FromBody] AccessLogSearchRequest request) { ArgumentNullException.ThrowIfNull(request); AccessLogResponse response = new() { ReturnStatus = StatusCodes.Status200OK }; try { string loginId = HttpContext.User.GetClaimValue(Constants.LoginId); bool permitted = await HttpContext.IsPermitted("ELIT.1.2.5_2"); if (!(permitted || loginId.Equals(value: Models.Objects.Systems.User.SuperUser_LoginId, comparisonType: StringComparison.OrdinalIgnoreCase))) { request.LoginId = loginId; } response = await _service.GetAccessLogAsync(accessType: request.AccessType, loginId: request.LoginId, startDate: request.StartDate, endDate: request.EndDate); response.ReturnStatus = StatusCodes.Status200OK; return Ok(response); } catch (Exception ex) { _logger.LogError(ex); response.ReturnStatus = StatusCodes.Status500InternalServerError; response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message); return StatusCode(StatusCodes.Status500InternalServerError, response); } } /// /// /// /// /// [ValidateSession] [HttpPost("loadNotificationCount")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))] public async Task LoadNotificationCount([FromBody] NoContentRequest request) { ArgumentNullException.ThrowIfNull(request); try { int value = HttpContext.User.GetClaimValue(Constants.UserId); value = await _service.LoadNotificationCountAsync(userId: value); return Ok(value); } catch (Exception ex) { _logger.LogError(ex); return StatusCode(StatusCodes.Status500InternalServerError); } } } }