diff --git a/BeReadyBackend/BeReadyBackend.csproj b/BeReadyBackend/BeReadyBackend.csproj index 58002fa..7a59f15 100644 --- a/BeReadyBackend/BeReadyBackend.csproj +++ b/BeReadyBackend/BeReadyBackend.csproj @@ -7,6 +7,12 @@ + + + + + + @@ -14,11 +20,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + - - - - diff --git a/BeReadyBackend/MappingProfiles/DtoToEntityMappings.cs b/BeReadyBackend/MappingProfiles/DtoToEntityMappings.cs new file mode 100644 index 0000000..dd327db --- /dev/null +++ b/BeReadyBackend/MappingProfiles/DtoToEntityMappings.cs @@ -0,0 +1,11 @@ +using AutoMapper; + +namespace BeReadyBackend.MappingProfiles; + +public class DtoToEntityMappings : Profile +{ + public DtoToEntityMappings() + { + + } +} \ No newline at end of file diff --git a/BeReadyBackend/MappingProfiles/EntityToDtoMappings.cs b/BeReadyBackend/MappingProfiles/EntityToDtoMappings.cs new file mode 100644 index 0000000..66ab0da --- /dev/null +++ b/BeReadyBackend/MappingProfiles/EntityToDtoMappings.cs @@ -0,0 +1,10 @@ +using AutoMapper; + +namespace BeReadyBackend.MappingProfiles; + +public class EntityToDtoMappings : Profile +{ + public EntityToDtoMappings() + { + } +} \ No newline at end of file diff --git a/BeReadyBackend/Program.cs b/BeReadyBackend/Program.cs index 608cf7e..4d27d20 100644 --- a/BeReadyBackend/Program.cs +++ b/BeReadyBackend/Program.cs @@ -1,44 +1,73 @@ +using AutoMapper; +using AutoMapper.EquivalencyExpression; +using BeReadyBackend; +using BeReadyBackend.MappingProfiles; +using FastEndpoints; +using FastEndpoints.Swagger; +using FastEndpoints.Security; +using Microsoft.Net.Http.Headers; +using BeReadyBackend.Repositories; + WebApplicationBuilder builder = WebApplication.CreateBuilder(args); -// Add services to the container. -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(); +// On ajoute ici FastEndpoints, un framework REPR et Swagger aux services disponibles dans le projet +builder.Services + .AddAuthenticationJwtBearer(s => s.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong") + .AddAuthorization() + .AddFastEndpoints() + .SwaggerDocument(options => + { + options.ShortSchemaNames = true; + }) + .AddCors(options => + { + options.AddDefaultPolicy(policyBuilder => + { + policyBuilder + .WithOrigins("http://localhost:4200") + .WithMethods("GET", "POST", "PUT", "DELETE", "PATCH") + .AllowAnyHeader() + .WithExposedHeaders(HeaderNames.ContentDisposition); + }); + }); + +builder.Services.AddDbContext(); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +MapperConfiguration mappingConfig = new(mc => +{ + mc.AddCollectionMappers(); + mc.AddProfile(new DtoToEntityMappings()); + mc.AddProfile(new EntityToDtoMappings()); +}, new LoggerFactory()); + + +AutoMapper.IMapper mapper = mappingConfig.CreateMapper(); +builder.Services.AddSingleton(mapper); WebApplication app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseSwagger(); - app.UseSwaggerUI(); -} +app.UseAuthentication() + .UseAuthorization() + .UseFastEndpoints(options => + { + options.Endpoints.ShortNames = true; + options.Endpoints.RoutePrefix = "API"; + }) + .UseSwaggerGen(); app.UseHttpsRedirection(); -string[] summaries = -[ - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" -]; +app.UseCors(); -app.MapGet("/weatherforecast", () => - { - WeatherForecast[] forecast = Enumerable.Range(1, 5).Select(index => - new WeatherForecast - ( - DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - Random.Shared.Next(-20, 55), - summaries[Random.Shared.Next(summaries.Length)] - )) - .ToArray(); - return forecast; - }) - .WithName("GetWeatherForecast") - .WithOpenApi(); - -app.Run(); - -record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) -{ - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); -} \ No newline at end of file +app.Run(); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/AchievementsRepository.cs b/BeReadyBackend/Repositories/AchievementsRepository.cs new file mode 100644 index 0000000..2ea56a7 --- /dev/null +++ b/BeReadyBackend/Repositories/AchievementsRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class AchievementsRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/BeReadyRepository.cs b/BeReadyBackend/Repositories/BeReadyRepository.cs new file mode 100644 index 0000000..cce23fc --- /dev/null +++ b/BeReadyBackend/Repositories/BeReadyRepository.cs @@ -0,0 +1,328 @@ +using System.Linq.Expressions; +using Ardalis.Specification; +using Ardalis.Specification.EntityFrameworkCore; +using AutoMapper.QueryableExtensions; +using Microsoft.EntityFrameworkCore; +using Plainquire.Page; + +namespace BeReadyBackend.Repositories; + +public class BeReadyRepository(DbContext databaseContext, AutoMapper.IMapper mapper) : RepositoryBase(databaseContext) where T : class +{ + private readonly DbContext _databaseContext = databaseContext; + + /// + /// + /// + /// + /// + public async Task FirstOrDefaultAsync(CancellationToken cancellationToken = default) + { + return await _databaseContext.Set().AsQueryable().FirstOrDefaultAsync(cancellationToken); + } + + /// + /// + /// + /// + /// + public async Task FirstAsync(CancellationToken cancellationToken = default) + { + return await _databaseContext.Set().AsQueryable().FirstAsync(cancellationToken); + } + + /// + /// + /// + /// + /// + /// + public async Task SingleAsync(ISpecification specification, CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification).SingleAsync(cancellationToken); + } + + /// + /// + /// + /// + /// + public async Task SingleAsync(CancellationToken cancellationToken = default) + { + return await _databaseContext.Set().AsQueryable().SingleAsync(cancellationToken); + } + + /// + /// + /// + /// + /// + /// + /// + public async Task SumAsync( + ISpecification specification, + Expression> selector, + CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification).SumAsync(selector, cancellationToken); + } + + // /// + // /// + // /// + // /// + // /// + // /// + // /// + // public async Task SumAsync( + // ISpecification specification, + // Expression> selector, + // CancellationToken cancellationToken = default) + // { + // return await ApplySpecification(specification).SumAsync(selector, cancellationToken); + // } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task ProjectToSingleOrDefaultAsync( + ISpecification specification, + CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .SingleOrDefaultAsync(cancellationToken: cancellationToken); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task ProjectToSingleOrDefaultAsync( + ISpecification specification, + Action postProcessor, + CancellationToken cancellationToken = default) + { + TResult? result = await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .SingleOrDefaultAsync(cancellationToken: cancellationToken); + postProcessor(result); + return result; + } + + // /// + // /// + // /// + // /// + // /// + // /// + // public async Task ProjectToSingleOrDefaultAsync( + // CancellationToken cancellationToken = default) + // { + // return await _databaseContext.Set().AsQueryable().ProjectTo(mapper.ConfigurationProvider).SingleOrDefaultAsync(cancellationToken: cancellationToken); + // } + + /// + /// + /// + /// + /// + /// + /// + public async Task ProjectToSingleAsync( + ISpecification specification, + CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .SingleAsync(cancellationToken: cancellationToken); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task ProjectToSingleAsync( + ISpecification specification, + Action postProcessor, + CancellationToken cancellationToken = default) + { + TResult result = await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .SingleAsync(cancellationToken: cancellationToken); + postProcessor(result); + return result; + } + + /// + /// + /// + /// + /// + /// + public async Task ProjectToSingleAsync( + CancellationToken cancellationToken = default) + { + return await _databaseContext.Set() + .AsQueryable() + .ProjectTo(mapper.ConfigurationProvider) + .SingleAsync(cancellationToken: cancellationToken); + } + + /// + /// + /// + /// + /// + /// + public async Task> ProjectToListAsync( + CancellationToken cancellationToken = default) + { + return await _databaseContext.Set() + .AsQueryable() + .ProjectTo(mapper.ConfigurationProvider) + .ToListAsync(cancellationToken: cancellationToken); + } + + /// + /// + /// + /// + /// + /// + /// + public async Task> ProjectToListAsync( + Action> postProcessor, + CancellationToken cancellationToken = default) + { + List results = await _databaseContext.Set() + .AsQueryable() + .ProjectTo(mapper.ConfigurationProvider) + .ToListAsync(cancellationToken: cancellationToken); + postProcessor(results); + return results; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task> ProjectToListAsync( + ISpecification specification, + Action> postProcessor, + CancellationToken cancellationToken = default) + { + List results = await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .ToListAsync(cancellationToken: cancellationToken); + postProcessor(results); + return results; + } + + /// + /// + /// + /// + /// + /// + /// + public async Task> ProjectToListAsync( + ISpecification specification, + CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .ToListAsync(cancellationToken: cancellationToken); + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + public async Task> ProjectToListAsync( + ISpecification specification, + EntityPage page, + Action> postProcessor, + CancellationToken cancellationToken = default) + { + List results = await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .Page(page) + .ToListAsync(cancellationToken: cancellationToken); + postProcessor(results); + return results; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task> ProjectToListAsync( + ISpecification specification, + EntityPage page, + CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification) + .ProjectTo(mapper.ConfigurationProvider) + .Page(page) + .ToListAsync(cancellationToken: cancellationToken); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task> SelectManyAsync( + ISpecification specification, + Expression>> selector, + CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification).SelectMany(selector).ToListAsync(cancellationToken: cancellationToken); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task> SelectAsync( + ISpecification specification, + Expression> selector, + CancellationToken cancellationToken = default) + { + return await ApplySpecification(specification).Select(selector).ToListAsync(cancellationToken: cancellationToken); + } +} \ No newline at end of file diff --git a/BeReadyBackend/Repositories/DesignationsRepository.cs b/BeReadyBackend/Repositories/DesignationsRepository.cs new file mode 100644 index 0000000..ae5c2f5 --- /dev/null +++ b/BeReadyBackend/Repositories/DesignationsRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class DesignationsRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/GroupsRepository.cs b/BeReadyBackend/Repositories/GroupsRepository.cs new file mode 100644 index 0000000..8926bda --- /dev/null +++ b/BeReadyBackend/Repositories/GroupsRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class GroupsRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/MessagesRepository.cs b/BeReadyBackend/Repositories/MessagesRepository.cs new file mode 100644 index 0000000..dc5c069 --- /dev/null +++ b/BeReadyBackend/Repositories/MessagesRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class MessagesRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/RandomChallengesRepository.cs b/BeReadyBackend/Repositories/RandomChallengesRepository.cs new file mode 100644 index 0000000..7cad882 --- /dev/null +++ b/BeReadyBackend/Repositories/RandomChallengesRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class RandomChallengesRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/StatusRepository.cs b/BeReadyBackend/Repositories/StatusRepository.cs new file mode 100644 index 0000000..3e6edb7 --- /dev/null +++ b/BeReadyBackend/Repositories/StatusRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class StatusRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/UserAchievementsRepository.cs b/BeReadyBackend/Repositories/UserAchievementsRepository.cs new file mode 100644 index 0000000..920acd3 --- /dev/null +++ b/BeReadyBackend/Repositories/UserAchievementsRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class UserAchievementsRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/UserFriendsRepository.cs b/BeReadyBackend/Repositories/UserFriendsRepository.cs new file mode 100644 index 0000000..0143c16 --- /dev/null +++ b/BeReadyBackend/Repositories/UserFriendsRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class UserFriendsRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/UserGroupsRepository.cs b/BeReadyBackend/Repositories/UserGroupsRepository.cs new file mode 100644 index 0000000..16a32d1 --- /dev/null +++ b/BeReadyBackend/Repositories/UserGroupsRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class UserGroupsRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/UserRandomChallengesRepository.cs b/BeReadyBackend/Repositories/UserRandomChallengesRepository.cs new file mode 100644 index 0000000..e47c426 --- /dev/null +++ b/BeReadyBackend/Repositories/UserRandomChallengesRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class UserRandomChallengesRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file diff --git a/BeReadyBackend/Repositories/UsersRepository.cs b/BeReadyBackend/Repositories/UsersRepository.cs new file mode 100644 index 0000000..ea2df2d --- /dev/null +++ b/BeReadyBackend/Repositories/UsersRepository.cs @@ -0,0 +1,5 @@ +using BeReadyBackend.Models; + +namespace BeReadyBackend.Repositories; + +public class UsersRepository(BeReadyDbContext beReadyDbContext, AutoMapper.IMapper mapper) : BeReadyRepository(beReadyDbContext, mapper); \ No newline at end of file