You need to sign in or sign up before continuing.
Commit 1551faff authored by hasan khaddour's avatar hasan khaddour

implment some of the Generics in the shared kernel.

parent 104902f3
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PSManagement.Application.Common.Services;
using PSManagement.Application.Contracts.Authentication;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.Infrastructure.Authentication;
using PSManagement.Infrastructure.Persistence.Repositories.UserRepository;
using PSManagement.Infrastructure.Services;
using PSManagement.Infrastructure.Services.Authentication;
using PSManagement.Infrastructure.Tokens;
namespace PSManagement.Infrastructure.DI
{
......@@ -12,12 +16,49 @@ namespace PSManagement.Infrastructure.DI
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services,IConfiguration configuration)
{
services.Configure<JwtSetting>(configuration.GetSection(JwtSetting.Section));
services.AddSingleton<IJwtTokenGenerator,JwtTokenGenerator>();
services
.AddAuthentication(configuration)
.AddAuthorization()
.AddServices()
.AddPersistence();
return services;
}
private static IServiceCollection AddServices(this IServiceCollection services)
{
services.AddSingleton<IDateTimeProvider, DateTimeProvider>();
services.AddScoped<IAuthenticationService,AuthenticationService>();
return services;
}
private static IServiceCollection AddPersistence(this IServiceCollection services)
{
//services.AddDbContext<AppDbContext>(options => options.UseSqlite("Data Source = CleanArchitecture.sqlite"));
//services.AddScoped<IRemindersRepository, RemindersRepository>();
services.AddScoped<IUsersRepository, UsersRepository>();
return services;
}
private static IServiceCollection AddAuthorization(this IServiceCollection services)
{
return services;
}
private static IServiceCollection AddAuthentication(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<JwtSetting>(configuration.GetSection(JwtSetting.Section));
services.AddSingleton<IJwtTokenGenerator, JwtTokenGenerator>();
services.AddScoped<IAuthenticationService, AuthenticationService>();
services
.ConfigureOptions<JwtBearerTokenValidationConfiguration>()
.AddAuthentication(defaultScheme: JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer();
return services;
}
}
}
......@@ -10,10 +10,15 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.17">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.7.0" />
</ItemGroup>
<ItemGroup>
......
using System;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
......@@ -6,7 +7,7 @@ using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Common.Persistence
{
public class AppDbContext
public class AppDbContext : DbContext
{
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using PSManagement.Infrastructure.Common.Persistence;
using PSManagement.SharedKernel.Entities;
using PSManagement.SharedKernel.Interfaces;
using PSManagement.SharedKernel.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Persistence.Repositories.BaseRepository
{
public class BaseRepository<T> : IRepository<T> where T :BaseEntity
{
protected AppDbContext _dbContext;
internal DbSet<T> dbSet;
public BaseRepository(AppDbContext context)
{
_dbContext = context;
dbSet = context.Set<T>();
}
public async Task<T> AddAsync(T entity)
{
EntityEntry<T> entry = await dbSet.AddAsync(entity);
await _dbContext.SaveChangesAsync();
return entry.Entity;
}
public async Task<IEnumerable<T>> ListAsync()
{
return await dbSet.ToListAsync();
}
public async Task<IEnumerable<T>> ListAsync(ISpecification<T> specification)
{
var q = ApplySpecification(specification);
return await q.ToListAsync<T>();
}
public Task DeleteAsync(T entity)
{
_dbContext.Set<T>().Remove(entity);
return _dbContext.SaveChangesAsync();
}
public async Task<T> GetByIdAsync(int id, ISpecification<T> specification=null)
{
var q = ApplySpecification(specification);
return await q.SingleOrDefaultAsync(e => e.Id == id);
}
public async Task<T> UpdateAsync(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
await _dbContext.SaveChangesAsync();
return entity;
}
private IQueryable<T> ApplySpecification(ISpecification<T> specification)
{
return SpecificationEvaluator<T>.GetQuery(dbSet.AsQueryable(), specification);
}
}
}
using PSManagement.SharedKernel.Entities;
using PSManagement.SharedKernel.Interfaces;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace PSManagement.Infrastructure.Persistence.Repositories.BaseRepository
{
public class SpecificationEvaluator<T> where T : BaseEntity
{
public static IQueryable<T> GetQuery(IQueryable<T> inputQuery, ISpecification<T> specification)
{
var query = inputQuery;
// modify the IQueryable using the specification's criteria expression
if (specification.Criteria != null)
{
query = query.Where(specification.Criteria);
}
// Includes all expression-based includes
query = specification.Includes.Aggregate(
query,
(current, include) => current.Include(include));
// Include any string-based include statements
query = specification.IncludeStrings.Aggregate(
query,
(current, include) => current.Include(include));
// Apply ordering if expressions are set
if (specification.OrderBy != null)
{
query = query.OrderBy(specification.OrderBy);
}
else if (specification.OrderByDescending != null)
{
query = query.OrderByDescending(specification.OrderByDescending);
}
//if (specification.GroupBy is not null)
//{
// query = query.GroupBy(specification.GroupBy).SelectMany(x => x);
//}
// Apply paging if enabled
if (specification.IsPagingEnabled)
{
query = query.Skip(specification.Skip)
.Take(specification.Take);
}
return query;
}
}
}
using PSManagement.Application.Contracts.Authentication;
using PSManagement.SharedKernel.Interfaces;
using PSManagement.SharedKernel.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Persistence.Repositories.UserRepository
{
public class UsersRepository : IUsersRepository
{
public static List<User> Users { get; set; } = new List<User>();
public async Task<User> AddAsync(User entity)
{
Users.Add(entity);
return entity;
}
public async Task DeleteAsync(User entity)
{
Users.Remove(entity);
}
public async Task<User> GetByEmail(string email)
{
return Users.Where(u => u.Email == email).FirstOrDefault();
}
public async Task<User> GetByIdAsync(int id, ISpecification<User> specification = null)
{
return Users.Where(u=>u.Id == id).FirstOrDefault();
}
public async Task<IEnumerable<User>> ListAsync()
{
return Users;
}
public async Task<IEnumerable<User>> ListAsync(ISpecification<User> spec)
{
return new List<User>();
}
public async Task<User> UpdateAsync(User entity)
{
return entity;
}
}
}
using PSManagement.Application.Contracts.Authentication;
using PSManagement.Application.Contracts.Authorization;
using PSManagement.SharedKernel.Utilities;
using System;
using System.Threading.Tasks;
......@@ -7,37 +9,56 @@ namespace PSManagement.Infrastructure.Services.Authentication
public class AuthenticationService :IAuthenticationService
{
private readonly IJwtTokenGenerator _jwtTokenGenerator;
private readonly IUsersRepository _userRepository;
public AuthenticationService(IJwtTokenGenerator jwtTokenGenerator)
public AuthenticationService(IJwtTokenGenerator jwtTokenGenerator, IUsersRepository userRepository)
{
_jwtTokenGenerator = jwtTokenGenerator;
_userRepository = userRepository;
}
public async Task<AuthenticationResult> Login(String email, String password) {
public async Task<Result<AuthenticationResult>> Login(String email, String password) {
User u = await _userRepository.GetByEmail(email);
if (u is null || u.Password != password) {
return Result.Failure<AuthenticationResult>(new Error("404", "the password or email maybe wrong!."));
return new AuthenticationResult {
Id = Guid.NewGuid(),
Email=email,
FirstName="First name ",
LastName ="last Name ",
Token="token"
};
}
String token = _jwtTokenGenerator.GenerateToken(u.Id,u.FirstName,u.LastName,u.Email);
return Result.Success<AuthenticationResult>(
new AuthenticationResult {
Id = u.Id,
Email=u.Email,
FirstName=u.FirstName,
LastName =u.LastName,
Token=token});
}
public async Task<AuthenticationResult> Register(String email, String firstName, String lastName, String password) {
public async Task<Result<AuthenticationResult>> Register(String email, String firstName, String lastName, String password) {
// check if the user exist
Guid userId = Guid.NewGuid();
var u = await _userRepository.GetByEmail(email);
if (u is not null) {
return Result.Failure<AuthenticationResult>(new Error("404","the user already exist "));
}
await _userRepository.AddAsync(
new User{
Email=email ,
FirstName=firstName,
LastName=lastName,
Password=password
});
// generate token
String token = _jwtTokenGenerator.GenerateToken(userId,firstName,lastName,email);
return new AuthenticationResult
String token = _jwtTokenGenerator.GenerateToken(2322323,firstName,lastName,email);
return Result.Success<AuthenticationResult>(
new AuthenticationResult
{
Id = Guid.NewGuid(),
Id = 233233,
Email = email,
FirstName =firstName,
LastName =lastName,
Token=token
};
FirstName = firstName,
LastName = lastName,
Token = token
});
}
......
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using PSManagement.Infrastructure.Authentication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Tokens
{
public sealed class JwtBearerTokenValidationConfiguration
: IConfigureNamedOptions<JwtBearerOptions>
{
private readonly JwtSetting _jwtSettings ;
public JwtBearerTokenValidationConfiguration(IOptions<JwtSetting> jwtSettings)
{
_jwtSettings = jwtSettings.Value;
}
public void Configure(string? name, JwtBearerOptions options) => Configure(options);
public void Configure(JwtBearerOptions options)
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = _jwtSettings.Issuer,
ValidAudience = _jwtSettings.Audience,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_jwtSettings.Secret)),
};
}
}
}
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using PSManagement.Application.Common.Services;
using PSManagement.Application.Contracts.Authentication;
using PSManagement.Application.Contracts.Authorization;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Infrastructure.Authentication
{
......@@ -22,7 +19,7 @@ namespace PSManagement.Infrastructure.Authentication
_jwtSetting = jwtOptions.Value;
}
public string GenerateToken(Guid id, string firstName, string lastName, string email)
public string GenerateToken(int id, string firstName, string lastName, string email)
{
var signingCredentials = new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSetting.Secret)),
......
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