- Api v1.0 #20

Merged
Yoann merged 26 commits from dev into main 2025-03-16 20:22:36 +01:00
50 changed files with 900 additions and 29 deletions
Showing only changes of commit 19c85ca534 - Show all commits

View File

@ -1,6 +1,16 @@
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using ldap_cesi.Context;
using ldap_cesi.Entities;
using ldap_cesi.Repository;
using ldap_cesi.Repository.Services;
using ldap_cesi.Services;
using ldap_cesi.Services.Interfaces;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Serilog;
namespace ldap_cesi.Configurations;
@ -8,12 +18,126 @@ public static class Conf
{
public static void BuildConf(this WebApplicationBuilder builder)
{
builder.AddRepositories();
builder.AddServices();
builder.Services.AddControllers();
builder.AddEFCoreConfiguration();
builder.CorseConfiguration();
builder.AddSwagger();
builder.AddSerilog();
builder.AddJwt();
builder.Services.AddAutoMapper(typeof(Program));
}
public static void AddRepositories(this WebApplicationBuilder builder)
{
builder.Services.AddScoped<IRepositoryService, ServiceRepository>();
builder.Services.AddScoped<IRepositorySite, SiteRepository>();
builder.Services.AddScoped<IRepositorySalarie, SalarieRepository>();
builder.Services.AddScoped<IRepositoryRole, RoleRepository>();
builder.Services.AddScoped<IRepositoryUtilisateur, UtilisateurRepository>();
}
public static void AddServices(this WebApplicationBuilder builder)
{
builder.Services.AddScoped<IServiceService, ServiceService >();
// builder.Services.AddScoped<IRoleService, RoleService>();
// builder.Services.AddScoped<ISiteService, SiteService>();
builder.Services.AddScoped<ISalarieService, SalarieService>();
builder.Services.AddScoped<IUtilisateurService, UtilisateurService>();
builder.Services.AddScoped<IJwtService, JwtService>();
builder.Services.AddSingleton<IRsaKeyService, RsaKeyService>();
}
public static void AddEFCoreConfiguration(this WebApplicationBuilder builder)
{
string connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<PgContext>(options => options.UseNpgsql(connectionString));
}
public static void CorseConfiguration(this WebApplicationBuilder builder)
{
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
}
public static void AddSerilog(this WebApplicationBuilder builder)
{
var loggerConfiguration = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Hour);
var logger = loggerConfiguration.CreateLogger();
builder.Logging.AddSerilog(logger);
builder.Services.AddLogging();
}
public static void AddJwt(this WebApplicationBuilder builder)
{
var rsaKeyService = builder.Services.BuildServiceProvider().GetRequiredService<IRsaKeyService>();
var rsaKey = rsaKeyService.GetRsaKey();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new RsaSecurityKey(rsaKey)
};
});
}
public static void AddSwagger(this WebApplicationBuilder builder)
{
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddAuthorization();
builder.Configuration.AddEnvironmentVariables();
builder.Services.AddSwaggerGen(c =>
{
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
Description = "JWT Token. Use \"Bearer {token}\""
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Id = "Bearer",
Type = ReferenceType.SecurityScheme
}
},
new List<string>()
}
});
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "LDAP - Backend",
Version = "v1"
});
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
});
}
}

View File

@ -26,10 +26,6 @@ public partial class PgContext : DbContext
public virtual DbSet<Utilisateur> Utilisateurs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseNpgsql("Host=192.168.1.196;Database=ldap;Username=postgres;Password=pimer0-buzz");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Role>(entity =>
@ -118,9 +114,13 @@ public partial class PgContext : DbContext
entity.Property(e => e.Nom)
.HasMaxLength(50)
.HasColumnName("nom");
entity.Property(e => e.Email)
.HasMaxLength(50)
.HasColumnName("email");
entity.Property(e => e.Prenom)
.HasMaxLength(50)
.HasColumnName("prenom");
entity.Ignore(e => e.AccessToken);
entity.HasOne(d => d.IdRoleNavigation).WithMany(p => p.Utilisateurs)
.HasForeignKey(d => d.IdRole)

View File

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Mvc;
namespace ldap_cesi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class HashController : ControllerBase
{
[HttpPost("hash")]
public IActionResult HashString([FromBody] string StringToHash)
{
if (string.IsNullOrEmpty(StringToHash))
{
return BadRequest("Vous devez fournir une chaine de caractere pour la hasher.");
}
string hashedString = BCrypt.Net.BCrypt.HashPassword(StringToHash);
return Ok(new { HashedString = hashedString });
}
}

View File

@ -0,0 +1,28 @@
using ldap_cesi.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace ldap_cesi.Controllers;
[ApiController]
[Route("/api/jwt")]
public class JwtController : ControllerBase
{
private readonly IJwtService _jwtService;
public JwtController(IJwtService jwtService)
{
_jwtService = jwtService;
}
[HttpGet("public-key")]
public IActionResult GetPublicKey()
{
var publicKey = _jwtService.GetPublicKey();
if (string.IsNullOrEmpty(publicKey))
{
return BadRequest("Impossible de récupérer la clé publique");
}
return Ok(publicKey);
}
}

View File

@ -0,0 +1,39 @@
using ldap_cesi.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace ldap_cesi.Controllers;
[ApiController]
[Route("api/salarie")]
public class SalarieController : ControllerBase
{
private ISalarieService _salarieService;
public SalarieController(ISalarieService salarieService)
{
_salarieService = salarieService;
}
// GET: api/salaries
/// <summary>
/// Endpoint qui retournes tous les salaries
/// </summary>
/// <returns>List<Salarie></returns>
[HttpGet]
public async Task<ActionResult> GetUtilisateurs()
{
var result = await _salarieService.GetAll();
return result.Success ? Ok(result) : BadRequest(result);
}
// GET: api/salaries
/// <summary>
/// Endpoint retourne le salarie correspondant à l'id en param
/// </summary>
/// <returns>Salarie</returns>
[HttpGet("{id}")]
public async Task<ActionResult> GetUtilisateurById(int id)
{
var result = await _salarieService.GetById(id);
return result.Success ? Ok(result) : BadRequest(result);
}
}

View File

@ -0,0 +1,55 @@
using ldap_cesi.DTOs.Inputs.Service;
using ldap_cesi.Services.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace ldap_cesi.Controllers;
[ApiController]
[Route("api/service")]
public class ServicesController : ControllerBase
{
private IServiceService _serviceService;
public ServicesController(IServiceService serviceService)
{
_serviceService = serviceService;
}
// GET: api/services
/// <summary>
/// Endpoint qui retournes tous les services
/// </summary>
/// <returns>Retourne tous les services</returns>
[HttpGet]
// [Authorize(Roles = "admin")]
public async Task<ActionResult> GetServices()
{
var result = await _serviceService.GetAll();
return result.Success ? Ok(result) : BadRequest(result);
}
// GET: api/services
/// <summary>
/// Endpoint retourne le service correspondant à l'id en param
/// </summary>
/// <returns>Service</returns>
[HttpGet("{id}")]
public async Task<ActionResult> GetServices(int id)
{
var result = await _serviceService.GetById(id);
return result.Success ? Ok(result) : BadRequest(result);
}
// {POST}: api/services
/// <summary>
/// Endpoint qui créé un service
/// </summary>
/// <returns>Retourne tous les services</returns>
[HttpPost]
public async Task<ActionResult> CreateService([FromBody] ServiceCreateDto serviceInputDto)
{
var result = await _serviceService.CreateService(serviceInputDto);
return result.Success ? Ok(result) : BadRequest(result);
}
}

View File

@ -0,0 +1,47 @@
using ldap_cesi.DTOs.Inputs;
using ldap_cesi.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace ldap_cesi.Controllers;
[ApiController]
[Route("api/utilisateur")]
public class UtilisateurController : ControllerBase
{
private IUtilisateurService _utilisateurService;
public UtilisateurController(IUtilisateurService utilisateurService)
{
_utilisateurService = utilisateurService;
}
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] UtilisateurLoginDto utilisateurInput)
{
var response = await _utilisateurService.Login(utilisateurInput);
return StatusCode(response.StatusCode, response);
}
// GET: api/utilisateurs
/// <summary>
/// Endpoint qui retournes tous les utilisateurs
/// </summary>
/// <returns>List<Utilisateur></returns>
[HttpGet]
public async Task<ActionResult> GetUtilisateurs()
{
var result = await _utilisateurService.GetAll();
return result.Success ? Ok(result) : BadRequest(result);
}
// GET: api/utilisateur
/// <summary>
/// Endpoint retourne l'utilisateur correspondant à l'id en param
/// </summary>
/// <returns>Utilisateur</returns>
[HttpGet("{id}")]
public async Task<ActionResult> GetUtilisateurById(int id)
{
var result = await _utilisateurService.GetById(id);
return result.Success ? Ok(result) : BadRequest(result);
}
}

View File

@ -0,0 +1,12 @@
namespace ldap_cesi.DTOs.Inputs.Salarie;
public class SalarieCreateDto
{
public string Nom { get; set; }
public string Prenom { get; set; }
public string Telephone_fix { get; set; }
public string Telephone_portable { get; set; }
public string Email { get; set; }
public int IdSite { get; set; }
public int IdService { get; set; }
}

View File

@ -0,0 +1,20 @@
namespace ldap_cesi.DTOs.Inputs.Service;
public class SalarieUpdateDto
{
public int Id { get; set; }
public string Nom { get; set; } = null!;
public string Prenom { get; set; } = null!;
public string TelephoneFixe { get; set; } = null!;
public string TelephonePortable { get; set; } = null!;
public string Email { get; set; } = null!;
public int IdSite { get; set; }
public int IdService { get; set; }
}

View File

@ -0,0 +1,6 @@
namespace ldap_cesi.DTOs.Inputs.Service;
public class ServiceCreateDto
{
public string Nom { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace ldap_cesi.DTOs.Inputs.Service;
public class ServiceUpdateDto
{
public int Id { get; set; }
public string Nom { get; set; } = null!;
}

View File

@ -0,0 +1,6 @@
namespace ldap_cesi.DTOs.Inputs.Site;
public class SiteCreateDto
{
public string Ville { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace ldap_cesi.DTOs.Inputs.Site;
public class SiteUpdateDto
{
public int Id { get; set; }
public string Ville { get; set; }
}

View File

@ -0,0 +1,7 @@
namespace ldap_cesi.DTOs.Inputs;
public class UtilisateurLoginDto
{
public string Email { get; set; }
public string MotDePasse { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace ldap_cesi.DTOs.Outputs.Utilisateur;
public class UtilisateurOutputDto
{
public int Id { get; set; }
public string Email { get; set; }
public string Nom { get; set; }
public string RoleNom { get; set; }
}

View File

@ -7,7 +7,7 @@ public partial class Site
{
public int Id { get; set; }
public string? Ville { get; set; }
public string Ville { get; set; }
public virtual ICollection<Salarie> Salaries { get; set; } = new List<Salarie>();
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
namespace ldap_cesi.Entities;
@ -7,13 +8,15 @@ public partial class Utilisateur
{
public int Id { get; set; }
public string? Nom { get; set; }
public string Nom { get; set; }
public string? Prenom { get; set; }
public string Prenom { get; set; }
public string? MotDePasse { get; set; }
public string MotDePasse { get; set; }
public string Email { get; set; }
public int IdRole { get; set; }
[NotMapped]
public string AccessToken { get; set; }
public virtual Role IdRoleNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,16 @@
using AutoMapper;
using ldap_cesi.DTOs.Inputs.Service;
using ldap_cesi.DTOs.Outputs.Utilisateur;
using ldap_cesi.Entities;
namespace ldap_cesi.Mapper;
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<Utilisateur, UtilisateurOutputDto>()
.ForMember(dest => dest.RoleNom, opt => opt.MapFrom(src => src.IdRoleNavigation.Nom));
CreateMap<ServiceCreateDto, Service>();
}
}

View File

@ -0,0 +1,7 @@
namespace ldap_cesi.Models;
public interface IResponseDataModel<T> : IResponseModel
{
public T Data { get; set; }
string Token { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace ldap_cesi.Models;
public interface IResponseModel
{
public int StatusCode { get; set; }
public string? Message { get; set; }
public bool Success { get; set; }
}

View File

@ -0,0 +1,7 @@
namespace ldap_cesi.Models;
public class ResponseDataModel<T> : ResponseModel, IResponseDataModel<T> where T : class
{
public T Data { get; set; } = null!;
public string Token { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace ldap_cesi.Models;
public class ResponseModel : IResponseModel
{
public bool Success { get; set; }
public string? Message { get; set; }
public string? TokenJWT { get; set; }
public int StatusCode { get; set; }
}

View File

@ -1,18 +1,29 @@
using ldap_cesi.Configurations;
var builder = WebApplication.CreateBuilder(args);
builder.BuildConf();
builder.Services.AddOpenApi();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();
app.Use(async (context, next) =>
{
if (context.Request.Path == "/")
{
context.Response.Redirect("/swagger");
return;
}
await next();
});
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@ -4,5 +4,5 @@ namespace ldap_cesi.Repository.Services;
public interface IRepositoryUtilisateur : IRepositoryBase<Utilisateur>
{
Task<Utilisateur> GetByEmailAsync(string email);
}

View File

@ -1,6 +1,7 @@
using ldap_cesi.Context;
using ldap_cesi.Entities;
using ldap_cesi.Repository.Services;
using Microsoft.EntityFrameworkCore;
namespace ldap_cesi.Repository;
@ -10,4 +11,10 @@ public class UtilisateurRepository : RepositoryBase<Utilisateur>, IRepositoryUti
{
}
public async Task<Utilisateur> GetByEmailAsync(string email)
{
return await _context.Utilisateurs.Include(u => u.IdRoleNavigation)
.FirstOrDefaultAsync(u => u.Email == email);
}
}

View File

@ -0,0 +1,10 @@
using ldap_cesi.Entities;
namespace ldap_cesi.Services.Interfaces;
public interface IJwtService
{
string GenerateToken(Utilisateur utilisateur);
string GetPublicKey();
Task<bool> ValidateToken(string token, int userId);
}

View File

@ -0,0 +1,6 @@
namespace ldap_cesi.Services.Interfaces;
public interface IRoleService
{
}

View File

@ -0,0 +1,8 @@
using System.Security.Cryptography;
namespace ldap_cesi.Services.Interfaces;
public interface IRsaKeyService
{
RSA GetRsaKey();
}

View File

@ -0,0 +1,10 @@
using ldap_cesi.Entities;
using ldap_cesi.Models;
namespace ldap_cesi.Services.Interfaces;
public interface ISalarieService
{
Task<IResponseDataModel<List<Salarie>>> GetAll();
Task<IResponseDataModel<Salarie>> GetById(int id);
}

View File

@ -0,0 +1,12 @@
using ldap_cesi.DTOs.Inputs.Service;
using ldap_cesi.Entities;
using ldap_cesi.Models;
namespace ldap_cesi.Services.Interfaces;
public interface IServiceService
{
Task<IResponseDataModel<List<Service>>> GetAll();
Task<IResponseDataModel<Service>> GetById(int id);
Task<IResponseDataModel<string>> CreateService(ServiceCreateDto serviceCreateDto);
}

View File

@ -0,0 +1,6 @@
namespace ldap_cesi.Services.Interfaces;
public interface ISiteService
{
}

View File

@ -0,0 +1,13 @@
using ldap_cesi.DTOs.Inputs;
using ldap_cesi.DTOs.Outputs.Utilisateur;
using ldap_cesi.Entities;
using ldap_cesi.Models;
namespace ldap_cesi.Services.Interfaces;
public interface IUtilisateurService
{
Task<IResponseDataModel<List<Utilisateur>>> GetAll();
Task<IResponseDataModel<Utilisateur>> GetById(int id);
Task<IResponseDataModel<UtilisateurOutputDto>> Login(UtilisateurLoginDto utilisateurInput);
}

View File

@ -0,0 +1,126 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using ldap_cesi.Context;
using ldap_cesi.Entities;
using ldap_cesi.Services.Interfaces;
using Microsoft.IdentityModel.Tokens;
namespace ldap_cesi.Services;
public class JwtService : IJwtService
{
private readonly IRsaKeyService _rsaKeyService;
private readonly IConfiguration _configuration;
private readonly PgContext _context;
private readonly ILogger<JwtService> _logger;
public JwtService(
IConfiguration configuration,
PgContext context,
IRsaKeyService rsaKeyService,
ILogger<JwtService> logger)
{
_configuration = configuration;
_context = context;
_rsaKeyService = rsaKeyService;
_logger = logger;
}
public string GenerateToken(Utilisateur utilisateur)
{
try
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, utilisateur.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.Name, utilisateur.Nom),
new Claim(ClaimTypes.Role, utilisateur.IdRoleNavigation.Nom),
new Claim(ClaimTypes.NameIdentifier, utilisateur.Id.ToString())
};
var key = new RsaSecurityKey(_rsaKeyService.GetRsaKey());
var creds = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);
var tokenExpiryMinutes = _configuration.GetValue<int>("Jwt:TokenExpiryMinutes", 30);
var token = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddMinutes(tokenExpiryMinutes),
signingCredentials: creds);
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
utilisateur.AccessToken = tokenString;
_context.Utilisateurs.Update(utilisateur);
_context.SaveChanges();
return tokenString;
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while generating the JWT token.");
throw;
}
}
public string GetPublicKey()
{
try
{
var publicKey = _rsaKeyService.GetRsaKey().ExportSubjectPublicKeyInfo();
return Convert.ToBase64String(publicKey);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while retrieving the public key.");
throw;
}
}
public async Task<bool> ValidateToken(string token, int userId)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new RsaSecurityKey(_rsaKeyService.GetRsaKey()),
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = _configuration["Jwt:Issuer"],
ValidAudience = _configuration["Jwt:Audience"],
ClockSkew = TimeSpan.Zero,
ValidateLifetime = true
};
var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
var nameIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier);
if (nameIdClaim == null || !int.TryParse(nameIdClaim.Value, out var tokenUserId) || tokenUserId != userId)
{
_logger.LogWarning("Token validation failed: Invalid user ID.");
return false;
}
var utilisateur = await _context.Utilisateurs.FindAsync(userId);
if (utilisateur == null)
{
_logger.LogWarning("Token validation failed: User not found.");
return false;
}
utilisateur.AccessToken = token;
_context.Utilisateurs.Update(utilisateur);
await _context.SaveChangesAsync();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while validating the JWT token.");
return false;
}
}
}

View File

@ -0,0 +1,15 @@
using ldap_cesi.Repository.Services;
using ldap_cesi.Services.Interfaces;
namespace ldap_cesi.Services;
public class RoleService : IRoleService
{
private IRepositoryRole _repositoryRole;
public RoleService(IRepositoryRole repositoryRole)
{
_repositoryRole = repositoryRole;
}
}

View File

@ -0,0 +1,36 @@
using System.Security.Cryptography;
using ldap_cesi.Services.Interfaces;
namespace ldap_cesi.Services;
public class RsaKeyService : IRsaKeyService
{
private readonly RSA _rsa;
private readonly string _keyPath;
public RsaKeyService(IConfiguration configuration)
{
_rsa = RSA.Create();
_keyPath = configuration["Jwt:KeyPath"] ?? "cle.bin";
LoadOrCreateRsaKey();
}
private void LoadOrCreateRsaKey()
{
if (File.Exists(_keyPath))
{
var keyBytes = File.ReadAllBytes(_keyPath);
_rsa.ImportRSAPrivateKey(keyBytes, out _);
}
else
{
var keyBytes = _rsa.ExportRSAPrivateKey();
File.WriteAllBytes(_keyPath, keyBytes);
}
}
public RSA GetRsaKey()
{
return _rsa;
}
}

View File

@ -0,0 +1,38 @@
using ldap_cesi.Entities;
using ldap_cesi.Models;
using ldap_cesi.Repository.Services;
using ldap_cesi.Services.Interfaces;
namespace ldap_cesi.Services;
public class SalarieService : ISalarieService
{
private IRepositorySalarie _repositorySalarie;
public SalarieService(IRepositorySalarie repositorySalarie)
{
_repositorySalarie = repositorySalarie;
}
public async Task<IResponseDataModel<List<Salarie>>> GetAll()
{
var salaries = await _repositorySalarie.GetAllAsync();
return new ResponseDataModel<List<Salarie>>
{
Success = true,
Data = salaries,
StatusCode = 200,
};
}
public async Task<IResponseDataModel<Salarie>> GetById(int id)
{
var service = await _repositorySalarie.GetByIdAsync(id);
return new ResponseDataModel<Salarie>
{
Success = true,
Data = service,
StatusCode = 200,
};
}
}

View File

@ -0,0 +1,54 @@
using AutoMapper;
using ldap_cesi.DTOs.Inputs.Service;
using ldap_cesi.Entities;
using ldap_cesi.Models;
using ldap_cesi.Repository.Services;
using ldap_cesi.Services.Interfaces;
namespace ldap_cesi.Services;
public class ServiceService : IServiceService
{
private readonly IRepositoryService _repositoryService;
private readonly IMapper _mapper;
public ServiceService(IRepositoryService repositoryService, IMapper mapper)
{
_repositoryService = repositoryService;
_mapper = mapper;
}
public async Task<IResponseDataModel<List<Service>>> GetAll()
{
var services = await _repositoryService.GetAllAsync();
return new ResponseDataModel<List<Service>>
{
Success = true,
Data = services,
StatusCode = 200,
};
}
public async Task<IResponseDataModel<Service>> GetById(int id)
{
var service = await _repositoryService.GetByIdAsync(id);
return new ResponseDataModel<Service>
{
Success = true,
Data = service,
StatusCode = 200,
};
}
public async Task<IResponseDataModel<string>> CreateService(ServiceCreateDto serviceCreateDto)
{
var service = _mapper.Map<Service>(serviceCreateDto);
var response = await _repositoryService.AddAsync(service);
return new ResponseDataModel<string>
{
Success = true,
Data = response.Id.ToString(),
};
}
}

View File

@ -0,0 +1,80 @@
using AutoMapper;
using ldap_cesi.DTOs.Inputs;
using ldap_cesi.DTOs.Outputs.Utilisateur;
using ldap_cesi.Entities;
using ldap_cesi.Models;
using ldap_cesi.Repository.Services;
using ldap_cesi.Services.Interfaces;
namespace ldap_cesi.Services;
public class UtilisateurService : IUtilisateurService
{
private readonly IRepositoryUtilisateur _repositoryUtilisateur;
private readonly IJwtService _jwtService;
private readonly IMapper _mapper;
public UtilisateurService(IRepositoryUtilisateur repositoryUtilisateur, IJwtService jwtService, IMapper mapper)
{
_repositoryUtilisateur = repositoryUtilisateur;
_jwtService = jwtService;
_mapper = mapper;
}
public async Task<IResponseDataModel<List<Utilisateur>>> GetAll()
{
var utilisateurs = await _repositoryUtilisateur.GetAllAsync();
return new ResponseDataModel<List<Utilisateur>>
{
Success = true,
StatusCode = 200,
Data = utilisateurs,
};
}
public async Task<IResponseDataModel<Utilisateur>> GetById(int id)
{
var utililisateur = await _repositoryUtilisateur.GetByIdAsync(id);
return new ResponseDataModel<Utilisateur>
{
Success = true,
StatusCode = 200,
Data = utililisateur,
};
}
public async Task<IResponseDataModel<UtilisateurOutputDto>> Login(UtilisateurLoginDto utilisateurInput)
{
var utilisateur = await _repositoryUtilisateur.GetByEmailAsync(utilisateurInput.Email);
if (utilisateur == null)
{
return new ResponseDataModel<UtilisateurOutputDto>
{
Success = false,
StatusCode = 404,
Message = "Utilisateur non trouvé."
};
}
if (!BCrypt.Net.BCrypt.Verify(utilisateurInput.MotDePasse, utilisateur.MotDePasse))
{
return new ResponseDataModel<UtilisateurOutputDto>
{
Success = false,
StatusCode = 401,
Message = "Mot de passe incorrect."
};
}
var token = _jwtService.GenerateToken(utilisateur);
var utilisateurOutputDto = _mapper.Map<UtilisateurOutputDto>(utilisateur);
return new ResponseDataModel<UtilisateurOutputDto>
{
Success = true,
StatusCode = 200,
Data = utilisateurOutputDto,
Token = token,
Message = "Connexion réussie."
};
}
}

View File

@ -5,30 +5,32 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>ldap_cesi</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="BCrypt" Version="1.0.0" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2"/>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.2">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0-preview.1.25081.1">
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.0-preview.1.25120.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
<PackageReference Include="OpenAI" Version="2.2.0-beta.2" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Controllers\" />
<Folder Include="Entities\" />
<Folder Include="Mapper\" />
<Folder Include="Services\" />
<Folder Include="Migrations\" />
</ItemGroup>
</Project>

View File

@ -1,6 +0,0 @@
@ldap_cesi_HostAddress = http://localhost:5080
GET {{ldap_cesi_HostAddress}}/weatherforecast/
Accept: application/json
###