Compare commits

..

30 Commits

Author SHA1 Message Date
carteronm e1e8a834b2 push fichiers inutiles 2026-06-11 10:48:28 +02:00
gokhoal 61f3d2889c chiffrement 2026-06-11 10:33:02 +02:00
carteronm 66a7e633a9 Rôles ajoutés 2026-06-11 01:49:21 +02:00
carteronm fff484d4ba Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	Knots/bin/Debug/net8.0/Knots.dll
#	Knots/bin/Debug/net8.0/Knots.exe
#	Knots/bin/Debug/net8.0/Knots.pdb
#	Knots/obj/Debug/net8.0/Knots.AssemblyInfo.cs
#	Knots/obj/Debug/net8.0/Knots.AssemblyInfoInputs.cache
#	Knots/obj/Debug/net8.0/Knots.dll
#	Knots/obj/Debug/net8.0/Knots.pdb
#	Knots/obj/Debug/net8.0/apphost.exe
#	Knots/obj/Debug/net8.0/ref/Knots.dll
#	Knots/obj/Debug/net8.0/refint/Knots.dll
2026-06-11 01:32:33 +02:00
carteronm e69550048b Préparation des rôles 2026-06-11 01:32:20 +02:00
gokhoal a29fb27b0d commit blabla3 2026-06-11 01:30:14 +02:00
gokhoal c23cc4a03a LES MESSAGES MARCHENT 2026-06-11 01:29:27 +02:00
carteronm 1d2f96b2f4 Fin création des groupes 2026-06-11 01:14:32 +02:00
carteronm f1cdc5de19 Modif BDD Discussion 2026-06-11 00:56:32 +02:00
carteronm 4e06dc5f23 Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	Knots/bin/Debug/net8.0/Knots.dll
#	Knots/bin/Debug/net8.0/Knots.pdb
#	Knots/obj/Debug/net8.0/Knots.csproj.CoreCompileInputs.cache
#	Knots/obj/Debug/net8.0/Knots.csproj.FileListAbsolute.txt
#	Knots/obj/Debug/net8.0/Knots.dll
#	Knots/obj/Debug/net8.0/Knots.pdb
#	Knots/obj/Debug/net8.0/ref/Knots.dll
#	Knots/obj/Debug/net8.0/refint/Knots.dll
2026-06-11 00:46:04 +02:00
carteronm 779acbe531 Groupe rectification 2026-06-11 00:45:49 +02:00
gokhoal e6021dcc61 envoi et creation messages 2026-06-11 00:44:28 +02:00
gokhoal 4f994ba183 conmmit blabla2 2026-06-11 00:20:02 +02:00
gokhoal 2bb1f730c9 Creatediscussions private et group 2026-06-11 00:19:32 +02:00
gokhoal c92e134698 Revert "Endpoint group"
This reverts commit b7dad57c
2026-06-11 00:15:58 +02:00
gokhoal 0b9e01c925 Revert "endpoint de creation de discussion"
This reverts commit af1b14b0d2.
2026-06-11 00:13:30 +02:00
gokhoal c1bd8a12a9 Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	Knots/bin/Debug/net8.0/Knots.dll
#	Knots/bin/Debug/net8.0/Knots.pdb
#	Knots/obj/Debug/net8.0/Knots.assets.cache
#	Knots/obj/Debug/net8.0/Knots.csproj.AssemblyReference.cache
#	Knots/obj/Debug/net8.0/Knots.csproj.CoreCompileInputs.cache
#	Knots/obj/Debug/net8.0/Knots.dll
#	Knots/obj/Debug/net8.0/Knots.pdb
#	Knots/obj/Debug/net8.0/ref/Knots.dll
#	Knots/obj/Debug/net8.0/refint/Knots.dll
#	Knots/obj/project.nuget.cache
#	Knots/obj/project.packagespec.json
#	Knots/obj/rider.project.model.nuget.info
#	Knots/obj/rider.project.restore.info
2026-06-11 00:13:10 +02:00
gokhoal c120d34e62 hub pour websocket 2026-06-11 00:12:29 +02:00
carteronm b7dad57cee Endpoint group 2026-06-10 23:33:04 +02:00
gokhoal af1b14b0d2 endpoint de creation de discussion 2026-06-10 22:46:40 +02:00
gokhoal 7cfb3909b6 changements de getmessageendpoint et du dto details 2026-06-10 21:33:37 +02:00
gokhoal ff317cc944 correction du modele User et du context 2026-06-10 20:15:05 +02:00
carteronm 79a926bc2d push de con 2026-06-10 17:29:50 +02:00
gokhoal 431e96d9e4 correction de l'endpoint 2026-06-10 17:19:16 +02:00
gokhoal eb70f4b3de changement structure bdd + gestion discussions 2026-06-10 17:17:01 +02:00
gokhoal 690d85009e Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	Knots/bin/Debug/net8.0/Knots.dll
#	Knots/bin/Debug/net8.0/Knots.exe
2026-06-10 17:02:43 +02:00
gokhoal cec4437f2f commit blabla 2026-06-10 17:02:21 +02:00
carteronm 33987f080e modif 2026-06-10 16:26:11 +02:00
gokhoal c5b5ac6b84 origin acceptee ajoutee 2026-06-10 16:09:44 +02:00
carteronm db72346683 Résolution du problème de merde 2026-06-10 15:57:09 +02:00
107 changed files with 3362 additions and 933 deletions
+3 -1
View File
@@ -5,5 +5,7 @@ public class GetDiscussionDto
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public bool IsGroup { get; set; }
public int MembersCount { get; set; }
public int? MembersCount { get; set; }
public int? GroupId { get; set; }
}
@@ -6,4 +6,7 @@ public class GetMessageDetailsDto
public string? Contenu { get; set; }
public DateTime Date { get; set; }
public Boolean Type { get; set; }
public int UserId { get; set; }
public string AuthorName { get; set; } = "";
}
@@ -16,6 +16,6 @@ public class CreateDiscussionEndpoint(KnotsDbContext db, AutoMapper.IMapper mapp
Models.Discussion? discussion = mapper.Map<Models.Discussion>(req);
db.Discussions.Add(discussion);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -0,0 +1,91 @@
using FastEndpoints;
using Knots.DTO.Discussion;
using Knots.Models;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using Knots.Services;
namespace Knots.Endpoints.Discussion;
public class CreateGroupDiscussionEndpoint(KnotsDbContext db, EncryptionService encryption) : Endpoint<CreateGroupDiscussionRequest, GetDiscussionDto>
{
public override void Configure()
{
Post("/discussions/group");
}
public override async Task HandleAsync(CreateGroupDiscussionRequest req, CancellationToken ct)
{
int currentUserId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
if (req.Usernames == null || req.Usernames.Count == 0)
{
await SendErrorsAsync(400, ct);
return;
}
List<Models.User> targets = await db.Users
.Where(u => req.Usernames.Contains(u.Username!))
.ToListAsync(ct);
if (targets.Count != req.Usernames.Count)
{
await SendNotFoundAsync(ct);
return;
}
if (targets.Any(t => t.Id == currentUserId))
{
await SendErrorsAsync(400, ct);
return;
}
int totalMembers = targets.Count + 1;
Models.Discussion discussion = new()
{
IsGroup = true,
Key = new Models.Key { EnKey = encryption.GenerateKey() },
UserDiscussions = targets
.Select(t => new UserDiscussion { UserId = t.Id })
.Append(new UserDiscussion { UserId = currentUserId })
.ToList()
};
db.Discussions.Add(discussion);
await db.SaveChangesAsync(ct); // discussion.Id disponible
Models.Group group = new()
{
Name = req.GroupName,
MembersAmount = totalMembers,
DiscussionId = discussion.Id,
GroupUsers = targets
.Select(t => new GroupUser { UserId = t.Id })
.Append(new GroupUser { UserId = currentUserId })
.ToList()
};
db.Groups.Add(group);
await db.SaveChangesAsync(ct); // group.Id disponible
discussion.GroupId = group.Id;
await db.SaveChangesAsync(ct);
await SendOkAsync(new GetDiscussionDto
{
Id = discussion.Id,
IsGroup = true,
Name = group.Name,
MembersCount = totalMembers
}, ct);
}
}
public class CreateGroupDiscussionRequest
{
public string GroupName { get; set; } = "";
public List<string> Usernames { get; set; } = [];
}
@@ -0,0 +1,85 @@
using FastEndpoints;
using Knots.DTO.Discussion;
using Knots.Models;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using Knots.Services;
namespace Knots.Endpoints.Discussion;
public class CreatePrivateDiscussionEndpoint(KnotsDbContext db, EncryptionService encryption)
: Endpoint<CreatePrivateDiscussionRequest, GetDiscussionDto>
{
public override void Configure()
{
Post("/discussions/private");
}
public override async Task HandleAsync(CreatePrivateDiscussionRequest req, CancellationToken ct)
{
int currentUserId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
// 1. retrouver l'utilisateur cible par son nom
Models.User? target = await db.Users
.SingleOrDefaultAsync(u => u.Username == req.Username, ct);
if (target is null)
{
await SendNotFoundAsync(ct); // utilisateur introuvable
return;
}
if (target.Id == currentUserId)
{
await SendErrorsAsync(400, ct); // pas de discussion avec soi-même
return;
}
// 2. vérifier qu'une discussion privée entre les deux n'existe pas déjà
Models.Discussion? existing = await db.Discussions
.Where(d => d.GroupId == null
&& d.UserDiscussions.Any(ud => ud.UserId == currentUserId)
&& d.UserDiscussions.Any(ud => ud.UserId == target.Id))
.FirstOrDefaultAsync(ct);
if (existing is not null)
{
await SendOkAsync(new GetDiscussionDto
{
Id = existing.Id,
IsGroup = false,
Name = target.Username!,
MembersCount = null
}, ct);
return;
}
// 3. créer la discussion + les deux participants
Models.Discussion discussion = new()
{
IsGroup = false,
Key = new Models.Key { EnKey = encryption.GenerateKey() },
UserDiscussions =
[
new UserDiscussion { UserId = currentUserId },
new UserDiscussion { UserId = target.Id }
]
};
db.Discussions.Add(discussion);
await db.SaveChangesAsync(ct);
await SendOkAsync(new GetDiscussionDto
{
Id = discussion.Id,
IsGroup = false,
Name = target.Username!,
MembersCount = null
}, ct);
}
}
public class CreatePrivateDiscussionRequest
{
public string Username { get; set; } = "";
}
@@ -16,6 +16,6 @@ public class DeleteDiscussionEndpoint(KnotsDbContext db, AutoMapper.IMapper mapp
Models.Discussion? discussion = mapper.Map<Models.Discussion>(req);
db.Discussions.Remove(discussion);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -19,11 +19,11 @@ public class GetDiscussionEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper)
if (databaseDiscussion == null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
var keyDto = mapper.Map<GetKeyDetailsDto>(databaseDiscussion);
await Send.OkAsync(keyDto, ct);
await SendOkAsync(keyDto, ct);
}
}
@@ -0,0 +1,35 @@
using System.Security.Claims;
using FastEndpoints;
using Microsoft.EntityFrameworkCore;
namespace Knots.Endpoints.Discussion;
public class GetDiscussionMembersEndpoint(KnotsDbContext db) : EndpointWithoutRequest<List<string>>
{
public override void Configure()
{
Get("/discussions/{discussionId}/members");
}
public override async Task HandleAsync(CancellationToken ct)
{
int discussionId = Route<int>("discussionId");
Models.Discussion? discussion = await db.Discussions
.Include(d => d.UserDiscussions)
.ThenInclude(ud => ud.User)
.SingleOrDefaultAsync(d => d.Id == discussionId, ct);
if (discussion is null)
{
await SendNotFoundAsync(ct);
return;
}
List<string> members = discussion.UserDiscussions
.Select(ud => ud.User.Username!)
.ToList();
await SendOkAsync(members, ct);
}
}
@@ -0,0 +1,52 @@
using FastEndpoints;
using Microsoft.EntityFrameworkCore;
namespace Knots.Endpoints.Discussion;
public class GetDiscussionMembersWithRolesEndpoint(KnotsDbContext db) : EndpointWithoutRequest<List<MemberWithRoleDto>>
{
public override void Configure()
{
Get("/discussions/{discussionId}/members/roles");
}
public override async Task HandleAsync(CancellationToken ct)
{
int discussionId = Route<int>("discussionId");
Models.Discussion? discussion = await db.Discussions
.Include(d => d.Group)
.ThenInclude(g => g!.GroupUsers)
.ThenInclude(gu => gu.User)
.Include(d => d.Group)
.ThenInclude(g => g!.GroupUsers)
.ThenInclude(gu => gu.Role)
.SingleOrDefaultAsync(d => d.Id == discussionId, ct);
if (discussion?.Group is null)
{
await SendNotFoundAsync(ct);
return;
}
List<MemberWithRoleDto> members = discussion.Group.GroupUsers
.Select(gu => new MemberWithRoleDto
{
UserId = gu.UserId,
Username = gu.User.Username!,
RoleId = gu.RoleId,
RoleLibelle = gu.Role?.Libelle
})
.ToList();
await SendOkAsync(members, ct);
}
}
public class MemberWithRoleDto
{
public int UserId { get; set; }
public string Username { get; set; } = "";
public int? RoleId { get; set; }
public string? RoleLibelle { get; set; }
}
@@ -0,0 +1,50 @@
using System.Security.Claims;
using FastEndpoints;
using Knots.DTO.Discussion;
using Microsoft.EntityFrameworkCore;
namespace Knots.Endpoints.Discussion;
public class GetMyDiscussionEndpoint(KnotsDbContext db) : EndpointWithoutRequest<List<GetDiscussionDto>>
{
public override void Configure()
{
Get("/discussions/my");
}
public override async Task HandleAsync(CancellationToken ct)
{
int userId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
// Discussions privées : l'utilisateur est l'un des participants
IQueryable<GetDiscussionDto> privees = db.Discussions
.Where(d => d.GroupId == null && d.UserDiscussions.Any(ud => ud.UserId == userId))
.Select(d => new GetDiscussionDto
{
Id = d.Id,
IsGroup = false,
Name = d.UserDiscussions
.Where(ud => ud.UserId != userId)
.Select(ud => ud.User.Username)
.FirstOrDefault() ?? "",
MembersCount = null,
GroupId = null
});
// Discussions de groupe : l'utilisateur est membre du groupe
IQueryable<GetDiscussionDto> groupes = db.Discussions
.Where(d => d.Group != null && d.Group.GroupUsers.Any(gu => gu.UserId == userId))
.Select(d => new GetDiscussionDto
{
Id = d.Id,
IsGroup = true,
Name = d.Group!.Name!,
MembersCount = d.Group.MembersAmount,
GroupId = d.Group.Id
});
List<GetDiscussionDto> discussions = await privees.Concat(groupes).ToListAsync(ct);
await SendOkAsync(discussions, ct);
}
}
+1 -1
View File
@@ -16,6 +16,6 @@ public class CreateGroupEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
Models.Group? group = mapper.Map<Models.Group>(req);
db.Groups.Add(group);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+1 -1
View File
@@ -16,6 +16,6 @@ public class DeleteGroupEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
Models.Group? group = mapper.Map<Models.Group>(req);
db.Groups.Remove(group);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+2 -2
View File
@@ -19,11 +19,11 @@ public class GetGroupEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : En
if (databaseGroup == null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
var keyDto = mapper.Map<GetKeyDetailsDto>(databaseGroup);
await Send.OkAsync(keyDto, ct);
await SendOkAsync(keyDto, ct);
}
}
@@ -18,12 +18,12 @@ public class PatchGroupMembersAmountEndpoint(KnotsDbContext knotsDbContext) : En
if (databaseGroup is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
databaseGroup.MembersAmount = req.MembersAmount;
await knotsDbContext.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -18,12 +18,12 @@ public class PatchGroupNameEndpoint(KnotsDbContext knotsDbContext) : Endpoint<Up
if (databaseGroup is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
databaseGroup.Name = req.Name;
await knotsDbContext.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -18,12 +18,12 @@ public class PatchGroupProfilePictureEndpoint(KnotsDbContext knotsDbContext) : E
if (databaseGroup is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
databaseGroup.ProfilePicture = req.ProfilePicture;
await knotsDbContext.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+1 -1
View File
@@ -16,6 +16,6 @@ public class CreateKeyEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : E
Models.Key? key = mapper.Map<Models.Key>(req);
db.Keys.Add(key);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+1 -1
View File
@@ -16,6 +16,6 @@ public class DeleteKeyEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : E
Models.Key? key = mapper.Map<Models.Key>(req);
db.Keys.Remove(key);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+2 -2
View File
@@ -19,11 +19,11 @@ public class GetKeyEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : Endp
if (databaseKey == null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
var keyDto = mapper.Map<GetKeyDetailsDto>(databaseKey);
await Send.OkAsync(keyDto, ct);
await SendOkAsync(keyDto, ct);
}
}
@@ -16,6 +16,6 @@ public class CreateMessageEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper)
Models.Message? message = mapper.Map<Models.Message>(req);
db.Messages.Add(message);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -16,6 +16,6 @@ public class DeleteMessageEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper)
Models.Message? message = mapper.Map<Models.Message>(req);
db.Messages.Remove(message);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+43 -10
View File
@@ -1,29 +1,62 @@
using System.Security.Claims;
using FastEndpoints;
using Knots.DTO.Message;
using Knots.DTO.User;
using Knots.Services;
using Microsoft.EntityFrameworkCore;
namespace Knots.Endpoints.Message;
public class GetMessageEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : Endpoint <GetMessageDetailsDto>
public class GetMessageEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper, EncryptionService encryption) : Endpoint<GetDiscussionMessagesRequest, List<GetMessageDetailsDto>>
{
public override void Configure()
{
Get("/messages/{@Id}");
Get("/discussions/{DiscussionId}/messages");
AllowAnonymous();
}
public override async Task HandleAsync(GetMessageDetailsDto req, CancellationToken ct)
public override async Task HandleAsync(GetDiscussionMessagesRequest req, CancellationToken ct)
{
Models.Message? databaseMessage = await db.Messages.SingleOrDefaultAsync(x => x.Id == req.Id, cancellationToken: ct);
if (databaseMessage == null)
int userId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
// l'utilisateur participe-t-il à cette discussion (privée ou via le groupe) ?
bool autorise = await db.Discussions
.Where(d => d.Id == req.DiscussionId)
.AnyAsync(d =>
d.UserDiscussions.Any(ud => ud.UserId == userId) ||
(d.Group != null && d.Group.GroupUsers.Any(gu => gu.UserId == userId)), ct);
if (!autorise)
{
await Send.NotFoundAsync(ct);
await SendForbiddenAsync(ct);
return;
}
var messageDto = mapper.Map<GetMessageDetailsDto>(databaseMessage);
await Send.OkAsync(messageDto, ct);
string? key = await db.Discussions
.Where(d => d.Id == req.DiscussionId)
.Select(d => d.Key!.EnKey)
.SingleAsync(ct);
var rows = await db.Messages
.Where(m => m.DiscussionId == req.DiscussionId)
.OrderBy(m => m.Date)
.Select(m => new { m.Id, m.Contenu, m.Date, m.UserId, AuthorName = m.User.Username! })
.ToListAsync(ct);
List<GetMessageDetailsDto> messages = rows.Select(m => new GetMessageDetailsDto
{
Id = m.Id,
Contenu = encryption.Decrypt(m.Contenu!, key!),
Date = m.Date,
UserId = m.UserId,
AuthorName = m.AuthorName
}).ToList();
await SendOkAsync(messages, ct);
}
}
public class GetDiscussionMessagesRequest
{
public int DiscussionId { get; set; }
}
@@ -0,0 +1,45 @@
using FastEndpoints;
using Knots.Models;
using Microsoft.EntityFrameworkCore;
namespace Knots.Endpoints.Role;
public class AssignRoleEndpoint(KnotsDbContext db) : Endpoint<AssignRoleRequest>
{
public override void Configure()
{
Post("/groups/{groupId}/members/{userId}/role");
}
public override async Task HandleAsync(AssignRoleRequest req, CancellationToken ct)
{
int groupId = Route<int>("groupId");
int userId = Route<int>("userId");
GroupUser? groupUser = await db.GroupUsers
.SingleOrDefaultAsync(gu => gu.GroupId == groupId && gu.UserId == userId, ct);
if (groupUser is null)
{
await SendNotFoundAsync(ct);
return;
}
bool roleExists = await db.Roles.AnyAsync(r => r.Id == req.RoleId, ct);
if (!roleExists)
{
await SendNotFoundAsync(ct);
return;
}
groupUser.RoleId = req.RoleId;
await db.SaveChangesAsync(ct);
await SendOkAsync(ct);
}
}
public class AssignRoleRequest
{
public int RoleId { get; set; }
}
+18 -8
View File
@@ -1,22 +1,32 @@
using FastEndpoints;
using Knots.DTO.Role;
using Knots.DTO.User;
using Knots.Models;
namespace Knots.Endpoints.Role;
public class CreateRoleEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : Endpoint<CreateRoleDto>
public class CreateRoleEndpoint(KnotsDbContext db) : Endpoint<CreateRoleRequest, RoleDto>
{
public override void Configure()
{
Post("/roles");
AllowAnonymous();
}
public override async Task HandleAsync(CreateRoleDto req, CancellationToken ct)
public override async Task HandleAsync(CreateRoleRequest req, CancellationToken ct)
{
Models.Role? role = mapper.Map<Models.Role>(req);
Models.Role role = new() { Libelle = req.Libelle };
db.Roles.Add(role);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendOkAsync(new RoleDto { Id = role.Id, Libelle = role.Libelle! }, ct);
}
}
public class CreateRoleRequest
{
public string Libelle { get; set; } = "";
}
public class RoleDto
{
public int Id { get; set; }
public string Libelle { get; set; } = "";
}
+1 -1
View File
@@ -16,6 +16,6 @@ public class DeleteRoleEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
Models.Role? role = mapper.Map<Models.Role>(req);
db.Roles.Remove(role);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+2 -2
View File
@@ -19,11 +19,11 @@ public class GetRoleEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : End
if (databaseRole == null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
var roleDto = mapper.Map<GetRoleDto>(databaseRole);
await Send.OkAsync(roleDto, ct);
await SendOkAsync(roleDto, ct);
}
}
+2 -2
View File
@@ -20,7 +20,7 @@ public class CreateUserEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
if (usernameExists)
{
AddError(x => x.Username, "Ce nom d'utilisateur est déjà pris.");
await Send.ErrorsAsync(cancellation: ct);
await SendErrorsAsync(cancellation: ct);
return;
}
@@ -28,6 +28,6 @@ public class CreateUserEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
Models.User? user = mapper.Map<Models.User>(req);
db.Users.Add(user);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+1 -1
View File
@@ -16,6 +16,6 @@ public class DeleteUserEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
Models.User? user = mapper.Map<Models.User>(req);
db.Users.Add(user);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+1 -1
View File
@@ -19,6 +19,6 @@ public class GetAllUsersEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
.ProjectTo<GetUserDetailsDto>(mapper.ConfigurationProvider)
.ToListAsync(ct);
await Send.OkAsync(users, ct);
await SendOkAsync(users, ct);
}
}
+2 -2
View File
@@ -18,11 +18,11 @@ public class GetUserEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) : End
if (databaseUser == null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
var userDto = mapper.Map<GetUserDetailsDto>(databaseUser);
await Send.OkAsync(userDto, ct);
await SendOkAsync(userDto, ct);
}
}
+2 -2
View File
@@ -20,13 +20,13 @@ public class LoginEndpoint(KnotsDbContext db, JwtService jwtService) : Endpoint<
if (user is null || !BCrypt.Net.BCrypt.Verify(req.Password, user.Password)) // hash à ajouter plus tard
{
await Send.UnauthorizedAsync(ct);
await SendUnauthorizedAsync(ct);
return;
}
string token = jwtService.GenerateToken(user);
await Send.OkAsync(new LoginResponseDto
await SendOkAsync(new LoginResponseDto
{
Token = token,
Id = user.Id,
@@ -18,7 +18,7 @@ public class PatchUserContactEndpoint(KnotsDbContext db, AutoMapper.IMapper mapp
if (databaseUser is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
@@ -42,6 +42,6 @@ public class PatchUserContactEndpoint(KnotsDbContext db, AutoMapper.IMapper mapp
mapper.Map(req, databaseUser);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -18,13 +18,13 @@ public class PatchUserDescriptionEndpoint(KnotsDbContext db, AutoMapper.IMapper
if (databaseUser is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
mapper.Map(req, databaseUser);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -18,13 +18,13 @@ public class PatchUserPasswordEndpoint(KnotsDbContext db, AutoMapper.IMapper map
if (databaseUser is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
mapper.Map(req, databaseUser);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -18,13 +18,13 @@ public class PatchUserProfilePictureEndpoint(KnotsDbContext db, AutoMapper.IMapp
if (databaseUser is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
mapper.Map(req, databaseUser);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
@@ -19,7 +19,7 @@ public class PatchUsernameEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper)
if (databaseUser is null)
{
await Send.NotFoundAsync(ct);
await SendNotFoundAsync(ct);
return;
}
@@ -29,13 +29,13 @@ public class PatchUsernameEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper)
if (usernameExists)
{
AddError(x => x.Username, "Ce nom d'utilisateur est déjà pris.");
await Send.ErrorsAsync(cancellation: ct);
await SendErrorsAsync(cancellation: ct);
return;
}
mapper.Map(req, databaseUser);
await db.SaveChangesAsync(ct);
await Send.NoContentAsync(ct);
await SendNoContentAsync(ct);
}
}
+60
View File
@@ -0,0 +1,60 @@
using Knots.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace Knots.Hubs;
[Authorize]
public class ChatHub(KnotsDbContext db, AutoMapper.IMapper mapper, EncryptionService encryption) : Hub
{
// Rejoindre une conversation (room)
public async Task JoinConversation(string discussionId)
{
await Groups.AddToGroupAsync(Context.ConnectionId, discussionId);
}
// Quitter une conversation
public async Task LeaveConversation(string discussionId)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, discussionId);
}
// Envoyer un message à une conversation
public async Task SendMessage(string discussionId, string content)
{
int id = int.Parse(discussionId);
Models.Discussion discussion = await db.Discussions
.Include(d => d.Key)
.SingleAsync(d => d.Id == id);
var message = new Models.Message
{
Contenu = encryption.Encrypt(content, discussion.Key!.EnKey!), // chiffré en base
Date = DateTime.UtcNow,
Type = false,
UserId = int.Parse(Context.UserIdentifier!),
DiscussionId = id
};
db.Messages.Add(message);
await db.SaveChangesAsync();
// diffusion en clair, avec les noms de champs attendus par le front
await Clients.Group(discussionId).SendAsync("ReceiveMessage", new
{
id = message.Id,
contenu = content,
date = message.Date,
userId = message.UserId
});
}
// Notifier que l'utilisateur est en train d'écrire
public async Task Typing(string discussionId)
{
await Clients.OthersInGroup(discussionId)
.SendAsync("UserTyping", Context.UserIdentifier);
}
}
+3 -2
View File
@@ -9,11 +9,12 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.2.0" />
<PackageReference Include="FastEndpoints" Version="8.0.1" />
<PackageReference Include="FastEndpoints.Swagger" Version="8.0.1" />
<PackageReference Include="FastEndpoints" Version="5.33.0" />
<PackageReference Include="FastEndpoints.Swagger" Version="5.33.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.3.11" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.28" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.25" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.25" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.25">
<PrivateAssets>all</PrivateAssets>
+48 -28
View File
@@ -5,13 +5,14 @@ namespace Knots;
public class KnotsDbContext : DbContext
{
public DbSet<Discussion> Discussions { get; set; }
public DbSet<UserDiscussion> UserDiscussions { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<Key> Keys { get; set; }
public DbSet<Message> Messages { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<User> Users => Set<User>();
public DbSet<Discussion> Discussions => Set<Discussion>();
public DbSet<Group> Groups => Set<Group>();
public DbSet<Message> Messages => Set<Message>();
public DbSet<Role> Roles => Set<Role>();
public DbSet<Key> Keys => Set<Key>();
public DbSet<UserDiscussion> UserDiscussions => Set<UserDiscussion>();
public DbSet<GroupUser> GroupUsers => Set<GroupUser>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
@@ -26,34 +27,53 @@ public class KnotsDbContext : DbContext
optionsBuilder.UseSqlServer(connectionString);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<GroupUser>()
.HasKey(gu => new { gu.GroupId, gu.UserId });
modelBuilder.Entity<GroupUser>()
.HasOne(gu => gu.Group)
.WithMany(g => g.GroupUsers)
.HasForeignKey(gu => gu.GroupId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<GroupUser>()
.HasOne(gu => gu.User)
.WithMany()
.HasForeignKey(gu => gu.UserId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<GroupUser>()
.HasOne(gu => gu.Role)
.WithMany(r => r.GroupUsers)
.HasForeignKey(gu => gu.RoleId);
modelBuilder.Entity<Discussion>()
.HasOne(d => d.Group)
.WithMany()
.HasForeignKey(d => d.GroupId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Group>()
.HasOne(g => g.Discussion)
.WithMany()
.HasForeignKey(g => g.DiscussionId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<UserDiscussion>()
.HasKey(ud => new { ud.UserId, ud.DiscussionId });
modelBuilder.Entity<UserDiscussion>()
.HasOne(ud => ud.User)
.WithMany(u => u.UserDiscussions)
.HasForeignKey(ud => ud.UserId);
modelBuilder.Entity<UserDiscussion>()
.HasOne(ud => ud.Discussion)
.WithMany(d => d.UserDiscussions)
.HasForeignKey(ud => ud.DiscussionId);
modelBuilder.Entity<Message>()
.HasOne(m => m.Discussion)
.WithMany(d => d.Messages)
.HasForeignKey(m => m.DiscussionId);
.HasForeignKey(ud => ud.DiscussionId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Message>()
.HasOne(m => m.User)
.WithMany(u => u.Messages)
.HasForeignKey(m => m.UserId);
modelBuilder.Entity<Group>()
.HasOne(g => g.Discussion)
.WithOne(d => d.Group)
.HasForeignKey<Group>(g => g.DiscussionId);
modelBuilder.Entity<UserDiscussion>()
.HasOne(ud => ud.User)
.WithMany(u => u.UserDiscussions)
.HasForeignKey(ud => ud.UserId)
.OnDelete(DeleteBehavior.Restrict);
}
}
@@ -0,0 +1,316 @@
// <auto-generated />
using System;
using Knots;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Knots.Migrations
{
[DbContext(typeof(KnotsDbContext))]
[Migration("20260610135459_AddRoleIdToUser")]
partial class AddRoleIdToUser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.25")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Knots.Models.Discussion", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<bool>("IsGroup")
.HasColumnType("bit");
b.HasKey("Id");
b.ToTable("Discussions");
});
modelBuilder.Entity("Knots.Models.Group", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.Property<int>("KeyId")
.HasColumnType("int");
b.Property<int>("MembersAmount")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("ProfilePicture")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("DiscussionId")
.IsUnique();
b.ToTable("Groups");
});
modelBuilder.Entity("Knots.Models.Key", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("EnKey")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.ToTable("Keys");
});
modelBuilder.Entity("Knots.Models.Message", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Contenu")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<DateTime>("Date")
.HasColumnType("datetime2");
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.Property<int?>("GroupId")
.HasColumnType("int");
b.Property<int?>("KeyId")
.HasColumnType("int");
b.Property<bool>("Type")
.HasColumnType("bit");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("DiscussionId");
b.HasIndex("GroupId");
b.HasIndex("KeyId");
b.HasIndex("UserId");
b.ToTable("Messages");
});
modelBuilder.Entity("Knots.Models.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Libelle")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.ToTable("Roles");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(70)
.HasColumnType("nvarchar(70)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ProfilePicture")
.HasColumnType("nvarchar(max)");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.Property<string>("Tel")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users");
});
modelBuilder.Entity("Knots.Models.UserDiscussion", b =>
{
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.HasKey("UserId", "DiscussionId");
b.HasIndex("DiscussionId");
b.ToTable("UserDiscussions");
});
modelBuilder.Entity("Knots.Models.Group", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithOne("Group")
.HasForeignKey("Knots.Models.Group", "DiscussionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Discussion");
});
modelBuilder.Entity("Knots.Models.Message", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany("Messages")
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.Group", "Group")
.WithMany()
.HasForeignKey("GroupId");
b.HasOne("Knots.Models.Key", "Key")
.WithMany("Messages")
.HasForeignKey("KeyId");
b.HasOne("Knots.Models.User", "User")
.WithMany("Messages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Discussion");
b.Navigation("Group");
b.Navigation("Key");
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.HasOne("Knots.Models.Role", "Role")
.WithMany("Users")
.HasForeignKey("RoleId");
b.Navigation("Role");
});
modelBuilder.Entity("Knots.Models.UserDiscussion", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany("UserDiscussions")
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.User", "User")
.WithMany("UserDiscussions")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Discussion");
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.Discussion", b =>
{
b.Navigation("Group");
b.Navigation("Messages");
b.Navigation("UserDiscussions");
});
modelBuilder.Entity("Knots.Models.Key", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("Knots.Models.Role", b =>
{
b.Navigation("Users");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.Navigation("Messages");
b.Navigation("UserDiscussions");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,270 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Knots.Migrations
{
/// <inheritdoc />
public partial class AddRoleIdToUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Messages_Discussions_DiscussionId",
table: "Messages");
migrationBuilder.DropForeignKey(
name: "FK_Messages_Groups_GroupId",
table: "Messages");
migrationBuilder.DropForeignKey(
name: "FK_Messages_Keys_KeyId",
table: "Messages");
migrationBuilder.DropColumn(
name: "KeyId",
table: "Discussions");
migrationBuilder.AddColumn<int>(
name: "RoleId",
table: "Users",
type: "int",
nullable: true);
migrationBuilder.AlterColumn<int>(
name: "KeyId",
table: "Messages",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<int>(
name: "GroupId",
table: "Messages",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<int>(
name: "DiscussionId",
table: "Messages",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AddColumn<int>(
name: "DiscussionId",
table: "Groups",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<DateTime>(
name: "CreatedAt",
table: "Discussions",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.AddColumn<bool>(
name: "IsGroup",
table: "Discussions",
type: "bit",
nullable: false,
defaultValue: false);
migrationBuilder.CreateTable(
name: "UserDiscussions",
columns: table => new
{
UserId = table.Column<int>(type: "int", nullable: false),
DiscussionId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserDiscussions", x => new { x.UserId, x.DiscussionId });
table.ForeignKey(
name: "FK_UserDiscussions_Discussions_DiscussionId",
column: x => x.DiscussionId,
principalTable: "Discussions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UserDiscussions_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Users_RoleId",
table: "Users",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "IX_Groups_DiscussionId",
table: "Groups",
column: "DiscussionId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_UserDiscussions_DiscussionId",
table: "UserDiscussions",
column: "DiscussionId");
migrationBuilder.AddForeignKey(
name: "FK_Groups_Discussions_DiscussionId",
table: "Groups",
column: "DiscussionId",
principalTable: "Discussions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Messages_Discussions_DiscussionId",
table: "Messages",
column: "DiscussionId",
principalTable: "Discussions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Messages_Groups_GroupId",
table: "Messages",
column: "GroupId",
principalTable: "Groups",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Messages_Keys_KeyId",
table: "Messages",
column: "KeyId",
principalTable: "Keys",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users",
column: "RoleId",
principalTable: "Roles",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Groups_Discussions_DiscussionId",
table: "Groups");
migrationBuilder.DropForeignKey(
name: "FK_Messages_Discussions_DiscussionId",
table: "Messages");
migrationBuilder.DropForeignKey(
name: "FK_Messages_Groups_GroupId",
table: "Messages");
migrationBuilder.DropForeignKey(
name: "FK_Messages_Keys_KeyId",
table: "Messages");
migrationBuilder.DropForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users");
migrationBuilder.DropTable(
name: "UserDiscussions");
migrationBuilder.DropIndex(
name: "IX_Users_RoleId",
table: "Users");
migrationBuilder.DropIndex(
name: "IX_Groups_DiscussionId",
table: "Groups");
migrationBuilder.DropColumn(
name: "RoleId",
table: "Users");
migrationBuilder.DropColumn(
name: "DiscussionId",
table: "Groups");
migrationBuilder.DropColumn(
name: "CreatedAt",
table: "Discussions");
migrationBuilder.DropColumn(
name: "IsGroup",
table: "Discussions");
migrationBuilder.AlterColumn<int>(
name: "KeyId",
table: "Messages",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "GroupId",
table: "Messages",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "DiscussionId",
table: "Messages",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AddColumn<int>(
name: "KeyId",
table: "Discussions",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddForeignKey(
name: "FK_Messages_Discussions_DiscussionId",
table: "Messages",
column: "DiscussionId",
principalTable: "Discussions",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Messages_Groups_GroupId",
table: "Messages",
column: "GroupId",
principalTable: "Groups",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Messages_Keys_KeyId",
table: "Messages",
column: "KeyId",
principalTable: "Keys",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}
@@ -0,0 +1,380 @@
// <auto-generated />
using System;
using Knots;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Knots.Migrations
{
[DbContext(typeof(KnotsDbContext))]
[Migration("20260610224937_FixGroupDiscussion")]
partial class FixGroupDiscussion
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.25")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Knots.Models.Discussion", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<int?>("GroupId")
.HasColumnType("int");
b.Property<bool>("IsGroup")
.HasColumnType("bit");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("Discussions");
});
modelBuilder.Entity("Knots.Models.Group", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.Property<int>("MembersAmount")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("ProfilePicture")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("DiscussionId");
b.ToTable("Groups");
});
modelBuilder.Entity("Knots.Models.GroupUser", b =>
{
b.Property<int>("GroupId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.HasKey("GroupId", "UserId");
b.HasIndex("RoleId");
b.HasIndex("UserId");
b.ToTable("GroupUsers");
});
modelBuilder.Entity("Knots.Models.Key", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("EnKey")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.ToTable("Keys");
});
modelBuilder.Entity("Knots.Models.Message", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("AuthorId")
.HasColumnType("int");
b.Property<string>("Contenu")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<DateTime>("Date")
.HasColumnType("datetime2");
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.Property<int?>("GroupId")
.HasColumnType("int");
b.Property<int?>("KeyId")
.HasColumnType("int");
b.Property<bool>("Type")
.HasColumnType("bit");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("DiscussionId");
b.HasIndex("GroupId");
b.HasIndex("KeyId");
b.HasIndex("UserId");
b.ToTable("Messages");
});
modelBuilder.Entity("Knots.Models.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Libelle")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.ToTable("Roles");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(70)
.HasColumnType("nvarchar(70)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ProfilePicture")
.HasColumnType("nvarchar(max)");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.Property<string>("Tel")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users");
});
modelBuilder.Entity("Knots.Models.UserDiscussion", b =>
{
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.HasKey("UserId", "DiscussionId");
b.HasIndex("DiscussionId");
b.ToTable("UserDiscussions");
});
modelBuilder.Entity("Knots.Models.Discussion", b =>
{
b.HasOne("Knots.Models.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Group");
});
modelBuilder.Entity("Knots.Models.Group", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany()
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Discussion");
});
modelBuilder.Entity("Knots.Models.GroupUser", b =>
{
b.HasOne("Knots.Models.Group", "Group")
.WithMany("GroupUsers")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.Role", "Role")
.WithMany("GroupUsers")
.HasForeignKey("RoleId");
b.HasOne("Knots.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Group");
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.Message", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany("Messages")
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.Group", "Group")
.WithMany()
.HasForeignKey("GroupId");
b.HasOne("Knots.Models.Key", "Key")
.WithMany("Messages")
.HasForeignKey("KeyId");
b.HasOne("Knots.Models.User", "User")
.WithMany("Messages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Discussion");
b.Navigation("Group");
b.Navigation("Key");
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.HasOne("Knots.Models.Role", "Role")
.WithMany("Users")
.HasForeignKey("RoleId");
b.Navigation("Role");
});
modelBuilder.Entity("Knots.Models.UserDiscussion", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany("UserDiscussions")
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.User", "User")
.WithMany("UserDiscussions")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Discussion");
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.Discussion", b =>
{
b.Navigation("Messages");
b.Navigation("UserDiscussions");
});
modelBuilder.Entity("Knots.Models.Group", b =>
{
b.Navigation("GroupUsers");
});
modelBuilder.Entity("Knots.Models.Key", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("Knots.Models.Role", b =>
{
b.Navigation("GroupUsers");
b.Navigation("Users");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.Navigation("Messages");
b.Navigation("UserDiscussions");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,21 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Knots.Migrations
{
/// <inheritdoc />
public partial class FixGroupDiscussion : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "AuthorId",
table: "Messages",
type: "int",
nullable: false,
defaultValue: 0);
}
}
}
+159 -11
View File
@@ -30,11 +30,19 @@ namespace Knots.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("KeyId")
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<int?>("GroupId")
.HasColumnType("int");
b.Property<bool>("IsGroup")
.HasColumnType("bit");
b.HasKey("Id");
b.HasIndex("GroupId");
b.ToTable("Discussions");
});
@@ -46,7 +54,7 @@ namespace Knots.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("KeyId")
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.Property<int>("MembersAmount")
@@ -62,9 +70,31 @@ namespace Knots.Migrations
b.HasKey("Id");
b.HasIndex("DiscussionId");
b.ToTable("Groups");
});
modelBuilder.Entity("Knots.Models.GroupUser", b =>
{
b.Property<int>("GroupId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.HasKey("GroupId", "UserId");
b.HasIndex("RoleId");
b.HasIndex("UserId");
b.ToTable("GroupUsers");
});
modelBuilder.Entity("Knots.Models.Key", b =>
{
b.Property<int>("Id")
@@ -91,6 +121,9 @@ namespace Knots.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("AuthorId")
.HasColumnType("int");
b.Property<string>("Contenu")
.IsRequired()
.HasMaxLength(1000)
@@ -99,13 +132,13 @@ namespace Knots.Migrations
b.Property<DateTime>("Date")
.HasColumnType("datetime2");
b.Property<int?>("DiscussionId")
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.Property<int>("GroupId")
b.Property<int?>("GroupId")
.HasColumnType("int");
b.Property<int>("KeyId")
b.Property<int?>("KeyId")
.HasColumnType("int");
b.Property<bool>("Type")
@@ -169,6 +202,9 @@ namespace Knots.Migrations
b.Property<string>("ProfilePicture")
.HasColumnType("nvarchar(max)");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.Property<string>("Tel")
.IsRequired()
.HasColumnType("nvarchar(max)");
@@ -180,33 +216,96 @@ namespace Knots.Migrations
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users");
});
modelBuilder.Entity("Knots.Models.Message", b =>
modelBuilder.Entity("Knots.Models.UserDiscussion", b =>
{
b.HasOne("Knots.Models.Discussion", null)
.WithMany("Messages")
.HasForeignKey("DiscussionId");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<int>("DiscussionId")
.HasColumnType("int");
b.HasKey("UserId", "DiscussionId");
b.HasIndex("DiscussionId");
b.ToTable("UserDiscussions");
});
modelBuilder.Entity("Knots.Models.Discussion", b =>
{
b.HasOne("Knots.Models.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Group");
});
modelBuilder.Entity("Knots.Models.Group", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany()
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Discussion");
});
modelBuilder.Entity("Knots.Models.GroupUser", b =>
{
b.HasOne("Knots.Models.Group", "Group")
.WithMany("GroupUsers")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.Key", "Key")
b.HasOne("Knots.Models.Role", "Role")
.WithMany("GroupUsers")
.HasForeignKey("RoleId");
b.HasOne("Knots.Models.User", "User")
.WithMany()
.HasForeignKey("KeyId")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Group");
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.Message", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany("Messages")
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.Group", "Group")
.WithMany()
.HasForeignKey("GroupId");
b.HasOne("Knots.Models.Key", "Key")
.WithMany("Messages")
.HasForeignKey("KeyId");
b.HasOne("Knots.Models.User", "User")
.WithMany("Messages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Discussion");
b.Navigation("Group");
b.Navigation("Key");
@@ -214,14 +313,63 @@ namespace Knots.Migrations
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.HasOne("Knots.Models.Role", "Role")
.WithMany("Users")
.HasForeignKey("RoleId");
b.Navigation("Role");
});
modelBuilder.Entity("Knots.Models.UserDiscussion", b =>
{
b.HasOne("Knots.Models.Discussion", "Discussion")
.WithMany("UserDiscussions")
.HasForeignKey("DiscussionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Knots.Models.User", "User")
.WithMany("UserDiscussions")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Discussion");
b.Navigation("User");
});
modelBuilder.Entity("Knots.Models.Discussion", b =>
{
b.Navigation("Messages");
b.Navigation("UserDiscussions");
});
modelBuilder.Entity("Knots.Models.Group", b =>
{
b.Navigation("GroupUsers");
});
modelBuilder.Entity("Knots.Models.Key", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("Knots.Models.Role", b =>
{
b.Navigation("GroupUsers");
b.Navigation("Users");
});
modelBuilder.Entity("Knots.Models.User", b =>
{
b.Navigation("Messages");
b.Navigation("UserDiscussions");
});
#pragma warning restore 612, 618
}
+6 -1
View File
@@ -8,7 +8,12 @@ public class Discussion
public bool IsGroup { get; set; } = false;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public Group? Group { get; set; }
public int? GroupId { get; set; }
public Group? Group { get; set; }
public int? KeyId { get; set; }
public Key? Key { get; set; }
public List<Message> Messages { get; set; } = [];
public List<UserDiscussion> UserDiscussions { get; set; } = [];
}
+4 -7
View File
@@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.Net.Mime;
namespace Knots.Models;
@@ -9,11 +8,9 @@ public class Group
[Required, MaxLength(50)] public string? Name { get; set; }
[Required] public int MembersAmount { get; set; }
public string? ProfilePicture { get; set; }
public int KeyId { get; set; }
List<Message> Messages { get; set; }
List<User> Users { get; set; }
public int DiscussionId { get; set; }
public List<GroupUser> GroupUsers { get; set; } = [];
public int DiscussionId { get; set; }
public Discussion Discussion { get; set; } = null!;
}
+13
View File
@@ -0,0 +1,13 @@
namespace Knots.Models;
public class GroupUser
{
public int GroupId { get; set; }
public Group Group { get; set; } = null!;
public int UserId { get; set; }
public User User { get; set; } = null!;
public int? RoleId { get; set; }
public Role? Role { get; set; }
}
-1
View File
@@ -6,5 +6,4 @@ public class Key
{
[Key] public int Id { get; set; }
[Required, MaxLength(50)] public string? EnKey { get; set; }
public List<Message> Messages { get; set; } = [];
}
+1 -2
View File
@@ -12,9 +12,8 @@ public class Message
public int UserId { get; set; }
public User User { get; set; } = null!;
public int DiscussionId { get; set; } // ← ajouté
public int DiscussionId { get; set; }
public Discussion Discussion { get; set; } = null!;
public Group? Group { get; set; }
public Key? Key { get; set; }
}
+2 -1
View File
@@ -6,5 +6,6 @@ public class Role
{
public int Id { get; set; }
[Required, MaxLength(50)] public string? Libelle { get; set; }
public List<User> Users { get; set; } = [];
public List<User> Users { get; set; } = [];
public List<GroupUser> GroupUsers { get; set; } = [];
}
+1 -1
View File
@@ -12,7 +12,7 @@ public class User
[Required, Length(10, 10)] public string? Tel { get; set; }
public string? ProfilePicture { get; set; }
public List<Message> Messages { get; set; } = [];
public List<UserDiscussion> UserDiscussions { get; set; } = [];
public int? RoleId { get; set; }
public Role? Role { get; set; }
public List<UserDiscussion> UserDiscussions { get; set; } = [];
}
+32 -7
View File
@@ -2,8 +2,10 @@ using System.Text;
using Knots;
using FastEndpoints;
using FastEndpoints.Swagger;
using Knots.Hubs;
using Knots.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi;
@@ -17,13 +19,18 @@ builder.Services.AddCors(options =>
{ options.AddDefaultPolicy(policyBuilder =>
{
policyBuilder
.WithOrigins("http://localhost:5250/")
.WithOrigins("http://localhost:5250", "http://localhost:4200")
.WithMethods("GET", "POST", "PUT", "PATCH", "DELETE")
.AllowAnyHeader();
.AllowAnyHeader()
.AllowCredentials();
});
});
builder.Services.AddFastEndpoints();
builder.Services.AddFastEndpoints(o =>
{
o.DisableAutoDiscovery = false;
});
builder.Services.SwaggerDocument();
builder.Services.AddScoped<JwtService>();
@@ -41,21 +48,39 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
path.StartsWithSegments("/hubs"))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
builder.Services.AddAuthorization();
builder.Services.AddSignalR();
builder.Services.AddAutoMapper(cfg => { }, typeof(Program).Assembly);
builder.Services.AddSingleton<EncryptionService>();
// On construit l'application en lui donnant vie
WebApplication app = builder.Build();
app.UseCors();
app.UseSwaggerGen();
app.UseHttpsRedirection();
app.UseAuthentication()
.UseAuthorization()
@@ -66,6 +91,6 @@ app.UseAuthentication()
}
).UseSwaggerGen();
app.UseHttpsRedirection();
app.MapHub<ChatHub>("hubs/chat");
app.Run();
+56
View File
@@ -0,0 +1,56 @@
using System.Security.Cryptography;
using System.Text;
namespace Knots.Services;
public class EncryptionService
{
private const int NonceSize = 12; // AesGcm.NonceByteSizes.MaxSize
private const int TagSize = 16; // AesGcm.TagByteSizes.MaxSize
// Génère une clé AES-256 (32 octets) encodée en Base64
public string GenerateKey()
=> Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
// Chiffre → renvoie Base64(nonce + tag + ciphertext)
public string Encrypt(string plainText, string base64Key)
{
byte[] key = Convert.FromBase64String(base64Key);
byte[] plain = Encoding.UTF8.GetBytes(plainText);
byte[] nonce = RandomNumberGenerator.GetBytes(NonceSize);
byte[] cipher = new byte[plain.Length];
byte[] tag = new byte[TagSize];
using AesGcm aes = new(key, TagSize);
aes.Encrypt(nonce, plain, cipher, tag);
byte[] result = new byte[NonceSize + TagSize + cipher.Length];
Buffer.BlockCopy(nonce, 0, result, 0, NonceSize);
Buffer.BlockCopy(tag, 0, result, NonceSize, TagSize);
Buffer.BlockCopy(cipher, 0, result, NonceSize + TagSize, cipher.Length);
return Convert.ToBase64String(result);
}
// Déchiffre Base64(nonce + tag + ciphertext)
public string Decrypt(string base64Cipher, string base64Key)
{
byte[] key = Convert.FromBase64String(base64Key);
byte[] data = Convert.FromBase64String(base64Cipher);
byte[] nonce = new byte[NonceSize];
byte[] tag = new byte[TagSize];
byte[] cipher = new byte[data.Length - NonceSize - TagSize];
Buffer.BlockCopy(data, 0, nonce, 0, NonceSize);
Buffer.BlockCopy(data, NonceSize, tag, 0, TagSize);
Buffer.BlockCopy(data, NonceSize + TagSize, cipher, 0, cipher.Length);
byte[] plain = new byte[cipher.Length];
using AesGcm aes = new(key, TagSize);
aes.Decrypt(nonce, cipher, tag, plain);
return Encoding.UTF8.GetString(plain);
}
}
@@ -11,7 +11,7 @@ public class CreateMessageDtoValidator : Validator<CreateMessageDto>
RuleFor(x => x.Contenu)
.NotEmpty()
.WithMessage("Le message ne peux pas être vide")
.MaximumLength(1000)
.MaximumLength(2000)
.WithMessage("Le message ne doit pas faire plus de 1000 caractères");
RuleFor(x => x.Date)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Knots")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+84d0376138f9f289ef91e21fdd18b25c871c1acf")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+61f3d2889c45fcfb95557be37845198db85b3972")]
[assembly: System.Reflection.AssemblyProductAttribute("Knots")]
[assembly: System.Reflection.AssemblyTitleAttribute("Knots")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
3f7b2a3ee7c375b1158b1a88381cf4975972813f9f9a5febadee3fc42d938a09
589797db71c3ee2db1d8c966ae2f187808629461cd5e264f494b12d939f74905
Binary file not shown.
@@ -1 +1 @@
bb48158ec8eb2df7ad212aee65554da457917fda1961b2e4475621e399c96301
8c008e0540a310c319081e4a6b8a7ce2f5c9b271d5260b8b45b33f49b9ad5228
@@ -182,9 +182,6 @@ C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Azure.Core.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Azure.Identity.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Attributes.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Core.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.JobQueues.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Messaging.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Messaging.Core.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Swagger.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\FluentValidation.dll
@@ -202,12 +199,10 @@ C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFramew
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFrameworkCore.Relational.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFrameworkCore.SqlServer.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Caching.Memory.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Configuration.Abstractions.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.DependencyInjection.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.DependencyModel.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Diagnostics.Abstractions.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.FileProviders.Abstractions.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Hosting.Abstractions.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Logging.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Logging.Abstractions.dll
@@ -349,3 +344,179 @@ C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Security.Crypto
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Security.Cryptography.Xml.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net8.0\System.Security.Cryptography.Pkcs.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\BCrypt-Net-Next.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\appsettings.Development.json
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\appsettings.json
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Knots.exe
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Knots.deps.json
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Knots.runtimeconfig.json
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Knots.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Knots.pdb
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\AutoMapper.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Azure.Core.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Azure.Identity.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\BCrypt-Net-Next.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Attributes.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Messaging.Core.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\FastEndpoints.Swagger.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\FluentValidation.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Humanizer.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.AspNetCore.OpenApi.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Bcl.AsyncInterfaces.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.CodeAnalysis.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.CodeAnalysis.CSharp.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.CodeAnalysis.CSharp.Workspaces.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.CodeAnalysis.Workspaces.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Data.SqlClient.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFrameworkCore.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFrameworkCore.Abstractions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFrameworkCore.Design.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFrameworkCore.Relational.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.EntityFrameworkCore.SqlServer.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Caching.Memory.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.DependencyInjection.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.DependencyModel.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Diagnostics.Abstractions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Hosting.Abstractions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Logging.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Logging.Abstractions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.ObjectPool.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Options.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.Primitives.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.WebEncoders.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Identity.Client.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Identity.Client.Extensions.Msal.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.IdentityModel.Abstractions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.IdentityModel.JsonWebTokens.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.IdentityModel.Logging.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.IdentityModel.Protocols.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.IdentityModel.Tokens.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.OpenApi.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.SqlServer.Server.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Win32.SystemEvents.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Mono.TextTemplating.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Namotion.Reflection.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Newtonsoft.Json.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NJsonSchema.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NJsonSchema.Annotations.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NJsonSchema.NewtonsoftJson.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NJsonSchema.Yaml.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NSwag.Annotations.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NSwag.AspNetCore.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NSwag.Core.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NSwag.Core.Yaml.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NSwag.Generation.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\NSwag.Generation.AspNetCore.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Swashbuckle.AspNetCore.Swagger.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Swashbuckle.AspNetCore.SwaggerGen.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\Swashbuckle.AspNetCore.SwaggerUI.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.ClientModel.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.CodeDom.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Composition.AttributedModel.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Composition.Convention.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Composition.Hosting.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Composition.Runtime.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Composition.TypedParts.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Configuration.ConfigurationManager.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Diagnostics.DiagnosticSource.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Drawing.Common.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.IdentityModel.Tokens.Jwt.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Memory.Data.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Runtime.Caching.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Security.Cryptography.Pkcs.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Security.Cryptography.ProtectedData.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Security.Cryptography.Xml.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Security.Permissions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Windows.Extensions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\YamlDotNet.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\cs\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\de\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\es\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\fr\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\it\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ja\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ko\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pl\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pt-BR\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ru\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\tr\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hans\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hant\Microsoft.CodeAnalysis.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\cs\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\de\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\es\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\fr\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\it\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ja\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ko\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pl\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pt-BR\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ru\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\tr\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hans\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hant\Microsoft.CodeAnalysis.CSharp.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\cs\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\de\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\es\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\fr\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\it\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ja\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ko\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pl\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pt-BR\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ru\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\tr\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hans\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hant\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\cs\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\de\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\es\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\fr\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\it\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ja\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ko\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pl\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\pt-BR\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\ru\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\tr\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hans\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\zh-Hant\Microsoft.CodeAnalysis.Workspaces.resources.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\unix\lib\net6.0\Microsoft.Data.SqlClient.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net6.0\Microsoft.Data.SqlClient.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win-arm\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win-arm64\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win-x86\native\Microsoft.Data.SqlClient.SNI.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net6.0\Microsoft.Win32.SystemEvents.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\unix\lib\net6.0\System.Drawing.Common.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net6.0\System.Drawing.Common.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net6.0\System.Runtime.Caching.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net8.0\System.Security.Cryptography.Pkcs.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net6.0\System.Security.Cryptography.ProtectedData.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\runtimes\win\lib\net6.0\System.Windows.Extensions.dll
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.csproj.AssemblyReference.cache
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.GeneratedMSBuildEditorConfig.editorconfig
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.AssemblyInfoInputs.cache
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.AssemblyInfo.cs
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.csproj.CoreCompileInputs.cache
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.MvcApplicationPartsAssemblyInfo.cs
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.MvcApplicationPartsAssemblyInfo.cache
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\staticwebassets.build.json
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\staticwebassets.development.json
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\staticwebassets\msbuild.Knots.Microsoft.AspNetCore.StaticWebAssets.props
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\staticwebassets\msbuild.build.Knots.props
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\staticwebassets\msbuild.buildMultiTargeting.Knots.props
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\staticwebassets\msbuild.buildTransitive.Knots.props
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\staticwebassets.pack.json
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\scopedcss\bundle\Knots.styles.css
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.csproj.Up2Date
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.dll
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\refint\Knots.dll
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.pdb
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\Knots.genruntimeconfig.cache
C:\Users\dogge\RiderProjects\Knots\Knots\obj\Debug\net8.0\ref\Knots.dll
C:\Users\dogge\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Net.WebSockets.WebSocketProtocol.dll
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Net.WebSockets.WebSocketProtocol.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+6 -2
View File
@@ -59,11 +59,11 @@
},
"FastEndpoints": {
"target": "Package",
"version": "[8.0.1, )"
"version": "[5.33.0, )"
},
"FastEndpoints.Swagger": {
"target": "Package",
"version": "[8.0.1, )"
"version": "[5.33.0, )"
},
"Microsoft.AspNetCore.Authentication": {
"target": "Package",
@@ -77,6 +77,10 @@
"target": "Package",
"version": "[8.0.25, )"
},
"Microsoft.AspNetCore.SignalR": {
"target": "Package",
"version": "[1.2.11, )"
},
"Microsoft.EntityFrameworkCore": {
"target": "Package",
"version": "[8.0.25, )"

Some files were not shown because too many files have changed in this diff Show More