Commit da9d0201 authored by hasan khaddour's avatar hasan khaddour

add background jobs.

parent e7db6cc3
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using PSManagement.Application.Contracts.Providers;
using PSManagement.Application.Contracts.SyncData;
using PSManagement.Infrastructure.Settings;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.BackgroundServcies
{
public class BackgroundJobSyncEmployees: BackgroundService
{
private readonly IDateTimeProvider _timeProvider;
private readonly IServiceScopeFactory _scopeFactory;
private readonly int _syncIntervalInMinutes;
public BackgroundJobSyncEmployees(
IDateTimeProvider timeProvider,
IOptions<EmployeesSyncJobSettings> settings,
IServiceScopeFactory scopeFactory)
{
_timeProvider = timeProvider;
_syncIntervalInMinutes = settings.Value.SyncIntervalInMinutes;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// This loop will run until the application shuts down
while (!stoppingToken.IsCancellationRequested)
{
try
{
using (var scope = _scopeFactory.CreateScope())
{
// Resolve the scoped IEmployeesRepository
var dataProvider = scope.ServiceProvider.GetRequiredService<IEmployeesProvider>();
var syncService = scope.ServiceProvider.GetRequiredService<ISyncEmployeesService>();
// Now you can use the repository to sync employees data
await syncService.SyncEmployees(dataProvider);
}
}
catch (Exception ex)
{
}
// Wait for an hour before running the task again
await Task.Delay(TimeSpan.FromMinutes(_syncIntervalInMinutes), stoppingToken);
}
}
}
}
......@@ -5,10 +5,15 @@ using Microsoft.Extensions.DependencyInjection;
using PSManagement.Application.Contracts.Authentication;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.Application.Contracts.Providers;
using PSManagement.Application.Contracts.SyncData;
using PSManagement.Application.Contracts.Tokens;
using PSManagement.Domain.Identity.Repositories;
using PSManagement.Infrastructure.Authentication;
using PSManagement.Infrastructure.Services;
using PSManagement.Infrastructure.BackgroundServcies;
using PSManagement.Infrastructure.Services.Authentication;
using PSManagement.Infrastructure.Services.Authorization;
using PSManagement.Infrastructure.Services.Providers;
using PSManagement.Infrastructure.Settings;
using PSManagement.Infrastructure.Tokens;
namespace PSManagement.Infrastructure.DI
......@@ -20,7 +25,8 @@ namespace PSManagement.Infrastructure.DI
services
.AddAuthentication(configuration)
.AddAuthorization()
.AddServices();
.AddServices()
.AddBackgroundServices(configuration);
return services;
......@@ -28,12 +34,28 @@ namespace PSManagement.Infrastructure.DI
private static IServiceCollection AddServices(this IServiceCollection services)
{
services.AddSingleton<IDateTimeProvider, DateTimeProvider>();
services.AddScoped<IEmployeesProvider, EmployeesProvider>();
return services;
}
private static IServiceCollection AddBackgroundServices(this IServiceCollection services,IConfiguration configuration)
{
services.Configure<EmployeesSyncJobSettings>(configuration.GetSection("EmpoyeesSyncJobSettings"));
services.AddScoped<ISyncEmployeesService, SyncEmployeesService>();
services.AddHostedService<BackgroundJobSyncEmployees>();
return services;
}
private static IServiceCollection AddAuthorization(this IServiceCollection services)
{
services.AddScoped<IUserRoleService, UserRolesService>();
services.AddScoped<IRoleService, RoleService>();
return services;
}
......
......@@ -26,8 +26,4 @@
<ProjectReference Include="..\PSManagement.Domain\PSManagement.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="BackgroundServcies\" />
</ItemGroup>
</Project>

using FluentResults;
using Ardalis.Result;
using PSManagement.Application.Contracts.Authentication;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.Application.Contracts.Tokens;
using PSManagement.Domain.Customers.DomainErrors;
using PSManagement.Domain.Identity.DomainErrors;
using PSManagement.Domain.Identity.Entities;
using PSManagement.Domain.Identity.Repositories;
using PSManagement.Domain.Identity.Specification;
using PSManagement.SharedKernel.Specification;
using System;
using System.Threading.Tasks;
......@@ -16,18 +16,20 @@ namespace PSManagement.Infrastructure.Services.Authentication
{
private readonly IJwtTokenGenerator _jwtTokenGenerator;
private readonly IUsersRepository _userRepository;
private readonly BaseSpecification<User> _specification;
public AuthenticationService(IJwtTokenGenerator jwtTokenGenerator, IUsersRepository userRepository)
{
_jwtTokenGenerator = jwtTokenGenerator;
_userRepository = userRepository;
_specification = new UserSpecification();
}
public async Task<Result<AuthenticationResult>> Login(String email, String password) {
User u = await _userRepository.GetByEmail(email);
User u = await _userRepository.GetByEmail(email,_specification);
if (u is null || u.HashedPassword != password) {
return Result.Fail<AuthenticationResult>(UserErrors.InvalidLoginAttempt);
return Result.Invalid(UserErrors.InvalidLoginAttempt);
}
String token = _jwtTokenGenerator.GenerateToken(u);
......@@ -43,7 +45,7 @@ namespace PSManagement.Infrastructure.Services.Authentication
// check if the user exist
var u = await _userRepository.GetByEmail(email);
if (u is not null) {
return Result.Fail(UserErrors.AlreadyUserExist);
return Result.Invalid(UserErrors.AlreadyUserExist);
}
var user = await _userRepository.AddAsync(
new User{
......@@ -53,7 +55,7 @@ namespace PSManagement.Infrastructure.Services.Authentication
});
// generate token
String token = _jwtTokenGenerator.GenerateToken(u);
return Result.Ok<AuthenticationResult>(
return (
new AuthenticationResult
{
Id = user.Id,
......
using FluentResults;
using Ardalis.Result;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.Domain.Identity.Entities;
using PSManagement.Domain.Identity.Repositories;
using PSManagement.SharedKernel.DomainException;
using PSManagement.SharedKernel.Repositories;
using System;
......@@ -13,9 +14,9 @@ namespace PSManagement.Infrastructure.Services.Authorization
{
public class RoleService : IRoleService
{
private readonly IRepository<Role> _roleRepository;
private readonly IRolesRepository _roleRepository;
public RoleService(IRepository<Role> roleRepository)
public RoleService(IRolesRepository roleRepository)
{
_roleRepository = roleRepository;
}
......@@ -32,14 +33,14 @@ namespace PSManagement.Infrastructure.Services.Authorization
// check if the role has been added succesfully
if (result is not null )
{
return Result.Ok();
return Result.Success();
}
else
{
return Result.Fail(new Error("Failed to add the role."));
return Result.Conflict("Failed to add the role.");
}
}
return Result.Fail(new Error("Failed to add the role."));
return Result.Conflict("Failed to add the role.");
}
public async Task<Result> DeleteRoleAsync(int roleId)
......@@ -47,17 +48,17 @@ namespace PSManagement.Infrastructure.Services.Authorization
var roleDetails = await _roleRepository.GetByIdAsync(roleId);
if (roleDetails == null)
{
return Result.Fail(new Error("The Role Not Found."));
return Result.NotFound("The Role Not Found.");
}
if (roleDetails.Name == "Admin")
{
return Result.Fail(new Error("You Cannot Remove the admin role."));
return Result.CriticalError("You Cannot Remove the admin role.");
}
await _roleRepository.DeleteAsync(roleDetails);
return Result.Ok() ;
return Result.Success() ;
}
......@@ -65,9 +66,9 @@ namespace PSManagement.Infrastructure.Services.Authorization
{
var roles =await _roleRepository.GetByIdAsync(id);
if (roles is null) {
return Result.Fail(new Error("The Role not found."));
return Result.NotFound("The Role not found.");
}
return Result.Ok(roles);
return roles;
}
......@@ -82,12 +83,12 @@ namespace PSManagement.Infrastructure.Services.Authorization
var role = await _roleRepository.GetByIdAsync(id);
if (role is null)
{
return Result.Fail(new Error("The Role not found."));
return Result.NotFound("The Role not found.");
}
role.Name = roleName;
role = await _roleRepository.UpdateAsync(role);
return Result.Ok(role);
return role;
}
}
}
using Ardalis.Result;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.Domain.Identity.DomainErrors;
using PSManagement.Domain.Identity.Entities;
using PSManagement.Domain.Identity.Repositories;
using PSManagement.Domain.Identity.Specification;
using PSManagement.SharedKernel.Repositories;
using PSManagement.SharedKernel.Specification;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Services.Authorization
{
public class UserRolesService : IUserRoleService
{
private readonly IUsersRepository _usersRepository;
private readonly IRolesRepository _rolesRepository;
private readonly BaseSpecification<User> _specification;
public UserRolesService(
IUsersRepository usersRepository,
IRolesRepository rolesRepository)
{
_usersRepository = usersRepository;
_rolesRepository = rolesRepository;
_specification = new UserSpecification();
}
public async Task<Result> AssignUserToRole(string email, string roleName)
{
User user = await _usersRepository.GetByEmail(email,_specification);
if (user is null) {
return Result.Invalid(UserErrors.UnExistUser);
}
Role role = await _rolesRepository.GetByRoleName(roleName);
if (role is null)
{
return Result.NotFound("UnExist Role.");
}
user.Roles.Add(role);
return Result.Success();
}
public async Task<Result<List<string>>> GetUserRolesAsync(string email)
{
User user = await _usersRepository.GetByEmail(email, _specification);
if (user is null)
{
return Result.Invalid(UserErrors.UnExistUser);
}
;
return Result.Success(user.Roles.Select(r => r.Name).ToList());
}
public async Task<bool> IsInRoleAsync(int userId, string roleName)
{
User user= await _usersRepository.GetByIdAsync(userId, _specification);
if (user is null)
return false;
return user.Roles.Any(u => u.Name == roleName);
}
public async Task<Result> RemoveUserFromRole(string email, string roleName)
{
User user = await _usersRepository.GetByEmail(email, _specification);
if (user is null)
{
return Result.Invalid(UserErrors.UnExistUser);
}
Role role = await _rolesRepository.GetByRoleName(roleName);
if (role is null)
{
return Result.NotFound("UnExist Role.");
}
user.Roles.Remove(role);
return Result.Success();
}
}
}
using PSManagement.Application.Contracts.Providers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Services
namespace PSManagement.Infrastructure.Services.Providers
{
public class DateTimeProvider : IDateTimeProvider
{
......
using PSManagement.Application.Contracts.Providers;
using PSManagement.Domain.Employees.Entities;
using PSManagement.Domain.Identity.Entities;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Services.Providers
{
public class EmployeesProvider :IEmployeesProvider
{
private static List<Employee> Employees = new List<Employee>
{
new Employee{Availability=new Availability(0,true),PersonalInfo= new ("Hasan","Khaddour"),HIASTId=1,User = new User{UserName="Hasan@mail.hiast",Email="Hasan@mail.hiast" },WorkInfo = new WorkInfo("Researcher","Worker") },
};
public Task<IEnumerable<Employee>> FetchEmployees()
{
return Task.FromResult(Employees.AsEnumerable());
}
}
}
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using PSManagement.Application.Contracts.Providers;
using PSManagement.Application.Contracts.SyncData;
using PSManagement.Domain.Employees.Entities;
using PSManagement.Domain.Employees.Repositories;
using PSManagement.Domain.Employees.Specification;
using PSManagement.SharedKernel.Specification;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using PSManagement.Infrastructure.Settings;
namespace PSManagement.Infrastructure.BackgroundServcies
{
public class SyncEmployeesService : ISyncEmployeesService
{
private readonly IEmployeesRepository _employeesRepository;
private readonly IEmployeesProvider _employeesProviders;
private readonly BaseSpecification<Employee> _specification;
private readonly IDateTimeProvider _timeProvider;
public SyncEmployeesService(
IEmployeesRepository employeesRepository,
IEmployeesProvider employeesProviders,
IDateTimeProvider timeProvider
)
{
_employeesRepository = employeesRepository;
_employeesProviders = employeesProviders;
_specification = new EmployeesSpecification();
_timeProvider = timeProvider;
}
public async Task<SyncResponse> SyncEmployees(IEmployeesProvider employeesProvider)
{
IEnumerable<Employee> NewestEmployees = await _employeesProviders.FetchEmployees();
int count = 0;
foreach (Employee employee in NewestEmployees) {
_specification.Criteria = empl => empl.HIASTId == employee.HIASTId;
Employee emp = _employeesRepository.ListAsync(_specification).Result.FirstOrDefault();
if (emp is null) {
await _employeesRepository.AddAsync(employee);
count++;
}
}
return new(count,_timeProvider.UtcNow);
}
}
}
namespace PSManagement.Infrastructure.Settings
{
public class EmployeesSyncJobSettings
{
public int SyncIntervalInMinutes { get; set; }
}
}
......@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Authentication
namespace PSManagement.Infrastructure.Settings
{
public class JwtSetting
{
......@@ -15,4 +15,5 @@ namespace PSManagement.Infrastructure.Authentication
public string Secret { get; set; } = null!;
public int ExpireMinutes { get; set; }
}
}
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using PSManagement.Infrastructure.Authentication;
using PSManagement.Infrastructure.Settings;
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -20,7 +20,7 @@ namespace PSManagement.Infrastructure.Tokens
_jwtSettings = jwtSettings.Value;
}
public void Configure(string? name, JwtBearerOptions options) => Configure(options);
public void Configure(string name, JwtBearerOptions options) => Configure(options);
public void Configure(JwtBearerOptions options)
{
......
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.Domain.Identity.Entities;
using System;
using System.IdentityModel.Tokens.Jwt;
......@@ -11,6 +10,8 @@ using System.Security.Claims;
using System.Text;
using System.Collections.Generic;
using PSManagement.Application.Contracts.Providers;
using PSManagement.Application.Contracts.Tokens;
using PSManagement.Infrastructure.Settings;
namespace PSManagement.Infrastructure.Authentication
{
......@@ -33,9 +34,7 @@ namespace PSManagement.Infrastructure.Authentication
List<Claim> claims = new List<Claim>{
new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Email, user.Email),
new Claim(JwtRegisteredClaimNames.GivenName, user.Employee?.PersonalInfo.FirstName),
new Claim(JwtRegisteredClaimNames.FamilyName, user.Employee?.PersonalInfo.LastName)
new Claim(JwtRegisteredClaimNames.Email, user.Email)
};
foreach (Role role in user.Roles) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment