🔀 Merging work-da with work-ape

merging_EF-API
Antoine PEREDERII 1 year ago
commit d23847f4c5

@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
</ItemGroup>

@ -0,0 +1,25 @@
using Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace DbContextLib.Identity;
public class AuthDbContext: IdentityDbContext<IdentityUser>
{
public AuthDbContext(DbContextOptions<AuthDbContext> options) : base(options) { }
public AuthDbContext() { }
/*
/// <summary>
/// Configures the database options if they are not already configured.
/// </summary>
/// <param name="optionsBuilder">The options builder instance.</param>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlite($"Data Source=uca.HeartTrack.db");
}
}*/
}

@ -0,0 +1,9 @@
namespace Dto;
public class ActivityFitFileDto
{
public string ActivityName { get; set; }
public string ActivityType { get; set; }
public int EffortFeel { get; set; }
//public IFormFile
}

@ -1,10 +1,13 @@
using Dto;
using System.Buffers;
using Dto;
using Model;
namespace ApiMappeur;
// anotine
public static class UserMappeur
{
private static readonly ArrayPool<UserDto> UserDtoPool = ArrayPool<UserDto>.Create();
private static readonly Dictionary<User, UserDto> userToDtoMap = new Dictionary<User, UserDto>();
private static readonly Dictionary<UserDto, User> dtoToUserMap = new Dictionary<UserDto, User>();
public static UserDto ToDto(this User user)
{
return new UserDto
@ -26,8 +29,71 @@ public static class UserMappeur
public static User ToModel(this UserDto userDto)
{
if (userDto.IsCoach)
return new User
{
Username = userDto.Username,
ProfilePicture = userDto.ProfilePicture,
LastName = userDto.LastName,
FirstName = userDto.FirstName,
Email = userDto.Email,
MotDePasse = userDto.Password,
Sexe = userDto.Sexe,
Lenght = userDto.Lenght,
Weight = userDto.Weight,
DateOfBirth = userDto.DateOfBirth,
Role = userDto.IsCoach ? new Coach() : new Athlete()
};
}
}
/*
using Dto;
using Model;
using System.Buffers;
namespace ApiMappeur
{
// anotine
public static class UserMappeur
{
private static readonly ArrayPool<UserDto> UserDtoPool = ArrayPool<UserDto>.Create();
public static UserDto ToDto(this User user)
{
UserDto userDto = UserDtoPool.Rent();
userDto.Id = user.Id;
userDto.Username = user.Username;
userDto.ProfilePicture = user.ProfilePicture;
userDto.LastName = user.LastName;
userDto.FirstName = user.FirstName;
userDto.Email = user.Email;
userDto.Password = user.MotDePasse;
userDto.Sexe = user.Sexe;
userDto.Lenght = user.Lenght;
userDto.Weight = user.Weight;
userDto.DateOfBirth = user.DateOfBirth;
userDto.IsCoach = user.Role is Coach;
return userDto;
}
public static User ToModel(this UserDto userDto)
{
if (userDto.IsCoach)
{
return new User(
userDto.Username,
userDto.ProfilePicture,
userDto.LastName,
userDto.FirstName,
userDto.Email,
userDto.Password,
userDto.Sexe,
userDto.Lenght,
userDto.Weight,
userDto.DateOfBirth,
new Coach()
);
}
return new User(
userDto.Username,
userDto.ProfilePicture,
@ -39,20 +105,13 @@ public static class UserMappeur
userDto.Lenght,
userDto.Weight,
userDto.DateOfBirth,
new Coach()
);
new Athlete());
}
public static void ReturnToPool(this UserDto userDto)
{
UserDtoPool.Return(userDto);
}
return new User(
userDto.Username,
userDto.ProfilePicture,
userDto.LastName,
userDto.FirstName,
userDto.Email,
userDto.Password,
userDto.Sexe,
userDto.Lenght,
userDto.Weight,
userDto.DateOfBirth,
new Athlete());
}
}
*/

@ -8,6 +8,7 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;
namespace Entities
{
@ -15,8 +16,10 @@ namespace Entities
/// Represents an athlete entity in the database.
/// </summary>
[Table("Athlete")]
public class AthleteEntity
public class AthleteEntity : IdentityUser
{
public AthleteEntity() : base() { }
/// <summary>
/// Gets or sets the unique identifier of the athlete.
/// </summary>
@ -28,36 +31,36 @@ namespace Entities
/// Gets or sets the username of the athlete.
/// </summary>
[MaxLength(100)]
[Required(ErrorMessage = "Athlete Username is required")]
public required string Username { get; set; }
[Required(ErrorMessage = "Athlete Username is ")]
public string Username { get; set; }
/// <summary>
/// Gets or sets the last name of the athlete.
/// </summary>
[MaxLength(100)]
[Required(ErrorMessage = "Athlete Last Name is required")]
public required string LastName { get; set; }
[Required(ErrorMessage = "Athlete Last Name is ")]
public string LastName { get; set; }
/// <summary>
/// Gets or sets the first name of the athlete.
/// </summary>
[MaxLength(150)]
[Required(ErrorMessage = "Athlete First Name is required")]
public required string FirstName { get; set; }
[Required(ErrorMessage = "Athlete First Name is ")]
public string FirstName { get; set; }
/// <summary>
/// Gets or sets the email of the athlete.
/// </summary>
[MaxLength(100)]
[Required(ErrorMessage = "Athlete Email is required")]
public required string Email { get; set; }
[Required(ErrorMessage = "Athlete Email is ")]
public string Email { get; set; }
/// <summary>
/// Gets or sets the gender of the athlete.
/// </summary>
[MaxLength(1)]
[Required(ErrorMessage = "Athlete Sexe is required")]
public required string Sexe { get; set; }
[Required(ErrorMessage = "Athlete Sexe is ")]
public string Sexe { get; set; }
/// <summary>
/// Gets or sets the height of the athlete.
@ -72,13 +75,13 @@ namespace Entities
/// <summary>
/// Gets or sets the password of the athlete.
/// </summary>
[Required(ErrorMessage = "Athlete Password is required")]
public required string Password { get; set; }
[Required(ErrorMessage = "Athlete Password is ")]
public string Password { get; set; }
/// <summary>
/// Gets or sets the date of birth of the athlete.
/// </summary>
[Required(ErrorMessage = "Athlete Date of Birth is required")]
[Required(ErrorMessage = "Athlete Date of Birth is ")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateOnly DateOfBirth { get; set; }
@ -87,7 +90,7 @@ namespace Entities
/// </summary>
public bool IsCoach { get; set; }
public required byte[] ProfilPicture { get; set; }
public byte[] ProfilPicture { get; set; }

@ -6,4 +6,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Extensions.Identity.Stores">
<HintPath>..\..\..\..\..\.nuget\packages\microsoft.extensions.identity.stores\8.0.2\lib\net8.0\Microsoft.Extensions.Identity.Stores.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

@ -0,0 +1,137 @@
using DbContextLib.Identity;
using Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Model.Manager;
using Model.Service;
using StubAPI;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace HeartTrackAPI;
public class AppBootstrap(IConfiguration configuration)
{
private IConfiguration Configuration { get; } = configuration;
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddEndpointsApiExplorer();
//services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOption>();
// include Xml comment
// addsecurityRequiment
// securityDef
services.AddSwaggerGen();
AddHeartTrackContextServices(services);
AddModelService(services);
AddIdentityServices(services);
AddApiVersioning(services);
AddSwagger(services);
services.AddHealthChecks();
}
private void AddHeartTrackContextServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("HeartTrackAuthConnection");
if (string.IsNullOrWhiteSpace(connectionString))
{
throw new InvalidOperationException("The connection string for the database is not set.");
}
else
{
services.AddDbContext<AuthDbContext>(options => options.UseInMemoryDatabase("AuthDb"));
// builder.Services.AddDbContext<HeartTrackContext>(options => options.UseSqlite(connectionString));
services.AddSingleton<IDataManager, StubData>();
}
}
private void AddModelService(IServiceCollection services)
{
services.AddSingleton<IDataManager, StubData>();
services.AddTransient<IActivityManager, ActivityManager>();
}
private void AddIdentityServices(IServiceCollection services)
{
// services.AddTransient<IEmailSender<AthleteEntity>, EmailSender>();
services.AddAuthorization();
services.AddIdentityApiEndpoints<IdentityUser>()
.AddEntityFrameworkStores<AuthDbContext>();
//services.AddIdentity<AthleteEntity, IdentityRole>()
// .AddEntityFrameworkStores<AuthDbContext>().AddDefaultTokenProviders();
}
private void AddApiVersioning(IServiceCollection services)
{
services.AddApiVersioning(opt =>
{
opt.ReportApiVersions = true;
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
// options.ApiVersionReader = new HeaderApiVersionReader("api-version");
opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new MediaTypeApiVersionReader("x-api-version"));
});
}
private void AddSwagger(IServiceCollection services)
{
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v1" });
options.SwaggerDoc("v2", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v2" });
});
services.AddVersionedApiExplorer(setup =>
{
setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true;
});
}
public void Configure(WebApplication app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.MapControllers();
app.UseAuthorization();
app.MapIdentityApi<IdentityUser>();
app.MapHealthChecks("/health");
// Configure the HTTP request pipeline.
if (true)
{
var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
app.UseSwagger();
app.UseSwaggerUI();
app.MapSwagger();
app.UseSwaggerUI(options =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
//foreach (var description in apiVersionDescriptionProvider)
{
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
}
});
}
}
}

@ -4,6 +4,7 @@ using HeartTrackAPI.Responce;
using Microsoft.AspNetCore.Mvc;
using Shared;
using Model;
using Model.Manager;
using Model.Repository;
namespace HeartTrackAPI.Controllers;
@ -13,6 +14,7 @@ public class ActivityController : Controller
{
private readonly IActivityRepository _activityService;
private readonly ILogger<ActivityController> _logger;
private readonly IActivityManager _activityManager;
public ActivityController(IActivityRepository activityService, ILogger<ActivityController> logger)
{
@ -46,6 +48,21 @@ public class ActivityController : Controller
return StatusCode(500);
}
}
/*
public async Task<IActionResult> PostFitFile([FromForm] IFormFile file)
{
if (file == null)
{
return BadRequest("No file was provided");
}
var activity = await _activityManager.AddActivityFromFitFile(file);
if (activity == null)
{
return BadRequest("The file provided is not a valid fit file");
}
return CreatedAtAction(nameof(GetActivities), activity.ToDto());
}*/
/*
[HttpGet("{id}")]
public async Task<ActionResult<ActivityDto>> GetActivity(int id)

@ -1,6 +1,8 @@
using Dto;
using Entities;
using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Model;
using Model.Manager;
@ -10,11 +12,13 @@ using Shared;
namespace HeartTrackAPI.Controllers;
[ApiController]
[Route("api/users")]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/users")]
public class UsersController : Controller
{
private readonly ILogger<UsersController> _logger;
private readonly IUserRepository _userService;
// private readonly
public UsersController(ILogger<UsersController> logger, IDataManager dataManager)
{
_logger = logger;
@ -159,4 +163,51 @@ public class UsersController : Controller
}
[HttpPost("{id}/friend/{friendId}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task<IActionResult> AddFriend(int id, int friendId)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(AddFriend), friendId,id);
var athlete = await _userService.GetItemById(id);
if (athlete == null)
{
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
var friend = await _userService.GetItemById(friendId);
if (friend == null)
{
_logger.LogError("Athlete with id {id} not found", friendId);
return NotFound($"Athlete with id {friendId} not found");
}
var isAdded = await _userService.AddFriend(athlete, friend);
if(!isAdded)
{
_logger.LogError("Error while adding friend with id {friendId} to athlete with id {id}", friendId, id);
return StatusCode(500);
}
return Ok();
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
return StatusCode(500);
}
}
[HttpPost("logout")]
[ProducesResponseType(200)]
[ProducesResponseType(401)]
[ProducesResponseType(500)]
public async Task<IActionResult> Logout(SignInManager<IdentityUser> signInManager, [FromBody] object? empty)
{
if (empty == null) return Unauthorized();
await signInManager.SignOutAsync();
return Ok();
}
}

@ -8,11 +8,17 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.1.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ApiMappeur\ApiMappeur.csproj" />
<ProjectReference Include="..\DbContextLib\DbContextLib.csproj" />
<ProjectReference Include="..\Dto\Dto.csproj" />
<ProjectReference Include="..\Model\Model.csproj" />
<ProjectReference Include="..\Shared\Shared.csproj" />

@ -1,25 +1,23 @@
using Model;
using DbContextLib;
using DbContextLib.Identity;
using Entities;
using HeartTrackAPI;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Model.Manager;
using Model.Repository;
using StubAPI;
var 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();
builder.Services.AddControllers();
builder.Services.AddSingleton<IDataManager, StubData>();
var app = builder.Build();
// Configure the HTTP request pipeline.
builder.Logging.AddConsole();
app.UseSwagger();
app.UseSwaggerUI();
var init = new AppBootstrap(builder.Configuration);
init.ConfigureServices(builder.Services);
app.UseHttpsRedirection();
var app = builder.Build();
app.MapControllers();
init.Configure(app, app.Environment);
// app?.Services?.GetService<HeartTrackContext>()?.Database.EnsureCreated();
app.Run();

@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace HeartTrackAPI.Utils;
public class SwaggerOptions: IConfigureNamedOptions<SwaggerGenOptions>
{
private readonly IApiVersionDescriptionProvider _provider;
public SwaggerOptions(
IApiVersionDescriptionProvider provider)
{
_provider = provider;
}
/// <summary>
/// Configure each API discovered for Swagger Documentation
/// </summary>
/// <param name="options"></param>
public void Configure(SwaggerGenOptions options)
{
// add swagger document for every API version discovered
foreach (var description in _provider.ApiVersionDescriptions)
{
options.SwaggerDoc(
description.GroupName,
CreateVersionInfo(description));
}
}
/// <summary>
/// Configure Swagger Options. Inherited from the Interface
/// </summary>
/// <param name="name"></param>
/// <param name="options"></param>
public void Configure(string name, SwaggerGenOptions options)
{
Configure(options);
}
/// <summary>
/// Create information about the version of the API
/// </summary>
/// <param name="description"></param>
/// <returns>Information about the API</returns>
private OpenApiInfo CreateVersionInfo(
ApiVersionDescription desc)
{
var info = new OpenApiInfo()
{
Title = ".NET Core (.NET 6) Web API For Lol",
Version = desc.ApiVersion.ToString()
};
if (desc.IsDeprecated)
{
info.Description += " This API version has been deprecated. Please use one of the new APIs available from the explorer.";
}
return info;
}
}

@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
"HeartTrackAuthConnection": "Data Source=uca.HeartTrack.db"
}
}

@ -0,0 +1,9 @@
namespace Model.Manager;
public class ActivityManager : IActivityManager
{
public void AddActivityFromFitFile(byte filePath)
{
throw new NotImplementedException();
}
}

@ -0,0 +1,7 @@
using Microsoft.AspNetCore.Http;
namespace Model.Manager;
public interface IActivityManager
{
public void AddActivityFromFitFile(byte filePath);
}

@ -0,0 +1,6 @@
namespace Model.Manager;
public class UserManager
{
}

@ -7,7 +7,18 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Entities\Entities.csproj" />
<ProjectReference Include="..\Shared\Shared.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.2" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Identity">
<HintPath>..\..\..\..\..\.dotnet\shared\Microsoft.AspNetCore.App\8.0.1\Microsoft.AspNetCore.Identity.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

@ -5,4 +5,6 @@ namespace Model.Repository;
public interface IUserRepository : IGenericRepository<User>
{
public Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false);
public Task<bool> AddFriend(User user, User friend);
}

@ -0,0 +1,31 @@
using Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
namespace Model.Service;
public class EmailSender : IEmailSender<AthleteEntity>
{
private IEmailSender<AthleteEntity> _emailSenderImplementation;
public async Task SendEmailAsync(string email, string subject, string htmlMessage)
{
throw new NotImplementedException();
}
public async Task SendConfirmationLinkAsync(AthleteEntity user, string email, string confirmationLink)
{
throw new NotImplementedException();
}
public async Task SendPasswordResetLinkAsync(AthleteEntity user, string email, string resetLink)
{
throw new NotImplementedException();
}
public async Task SendPasswordResetCodeAsync(AthleteEntity user, string email, string resetCode)
{
throw new NotImplementedException();
}
}

@ -8,7 +8,7 @@ public class User
public string LastName { get; set; }
public string FirstName { get; set; }
public string Email { get; set; }
public string MotDePasse { get; set; }
public string? MotDePasse { get; set; }
public string Sexe { get; set; }
public float Lenght { get; set; }
public float Weight { get; set; }
@ -17,6 +17,8 @@ public class User
protected List<Notification> Notifications { get; set; } = new List<Notification>();
public List<User> Users { get; set; } = new List<User>();
public User( string username, string profilePicture, string nom, string prenom, string email, string motDePasse, string sexe, float taille, float poids, DateTime dateNaissance, Role role)
{
Username = username;

@ -10,7 +10,6 @@ public partial class DbDataManager: IDataManager
{
public IActivityRepository ActivityRepo { get; }
public IUserRepository UserRepo { get; }
protected HeartTrackContext DbContext { get; }
// mettre si pb lors d'une requete si rollback ou pas

@ -49,5 +49,10 @@ public partial class DbDataManager
{
throw new NotImplementedException();
}
public async Task<bool> AddFriend(User user, User friend)
{
throw new NotImplementedException();
}
}
}

@ -34,6 +34,23 @@ public class UserService : IUserRepository
public async Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria? orderingProperty = null, bool descending = false)
=> athletes.GetItemsWithFilterAndOrdering(c=>true,index, count,orderingProperty != AthleteOrderCriteria.None ? orderingProperty: null , descending);
public async Task<bool> AddFriend(User user, User friend)
{
if (user == null || friend == null)
{
return false;
}
if (user.Users.Contains(friend))
{
return false;
}
user.Users.Add(friend);
return true;
}
public async Task<IEnumerable<User>> GetItems(int index, int count, string? orderingProperty = null,
bool descending = false)
{

Loading…
Cancel
Save