Improved permissions

This commit is contained in:
Sven Heidemann 2022-02-21 18:27:33 +01:00
parent 6c6ef2a8e9
commit 5bd57a9fef
5 changed files with 150 additions and 288 deletions

View File

@ -4,10 +4,8 @@ using System.Threading.Tasks;
using gswi.Model.DTOs; using gswi.Model.DTOs;
using gswi.Share.Common; using gswi.Share.Common;
namespace gswi.Interface.Services namespace gswi.Interface.Services {
{ public interface IAuthService {
public interface IAuthService
{
Task<List<AuthUserDTO>> GetAllAuthUsersAsync(); Task<List<AuthUserDTO>> GetAllAuthUsersAsync();
Task<GetFilteredAuthUsersResultDTO> GetFilteredAuthUsersAsync(AuthUserSelectCriterion selectCriterion); Task<GetFilteredAuthUsersResultDTO> GetFilteredAuthUsersAsync(AuthUserSelectCriterion selectCriterion);
Task<AuthUserDTO> GetAuthUserByEMailAsync(string email); Task<AuthUserDTO> GetAuthUserByEMailAsync(string email);

View File

@ -4,8 +4,8 @@ namespace gswi.Model
{ {
public enum AuthRoles public enum AuthRoles
{ {
User = 0, Supporter = 0,
Supporter = 1, User = 1,
Admin = 2 Admin = 2
} }
} }

View File

@ -6,8 +6,6 @@ using System.Security.Claims;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using NLog;
using gswi.Configuration; using gswi.Configuration;
using gswi.Interface.Repositories; using gswi.Interface.Repositories;
using gswi.Interface.Services; using gswi.Interface.Services;
@ -17,11 +15,11 @@ using gswi.Model.Filters;
using gswi.Share.Common; using gswi.Share.Common;
using gswi.SMTP.Interface; using gswi.SMTP.Interface;
using gswi.SMTP.Model; using gswi.SMTP.Model;
using Microsoft.IdentityModel.Tokens;
using NLog;
namespace gswi.Service namespace gswi.Service {
{ public class AuthServiceImpl : IAuthService {
public class AuthServiceImpl : IAuthService
{
private readonly IAuthUserRepository _authUserRepository; private readonly IAuthUserRepository _authUserRepository;
private readonly IUnitOfWork _unitOfWork; private readonly IUnitOfWork _unitOfWork;
private readonly AuthentificationSettings _authSettings; private readonly AuthentificationSettings _authSettings;
@ -36,8 +34,7 @@ namespace gswi.Service
AuthentificationSettings authSettings, AuthentificationSettings authSettings,
ISMTPClient smtpClient, ISMTPClient smtpClient,
FrontendSettings frontendSettings FrontendSettings frontendSettings
) ) {
{
_unitOfWork = unitOfWork; _unitOfWork = unitOfWork;
_authUserRepository = authUserRepository; _authUserRepository = authUserRepository;
_authSettings = authSettings; _authSettings = authSettings;
@ -45,15 +42,13 @@ namespace gswi.Service
_frontendSettings = frontendSettings; _frontendSettings = frontendSettings;
} }
private static string _randomString(int length) private static string _randomString(int length) {
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return new string(Enumerable.Repeat(chars, length) return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray()); .Select(s => s[random.Next(s.Length)]).ToArray());
} }
private string _generateToken(IEnumerable<Claim> claims) private string _generateToken(IEnumerable<Claim> claims) {
{
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_authSettings.SecretKey)); var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_authSettings.SecretKey));
var signingCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256); var signingCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
@ -68,18 +63,15 @@ namespace gswi.Service
return new JwtSecurityTokenHandler().WriteToken(tokenOptions); return new JwtSecurityTokenHandler().WriteToken(tokenOptions);
} }
private string _generateRefreshToken() private string _generateRefreshToken() {
{
var randomNumber = new byte[32]; var randomNumber = new byte[32];
using (var rng = RandomNumberGenerator.Create()) using (var rng = RandomNumberGenerator.Create()) {
{
rng.GetBytes(randomNumber); rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber); return Convert.ToBase64String(randomNumber);
} }
} }
private async Task<string> _createAndSaveRefreshToken(AuthUser user) private async Task<string> _createAndSaveRefreshToken(AuthUser user) {
{
var refreshToken = this._generateRefreshToken(); var refreshToken = this._generateRefreshToken();
user.RefreshToken = refreshToken; user.RefreshToken = refreshToken;
@ -90,10 +82,8 @@ namespace gswi.Service
return refreshToken; return refreshToken;
} }
private ClaimsPrincipal _getPrincipalFromExpiredToken(string token) private ClaimsPrincipal _getPrincipalFromExpiredToken(string token) {
{ var tokenValidationParameters = new TokenValidationParameters {
var tokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false, //you might want to validate the audience and issuer depending on your use case ValidateAudience = false, //you might want to validate the audience and issuer depending on your use case
ValidateIssuer = false, ValidateIssuer = false,
ValidateIssuerSigningKey = true, ValidateIssuerSigningKey = true,
@ -109,64 +99,52 @@ namespace gswi.Service
return principal; return principal;
} }
private async Task _createAndSaveConfirmationId(AuthUser user) private async Task _createAndSaveConfirmationId(AuthUser user) {
{
bool end = false; bool end = false;
while (!end) while (!end) {
{
string id = _randomString(16); string id = _randomString(16);
var userFromDb = await _authUserRepository.FindAuthUserByEMailConfirmationIdAsync(id); var userFromDb = await _authUserRepository.FindAuthUserByEMailConfirmationIdAsync(id);
if (userFromDb is null) if (userFromDb is null) {
{
end = true; end = true;
user.ConfirmationId = id; user.ConfirmationId = id;
} }
} }
} }
private async Task _createAndSaveForgotPasswordId(AuthUser user) private async Task _createAndSaveForgotPasswordId(AuthUser user) {
{
bool end = false; bool end = false;
while (!end) while (!end) {
{
string id = _randomString(16); string id = _randomString(16);
var userFromDb = await _authUserRepository.FindAuthUserByEMailForgotPasswordIdAsync(id); var userFromDb = await _authUserRepository.FindAuthUserByEMailForgotPasswordIdAsync(id);
if (userFromDb is null) if (userFromDb is null) {
{
end = true; end = true;
user.ForgotPasswordId = id; user.ForgotPasswordId = id;
} }
} }
} }
private async Task _sendConfirmationIdToUser(AuthUser user) private async Task _sendConfirmationIdToUser(AuthUser user) {
{
string url = _frontendSettings.URL.EndsWith("/") ? _frontendSettings.URL : $"{_frontendSettings}/"; string url = _frontendSettings.URL.EndsWith("/") ? _frontendSettings.URL : $"{_frontendSettings}/";
await _smtpClient.SendEmailAsync(new EMail() await _smtpClient.SendEmailAsync(new EMail() {
{
Receiver = user.EMail, Receiver = user.EMail,
Subject = $"E-Mail für {user.FirstName} {user.LastName} bestätigen", Subject = $"E-Mail für {user.FirstName} {user.LastName} bestätigen",
Message = $"{url}auth/register/{user.ConfirmationId}" Message = $"{url}auth/register/{user.ConfirmationId}"
}); });
} }
private async Task _sendForgotPasswordIdToUser(AuthUser user) private async Task _sendForgotPasswordIdToUser(AuthUser user) {
{
string url = _frontendSettings.URL.EndsWith("/") ? _frontendSettings.URL : $"{_frontendSettings}/"; string url = _frontendSettings.URL.EndsWith("/") ? _frontendSettings.URL : $"{_frontendSettings}/";
await _smtpClient.SendEmailAsync(new EMail() await _smtpClient.SendEmailAsync(new EMail() {
{
Receiver = user.EMail, Receiver = user.EMail,
Subject = $"Passwort für {user.FirstName} {user.LastName} zurücksetzen", Subject = $"Passwort für {user.FirstName} {user.LastName} zurücksetzen",
Message = $"{url}auth/forgot-password/{user.ForgotPasswordId}" Message = $"{url}auth/forgot-password/{user.ForgotPasswordId}"
}); });
} }
public async Task<List<AuthUserDTO>> GetAllAuthUsersAsync() public async Task<List<AuthUserDTO>> GetAllAuthUsersAsync() {
{
var authUserDTOs = new List<AuthUserDTO>(); var authUserDTOs = new List<AuthUserDTO>();
var authUsers = await _authUserRepository.GetAllAuthUsersAsync(); var authUsers = await _authUserRepository.GetAllAuthUsersAsync();
authUsers.ForEach(authUser => authUsers.ForEach(authUser => {
{
authUserDTOs.Add(authUser.ToAuthUserDTO()); authUserDTOs.Add(authUser.ToAuthUserDTO());
}); });
return authUserDTOs; return authUserDTOs;
@ -180,38 +158,31 @@ namespace gswi.Service
users.ForEach(user => { users.ForEach(user => {
result.Add(user.ToAuthUserDTO()); result.Add(user.ToAuthUserDTO());
}); });
return new GetFilteredAuthUsersResultDTO() { return new GetFilteredAuthUsersResultDTO() {
Users = result, Users = result,
TotalCount = totalCount TotalCount = totalCount
}; };
} }
public async Task<AuthUserDTO> GetAuthUserByEMailAsync(string email) public async Task<AuthUserDTO> GetAuthUserByEMailAsync(string email) {
{ try {
try
{
var authUser = await _authUserRepository.GetAuthUserByEMailAsync(email); var authUser = await _authUserRepository.GetAuthUserByEMailAsync(email);
return authUser.ToAuthUserDTO(); return authUser.ToAuthUserDTO();
} } catch (Exception e) {
catch (Exception e)
{
_logger.Error(e); _logger.Error(e);
throw new ServiceException(ServiceErrorCode.InvalidData, $"AuthUser with email {email} not found"); throw new ServiceException(ServiceErrorCode.InvalidData, $"AuthUser with email {email} not found");
} }
} }
public async Task<AuthUserDTO> FindAuthUserByEMailAsync(string email) public async Task<AuthUserDTO> FindAuthUserByEMailAsync(string email) {
{
var authUser = await _authUserRepository.FindAuthUserByEMailAsync(email); var authUser = await _authUserRepository.FindAuthUserByEMailAsync(email);
return authUser != null ? authUser.ToAuthUserDTO() : null; return authUser != null ? authUser.ToAuthUserDTO() : null;
} }
public async Task<long> AddAuthUserAsync(AuthUserDTO authUserDTO) public async Task<long> AddAuthUserAsync(AuthUserDTO authUserDTO) {
{
var authUserDb = await _authUserRepository.FindAuthUserByEMailAsync(authUserDTO.EMail); var authUserDb = await _authUserRepository.FindAuthUserByEMailAsync(authUserDTO.EMail);
if (authUserDb != null) if (authUserDb != null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "User already exists"); throw new ServiceException(ServiceErrorCode.InvalidUser, "User already exists");
} }
@ -220,32 +191,26 @@ namespace gswi.Service
var authUser = authUserDTO.ToAuthUser(); var authUser = authUserDTO.ToAuthUser();
if (!IsValidEmail(authUser.EMail)) if (!IsValidEmail(authUser.EMail)) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Invalid E-Mail"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Invalid E-Mail");
} }
try
{
try {
_authUserRepository.AddAuthUser(authUser); _authUserRepository.AddAuthUser(authUser);
await _createAndSaveConfirmationId(authUser); await _createAndSaveConfirmationId(authUser);
await _sendConfirmationIdToUser(authUser); await _sendConfirmationIdToUser(authUser);
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
_logger.Info($"Added authUser with email: {authUser.EMail}"); _logger.Info($"Added authUser with email: {authUser.EMail}");
return authUser.Id; return authUser.Id;
} } catch (Exception e) {
catch (Exception e)
{
_logger.Error(e); _logger.Error(e);
throw new ServiceException(ServiceErrorCode.UnableToAdd, $"Cannot add authUser {authUserDTO.EMail}"); throw new ServiceException(ServiceErrorCode.UnableToAdd, $"Cannot add authUser {authUserDTO.EMail}");
} }
} }
public async Task<bool> ConfirmEMail(string id) public async Task<bool> ConfirmEMail(string id) {
{
var user = await _authUserRepository.FindAuthUserByEMailConfirmationIdAsync(id); var user = await _authUserRepository.FindAuthUserByEMailConfirmationIdAsync(id);
if (user.ConfirmationId == id) if (user.ConfirmationId == id) {
{
user.ConfirmationId = null; user.ConfirmationId = null;
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
return true; return true;
@ -253,27 +218,22 @@ namespace gswi.Service
return false; return false;
} }
public async Task<TokenDTO> Login(AuthUserDTO userDTO) public async Task<TokenDTO> Login(AuthUserDTO userDTO) {
{ if (userDTO == null) {
if (userDTO == null)
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"User is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"User is empty");
} }
var userFromDb = await _authUserRepository.FindAuthUserByEMailAsync(userDTO.EMail); var userFromDb = await _authUserRepository.FindAuthUserByEMailAsync(userDTO.EMail);
if (userFromDb == null) if (userFromDb == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found"); throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found");
} }
if (userFromDb.ConfirmationId != null) if (userFromDb.ConfirmationId != null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "E-Mail not confirmed"); throw new ServiceException(ServiceErrorCode.InvalidUser, "E-Mail not confirmed");
} }
userDTO.Password = ComputeHash(userDTO.Password, new SHA256CryptoServiceProvider()); userDTO.Password = ComputeHash(userDTO.Password, new SHA256CryptoServiceProvider());
if (userFromDb.Password != userDTO.Password) if (userFromDb.Password != userDTO.Password) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "Wrong password"); throw new ServiceException(ServiceErrorCode.InvalidUser, "Wrong password");
} }
@ -284,24 +244,20 @@ namespace gswi.Service
var refreshString = await this._createAndSaveRefreshToken(userFromDb); var refreshString = await this._createAndSaveRefreshToken(userFromDb);
if (userFromDb.ForgotPasswordId != null) if (userFromDb.ForgotPasswordId != null) {
{
userFromDb.ForgotPasswordId = null; userFromDb.ForgotPasswordId = null;
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
} }
return new TokenDTO return new TokenDTO {
{
Token = tokenString, Token = tokenString,
RefreshToken = refreshString RefreshToken = refreshString
}; };
} }
public async Task ForgotPassword(string email) public async Task ForgotPassword(string email) {
{
var user = await _authUserRepository.FindAuthUserByEMailAsync(email); var user = await _authUserRepository.FindAuthUserByEMailAsync(email);
if (user is null) if (user is null) {
{
return; return;
} }
await _createAndSaveForgotPasswordId(user); await _createAndSaveForgotPasswordId(user);
@ -309,30 +265,24 @@ namespace gswi.Service
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
} }
public async Task<EMailStringDTO> ConfirmForgotPassword(string id) public async Task<EMailStringDTO> ConfirmForgotPassword(string id) {
{
var user = await _authUserRepository.FindAuthUserByEMailForgotPasswordIdAsync(id); var user = await _authUserRepository.FindAuthUserByEMailForgotPasswordIdAsync(id);
return new EMailStringDTO() return new EMailStringDTO() {
{
EMail = user.EMail EMail = user.EMail
}; };
} }
public async Task ResetPassword(ResetPasswordDTO rpDTO) public async Task ResetPassword(ResetPasswordDTO rpDTO) {
{
var user = await _authUserRepository.FindAuthUserByEMailForgotPasswordIdAsync(rpDTO.Id); var user = await _authUserRepository.FindAuthUserByEMailForgotPasswordIdAsync(rpDTO.Id);
if (user == null) if (user == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found"); throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found");
} }
if (user.ConfirmationId != null) if (user.ConfirmationId != null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "E-Mail not confirmed"); throw new ServiceException(ServiceErrorCode.InvalidUser, "E-Mail not confirmed");
} }
if (rpDTO.Password == null || rpDTO.Password == "") if (rpDTO.Password == null || rpDTO.Password == "") {
{
throw new ServiceException(ServiceErrorCode.InvalidData, "Password is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, "Password is empty");
} }
@ -341,57 +291,46 @@ namespace gswi.Service
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
} }
public async Task UpdateUser(UpdateUserDTO updateUserDTO) public async Task UpdateUser(UpdateUserDTO updateUserDTO) {
{ if (updateUserDTO == null) {
if (updateUserDTO == null)
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"User is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"User is empty");
} }
if (updateUserDTO.AuthUserDTO == null) if (updateUserDTO.AuthUserDTO == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Existing user is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Existing user is empty");
} }
if (updateUserDTO.NewAuthUserDTO == null) if (updateUserDTO.NewAuthUserDTO == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"New user is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"New user is empty");
} }
if (!IsValidEmail(updateUserDTO.AuthUserDTO.EMail) || !IsValidEmail(updateUserDTO.NewAuthUserDTO.EMail)) if (!IsValidEmail(updateUserDTO.AuthUserDTO.EMail) || !IsValidEmail(updateUserDTO.NewAuthUserDTO.EMail)) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Invalid E-Mail"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Invalid E-Mail");
} }
var user = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.AuthUserDTO.EMail); var user = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.AuthUserDTO.EMail);
if (user == null) if (user == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found"); throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found");
} }
if (user.ConfirmationId != null) if (user.ConfirmationId != null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "E-Mail not confirmed"); throw new ServiceException(ServiceErrorCode.InvalidUser, "E-Mail not confirmed");
} }
// update first name // update first name
if (updateUserDTO.NewAuthUserDTO.FirstName != null && updateUserDTO.AuthUserDTO.FirstName != updateUserDTO.NewAuthUserDTO.FirstName) if (updateUserDTO.NewAuthUserDTO.FirstName != null && updateUserDTO.AuthUserDTO.FirstName != updateUserDTO.NewAuthUserDTO.FirstName) {
{
user.FirstName = updateUserDTO.NewAuthUserDTO.FirstName; user.FirstName = updateUserDTO.NewAuthUserDTO.FirstName;
} }
// update last name // update last name
if (updateUserDTO.NewAuthUserDTO.LastName != null && updateUserDTO.NewAuthUserDTO.LastName != "" && updateUserDTO.AuthUserDTO.LastName != updateUserDTO.NewAuthUserDTO.LastName) if (updateUserDTO.NewAuthUserDTO.LastName != null && updateUserDTO.NewAuthUserDTO.LastName != "" && updateUserDTO.AuthUserDTO.LastName != updateUserDTO.NewAuthUserDTO.LastName) {
{
user.LastName = updateUserDTO.NewAuthUserDTO.LastName; user.LastName = updateUserDTO.NewAuthUserDTO.LastName;
} }
// update E-Mail // update E-Mail
if (updateUserDTO.NewAuthUserDTO.EMail != null && updateUserDTO.NewAuthUserDTO.EMail != "" && updateUserDTO.AuthUserDTO.EMail != updateUserDTO.NewAuthUserDTO.EMail) if (updateUserDTO.NewAuthUserDTO.EMail != null && updateUserDTO.NewAuthUserDTO.EMail != "" && updateUserDTO.AuthUserDTO.EMail != updateUserDTO.NewAuthUserDTO.EMail) {
{
var userByNewEMail = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.NewAuthUserDTO.EMail); var userByNewEMail = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.NewAuthUserDTO.EMail);
if (userByNewEMail != null) if (userByNewEMail != null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "User already exists"); throw new ServiceException(ServiceErrorCode.InvalidUser, "User already exists");
} }
user.EMail = updateUserDTO.NewAuthUserDTO.EMail; user.EMail = updateUserDTO.NewAuthUserDTO.EMail;
@ -400,66 +339,53 @@ namespace gswi.Service
bool isExistingPasswordSet = false; bool isExistingPasswordSet = false;
bool isnewPasswordSet = false; bool isnewPasswordSet = false;
// hash passwords in DTOs // hash passwords in DTOs
if (updateUserDTO.AuthUserDTO.Password != null && updateUserDTO.AuthUserDTO.Password != "") if (updateUserDTO.AuthUserDTO.Password != null && updateUserDTO.AuthUserDTO.Password != "") {
{
isExistingPasswordSet = true; isExistingPasswordSet = true;
updateUserDTO.AuthUserDTO.Password = ComputeHash(updateUserDTO.AuthUserDTO.Password, new SHA256CryptoServiceProvider()); updateUserDTO.AuthUserDTO.Password = ComputeHash(updateUserDTO.AuthUserDTO.Password, new SHA256CryptoServiceProvider());
} }
if (updateUserDTO.AuthUserDTO.Password != user.Password) if (updateUserDTO.AuthUserDTO.Password != user.Password) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "Wrong password"); throw new ServiceException(ServiceErrorCode.InvalidUser, "Wrong password");
} }
if (updateUserDTO.NewAuthUserDTO.Password != null && updateUserDTO.NewAuthUserDTO.Password != "") if (updateUserDTO.NewAuthUserDTO.Password != null && updateUserDTO.NewAuthUserDTO.Password != "") {
{
isnewPasswordSet = true; isnewPasswordSet = true;
updateUserDTO.NewAuthUserDTO.Password = ComputeHash(updateUserDTO.NewAuthUserDTO.Password, new SHA256CryptoServiceProvider()); updateUserDTO.NewAuthUserDTO.Password = ComputeHash(updateUserDTO.NewAuthUserDTO.Password, new SHA256CryptoServiceProvider());
} }
// update password // update password
if (isExistingPasswordSet && isnewPasswordSet && updateUserDTO.AuthUserDTO.Password != updateUserDTO.NewAuthUserDTO.Password) if (isExistingPasswordSet && isnewPasswordSet && updateUserDTO.AuthUserDTO.Password != updateUserDTO.NewAuthUserDTO.Password) {
{
user.Password = updateUserDTO.NewAuthUserDTO.Password; user.Password = updateUserDTO.NewAuthUserDTO.Password;
} }
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
} }
public async Task UpdateUserAsAdmin(AdminUpdateUserDTO updateUserDTO) public async Task UpdateUserAsAdmin(AdminUpdateUserDTO updateUserDTO) {
{ if (updateUserDTO == null) {
if (updateUserDTO == null)
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"User is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"User is empty");
} }
if (updateUserDTO.AuthUserDTO == null) if (updateUserDTO.AuthUserDTO == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Existing user is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Existing user is empty");
} }
if (updateUserDTO.NewAuthUserDTO == null) if (updateUserDTO.NewAuthUserDTO == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"New user is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"New user is empty");
} }
if (!IsValidEmail(updateUserDTO.AuthUserDTO.EMail) || !IsValidEmail(updateUserDTO.NewAuthUserDTO.EMail)) if (!IsValidEmail(updateUserDTO.AuthUserDTO.EMail) || !IsValidEmail(updateUserDTO.NewAuthUserDTO.EMail)) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Invalid E-Mail"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Invalid E-Mail");
} }
var user = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.AuthUserDTO.EMail); var user = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.AuthUserDTO.EMail);
if (user == null) if (user == null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found"); throw new ServiceException(ServiceErrorCode.InvalidUser, "User not found");
} }
if (user.ConfirmationId != null && updateUserDTO.NewAuthUserDTO.IsConfirmed) if (user.ConfirmationId != null && updateUserDTO.NewAuthUserDTO.IsConfirmed) {
{
user.ConfirmationId = null; user.ConfirmationId = null;
} } else if (user.ConfirmationId == null && !updateUserDTO.NewAuthUserDTO.IsConfirmed) {
else if (user.ConfirmationId == null && !updateUserDTO.NewAuthUserDTO.IsConfirmed)
{
await _createAndSaveConfirmationId(user); await _createAndSaveConfirmationId(user);
} }
@ -469,47 +395,39 @@ namespace gswi.Service
// } // }
// update first name // update first name
if (updateUserDTO.NewAuthUserDTO.FirstName != null && updateUserDTO.AuthUserDTO.FirstName != updateUserDTO.NewAuthUserDTO.FirstName) if (updateUserDTO.NewAuthUserDTO.FirstName != null && updateUserDTO.AuthUserDTO.FirstName != updateUserDTO.NewAuthUserDTO.FirstName) {
{
user.FirstName = updateUserDTO.NewAuthUserDTO.FirstName; user.FirstName = updateUserDTO.NewAuthUserDTO.FirstName;
} }
// update last name // update last name
if (updateUserDTO.NewAuthUserDTO.LastName != null && updateUserDTO.NewAuthUserDTO.LastName != "" && updateUserDTO.AuthUserDTO.LastName != updateUserDTO.NewAuthUserDTO.LastName) if (updateUserDTO.NewAuthUserDTO.LastName != null && updateUserDTO.NewAuthUserDTO.LastName != "" && updateUserDTO.AuthUserDTO.LastName != updateUserDTO.NewAuthUserDTO.LastName) {
{
user.LastName = updateUserDTO.NewAuthUserDTO.LastName; user.LastName = updateUserDTO.NewAuthUserDTO.LastName;
} }
// update E-Mail // update E-Mail
if (updateUserDTO.NewAuthUserDTO.EMail != null && updateUserDTO.NewAuthUserDTO.EMail != "" && updateUserDTO.AuthUserDTO.EMail != updateUserDTO.NewAuthUserDTO.EMail) if (updateUserDTO.NewAuthUserDTO.EMail != null && updateUserDTO.NewAuthUserDTO.EMail != "" && updateUserDTO.AuthUserDTO.EMail != updateUserDTO.NewAuthUserDTO.EMail) {
{
var userByNewEMail = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.NewAuthUserDTO.EMail); var userByNewEMail = await _authUserRepository.FindAuthUserByEMailAsync(updateUserDTO.NewAuthUserDTO.EMail);
if (userByNewEMail != null) if (userByNewEMail != null) {
{
throw new ServiceException(ServiceErrorCode.InvalidUser, "User already exists"); throw new ServiceException(ServiceErrorCode.InvalidUser, "User already exists");
} }
user.EMail = updateUserDTO.NewAuthUserDTO.EMail; user.EMail = updateUserDTO.NewAuthUserDTO.EMail;
} }
// update password // update password
if (updateUserDTO.ChangePassword && updateUserDTO.AuthUserDTO.Password != updateUserDTO.NewAuthUserDTO.Password) if (updateUserDTO.ChangePassword && updateUserDTO.AuthUserDTO.Password != updateUserDTO.NewAuthUserDTO.Password) {
{
user.Password = ComputeHash(updateUserDTO.NewAuthUserDTO.Password, new SHA256CryptoServiceProvider()); user.Password = ComputeHash(updateUserDTO.NewAuthUserDTO.Password, new SHA256CryptoServiceProvider());
} }
// update role // update role
if (user.AuthRole == updateUserDTO.AuthUserDTO.AuthRole && user.AuthRole != updateUserDTO.NewAuthUserDTO.AuthRole) if (user.AuthRole == updateUserDTO.AuthUserDTO.AuthRole && user.AuthRole != updateUserDTO.NewAuthUserDTO.AuthRole) {
{
user.AuthRole = updateUserDTO.NewAuthUserDTO.AuthRole; user.AuthRole = updateUserDTO.NewAuthUserDTO.AuthRole;
} }
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
} }
public async Task<TokenDTO> Refresh(TokenDTO tokenDTO) public async Task<TokenDTO> Refresh(TokenDTO tokenDTO) {
{ if (tokenDTO is null) {
if (tokenDTO is null)
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is empty");
} }
@ -517,25 +435,21 @@ namespace gswi.Service
var email = principal.Identity.Name; var email = principal.Identity.Name;
var user = await this._authUserRepository.FindAuthUserByEMailAsync(email); var user = await this._authUserRepository.FindAuthUserByEMailAsync(email);
if (user == null || user.RefreshToken != tokenDTO.RefreshToken || user.RefreshTokenExpiryTime <= DateTime.Now) if (user == null || user.RefreshToken != tokenDTO.RefreshToken || user.RefreshTokenExpiryTime <= DateTime.Now) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is expired"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is expired");
} }
var newToken = this._generateToken(principal.Claims); var newToken = this._generateToken(principal.Claims);
var newRefreshToken = await this._createAndSaveRefreshToken(user); var newRefreshToken = await this._createAndSaveRefreshToken(user);
return new TokenDTO() return new TokenDTO() {
{
Token = newToken, Token = newToken,
RefreshToken = newRefreshToken RefreshToken = newRefreshToken
}; };
} }
public async Task Revoke(TokenDTO tokenDTO) public async Task Revoke(TokenDTO tokenDTO) {
{ if (tokenDTO == null || tokenDTO.Token == null || tokenDTO.RefreshToken == null) {
if (tokenDTO == null || tokenDTO.Token == null || tokenDTO.RefreshToken == null)
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is empty"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is empty");
}; };
@ -543,60 +457,46 @@ namespace gswi.Service
var email = principal.Identity.Name; var email = principal.Identity.Name;
var user = await this._authUserRepository.FindAuthUserByEMailAsync(email); var user = await this._authUserRepository.FindAuthUserByEMailAsync(email);
if (user == null || user.RefreshToken != tokenDTO.RefreshToken || user.RefreshTokenExpiryTime <= DateTime.Now) if (user == null || user.RefreshToken != tokenDTO.RefreshToken || user.RefreshTokenExpiryTime <= DateTime.Now) {
{
throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is expired"); throw new ServiceException(ServiceErrorCode.InvalidData, $"Token is expired");
} }
user.RefreshToken = null; user.RefreshToken = null;
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
} }
public async Task DeleteAuthUserByEMailAsync(string email) public async Task DeleteAuthUserByEMailAsync(string email) {
{ try {
try
{
await _authUserRepository.DeleteAuthUserByEMailAsync(email); await _authUserRepository.DeleteAuthUserByEMailAsync(email);
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
_logger.Info($"Deleted authUser with email: {email}"); _logger.Info($"Deleted authUser with email: {email}");
} } catch (Exception e) {
catch (Exception e)
{
_logger.Error(e); _logger.Error(e);
throw new ServiceException(ServiceErrorCode.UnableToDelete, $"Cannot delete authUser with email {email}"); throw new ServiceException(ServiceErrorCode.UnableToDelete, $"Cannot delete authUser with email {email}");
} }
} }
public async Task DeleteAuthUserAsync(AuthUserDTO authUserDTO) public async Task DeleteAuthUserAsync(AuthUserDTO authUserDTO) {
{ try {
try
{
_authUserRepository.DeleteAuthUser(authUserDTO.ToAuthUser()); _authUserRepository.DeleteAuthUser(authUserDTO.ToAuthUser());
await _unitOfWork.SaveChangesAsync(); await _unitOfWork.SaveChangesAsync();
_logger.Info($"Deleted authUser {authUserDTO.EMail}"); _logger.Info($"Deleted authUser {authUserDTO.EMail}");
} } catch (Exception e) {
catch (Exception e)
{
_logger.Error(e); _logger.Error(e);
throw new ServiceException(ServiceErrorCode.UnableToDelete, $"Cannot delete authUser {authUserDTO.EMail}"); throw new ServiceException(ServiceErrorCode.UnableToDelete, $"Cannot delete authUser {authUserDTO.EMail}");
} }
} }
private string ComputeHash(string input, HashAlgorithm algorithm) private string ComputeHash(string input, HashAlgorithm algorithm) {
{
Byte[] inputBytes = Encoding.UTF8.GetBytes(input); Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
Byte[] hashedBytes = algorithm.ComputeHash(inputBytes); Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);
return BitConverter.ToString(hashedBytes); return BitConverter.ToString(hashedBytes);
} }
private bool IsValidEmail(string email) private bool IsValidEmail(string email) {
{ try {
try
{
var addr = new System.Net.Mail.MailAddress(email); var addr = new System.Net.Mail.MailAddress(email);
return addr.Address == email; return addr.Address == email;
} } catch {
catch
{
return false; return false;
} }
} }

View File

@ -4,25 +4,22 @@ using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims; using System.Security.Claims;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using gswi.Interface.Services; using gswi.Interface.Services;
using gswi.Model.DTOs; using gswi.Model.DTOs;
using gswi.Share.Common; using gswi.Share.Common;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
namespace gswi.Controllers namespace gswi.Controllers {
{
[Route("api/auth")] [Route("api/auth")]
[ApiController] [ApiController]
public class AuthController : ControllerBase public class AuthController : ControllerBase {
{
private readonly IAuthService _authService; private readonly IAuthService _authService;
public AuthController( public AuthController(
IAuthService authServce IAuthService authServce
) ) {
{
_authService = authServce; _authService = authServce;
} }
@ -30,118 +27,102 @@ namespace gswi.Controllers
// Get /api/auth/users // Get /api/auth/users
[HttpGet("users")] [HttpGet("users")]
[Authorize] [Authorize]
public async Task<List<AuthUserDTO>> GetAllAuthUsers() public async Task<List<AuthUserDTO>> GetAllAuthUsers() {
{
return await _authService.GetAllAuthUsersAsync(); return await _authService.GetAllAuthUsersAsync();
} }
// POST /api/auth/users/get/filtered // POST /api/auth/users/get/filtered
[HttpPost("users/get/filtered")] [HttpPost("users/get/filtered")]
[Authorize] [Authorize]
public async Task<GetFilteredAuthUsersResultDTO> GetFilteredAuthUsers(AuthUserSelectCriterion selectCriterion) public async Task<GetFilteredAuthUsersResultDTO> GetFilteredAuthUsers(AuthUserSelectCriterion selectCriterion) {
{
return await _authService.GetFilteredAuthUsersAsync(selectCriterion); return await _authService.GetFilteredAuthUsersAsync(selectCriterion);
} }
// Get /api/auth/users/get/<mail> // Get /api/auth/users/get/<mail>
[HttpGet("users/get/{email}")] [HttpGet("users/get/{email}")]
[Authorize] [Authorize]
public async Task<AuthUserDTO> GetUserFromEMail(string email) public async Task<AuthUserDTO> GetUserFromEMail(string email) {
{
return await _authService.GetAuthUserByEMailAsync(email); return await _authService.GetAuthUserByEMailAsync(email);
} }
// Get /api/auth/users/find/<mail> // Get /api/auth/users/find/<mail>
[HttpGet("users/find/{email}")] [HttpGet("users/find/{email}")]
[Authorize] [Authorize]
public async Task<AuthUserDTO> FindUserFromEMail(string email) public async Task<AuthUserDTO> FindUserFromEMail(string email) {
{
return await _authService.FindAuthUserByEMailAsync(email); return await _authService.FindAuthUserByEMailAsync(email);
} }
/* Auth requests */ /* Auth requests */
// POST /api/auth/register // POST /api/auth/register
[HttpPost("register")] [HttpPost("register")]
public async Task Register(AuthUserDTO userDTO) public async Task Register(AuthUserDTO userDTO) {
{
await _authService.AddAuthUserAsync(userDTO); await _authService.AddAuthUserAsync(userDTO);
} }
// POST /api/auth/register/<id> // POST /api/auth/register/<id>
[HttpPost("register/{id}")] [HttpPost("register/{id}")]
public async Task<bool> ConfirmEMail(string id) public async Task<bool> ConfirmEMail(string id) {
{
return await _authService.ConfirmEMail(id); return await _authService.ConfirmEMail(id);
} }
// POST /api/auth/login // POST /api/auth/login
[HttpPost("login")] [HttpPost("login")]
public async Task<TokenDTO> Login(AuthUserDTO userDTO) public async Task<TokenDTO> Login(AuthUserDTO userDTO) {
{
return await _authService.Login(userDTO); return await _authService.Login(userDTO);
} }
// POST /api/auth/forgot-password // POST /api/auth/forgot-password
[HttpPost("forgot-password")] [HttpPost("forgot-password")]
public async Task ForgotPassword([FromBody] string email) public async Task ForgotPassword([FromBody] string email) {
{
await _authService.ForgotPassword(email); await _authService.ForgotPassword(email);
} }
// POST /api/auth/confirm-forgot-password // POST /api/auth/confirm-forgot-password
[HttpPost("confirm-forgot-password")] [HttpPost("confirm-forgot-password")]
public async Task<EMailStringDTO> ConfirmForgotPassword([FromBody] string id) public async Task<EMailStringDTO> ConfirmForgotPassword([FromBody] string id) {
{
return await _authService.ConfirmForgotPassword(id); return await _authService.ConfirmForgotPassword(id);
} }
// POST /api/auth/reset-password // POST /api/auth/reset-password
[HttpPost("reset-password")] [HttpPost("reset-password")]
public async Task ResetPassword(ResetPasswordDTO rpDTO) public async Task ResetPassword(ResetPasswordDTO rpDTO) {
{
await _authService.ResetPassword(rpDTO); await _authService.ResetPassword(rpDTO);
} }
// POST /api/auth/update-user // POST /api/auth/update-user
[HttpPost("update-user")] [HttpPost("update-user")]
public async Task UpdateUser(UpdateUserDTO updateUserDTO) public async Task UpdateUser(UpdateUserDTO updateUserDTO) {
{
await _authService.UpdateUser(updateUserDTO); await _authService.UpdateUser(updateUserDTO);
} }
// POST /api/auth/update-user-as-admin // POST /api/auth/update-user-as-admin
[HttpPost("update-user-as-admin")] [HttpPost("update-user-as-admin")]
[Authorize] [Authorize]
public async Task UpdateUserAsAdmin(AdminUpdateUserDTO updateUserDTO) public async Task UpdateUserAsAdmin(AdminUpdateUserDTO updateUserDTO) {
{
await _authService.UpdateUserAsAdmin(updateUserDTO); await _authService.UpdateUserAsAdmin(updateUserDTO);
} }
// POST /api/auth/refresh // POST /api/auth/refresh
[HttpPost("refresh")] [HttpPost("refresh")]
public async Task<TokenDTO> Refresh(TokenDTO tokenDTO) public async Task<TokenDTO> Refresh(TokenDTO tokenDTO) {
{
return await _authService.Refresh(tokenDTO); return await _authService.Refresh(tokenDTO);
} }
// POST /api/auth/revoke // POST /api/auth/revoke
[HttpPost("revoke")] [HttpPost("revoke")]
public async Task Revoke(TokenDTO tokenDTO) public async Task Revoke(TokenDTO tokenDTO) {
{
await _authService.Revoke(tokenDTO); await _authService.Revoke(tokenDTO);
} }
// POST /api/auth/delete-user // POST /api/auth/delete-user
[HttpPost("delete-user")] [HttpPost("delete-user")]
public async Task DeleteAuthUserAsync(AuthUserDTO userDTO) public async Task DeleteAuthUserAsync(AuthUserDTO userDTO) {
{
await _authService.DeleteAuthUserAsync(userDTO); await _authService.DeleteAuthUserAsync(userDTO);
} }
// POST /api/auth/delete-user // POST /api/auth/delete-user
[HttpPost("delete-user-by-mail/{mail}")] [HttpPost("delete-user-by-mail/{mail}")]
public async Task DeleteAuthUserByEMailAsync(string mail) public async Task DeleteAuthUserByEMailAsync(string mail) {
{
await _authService.DeleteAuthUserByEMailAsync(mail); await _authService.DeleteAuthUserByEMailAsync(mail);
} }
} }

View File

@ -1,73 +1,56 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Security.Cryptography;
using Microsoft.EntityFrameworkCore;
using gswi.Data; using gswi.Data;
using gswi.Model; using gswi.Model;
using Microsoft.EntityFrameworkCore;
namespace gswi namespace gswi {
{ public class DataSeeder {
public class DataSeeder
{
private readonly DatabaseContext _databaseContext; private readonly DatabaseContext _databaseContext;
public DataSeeder(DatabaseContext databaseContext) public DataSeeder(DatabaseContext databaseContext) {
{
_databaseContext = databaseContext; _databaseContext = databaseContext;
} }
public void SeedData() public void SeedData() {
{
_databaseContext.Database.EnsureCreated(); _databaseContext.Database.EnsureCreated();
if (!_databaseContext.AuthUsers.Any()) if (!_databaseContext.AuthUsers.Any()) {
{ var admin = new AuthUser() {
var admin = new AuthUser()
{
FirstName = "Admin", FirstName = "Admin",
LastName = "Administator", LastName = "Admin",
EMail = "admin@localhost", EMail = "admin@localhost.local",
Password = ComputeHash("Administator", new SHA256CryptoServiceProvider()), Password = ComputeHash("localhost.local", new SHA256CryptoServiceProvider()),
AuthRole = AuthRoles.Admin AuthRole = AuthRoles.Admin
}; };
var authUser = new AuthUser() var support = new AuthUser() {
{ FirstName = "Support",
FirstName = "Max", LastName = "Supporter",
LastName = "Mustermann", EMail = "support@localhost.local",
EMail = "max.mustermann@gmail.com", Password = ComputeHash("localhost.local", new SHA256CryptoServiceProvider()),
Password = ComputeHash("test1234", new SHA256CryptoServiceProvider()), AuthRole = AuthRoles.Supporter
}; };
var authUser1 = new AuthUser() var user = new AuthUser() {
{ FirstName = "User",
FirstName = "Max", LastName = "User",
LastName = "Tester", EMail = "user@localhost.local",
EMail = "max.mustermann@mustermail.com", Password = ComputeHash("localhost.local", new SHA256CryptoServiceProvider()),
Password = ComputeHash("test1234", new SHA256CryptoServiceProvider()), AuthRole = AuthRoles.User
};
var authUser2 = new AuthUser()
{
FirstName = "Max",
LastName = "Muster",
EMail = "max.mustermann@yahoo.com",
Password = ComputeHash("test1234", new SHA256CryptoServiceProvider()),
}; };
_databaseContext.AuthUsers.Add(admin); _databaseContext.AuthUsers.Add(admin);
_databaseContext.AuthUsers.Add(authUser); _databaseContext.AuthUsers.Add(support);
_databaseContext.AuthUsers.Add(authUser1); _databaseContext.AuthUsers.Add(user);
_databaseContext.AuthUsers.Add(authUser2);
} }
_databaseContext.SaveChanges(); _databaseContext.SaveChanges();
} }
public string ComputeHash(string input, HashAlgorithm algorithm) public string ComputeHash(string input, HashAlgorithm algorithm) {
{
Byte[] inputBytes = Encoding.UTF8.GetBytes(input); Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
Byte[] hashedBytes = algorithm.ComputeHash(inputBytes); Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);
return BitConverter.ToString(hashedBytes); return BitConverter.ToString(hashedBytes);