update user password via excel
This commit is contained in:
parent
b93734f888
commit
68cf33d5a6
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Setups;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
@ -71,6 +72,14 @@ public class ResetPasswordRequest : ByUserIdRequest
|
||||||
public string ConfirmPassword { get; set; }
|
public string ConfirmPassword { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class BulkPasswordUploadRequest : FileUploadRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// When true, uploaded users are forced to change their password at next login.
|
||||||
|
/// </summary>
|
||||||
|
public bool ForcePasswordChange { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class PasswordChangeRequest : ResetPasswordRequest
|
public class PasswordChangeRequest : ResetPasswordRequest
|
||||||
{
|
{
|
||||||
[Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Old Password must be between 1 and 30 characters.")]
|
[Required, NotNull, StringLength(maximumLength: 30, MinimumLength = 1, ErrorMessage = "Old Password must be between 1 and 30 characters.")]
|
||||||
|
|
|
||||||
|
|
@ -124,4 +124,22 @@ namespace OnlineSalesAutoCrop.CoreAPI.Models.Responses.Systems
|
||||||
public string LoginId { get; set; }
|
public string LoginId { get; set; }
|
||||||
public decimal Value { get; set; }
|
public decimal Value { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class BulkPasswordUploadItem
|
||||||
|
{
|
||||||
|
public int RowNo { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public string EmployeeCode { get; set; }
|
||||||
|
public string LoginId { get; set; }
|
||||||
|
public bool Updated { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BulkPasswordUploadResponse : ResponseBase
|
||||||
|
{
|
||||||
|
public int TotalRows { get; set; }
|
||||||
|
public int SuccessCount { get; set; }
|
||||||
|
public int FailedCount { get; set; }
|
||||||
|
public List<BulkPasswordUploadItem> Items { get; set; } = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -32,6 +32,7 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems
|
||||||
Task<bool> AddUserAsync(NewUserRequest user, string ipAddress, int createdBy);
|
Task<bool> AddUserAsync(NewUserRequest user, string ipAddress, int createdBy);
|
||||||
Task<bool> UpdateMyInfoAsync(string address, string contactNo, int modifiedBy, int emplyeeId);
|
Task<bool> UpdateMyInfoAsync(string address, string contactNo, int modifiedBy, int emplyeeId);
|
||||||
Task<bool> ResetPasswordAsync(int userId, string newPassword, string ipAddress, int changedBy);
|
Task<bool> ResetPasswordAsync(int userId, string newPassword, string ipAddress, int changedBy);
|
||||||
|
Task<BulkPasswordUploadResponse> UpdatePasswordsFromExcelAsync(string fileSpec, string ipAddress, int changedBy, bool forcePasswordChange);
|
||||||
Task<bool> UpdateMyThemeAsync(int userId, string menuLayout, string themeName, string schemeName);
|
Task<bool> UpdateMyThemeAsync(int userId, string menuLayout, string themeName, string schemeName);
|
||||||
Task<bool> SaveAuthorizeLimitAsync(decimal maxAuthLimit, int userId, string ipAddress, string savedBy);
|
Task<bool> SaveAuthorizeLimitAsync(decimal maxAuthLimit, int userId, string ipAddress, string savedBy);
|
||||||
Task<bool> UploadDocumentAsync(int userId, int id, int documentOf, string orgFileName, string fileName);
|
Task<bool> UploadDocumentAsync(int userId, int id, int documentOf, string orgFileName, string fileName);
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,6 @@ public class IntegrationService : IIntegrationService
|
||||||
{
|
{
|
||||||
var materialPriceType = await GetMaterialPriceTypeAsync(tc, request.ConditionType) ;
|
var materialPriceType = await GetMaterialPriceTypeAsync(tc, request.ConditionType) ;
|
||||||
|
|
||||||
|
|
||||||
var validationMessages = Validate(request, materialPriceType.PriceType);
|
var validationMessages = Validate(request, materialPriceType.PriceType);
|
||||||
|
|
||||||
if(validationMessages.Any())
|
if(validationMessages.Any())
|
||||||
|
|
|
||||||
|
|
@ -1169,6 +1169,193 @@ namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.Systems
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates password of multiple users from an uploaded excel file having EmployeeCode and Password columns.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSpec">Full path of the uploaded excel file.</param>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <param name="changedBy"></param>
|
||||||
|
/// <param name="forcePasswordChange">When true, user must change the password at next login.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BulkPasswordUploadResponse> UpdatePasswordsFromExcelAsync(string fileSpec, string ipAddress, int changedBy, bool forcePasswordChange)
|
||||||
|
{
|
||||||
|
BulkPasswordUploadResponse response = new() { ReturnStatus = 200 };
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(fileSpec) || !System.IO.File.Exists(fileSpec))
|
||||||
|
{
|
||||||
|
response.ReturnStatus = 417;
|
||||||
|
response.ReturnMessage.Add("Uploaded excel file was not found.");
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Read data from Excel
|
||||||
|
|
||||||
|
DataTable table = null;
|
||||||
|
DataSet ds = ExcelReader.GetDataSetFromFile(fileSpec: fileSpec, firstRowColumnHeader: true);
|
||||||
|
if (ds != null && ds.Tables.Count > 0)
|
||||||
|
table = ds.Tables[0];
|
||||||
|
|
||||||
|
if (table == null || table.Rows.Count <= 0)
|
||||||
|
{
|
||||||
|
response.ReturnStatus = 417;
|
||||||
|
response.ReturnMessage.Add("There is no data in the excel file to process.");
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
string empCodeColumn = GetColumnName(table: table, columnName: "EmployeeCode");
|
||||||
|
string passwordColumn = GetColumnName(table: table, columnName: "Password");
|
||||||
|
if (string.IsNullOrEmpty(empCodeColumn) || string.IsNullOrEmpty(passwordColumn))
|
||||||
|
{
|
||||||
|
response.ReturnStatus = 417;
|
||||||
|
response.ReturnMessage.Add("Excel file must have [EmployeeCode] and [Password] columns in the first row.");
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int rowNo = 1; //First row of the excel file is the column header
|
||||||
|
foreach (DataRow row in table.Rows)
|
||||||
|
{
|
||||||
|
rowNo++;
|
||||||
|
|
||||||
|
string employeeCode = $"{row[empCodeColumn]}".Trim();
|
||||||
|
string password = $"{row[passwordColumn]}".Trim();
|
||||||
|
if (string.IsNullOrEmpty(employeeCode) && string.IsNullOrEmpty(password))
|
||||||
|
continue; //Skip completely blank row
|
||||||
|
|
||||||
|
response.TotalRows++;
|
||||||
|
BulkPasswordUploadItem item = new() { RowNo = rowNo, EmployeeCode = employeeCode };
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(employeeCode))
|
||||||
|
{
|
||||||
|
item.Message = "Employee Code is empty.";
|
||||||
|
response.FailedCount++;
|
||||||
|
response.Items.Add(item);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
item.Message = "Password is empty.";
|
||||||
|
response.FailedCount++;
|
||||||
|
response.Items.Add(item);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Find the user by Employee Code
|
||||||
|
|
||||||
|
int userId = 0;
|
||||||
|
int matchCount = 0;
|
||||||
|
string loginId = string.Empty;
|
||||||
|
using (IDataReader dr = tc.ExecuteReader("SELECT UserId, LoginId FROM Users WHERE EmployeeCode=%s OR EmployeeNumber=%s", employeeCode, employeeCode))
|
||||||
|
{
|
||||||
|
while (dr.Read())
|
||||||
|
{
|
||||||
|
matchCount++;
|
||||||
|
if (matchCount == 1)
|
||||||
|
{
|
||||||
|
userId = dr.GetInt32(0);
|
||||||
|
loginId = dr.IsDBNull(1) ? string.Empty : dr.GetString(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dr.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchCount <= 0)
|
||||||
|
{
|
||||||
|
item.Message = $"No user found against Employee Code [{employeeCode}].";
|
||||||
|
response.FailedCount++;
|
||||||
|
response.Items.Add(item);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchCount > 1)
|
||||||
|
{
|
||||||
|
item.Message = $"More than one user found against Employee Code [{employeeCode}].";
|
||||||
|
response.FailedCount++;
|
||||||
|
response.Items.Add(item);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
SqlParameter[] p =
|
||||||
|
[
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@NewPwd", pType: SqlDbType.VarChar, pValue: EncryptPassword(password: password), size: 75),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LastPwds", pType: SqlDbType.VarChar, pValue: string.Empty, size: 700),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@LastPwdChgDate", pType: SqlDbType.DateTime, pValue: DateTime.Now),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@PwdExpireDate", pType: SqlDbType.DateTime, pValue: DateTime.Now),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@IpAddress", pType: SqlDbType.VarChar, pValue: ipAddress, size: 20),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: userId),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@ChangedBy", pType: SqlDbType.Int, pValue: changedBy),
|
||||||
|
SqlHelperExtension.CreateInParam(pName: "@ResetPwd", pType: SqlDbType.SmallInt, pValue: (short)(forcePasswordChange ? 1 : 0))
|
||||||
|
];
|
||||||
|
_ = tc.ExecuteNonQuerySp(spName: "dbo.UpdateUserPassword", parameterValues: p);
|
||||||
|
|
||||||
|
item.Updated = true;
|
||||||
|
item.UserId = userId;
|
||||||
|
item.LoginId = loginId;
|
||||||
|
item.Message = "Password updated successfully.";
|
||||||
|
response.SuccessCount++;
|
||||||
|
response.Items.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
tc.End();
|
||||||
|
}
|
||||||
|
catch (Exception ie)
|
||||||
|
{
|
||||||
|
tc?.HandleError();
|
||||||
|
|
||||||
|
throw DBCustomError.GenerateCustomError(ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.TotalRows <= 0)
|
||||||
|
{
|
||||||
|
response.ReturnStatus = 417;
|
||||||
|
response.ReturnMessage.Add("There is no data in the excel file to process.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.ReturnMessage.Add($"{response.SuccessCount} of {response.TotalRows} user password(s) updated successfully.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(e.Message, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the actual column name of the DataTable ignoring case and spaces, null when not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="table"></param>
|
||||||
|
/// <param name="columnName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string GetColumnName(DataTable table, string columnName)
|
||||||
|
{
|
||||||
|
foreach (DataColumn column in table.Columns)
|
||||||
|
{
|
||||||
|
if (string.Equals(column.ColumnName.Replace(" ", string.Empty).Trim(), columnName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return column.ColumnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -604,6 +604,94 @@ namespace OnlineSalesAutoCrop.CoreAPI.Controllers.Web
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates password of multiple users from an excel file having EmployeeCode and Password columns.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[ValidateSession]
|
||||||
|
[HttpPost("uploadPasswords")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BulkPasswordUploadResponse))]
|
||||||
|
public async Task<IActionResult> UploadPasswords([FromForm] BulkPasswordUploadRequest request)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(request);
|
||||||
|
|
||||||
|
BulkPasswordUploadResponse response = new() { ReturnStatus = StatusCodes.Status200OK };
|
||||||
|
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 == null || request.FileData.Length <= 0)
|
||||||
|
{
|
||||||
|
response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
|
||||||
|
response.ReturnMessage.Add("There is no valid data to process.");
|
||||||
|
return StatusCode(StatusCodes.Status417ExpectationFailed, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result result = fileExtension.Equals(".xls") ? ExcelFileValidator.Validate(request.FileData) : ExcelxFileValidator.Validate(request.FileData);
|
||||||
|
if (!result.Acceptable)
|
||||||
|
{
|
||||||
|
response.ReturnStatus = StatusCodes.Status417ExpectationFailed;
|
||||||
|
response.ReturnMessage.Add("This is not a valid Excel file.");
|
||||||
|
return BadRequest(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
string fileSpec = Path.Combine(_appSettings.UploadFolder, $"PWD_{DateTime.Now:yyyyMMddHHmmssfff}{fileExtension}");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var stream = new FileStream(fileSpec, FileMode.Create))
|
||||||
|
{
|
||||||
|
await request.FileData.CopyToAsync(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
string ipAddress = Request.HttpContext.GetIpAddress();
|
||||||
|
int changedBy = HttpContext.User.GetClaimValue<int>(Constants.UserId);
|
||||||
|
response = await _service.UpdatePasswordsFromExcelAsync(fileSpec: fileSpec, ipAddress: ipAddress, changedBy: changedBy, forcePasswordChange: request.ForcePasswordChange);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (System.IO.File.Exists(fileSpec))
|
||||||
|
System.IO.File.Delete(fileSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user