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; ...@@ -5,10 +5,15 @@ using Microsoft.Extensions.DependencyInjection;
using PSManagement.Application.Contracts.Authentication; using PSManagement.Application.Contracts.Authentication;
using PSManagement.Application.Contracts.Authorization; using PSManagement.Application.Contracts.Authorization;
using PSManagement.Application.Contracts.Providers; using PSManagement.Application.Contracts.Providers;
using PSManagement.Application.Contracts.SyncData;
using PSManagement.Application.Contracts.Tokens;
using PSManagement.Domain.Identity.Repositories; using PSManagement.Domain.Identity.Repositories;
using PSManagement.Infrastructure.Authentication; using PSManagement.Infrastructure.Authentication;
using PSManagement.Infrastructure.Services; using PSManagement.Infrastructure.BackgroundServcies;
using PSManagement.Infrastructure.Services.Authentication; using PSManagement.Infrastructure.Services.Authentication;
using PSManagement.Infrastructure.Services.Authorization;
using PSManagement.Infrastructure.Services.Providers;
using PSManagement.Infrastructure.Settings;
using PSManagement.Infrastructure.Tokens; using PSManagement.Infrastructure.Tokens;
namespace PSManagement.Infrastructure.DI namespace PSManagement.Infrastructure.DI
...@@ -20,7 +25,8 @@ namespace PSManagement.Infrastructure.DI ...@@ -20,7 +25,8 @@ namespace PSManagement.Infrastructure.DI
services services
.AddAuthentication(configuration) .AddAuthentication(configuration)
.AddAuthorization() .AddAuthorization()
.AddServices(); .AddServices()
.AddBackgroundServices(configuration);
return services; return services;
...@@ -28,12 +34,28 @@ namespace PSManagement.Infrastructure.DI ...@@ -28,12 +34,28 @@ namespace PSManagement.Infrastructure.DI
private static IServiceCollection AddServices(this IServiceCollection services) private static IServiceCollection AddServices(this IServiceCollection services)
{ {
services.AddSingleton<IDateTimeProvider, DateTimeProvider>(); services.AddSingleton<IDateTimeProvider, DateTimeProvider>();
services.AddScoped<IEmployeesProvider, EmployeesProvider>();
return services; 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) private static IServiceCollection AddAuthorization(this IServiceCollection services)
{ {
services.AddScoped<IUserRoleService, UserRolesService>();
services.AddScoped<IRoleService, RoleService>();
return services; return services;
} }
......
...@@ -26,8 +26,4 @@ ...@@ -26,8 +26,4 @@
<ProjectReference Include="..\PSManagement.Domain\PSManagement.Domain.csproj" /> <ProjectReference Include="..\PSManagement.Domain\PSManagement.Domain.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="BackgroundServcies\" />
</ItemGroup>
</Project> </Project>
 using Ardalis.Result;
using FluentResults;
using PSManagement.Application.Contracts.Authentication; using PSManagement.Application.Contracts.Authentication;
using PSManagement.Application.Contracts.Authorization; using PSManagement.Application.Contracts.Tokens;
using PSManagement.Domain.Customers.DomainErrors; using PSManagement.Domain.Customers.DomainErrors;
using PSManagement.Domain.Identity.DomainErrors; using PSManagement.Domain.Identity.DomainErrors;
using PSManagement.Domain.Identity.Entities; using PSManagement.Domain.Identity.Entities;
using PSManagement.Domain.Identity.Repositories; using PSManagement.Domain.Identity.Repositories;
using PSManagement.Domain.Identity.Specification;
using PSManagement.SharedKernel.Specification;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -16,18 +16,20 @@ namespace PSManagement.Infrastructure.Services.Authentication ...@@ -16,18 +16,20 @@ namespace PSManagement.Infrastructure.Services.Authentication
{ {
private readonly IJwtTokenGenerator _jwtTokenGenerator; private readonly IJwtTokenGenerator _jwtTokenGenerator;
private readonly IUsersRepository _userRepository; private readonly IUsersRepository _userRepository;
private readonly BaseSpecification<User> _specification;
public AuthenticationService(IJwtTokenGenerator jwtTokenGenerator, IUsersRepository userRepository) public AuthenticationService(IJwtTokenGenerator jwtTokenGenerator, IUsersRepository userRepository)
{ {
_jwtTokenGenerator = jwtTokenGenerator; _jwtTokenGenerator = jwtTokenGenerator;
_userRepository = userRepository; _userRepository = userRepository;
_specification = new UserSpecification();
} }
public async Task<Result<AuthenticationResult>> Login(String email, String password) { 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) { if (u is null || u.HashedPassword != password) {
return Result.Fail<AuthenticationResult>(UserErrors.InvalidLoginAttempt); return Result.Invalid(UserErrors.InvalidLoginAttempt);
} }
String token = _jwtTokenGenerator.GenerateToken(u); String token = _jwtTokenGenerator.GenerateToken(u);
...@@ -43,7 +45,7 @@ namespace PSManagement.Infrastructure.Services.Authentication ...@@ -43,7 +45,7 @@ namespace PSManagement.Infrastructure.Services.Authentication
// check if the user exist // check if the user exist
var u = await _userRepository.GetByEmail(email); var u = await _userRepository.GetByEmail(email);
if (u is not null) { if (u is not null) {
return Result.Fail(UserErrors.AlreadyUserExist); return Result.Invalid(UserErrors.AlreadyUserExist);
} }
var user = await _userRepository.AddAsync( var user = await _userRepository.AddAsync(
new User{ new User{
...@@ -53,7 +55,7 @@ namespace PSManagement.Infrastructure.Services.Authentication ...@@ -53,7 +55,7 @@ namespace PSManagement.Infrastructure.Services.Authentication
}); });
// generate token // generate token
String token = _jwtTokenGenerator.GenerateToken(u); String token = _jwtTokenGenerator.GenerateToken(u);
return Result.Ok<AuthenticationResult>( return (
new AuthenticationResult new AuthenticationResult
{ {
Id = user.Id, Id = user.Id,
......
using FluentResults; using Ardalis.Result;
using PSManagement.Application.Contracts.Authorization; using PSManagement.Application.Contracts.Authorization;
using PSManagement.Domain.Identity.Entities; using PSManagement.Domain.Identity.Entities;
using PSManagement.Domain.Identity.Repositories;
using PSManagement.SharedKernel.DomainException; using PSManagement.SharedKernel.DomainException;
using PSManagement.SharedKernel.Repositories; using PSManagement.SharedKernel.Repositories;
using System; using System;
...@@ -13,9 +14,9 @@ namespace PSManagement.Infrastructure.Services.Authorization ...@@ -13,9 +14,9 @@ namespace PSManagement.Infrastructure.Services.Authorization
{ {
public class RoleService : IRoleService public class RoleService : IRoleService
{ {
private readonly IRepository<Role> _roleRepository; private readonly IRolesRepository _roleRepository;
public RoleService(IRepository<Role> roleRepository) public RoleService(IRolesRepository roleRepository)
{ {
_roleRepository = roleRepository; _roleRepository = roleRepository;
} }
...@@ -32,14 +33,14 @@ namespace PSManagement.Infrastructure.Services.Authorization ...@@ -32,14 +33,14 @@ namespace PSManagement.Infrastructure.Services.Authorization
// check if the role has been added succesfully // check if the role has been added succesfully
if (result is not null ) if (result is not null )
{ {
return Result.Ok(); return Result.Success();
} }
else 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) public async Task<Result> DeleteRoleAsync(int roleId)
...@@ -47,17 +48,17 @@ namespace PSManagement.Infrastructure.Services.Authorization ...@@ -47,17 +48,17 @@ namespace PSManagement.Infrastructure.Services.Authorization
var roleDetails = await _roleRepository.GetByIdAsync(roleId); var roleDetails = await _roleRepository.GetByIdAsync(roleId);
if (roleDetails == null) if (roleDetails == null)
{ {
return Result.Fail(new Error("The Role Not Found.")); return Result.NotFound("The Role Not Found.");
} }
if (roleDetails.Name == "Admin") 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); await _roleRepository.DeleteAsync(roleDetails);
return Result.Ok() ; return Result.Success() ;
} }
...@@ -65,9 +66,9 @@ namespace PSManagement.Infrastructure.Services.Authorization ...@@ -65,9 +66,9 @@ namespace PSManagement.Infrastructure.Services.Authorization
{ {
var roles =await _roleRepository.GetByIdAsync(id); var roles =await _roleRepository.GetByIdAsync(id);
if (roles is null) { 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 ...@@ -82,12 +83,12 @@ namespace PSManagement.Infrastructure.Services.Authorization
var role = await _roleRepository.GetByIdAsync(id); var role = await _roleRepository.GetByIdAsync(id);
if (role is null) if (role is null)
{ {
return Result.Fail(new Error("The Role not found.")); return Result.NotFound("The Role not found.");
} }
role.Name = roleName; role.Name = roleName;
role = await _roleRepository.UpdateAsync(role); 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 PSManagement.Application.Contracts.Providers;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Services namespace PSManagement.Infrastructure.Services.Providers
{ {
public class DateTimeProvider : IDateTimeProvider 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; ...@@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Authentication namespace PSManagement.Infrastructure.Settings
{ {
public class JwtSetting public class JwtSetting
{ {
...@@ -15,4 +15,5 @@ namespace PSManagement.Infrastructure.Authentication ...@@ -15,4 +15,5 @@ namespace PSManagement.Infrastructure.Authentication
public string Secret { get; set; } = null!; public string Secret { get; set; } = null!;
public int ExpireMinutes { get; set; } public int ExpireMinutes { get; set; }
} }
} }
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using PSManagement.Infrastructure.Authentication; using PSManagement.Infrastructure.Settings;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
...@@ -20,7 +20,7 @@ namespace PSManagement.Infrastructure.Tokens ...@@ -20,7 +20,7 @@ namespace PSManagement.Infrastructure.Tokens
_jwtSettings = jwtSettings.Value; _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) public void Configure(JwtBearerOptions options)
{ {
......
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.Domain.Identity.Entities; using PSManagement.Domain.Identity.Entities;
using System; using System;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
...@@ -11,6 +10,8 @@ using System.Security.Claims; ...@@ -11,6 +10,8 @@ using System.Security.Claims;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using PSManagement.Application.Contracts.Providers; using PSManagement.Application.Contracts.Providers;
using PSManagement.Application.Contracts.Tokens;
using PSManagement.Infrastructure.Settings;
namespace PSManagement.Infrastructure.Authentication namespace PSManagement.Infrastructure.Authentication
{ {
...@@ -33,9 +34,7 @@ namespace PSManagement.Infrastructure.Authentication ...@@ -33,9 +34,7 @@ namespace PSManagement.Infrastructure.Authentication
List<Claim> claims = new List<Claim>{ List<Claim> claims = new List<Claim>{
new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()), new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Email, user.Email), new Claim(JwtRegisteredClaimNames.Email, user.Email)
new Claim(JwtRegisteredClaimNames.GivenName, user.Employee?.PersonalInfo.FirstName),
new Claim(JwtRegisteredClaimNames.FamilyName, user.Employee?.PersonalInfo.LastName)
}; };
foreach (Role role in user.Roles) { 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