Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e1e8a834b2 | |||
| 61f3d2889c | |||
| 66a7e633a9 | |||
| fff484d4ba | |||
| e69550048b | |||
| a29fb27b0d | |||
| c23cc4a03a | |||
| 1d2f96b2f4 | |||
| f1cdc5de19 | |||
| 4e06dc5f23 | |||
| 779acbe531 | |||
| e6021dcc61 | |||
| 4f994ba183 | |||
| 2bb1f730c9 | |||
| c92e134698 | |||
| 0b9e01c925 | |||
| c1bd8a12a9 | |||
| c120d34e62 | |||
| b7dad57cee | |||
| af1b14b0d2 | |||
| 7cfb3909b6 | |||
| ff317cc944 | |||
| 79a926bc2d | |||
| 431e96d9e4 | |||
| eb70f4b3de | |||
| 690d85009e | |||
| cec4437f2f | |||
| 33987f080e | |||
| c5b5ac6b84 | |||
| db72346683 | |||
| 70c4570b48 | |||
| 6b5084238c | |||
| 103010f59e | |||
| 719be662d2 |
Generated
+1
-1
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="@romaric-thibault.fr" uuid="6e1760b6-e554-4516-9799-154d6f998f71">
|
||||
<data-source source="LOCAL" name="@romaric-thibault.fr" uuid="821fc51f-62ea-4fa2-99b3-cb667f09e32a">
|
||||
<driver-ref>sqlserver.jb</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>com.jetbrains.jdbc.sqlserver.SqlServerDriver</jdbc-driver>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; } = "";
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using FastEndpoints;
|
||||
using Knots.DTO.User;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Knots.Endpoints.User;
|
||||
|
||||
@@ -13,9 +14,20 @@ public class CreateUserEndpoint(KnotsDbContext db, AutoMapper.IMapper mapper) :
|
||||
|
||||
public override async Task HandleAsync(CreateUserDto req, CancellationToken ct)
|
||||
{
|
||||
bool usernameExists = await db.Users
|
||||
.AnyAsync(x => x.Username == req.Username, cancellationToken: ct);
|
||||
|
||||
if (usernameExists)
|
||||
{
|
||||
AddError(x => x.Username, "Ce nom d'utilisateur est déjà pris.");
|
||||
await SendErrorsAsync(cancellation: ct);
|
||||
return;
|
||||
}
|
||||
|
||||
req.Password = BCrypt.Net.BCrypt.HashPassword(req.Password);
|
||||
Models.User? user = mapper.Map<Models.User>(req);
|
||||
db.Users.Add(user);
|
||||
await db.SaveChangesAsync(ct);
|
||||
await Send.NoContentAsync(ct);
|
||||
await SendNoContentAsync(ct);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -18,15 +18,15 @@ public class LoginEndpoint(KnotsDbContext db, JwtService jwtService) : Endpoint<
|
||||
Models.User? user = await db.Users
|
||||
.SingleOrDefaultAsync(x => x.Username == req.Username, cancellationToken: ct);
|
||||
|
||||
if (user is null || user.Password != req.Password) // hash à ajouter plus tard
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -8,11 +8,13 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="16.1.1" />
|
||||
<PackageReference Include="FastEndpoints" Version="8.0.1" />
|
||||
<PackageReference Include="FastEndpoints.Swagger" Version="8.0.1" />
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.2.0" />
|
||||
<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
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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; } = [];
|
||||
}
|
||||
@@ -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!;
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; } = [];
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; } = [];
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
@@ -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.
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.
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.
@@ -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+e8d5ac797b67a6c7c6719e831ac1f150893f28ad")]
|
||||
[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 @@
|
||||
f590fd7039e5e02a09290e867dcff1d085dc86bbc598b2bf76d4d65ccda866ca
|
||||
589797db71c3ee2db1d8c966ae2f187808629461cd5e264f494b12d939f74905
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
c63bb86637486085df3f28dc9ab57c639ae176fe7083ba40d0795948620e0a00
|
||||
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
|
||||
@@ -348,3 +343,180 @@ C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\Microsoft.Extensions.W
|
||||
C:\Users\Carte\RiderProjects\Knots\Knots\bin\Debug\net8.0\System.Security.Cryptography.Pkcs.dll
|
||||
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.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user