From 6b9730996134f6943f459b98114a3b68c8922efe Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Sat, 23 Nov 2024 21:37:08 +0300 Subject: [PATCH 1/2] refactoring --- src/Argon.Api/Extensions/SwaggerExtension.cs | 36 ------ .../Grains.Interfaces/IServerGrain.cs | 34 ------ .../ChannelGrainState.cs | 10 -- src/Argon.Api/Grains/AuthorizationGrain.cs | 2 + src/Argon.Api/Grains/ChannelGrain.cs | 41 +++---- src/Argon.Api/Grains/FusionGrain.cs | 64 +++++------ .../Interfaces}/IAuthorizationGrain.cs | 0 .../Interfaces}/IChannelGrain.cs | 15 +-- .../Interfaces}/IEmailManager.cs | 0 .../Interfaces}/IFusionSessionGrain.cs | 3 +- .../Grains/Interfaces/IServerGrain.cs | 40 +++++++ .../Interfaces}/ISessionManager.cs | 5 +- .../Interfaces}/ITestGrain.cs | 0 .../Interfaces}/IUserGrain.cs | 14 +-- src/Argon.Api/Grains/ServerGrain.cs | 107 ++++++++---------- src/Argon.Api/Grains/SessionManager.cs | 3 +- .../Grains/States/ChannelGrainState.cs | 18 +++ src/Argon.Api/Grains/UserGrain.cs | 47 ++++---- src/Argon.Api/Properties/launchSettings.json | 4 +- .../Services/IPasswordHashingService.cs | 2 +- src/Argon.Api/Services/ServerInteraction.cs | 19 ++-- src/Argon.Api/Services/UserInteraction.cs | 19 ++-- src/Argon.Api/appsettings.json | 2 +- 23 files changed, 214 insertions(+), 271 deletions(-) delete mode 100644 src/Argon.Api/Extensions/SwaggerExtension.cs delete mode 100644 src/Argon.Api/Grains.Interfaces/IServerGrain.cs delete mode 100644 src/Argon.Api/Grains.Persistence.States/ChannelGrainState.cs rename src/Argon.Api/{Grains.Interfaces => Grains/Interfaces}/IAuthorizationGrain.cs (100%) rename src/Argon.Api/{Grains.Interfaces => Grains/Interfaces}/IChannelGrain.cs (51%) rename src/Argon.Api/{Grains.Interfaces => Grains/Interfaces}/IEmailManager.cs (100%) rename src/Argon.Api/{Grains.Interfaces => Grains/Interfaces}/IFusionSessionGrain.cs (83%) create mode 100644 src/Argon.Api/Grains/Interfaces/IServerGrain.cs rename src/Argon.Api/{Grains.Interfaces => Grains/Interfaces}/ISessionManager.cs (84%) rename src/Argon.Api/{Grains.Interfaces => Grains/Interfaces}/ITestGrain.cs (100%) rename src/Argon.Api/{Grains.Interfaces => Grains/Interfaces}/IUserGrain.cs (56%) create mode 100644 src/Argon.Api/Grains/States/ChannelGrainState.cs diff --git a/src/Argon.Api/Extensions/SwaggerExtension.cs b/src/Argon.Api/Extensions/SwaggerExtension.cs deleted file mode 100644 index 4792199..0000000 --- a/src/Argon.Api/Extensions/SwaggerExtension.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Argon.Api.Extensions; - -using Microsoft.OpenApi.Models; - -public static class SwaggerExtension -{ - public static WebApplicationBuilder AddSwaggerWithAuthHeader(this WebApplicationBuilder builder) - { - builder.Services.AddSwaggerGen(c => - { - c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - { - In = ParameterLocation.Header, - Description = "Please insert JWT with Bearer into field", - Name = "Authorization", - Type = SecuritySchemeType.ApiKey - }); - c.AddSecurityRequirement(new OpenApiSecurityRequirement - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "Bearer" - } - }, - [] - } - }); - }).AddEndpointsApiExplorer(); - - return builder; - } -} \ No newline at end of file diff --git a/src/Argon.Api/Grains.Interfaces/IServerGrain.cs b/src/Argon.Api/Grains.Interfaces/IServerGrain.cs deleted file mode 100644 index a82dff4..0000000 --- a/src/Argon.Api/Grains.Interfaces/IServerGrain.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Argon.Api.Grains.Interfaces; - -using Entities; - -[Alias("Argon.Api.Grains.Interfaces.IServerGrain")] -public interface IServerGrain : IGrainWithGuidKey -{ - [Alias("CreateServer")] - Task CreateServer(ServerInput input, Guid creatorId); - - [Alias("GetServer")] - Task GetServer(); - - [Alias("UpdateServer")] - Task UpdateServer(ServerInput input); - - [Alias("DeleteServer")] - Task DeleteServer(); - - [Alias("CreateChannel")] - Task CreateChannel(ChannelInput input); - - public const string ProviderId = "argon.server.grain.stream"; - public const string EventNamespace = "@"; -} - -[DataContract, MemoryPackable(GenerateType.VersionTolerant), MessagePackObject, Serializable, GenerateSerializer, Alias(nameof(ServerInput))] -public sealed partial record ServerInput( - [property: DataMember(Order = 0), MemoryPackOrder(0), Key(0), Id(0)] - string? Name, - [property: DataMember(Order = 1), MemoryPackOrder(1), Key(1), Id(1)] - string? Description, - [property: DataMember(Order = 2), MemoryPackOrder(2), Key(2), Id(2)] - string? AvatarUrl); \ No newline at end of file diff --git a/src/Argon.Api/Grains.Persistence.States/ChannelGrainState.cs b/src/Argon.Api/Grains.Persistence.States/ChannelGrainState.cs deleted file mode 100644 index e996e73..0000000 --- a/src/Argon.Api/Grains.Persistence.States/ChannelGrainState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Argon.Api.Grains.Persistence.States; - -using Entities; - -[DataContract, MemoryPackable(GenerateType.VersionTolerant), MessagePackObject, Serializable, GenerateSerializer] -public sealed partial record ChannelGrainState -{ - [DataMember(Order = 0), MemoryPackOrder(0), Id(0)] - public Dictionary Users { get; set; } = new(); -} \ No newline at end of file diff --git a/src/Argon.Api/Grains/AuthorizationGrain.cs b/src/Argon.Api/Grains/AuthorizationGrain.cs index d9f8cf3..e964bea 100644 --- a/src/Argon.Api/Grains/AuthorizationGrain.cs +++ b/src/Argon.Api/Grains/AuthorizationGrain.cs @@ -1,6 +1,7 @@ namespace Argon.Api.Grains; using Contracts; +using Contracts.Models; using Entities; using Features.Otp; using Interfaces; @@ -96,6 +97,7 @@ await strategy.ExecuteAsync(async () => Username = input.Username, PasswordDigest = passwordHashingService.HashPassword(input.Password), PhoneNumber = input.PhoneNumber, + DisplayName = input.DisplayName, }; await context.Users.AddAsync(user); diff --git a/src/Argon.Api/Grains/ChannelGrain.cs b/src/Argon.Api/Grains/ChannelGrain.cs index 1240421..f64c6bc 100644 --- a/src/Argon.Api/Grains/ChannelGrain.cs +++ b/src/Argon.Api/Grains/ChannelGrain.cs @@ -1,26 +1,24 @@ namespace Argon.Api.Grains; -using AutoMapper; using Contracts; +using Contracts.Models; using Entities; +using Features.Rpc; using Interfaces; using Microsoft.EntityFrameworkCore; -using Orleans.Streams; using Persistence.States; using Sfu; -using static ChannelUserChangedStateEvent; public class ChannelGrain( IArgonSelectiveForwardingUnit sfu, ApplicationDbContext context, [PersistentState("channelGrainState", "OrleansStorage")] - IPersistentState state, - IMapper mapper) : Grain, IChannelGrain + IPersistentState state) : Grain, IChannelGrain { - private IAsyncStream _userStateEmitter = null!; + private IArgonStream _userStateEmitter = null!; - private ChannelDto _self { get; set; } + private Channel _self { get; set; } private ArgonServerId ServerId => new(_self.ServerId); private ArgonChannelId ChannelId => new(ServerId, this.GetPrimaryKey()); @@ -28,11 +26,7 @@ public async override Task OnActivateAsync(CancellationToken cancellationToken) { _self = await GetChannel(); - var streamProvider = this.GetStreamProvider("default"); - - var streamId = StreamId.Create(_self.ServerId.ToString("N"), this.GetPrimaryKey()); - - _userStateEmitter = streamProvider.GetStream(streamId); + _userStateEmitter = await this.Streams().CreateServerStream(); } @@ -42,15 +36,11 @@ public async Task> Join(Guid userId) if (_self.ChannelType != ChannelType.Voice) return Maybe.None(); - var user = (await context.Servers.Include(x => x.UsersToServerRelations) - .FirstAsync(x => x.Id == _self.ServerId)).UsersToServerRelations - .First(x => x.UserId == userId); - - state.State.Users.Add(userId, mapper.Map(user)); + state.State.Users.Add(userId, new ChannelRealtimeMember(userId)); await state.WriteStateAsync(); - await _userStateEmitter.OnNextAsync( - new OnChannelUserChangedState(userId, ON_JOINED)); + //await _userStateEmitter.Fire( + // new OnChannelUserChangedState(userId, ON_JOINED)); return await sfu.IssueAuthorizationTokenAsync(userId, ChannelId, SfuPermission.DefaultUser); } @@ -58,28 +48,27 @@ await _userStateEmitter.OnNextAsync( public async Task Leave(Guid userId) { state.State.Users.Remove(userId); - await _userStateEmitter.OnNextAsync(new(userId, ON_LEAVED)); + //await _userStateEmitter.OnNextAsync(new(userId, ON_LEAVED)); await sfu.KickParticipantAsync(userId, ChannelId); await state.WriteStateAsync(); } - public async Task GetChannel() + public async Task GetChannel() { - var channel = mapper.Map(await Get()); - channel.ConnectedUsers = state.State.Users; + var channel = await Get(); + //channel.ConnectedUsers = state.State.Users; return channel; } - public async Task UpdateChannel(ChannelInput input) + public async Task UpdateChannel(ChannelInput input) { var channel = await Get(); channel.Name = input.Name; - channel.AccessLevel = input.AccessLevel; channel.Description = input.Description ?? channel.Description; channel.ChannelType = input.ChannelType; context.Channels.Update(channel); await context.SaveChangesAsync(); - return mapper.Map(await Get()); + return (await Get()); } private async Task Get() => await context.Channels.FirstAsync(c => c.Id == this.GetPrimaryKey()); diff --git a/src/Argon.Api/Grains/FusionGrain.cs b/src/Argon.Api/Grains/FusionGrain.cs index 153d9a6..8afaa2d 100644 --- a/src/Argon.Api/Grains/FusionGrain.cs +++ b/src/Argon.Api/Grains/FusionGrain.cs @@ -1,57 +1,55 @@ namespace Argon.Api.Grains; +using Contracts; using Extensions; using Features.Jwt; using Interfaces; -using Orleans.Streams; using R3; -using Services; using static DeactivationReasonCode; -using static FusionGrainEventKind; public class FusionGrain(IGrainFactory grainFactory) : Grain, IFusionSessionGrain { - private IAsyncStream _stream = null!; private DateTimeOffset _latestSignalTime = DateTimeOffset.UtcNow; private DisposableBag disposableBag; private Guid _userId; - private Guid _macineId; + private Guid _machineId; public async ValueTask SelfDestroy() - => GrainContext.Deactivate(new(ApplicationRequested, "omae wa mou shindeiru")); - - - public override Task OnActivateAsync(CancellationToken cancellationToken) { - var streamProvider = this.GetStreamProvider("default"); - - var streamId = StreamId.Create(IFusionSessionGrain.SelfNs, this.GetPrimaryKey()); - - _stream = streamProvider.GetStream( - streamId); - - return base.OnActivateAsync(cancellationToken); + var servers = await grainFactory + .GetGrain(_userId) + .GetMyServersIds(); + foreach (var server in servers) + await grainFactory + .GetGrain(server) + .SetUserStatus(_userId, UserStatus.Offline); + _userId = default; + _machineId = default; + GrainContext.Deactivate(new(ApplicationRequested, "omae wa mou shindeiru")); } private Task OnValidateActiveAsync(CancellationToken arg) => _latestSignalTime.WhenAsync(x => DateTimeOffset.UtcNow - x > TimeSpan.FromMinutes(1), SelfDestroy); public async override Task OnDeactivateAsync(DeactivationReason reason, CancellationToken cancellationToken) - { - disposableBag.Dispose(); - //if (reason.ReasonCode == Migrating) // TODO stream is readonly - // await _stream.OnNextAsync(CONNECTION_REQUIRED_MIGRATE); - //else - // await _stream.OnNextAsync(CONNECTION_DESTROYED); - } + => disposableBag.Dispose(); - public async ValueTask BeginRealtimeSession(Guid userId, Guid machineKey) + public async ValueTask BeginRealtimeSession(Guid userId, Guid machineKey, UserStatus? preferredStatus = null) { - this.RegisterGrainTimer(OnValidateActiveAsync, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)) + this.RegisterGrainTimer(OnValidateActiveAsync, TimeSpan.FromMinutes(2), TimeSpan.FromMinutes(2)) .AddTo(ref disposableBag); this._userId = userId; - this._macineId = machineKey; - await grainFactory.GetGrain(userId).IndicateLastActive(machineKey); + this._machineId = machineKey; + await grainFactory + .GetGrain(userId) + .IndicateLastActive(machineKey); + var servers = await grainFactory + .GetGrain(userId) + .GetMyServersIds(); + foreach (var server in servers) + await grainFactory + .GetGrain(server) + .SetUserStatus(userId, preferredStatus ?? UserStatus.Online); } public ValueTask EndRealtimeSession() @@ -67,13 +65,5 @@ public ValueTask Signal() } public ValueTask GetTokenUserData() - => new(new TokenUserData(_userId, _macineId)); -} - - -public enum FusionGrainEventKind -{ - CONNECTION_ESTABLISHED, - CONNECTION_REQUIRED_MIGRATE, - CONNECTION_DESTROYED + => new(new TokenUserData(_userId, _machineId)); } \ No newline at end of file diff --git a/src/Argon.Api/Grains.Interfaces/IAuthorizationGrain.cs b/src/Argon.Api/Grains/Interfaces/IAuthorizationGrain.cs similarity index 100% rename from src/Argon.Api/Grains.Interfaces/IAuthorizationGrain.cs rename to src/Argon.Api/Grains/Interfaces/IAuthorizationGrain.cs diff --git a/src/Argon.Api/Grains.Interfaces/IChannelGrain.cs b/src/Argon.Api/Grains/Interfaces/IChannelGrain.cs similarity index 51% rename from src/Argon.Api/Grains.Interfaces/IChannelGrain.cs rename to src/Argon.Api/Grains/Interfaces/IChannelGrain.cs index 707a912..26e5c6b 100644 --- a/src/Argon.Api/Grains.Interfaces/IChannelGrain.cs +++ b/src/Argon.Api/Grains/Interfaces/IChannelGrain.cs @@ -1,6 +1,7 @@ namespace Argon.Api.Grains.Interfaces; using Contracts; +using Contracts.Models; using Entities; using Sfu; @@ -13,10 +14,10 @@ public interface IChannelGrain : IGrainWithGuidKey Task Leave(Guid userId); [Alias("GetChannel")] - Task GetChannel(); + Task GetChannel(); [Alias("UpdateChannel")] - Task UpdateChannel(ChannelInput input); + Task UpdateChannel(ChannelInput input); // for join\leave\mute\unmute notifications @@ -24,13 +25,9 @@ public interface IChannelGrain : IGrainWithGuidKey public const string ChannelMessageNotificationStream = $"{nameof(IChannelGrain)}.user.messages"; } -[DataContract, MemoryPackable(GenerateType.VersionTolerant), MessagePackObject, Serializable, GenerateSerializer, Alias(nameof(ChannelInput))] -public sealed partial record ChannelInput( - [property: DataMember(Order = 0), MemoryPackOrder(0), Key(0), Id(0)] +[MessagePackObject(true)] +public sealed record ChannelInput( string Name, - [property: DataMember(Order = 1), MemoryPackOrder(1), Key(1), Id(1)] - ServerRole AccessLevel, - [property: DataMember(Order = 2), MemoryPackOrder(2), Key(2), Id(2)] + ChannelEntitlementOverwrite AccessLevel, string? Description, - [property: DataMember(Order = 3), MemoryPackOrder(3), Key(3), Id(3)] ChannelType ChannelType); \ No newline at end of file diff --git a/src/Argon.Api/Grains.Interfaces/IEmailManager.cs b/src/Argon.Api/Grains/Interfaces/IEmailManager.cs similarity index 100% rename from src/Argon.Api/Grains.Interfaces/IEmailManager.cs rename to src/Argon.Api/Grains/Interfaces/IEmailManager.cs diff --git a/src/Argon.Api/Grains.Interfaces/IFusionSessionGrain.cs b/src/Argon.Api/Grains/Interfaces/IFusionSessionGrain.cs similarity index 83% rename from src/Argon.Api/Grains.Interfaces/IFusionSessionGrain.cs rename to src/Argon.Api/Grains/Interfaces/IFusionSessionGrain.cs index 4ba5911..a17a138 100644 --- a/src/Argon.Api/Grains.Interfaces/IFusionSessionGrain.cs +++ b/src/Argon.Api/Grains/Interfaces/IFusionSessionGrain.cs @@ -1,12 +1,13 @@ namespace Argon.Api.Grains.Interfaces; +using Argon.Contracts; using Features.Jwt; [Alias("Argon.Api.Grains.Interfaces.IFusionSessionGrain")] public interface IFusionSessionGrain : IGrainWithGuidKey { [Alias("BeginRealtimeSession")] - ValueTask BeginRealtimeSession(Guid userId, Guid machineKey); + ValueTask BeginRealtimeSession(Guid userId, Guid machineKey, UserStatus? preferredStatus = null); [Alias("EndRealtimeSession")] ValueTask EndRealtimeSession(); diff --git a/src/Argon.Api/Grains/Interfaces/IServerGrain.cs b/src/Argon.Api/Grains/Interfaces/IServerGrain.cs new file mode 100644 index 0000000..9aa0a5d --- /dev/null +++ b/src/Argon.Api/Grains/Interfaces/IServerGrain.cs @@ -0,0 +1,40 @@ +namespace Argon.Api.Grains.Interfaces; + +using Contracts; +using Contracts.Models; + +[Alias("Argon.Api.Grains.Interfaces.IServerGrain")] +public interface IServerGrain : IGrainWithGuidKey +{ + [Alias("CreateServer")] + Task> CreateServer(ServerInput input, Guid creatorId); + + [Alias("GetServer")] + Task GetServer(); + + [Alias("UpdateServer")] + Task UpdateServer(ServerInput input); + + [Alias("DeleteServer")] + Task DeleteServer(); + + [Alias("CreateChannel")] + Task CreateChannel(ChannelInput input, Guid initiator); + + [Alias("SetUserStatus")] + ValueTask SetUserStatus(Guid userId, UserStatus status); + + public const string ProviderId = "argon.server.grain.stream"; + public const string EventNamespace = "@"; +} + +public enum ServerCreationError +{ + BAD_MODEL +} + +[MessagePackObject(true)] +public sealed partial record ServerInput( + string? Name, + string? Description, + string? AvatarUrl); \ No newline at end of file diff --git a/src/Argon.Api/Grains.Interfaces/ISessionManager.cs b/src/Argon.Api/Grains/Interfaces/ISessionManager.cs similarity index 84% rename from src/Argon.Api/Grains.Interfaces/ISessionManager.cs rename to src/Argon.Api/Grains/Interfaces/ISessionManager.cs index 46148f6..c4ab7ed 100644 --- a/src/Argon.Api/Grains.Interfaces/ISessionManager.cs +++ b/src/Argon.Api/Grains/Interfaces/ISessionManager.cs @@ -1,13 +1,12 @@ namespace Argon.Api.Grains.Interfaces; -using Entities; - +using Contracts.Models; [Alias("Argon.Api.Grains.Interfaces.ISessionManager")] public interface ISessionManager : IGrainWithGuidKey { [Alias("GetUser")] - Task GetUser(); + Task GetUser(); [Alias("Logout")] Task Logout(); // TODO: revoke jwt by adding it into a blacklist diff --git a/src/Argon.Api/Grains.Interfaces/ITestGrain.cs b/src/Argon.Api/Grains/Interfaces/ITestGrain.cs similarity index 100% rename from src/Argon.Api/Grains.Interfaces/ITestGrain.cs rename to src/Argon.Api/Grains/Interfaces/ITestGrain.cs diff --git a/src/Argon.Api/Grains.Interfaces/IUserGrain.cs b/src/Argon.Api/Grains/Interfaces/IUserGrain.cs similarity index 56% rename from src/Argon.Api/Grains.Interfaces/IUserGrain.cs rename to src/Argon.Api/Grains/Interfaces/IUserGrain.cs index 3177301..d84d7fe 100644 --- a/src/Argon.Api/Grains.Interfaces/IUserGrain.cs +++ b/src/Argon.Api/Grains/Interfaces/IUserGrain.cs @@ -1,24 +1,24 @@ namespace Argon.Api.Grains.Interfaces; using Contracts; -using Entities; +using Contracts.Models; [Alias("Argon.Api.Grains.Interfaces.IUserGrain")] public interface IUserGrain : IGrainWithGuidKey { - [Alias("CreateUser")] - Task CreateUser(UserCredentialsInput input); - [Alias("UpdateUser")] - Task UpdateUser(UserEditInput input); + Task UpdateUser(UserEditInput input); [Alias("DeleteUser")] Task DeleteUser(); [Alias("GetUser")] - Task GetUser(); + Task GetUser(); [Alias("GetMyServers")] - Task> GetMyServers(); + Task> GetMyServers(); + + [Alias("GetMyServersIds")] + Task> GetMyServersIds(); } diff --git a/src/Argon.Api/Grains/ServerGrain.cs b/src/Argon.Api/Grains/ServerGrain.cs index 2f5616f..f12bfb2 100644 --- a/src/Argon.Api/Grains/ServerGrain.cs +++ b/src/Argon.Api/Grains/ServerGrain.cs @@ -6,9 +6,17 @@ namespace Argon.Api.Grains; using Interfaces; using Microsoft.EntityFrameworkCore; using Argon.Api.Features.Rpc; -using AutoMapper; +using Contracts.Models; +using Persistence.States; +using Argon.Api.Features.Repositories; +using Argon.Features; -public class ServerGrain(IGrainFactory grainFactory, ApplicationDbContext context, IMapper mapper) : Grain, IServerGrain +public class ServerGrain( + IGrainFactory grainFactory, + ApplicationDbContext context, + [PersistentState(nameof(RealtimeServerGrainState), IFusionSessionGrain.StorageId)] + IPersistentState realtimeState, + IServerRepository serverRepository) : Grain, IServerGrain { private IArgonStream _serverEvents; @@ -16,48 +24,42 @@ public async override Task OnActivateAsync(CancellationToken cancellationToken) => _serverEvents = await this.Streams().CreateServerStream(); - public async Task CreateServer(ServerInput input, Guid creatorId) + public async Task> CreateServer(ServerInput input, Guid creatorId) { - var server = new Server - { - Id = this.GetPrimaryKey(), - Name = input.Name, - Description = input.Description, - AvatarUrl = input.AvatarUrl, - UsersToServerRelations = - [ - new() - { - UserId = creatorId, - Role = ServerRole.Owner, - Joined = DateTime.UtcNow, - ServerId = this.GetPrimaryKey() - } - ], - Channels = CreateDefaultChannels(creatorId) - }; + if (string.IsNullOrEmpty(input.Name)) + return ServerCreationError.BAD_MODEL; - context.Servers.Add(server); - await context.SaveChangesAsync(); + await serverRepository.CreateAsync(this.GetPrimaryKey(), input, creatorId); + await UserJoined(creatorId); return await GetServer(); } - public async Task GetServer() => mapper.Map(await Get()); + public Task GetServer() => GetAsync(); - public async Task UpdateServer(ServerInput input) + public async Task UpdateServer(ServerInput input) { - var server = await Get(); - server.Name = input.Name ?? server.Name; - server.Description = input.Description ?? server.Description; - server.AvatarUrl = input.AvatarUrl ?? server.AvatarUrl; + var server = await GetAsync(); + + var copy = server with { }; + server.Name = input.Name ?? server.Name; + server.Description = input.Description ?? server.Description; + server.AvatarFileId = input.AvatarUrl ?? server.AvatarFileId; context.Servers.Update(server); await context.SaveChangesAsync(); - await _serverEvents.Fire(new ServerModified(PropertyBag.Empty - .Set("name", input.Name) - .Set("description", input.Description) - .Set("avatarUrl", input.AvatarUrl) - )); - return mapper.Map(await Get()); + await _serverEvents.Fire(new ServerModified(ObjDiff.Compare(copy, server))); + return await GetAsync(); + } + + public async ValueTask UserJoined(Guid userId) + { + await _serverEvents.Fire(new JoinToServerUser(userId)); + await SetUserStatus(userId, UserStatus.Offline); + } + + public async ValueTask SetUserStatus(Guid userId, UserStatus status) + { + realtimeState.State.UserStatuses[userId] = status; + await _serverEvents.Fire(new UserChangedStatus(userId, status, PropertyBag.Empty)); } public async Task DeleteServer() @@ -67,38 +69,25 @@ public async Task DeleteServer() await context.SaveChangesAsync(); } - public async Task CreateChannel(ChannelInput input) + public async Task CreateChannel(ChannelInput input, Guid initiator) { var channel = new Channel { Name = input.Name, - AccessLevel = input.AccessLevel, + CreatorId = initiator, + Description = input.Description, + ChannelType = input.ChannelType, ServerId = this.GetPrimaryKey() }; - channel.Description = input.Description ?? channel.Description; - channel.ChannelType = input.ChannelType; await context.Channels.AddAsync(channel); await context.SaveChangesAsync(); - await _serverEvents.Fire(new ChannelCreated(channel.Id)); - return mapper.Map(channel); + await _serverEvents.Fire(new ChannelCreated(channel)); + return channel; } - private List CreateDefaultChannels(Guid CreatorId) => - [ - CreateChannel(CreatorId, "General", "General text channel", ChannelType.Text), - CreateChannel(CreatorId, "General", "General voice channel", ChannelType.Voice), - CreateChannel(CreatorId, "General", "General anouncements channel", ChannelType.Announcement) - ]; - - private Channel CreateChannel(Guid CreatorId, string name, string description, ChannelType channelType) => new() - { - Name = name, - Description = description, - UserId = CreatorId, - ChannelType = channelType, - AccessLevel = ServerRole.User - }; - - private async Task Get() => await context.Servers.Include(x => x.Channels).Include(x => x.UsersToServerRelations) - .FirstAsync(s => s.Id == this.GetPrimaryKey()); + private async Task GetAsync() => + await context.Servers + .Include(x => x.Channels) + .Include(x => x.Users) + .FirstAsync(s => s.Id == this.GetPrimaryKey()); } \ No newline at end of file diff --git a/src/Argon.Api/Grains/SessionManager.cs b/src/Argon.Api/Grains/SessionManager.cs index e481eac..740ce1a 100644 --- a/src/Argon.Api/Grains/SessionManager.cs +++ b/src/Argon.Api/Grains/SessionManager.cs @@ -1,5 +1,6 @@ namespace Argon.Api.Grains; +using Contracts.Models; using Entities; using Interfaces; using Microsoft.Extensions.Logging; @@ -13,7 +14,7 @@ public class SessionManager( IPasswordHashingService passwordHashingService, ApplicationDbContext context) : Grain, ISessionManager { - public async Task GetUser() => await grainFactory.GetGrain(this.GetPrimaryKey()).GetUser(); + public async Task GetUser() => await grainFactory.GetGrain(this.GetPrimaryKey()).GetUser(); public Task Logout() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/src/Argon.Api/Grains/States/ChannelGrainState.cs b/src/Argon.Api/Grains/States/ChannelGrainState.cs new file mode 100644 index 0000000..90652e3 --- /dev/null +++ b/src/Argon.Api/Grains/States/ChannelGrainState.cs @@ -0,0 +1,18 @@ +namespace Argon.Api.Grains.Persistence.States; + +using Contracts; +using Entities; + +[DataContract, MemoryPackable(GenerateType.VersionTolerant), MessagePackObject, Serializable, GenerateSerializer] +public sealed partial record ChannelGrainState +{ + [DataMember(Order = 0), MemoryPackOrder(0), Id(0)] + public Dictionary Users { get; set; } = new(); +} + +[DataContract, MemoryPackable(GenerateType.VersionTolerant), MessagePackObject, Serializable, GenerateSerializer] +public sealed partial record RealtimeServerGrainState +{ + [DataMember(Order = 0), MemoryPackOrder(0), Id(0)] + public Dictionary UserStatuses { get; set; } = new(); +} \ No newline at end of file diff --git a/src/Argon.Api/Grains/UserGrain.cs b/src/Argon.Api/Grains/UserGrain.cs index 3f1377a..7e48f34 100644 --- a/src/Argon.Api/Grains/UserGrain.cs +++ b/src/Argon.Api/Grains/UserGrain.cs @@ -1,29 +1,15 @@ namespace Argon.Api.Grains; -using AutoMapper; using Contracts; +using Contracts.Models; using Entities; using Interfaces; using Microsoft.EntityFrameworkCore; using Services; -public class UserGrain(IPasswordHashingService passwordHashingService, ApplicationDbContext context, IMapper mapper) : Grain, IUserGrain +public class UserGrain(IPasswordHashingService passwordHashingService, ApplicationDbContext context) : Grain, IUserGrain { - public async Task CreateUser(UserCredentialsInput input) - { - var user = new User - { - Email = input.Email, - Username = input.Username, - PhoneNumber = input.PhoneNumber, - PasswordDigest = passwordHashingService.HashPassword(input.Password) - }; - context.Users.Add(user); - await context.SaveChangesAsync(); - return mapper.Map(user); - } - - public async Task UpdateUser(UserEditInput input) + public async Task UpdateUser(UserEditInput input) { var user = await Get(); user.Username = input.Username ?? user.Username; @@ -31,7 +17,7 @@ public async Task UpdateUser(UserEditInput input) user.AvatarFileId = input.AvatarId ?? user.AvatarFileId; context.Users.Update(user); await context.SaveChangesAsync(); - return mapper.Map(user); + return user; } public Task DeleteUser() @@ -42,20 +28,31 @@ public Task DeleteUser() return context.SaveChangesAsync(); } - public async Task GetUser() => mapper.Map(await Get()); + public async Task GetUser() + { + var user = await Get(); + return user; + } - public async Task> GetMyServers() + public async Task> GetMyServers() { var user = await context.Users - .Include(user => user.UsersToServerRelations).ThenInclude(usersToServerRelation => usersToServerRelation.Server) + .Include(user => user.ServerMembers).ThenInclude(usersToServerRelation => usersToServerRelation.Server) .FirstAsync(u => u.Id == this.GetPrimaryKey()); - return user.UsersToServerRelations + var r = user.ServerMembers .Select(x => x.Server) - .ToList() - .Select(mapper.Map) .ToList(); + return r; + } + + public async Task> GetMyServersIds() + { + var user = await context.Users + .Include(user => user.ServerMembers) + .FirstAsync(u => u.Id == this.GetPrimaryKey()); + return user.ServerMembers.Select(x => x.ServerId).ToList(); } - private async Task Get() => await context.Users.Include(x => x.UsersToServerRelations).ThenInclude(x => x.Server) + private async Task Get() => await context.Users.Include(x => x.ServerMembers).ThenInclude(x => x.Server) .ThenInclude(x => x.Channels).FirstAsync(user => user.Id == this.GetPrimaryKey()); } \ No newline at end of file diff --git a/src/Argon.Api/Properties/launchSettings.json b/src/Argon.Api/Properties/launchSettings.json index 306c432..b55cb6b 100644 --- a/src/Argon.Api/Properties/launchSettings.json +++ b/src/Argon.Api/Properties/launchSettings.json @@ -1,4 +1,4 @@ -{ +{ "$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, @@ -14,7 +14,7 @@ "dotnetRunMessages": true, "launchBrowser": false, "launchUrl": "swagger", - "applicationUrl": "https://localhost:5100", + "applicationUrl": "http://localhost:5100", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Argon.Api/Services/IPasswordHashingService.cs b/src/Argon.Api/Services/IPasswordHashingService.cs index 7ca6ee0..1b9ac1d 100644 --- a/src/Argon.Api/Services/IPasswordHashingService.cs +++ b/src/Argon.Api/Services/IPasswordHashingService.cs @@ -1,6 +1,6 @@ namespace Argon.Api.Services; -using Entities; +using Contracts.Models; using Features.Otp; public interface IPasswordHashingService diff --git a/src/Argon.Api/Services/ServerInteraction.cs b/src/Argon.Api/Services/ServerInteraction.cs index 34978ae..1925772 100644 --- a/src/Argon.Api/Services/ServerInteraction.cs +++ b/src/Argon.Api/Services/ServerInteraction.cs @@ -1,28 +1,29 @@ namespace Argon.Api.Services; -using AutoMapper; using Grains.Interfaces; using Contracts; +using Contracts.Models; using Entities; -public class ServerInteraction(IGrainFactory grainFactory, IFusionContext fusionContext, IMapper mapper) : IServerInteraction +public class ServerInteraction(IGrainFactory grainFactory, IFusionContext fusionContext) : IServerInteraction { - public async ValueTask CreateChannel(Guid serverId, string name, ChannelType kind) + public async Task CreateChannel(CreateChannelRequest request) { + var user = await fusionContext.GetUserDataAsync(); var result = await grainFactory - .GetGrain(serverId) - .CreateChannel(new ChannelInput(name, ServerRole.User, "", kind)); - return result.Id; + .GetGrain(request.serverId) + .CreateChannel(new ChannelInput(request.name, new ChannelEntitlementOverwrite(), request.desc, request.kind), user.id); + return new CreateChannelResponse(request.serverId, result.Id); } - public ValueTask DeleteChannel(Guid serverId, Guid channelId) + public Task DeleteChannel(DeleteChannelRequest request) => throw new NotImplementedException(); - public async ValueTask JoinToVoiceChannel(Guid serverId, Guid channelId) + public async Task JoinToVoiceChannel(JoinToVoiceChannelRequest request) { var user = await fusionContext.GetUserDataAsync(); var result = await grainFactory - .GetGrain(channelId) + .GetGrain(request.channelId) .Join(user.id); return new ChannelJoinResponse(result.Value.value); } diff --git a/src/Argon.Api/Services/UserInteraction.cs b/src/Argon.Api/Services/UserInteraction.cs index 22f4f2a..0784d1d 100644 --- a/src/Argon.Api/Services/UserInteraction.cs +++ b/src/Argon.Api/Services/UserInteraction.cs @@ -1,35 +1,34 @@ namespace Argon.Api.Services; using ActualLab.Rpc.Infrastructure; -using AutoMapper; using Grains.Interfaces; using Contracts; +using Contracts.Models; using Features.Jwt; -public class UserInteraction(IGrainFactory grainFactory, IFusionContext fusionContext, IMapper mapper) : IUserInteraction +public class UserInteraction(IGrainFactory grainFactory, IFusionContext fusionContext) : IUserInteraction { - public async Task GetMe() + public async Task GetMe() { var userData = await fusionContext.GetUserDataAsync(); - var user = await grainFactory.GetGrain(userData.id).GetUser(); - return mapper.Map(user); + return await grainFactory.GetGrain(userData.id).GetUser(); } - public async Task CreateServer(CreateServerRequest request) + public async Task CreateServer(CreateServerRequest request) { var userData = await fusionContext.GetUserDataAsync(); var serverId = Guid.NewGuid(); var server = await grainFactory .GetGrain(serverId) - .CreateServer(new ServerInput(request.Name, request.Description, request.AvatarUrl), userData.id); - return mapper.Map(server); + .CreateServer(new ServerInput(request.Name, request.Description, request.AvatarFileId), userData.id); + return server.Value; } - public async Task> GetServers() + public async Task> GetServers() { var userData = await fusionContext.GetUserDataAsync(); var servers = await grainFactory.GetGrain(userData.id).GetMyServers(); - return servers.Select(mapper.Map).ToList(); + return servers.ToList(); } } diff --git a/src/Argon.Api/appsettings.json b/src/Argon.Api/appsettings.json index 1e57e2e..adead91 100644 --- a/src/Argon.Api/appsettings.json +++ b/src/Argon.Api/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=argon_api", + "DefaultConnection": "Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=apiDb;Include Error Detail=true", "cache": "localhost:6379", "rmq": "amqp://svck:Password123@localhost:5672", "nats": "nats://localhost:4222", From dddd47b131ce7519e4da6636d5989c57648c3785 Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Sat, 23 Nov 2024 21:37:30 +0300 Subject: [PATCH 2/2] bump --- .../Features/Captcha/CloudflareCaptcha.cs | 1 + src/Argon.Api/Features/EF/ColourConverter.cs | 13 + .../Repositories/IServerRepository.cs | 106 ++++ .../Utils}/ActorExtensions.cs | 0 .../Features/Utils/AsyncContainer.cs | 15 + .../Utils}/HttpContextExtensions.cs | 2 +- src/Argon.Api/Features/Utils/ObjDiff.cs | 54 ++ .../Features/Utils/SwaggerExtension.cs | 57 ++ ...20185058_AddOrleansPersistence.Designer.cs | 29 - .../20241020185058_AddOrleansPersistence.cs | 25 - .../20241105120248_Init.Designer.cs | 248 -------- .../Migrations/20241105120248_Init.cs | 145 ----- ...20241106102428_updateUserModel.Designer.cs | 248 -------- .../20241106102428_updateUserModel.cs | 50 -- ...04036_DisplayNameAndAgreements.Designer.cs | 289 --------- ...20241111204036_DisplayNameAndAgreements.cs | 96 --- ...1112184733_changesUserRelation.Designer.cs | 262 --------- .../20241112184733_changesUserRelation.cs | 111 ---- .../20241123160114_initial.Designer.cs | 554 ++++++++++++++++++ .../Migrations/20241123160114_initial.cs | 360 ++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 444 +++++++++++--- 21 files changed, 1529 insertions(+), 1580 deletions(-) create mode 100644 src/Argon.Api/Features/EF/ColourConverter.cs create mode 100644 src/Argon.Api/Features/Repositories/IServerRepository.cs rename src/Argon.Api/{Extensions => Features/Utils}/ActorExtensions.cs (100%) create mode 100644 src/Argon.Api/Features/Utils/AsyncContainer.cs rename src/Argon.Api/{Extensions => Features/Utils}/HttpContextExtensions.cs (97%) create mode 100644 src/Argon.Api/Features/Utils/ObjDiff.cs create mode 100644 src/Argon.Api/Features/Utils/SwaggerExtension.cs delete mode 100644 src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.Designer.cs delete mode 100644 src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.cs delete mode 100644 src/Argon.Api/Migrations/20241105120248_Init.Designer.cs delete mode 100644 src/Argon.Api/Migrations/20241105120248_Init.cs delete mode 100644 src/Argon.Api/Migrations/20241106102428_updateUserModel.Designer.cs delete mode 100644 src/Argon.Api/Migrations/20241106102428_updateUserModel.cs delete mode 100644 src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.Designer.cs delete mode 100644 src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.cs delete mode 100644 src/Argon.Api/Migrations/20241112184733_changesUserRelation.Designer.cs delete mode 100644 src/Argon.Api/Migrations/20241112184733_changesUserRelation.cs create mode 100644 src/Argon.Api/Migrations/20241123160114_initial.Designer.cs create mode 100644 src/Argon.Api/Migrations/20241123160114_initial.cs diff --git a/src/Argon.Api/Features/Captcha/CloudflareCaptcha.cs b/src/Argon.Api/Features/Captcha/CloudflareCaptcha.cs index c6e0e21..26fd8e7 100644 --- a/src/Argon.Api/Features/Captcha/CloudflareCaptcha.cs +++ b/src/Argon.Api/Features/Captcha/CloudflareCaptcha.cs @@ -1,5 +1,6 @@ namespace Argon.Api.Features.Captcha; +using Argon.Features; using Extensions; using Flurl.Http; using Microsoft.Extensions.Options; diff --git a/src/Argon.Api/Features/EF/ColourConverter.cs b/src/Argon.Api/Features/EF/ColourConverter.cs new file mode 100644 index 0000000..27f1b3e --- /dev/null +++ b/src/Argon.Api/Features/EF/ColourConverter.cs @@ -0,0 +1,13 @@ +namespace Argon.Api.Features.EF; + +using System.Drawing; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +public class ColourConverter() : ValueConverter(x => ToInt(x), x => ToColor(x)) +{ + private static Color ToColor(int val) + => Color.FromArgb(val); + + private static int ToInt(Color val) + => val.ToArgb(); +} \ No newline at end of file diff --git a/src/Argon.Api/Features/Repositories/IServerRepository.cs b/src/Argon.Api/Features/Repositories/IServerRepository.cs new file mode 100644 index 0000000..c3fc8c7 --- /dev/null +++ b/src/Argon.Api/Features/Repositories/IServerRepository.cs @@ -0,0 +1,106 @@ +namespace Argon.Api.Features.Repositories; + +using System.Diagnostics; +using Contracts.Models; +using Contracts.Models.ArchetypeModel; +using Entities; +using Grains.Interfaces; +using Microsoft.EntityFrameworkCore; + +public static class TemplateFeature +{ + public static IServiceCollection AddEfRepositories(this WebApplicationBuilder builder) + { + builder.Services.AddScoped(); + return builder.Services; + } +} + +public interface IServerRepository +{ + ValueTask CreateAsync(Guid serverId, ServerInput data, Guid initiator); +} + +public class ServerRepository(ApplicationDbContext context) : IServerRepository +{ + public async ValueTask CreateAsync(Guid serverId, ServerInput data, Guid initiator) + { + var strategy = context.Database.CreateExecutionStrategy(); + return await strategy.ExecuteAsync(async () => + { + await using var transaction = await context.Database.BeginTransactionAsync(); + try + { + var server = new Server() + { + Id = serverId, + AvatarFileId = data.AvatarUrl, + CreatorId = initiator, + Description = data.Description, + Name = data.Name! + }; + + var e = await context.Servers.AddAsync(server); + + await context.SaveChangesAsync(); + + var sm = new ServerMember() + { + Id = initiator, + ServerId = serverId, + UserId = initiator, + CreatorId = initiator, + }; + + await context.UsersToServerRelations.AddAsync(sm); + + await context.SaveChangesAsync(); + + await CloneArchetypesAsync(e.Entity.Id, sm.Id); + + await transaction.CommitAsync(); + + return e.Entity; + } + catch (Exception) + { + await transaction.RollbackAsync(); + throw; + } + }); + } + + + private async ValueTask CloneArchetypesAsync(Guid serverId, Guid initiator) + { + var everyone = await context.Archetypes.FindAsync(Archetype.DefaultArchetype_Everyone); + var owner = await context.Archetypes.FindAsync(Archetype.DefaultArchetype_Owner); + + owner!.Id = Guid.NewGuid(); + owner.CreatorId = initiator; + owner.Server = null!; + owner.ServerId = serverId; + owner.ServerMemberRoles = new List(); + + everyone!.Id = Guid.NewGuid(); + everyone.CreatorId = initiator; + everyone.ServerId = serverId; + everyone.Server = null!; + everyone.ServerMemberRoles = new List(); + + await context.Archetypes.AddAsync(everyone); + await context.Archetypes.AddAsync(owner); + + Debug.Assert(await context.SaveChangesAsync() == 2); + + var e = new ServerMemberArchetype() + { + ArchetypeId = owner.Id, + ServerMemberId = initiator + }; + + await context.ServerMemberArchetypes.AddAsync(e); + + Debug.Assert(await context.SaveChangesAsync() == 1); + } +} \ No newline at end of file diff --git a/src/Argon.Api/Extensions/ActorExtensions.cs b/src/Argon.Api/Features/Utils/ActorExtensions.cs similarity index 100% rename from src/Argon.Api/Extensions/ActorExtensions.cs rename to src/Argon.Api/Features/Utils/ActorExtensions.cs diff --git a/src/Argon.Api/Features/Utils/AsyncContainer.cs b/src/Argon.Api/Features/Utils/AsyncContainer.cs new file mode 100644 index 0000000..89f023e --- /dev/null +++ b/src/Argon.Api/Features/Utils/AsyncContainer.cs @@ -0,0 +1,15 @@ +namespace Argon.Features; + +public class AsyncContainer(Func> taskFactory) + where T : class +{ + private readonly Task _lazyTask = taskFactory(); + private volatile T? _value; + + public T Value => _value ?? throw new Exception($"Not created"); + + public bool IsValueCreated => _value is not null; + + public async ValueTask DoCreateAsync() + => Interlocked.Exchange(ref _value, await _lazyTask); +} \ No newline at end of file diff --git a/src/Argon.Api/Extensions/HttpContextExtensions.cs b/src/Argon.Api/Features/Utils/HttpContextExtensions.cs similarity index 97% rename from src/Argon.Api/Extensions/HttpContextExtensions.cs rename to src/Argon.Api/Features/Utils/HttpContextExtensions.cs index a2d8fad..30ecd08 100644 --- a/src/Argon.Api/Extensions/HttpContextExtensions.cs +++ b/src/Argon.Api/Features/Utils/HttpContextExtensions.cs @@ -1,4 +1,4 @@ -namespace Argon.Api.Extensions; +namespace Argon.Features; using System.Security.Claims; diff --git a/src/Argon.Api/Features/Utils/ObjDiff.cs b/src/Argon.Api/Features/Utils/ObjDiff.cs new file mode 100644 index 0000000..6512de3 --- /dev/null +++ b/src/Argon.Api/Features/Utils/ObjDiff.cs @@ -0,0 +1,54 @@ +namespace Argon.Features; + +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Reflection; +using ActualLab.Collections; +using ActualLab.Text; + +public static class ObjDiff +{ + private static readonly ConcurrentDictionary comparer_cache = new(); + + + private static bool IsAreEqual(Type t, object t1, object t2) + { + var comparerType = typeof(EqualityComparer<>).MakeGenericType(t); + + if (comparer_cache.TryGetValue(t, out var cmp)) + { + var equalsMethod = comparerType.GetMethod("Equals", [t, t])!; + return (bool)equalsMethod.Invoke(cmp, new[] { t1, t2 })!; + } + else + { + var defaultComparer = comparerType.GetProperty("Default")!.GetValue(null)!; + + comparer_cache.TryAdd(t, defaultComparer); + + var equalsMethod = comparerType.GetMethod("Equals", [t, t])!; + return (bool)equalsMethod.Invoke(defaultComparer, new[] { t1, t2 })!; + } + } + + + public static PropertyBag Compare(T prev, T next) + { + if (EqualityComparer.Default.Equals(prev, next)) + return PropertyBag.Empty; + + var props = PropertyBag.Empty; + var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); + + foreach (var prop in properties) + { + var prevValue = prop.GetValue(prev)!; + var updatedValue = prop.GetValue(next)!; + + if (!IsAreEqual(prop.PropertyType, prevValue, updatedValue)) + props.Set(new Symbol(prop.Name), updatedValue); + } + + return props; + } +} \ No newline at end of file diff --git a/src/Argon.Api/Features/Utils/SwaggerExtension.cs b/src/Argon.Api/Features/Utils/SwaggerExtension.cs new file mode 100644 index 0000000..a0dda70 --- /dev/null +++ b/src/Argon.Api/Features/Utils/SwaggerExtension.cs @@ -0,0 +1,57 @@ +namespace Argon.Api.Extensions; + +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +public static class SwaggerExtension +{ + public static WebApplicationBuilder AddSwaggerWithAuthHeader(this WebApplicationBuilder builder) + { + builder.Services.AddSwaggerGen(c => + { + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + In = ParameterLocation.Header, + Description = "Please insert JWT with Bearer into field", + Name = "Authorization", + Type = SecuritySchemeType.ApiKey + }); + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + [] + } + }); + c.OperationFilter(); + }).AddEndpointsApiExplorer(); + + return builder; + } +} + +public class AddHeaderParameterOperationFilter : IOperationFilter +{ + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + operation.Parameters ??= new List(); + operation.Parameters.Add(new OpenApiParameter + { + Name = "X-Host-Name", + In = ParameterLocation.Header, + Description = "Host Name", + Required = true, + Schema = new OpenApiSchema + { + Type = "string" + } + }); + } +} \ No newline at end of file diff --git a/src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.Designer.cs b/src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.Designer.cs deleted file mode 100644 index d55dd9b..0000000 --- a/src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.Designer.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -using Argon.Api.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Argon.Api.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20241020185058_AddOrleansPersistence")] - partial class AddOrleansPersistence - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.cs b/src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.cs deleted file mode 100644 index 11a399a..0000000 --- a/src/Argon.Api/Migrations/20241020185058_AddOrleansPersistence.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Argon.Api.Migrations -{ - /// - public partial class AddOrleansPersistence : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - // read file orleans_up.sql in the same directory - var sql = System.IO.File.ReadAllText("Migrations/orleans_up.sql"); - migrationBuilder.Sql(sql); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - var sql = System.IO.File.ReadAllText("Migrations/orleans_down.sql"); - migrationBuilder.Sql(sql); - } - } -} \ No newline at end of file diff --git a/src/Argon.Api/Migrations/20241105120248_Init.Designer.cs b/src/Argon.Api/Migrations/20241105120248_Init.Designer.cs deleted file mode 100644 index d5ca048..0000000 --- a/src/Argon.Api/Migrations/20241105120248_Init.Designer.cs +++ /dev/null @@ -1,248 +0,0 @@ -// -using System; -using Argon.Api.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Argon.Api.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20241105120248_Init")] - partial class Init - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AccessLevel") - .HasColumnType("integer"); - - b.Property("ChannelType") - .HasColumnType("integer"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.ToTable("Channels"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("Servers"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .HasMaxLength(1023) - .HasColumnType("character varying(1023)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("OTP") - .HasMaxLength(7) - .HasColumnType("character varying(7)"); - - b.Property("PasswordDigest") - .HasMaxLength(511) - .HasColumnType("character varying(511)"); - - b.Property("PhoneNumber") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .IsRequired() - .HasColumnType("text"); - - b.Property("BanReason") - .HasColumnType("text"); - - b.Property("BannedUntil") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CustomAvatarUrl") - .HasColumnType("text"); - - b.Property("CustomUsername") - .IsRequired() - .HasColumnType("text"); - - b.Property("IsBanned") - .HasColumnType("boolean"); - - b.Property("IsMuted") - .HasColumnType("boolean"); - - b.Property("Joined") - .HasColumnType("timestamp with time zone"); - - b.Property("MuteReason") - .HasColumnType("text"); - - b.Property("MutedUntil") - .HasColumnType("timestamp with time zone"); - - b.Property("Role") - .HasColumnType("integer"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.HasIndex("UserId"); - - b.ToTable("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.HasOne("Argon.Api.Entities.Server", null) - .WithMany("Channels") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.HasOne("Argon.Api.Entities.Server", "Server") - .WithMany("UsersToServerRelations") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Argon.Api.Entities.User", "User") - .WithMany("UsersToServerRelations") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Server"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Navigation("Channels"); - - b.Navigation("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Navigation("UsersToServerRelations"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Argon.Api/Migrations/20241105120248_Init.cs b/src/Argon.Api/Migrations/20241105120248_Init.cs deleted file mode 100644 index 186e230..0000000 --- a/src/Argon.Api/Migrations/20241105120248_Init.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Argon.Api.Migrations -{ - /// - public partial class Init : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Servers", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), - Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), - Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - AvatarUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Servers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Users", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), - Email = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), - Username = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - PhoneNumber = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), - PasswordDigest = table.Column(type: "character varying(511)", maxLength: 511, nullable: true), - AvatarUrl = table.Column(type: "character varying(1023)", maxLength: 1023, nullable: true), - OTP = table.Column(type: "character varying(7)", maxLength: 7, nullable: true), - DeletedAt = table.Column(type: "timestamp with time zone", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Users", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Channels", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), - Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), - Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), - UserId = table.Column(type: "uuid", nullable: false), - ChannelType = table.Column(type: "integer", nullable: false), - AccessLevel = table.Column(type: "integer", nullable: false), - ServerId = table.Column(type: "uuid", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Channels", x => x.Id); - table.ForeignKey( - name: "FK_Channels_Servers_ServerId", - column: x => x.ServerId, - principalTable: "Servers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "UsersToServerRelations", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), - ServerId = table.Column(type: "uuid", nullable: false), - Joined = table.Column(type: "timestamp with time zone", nullable: false), - Role = table.Column(type: "integer", nullable: false), - UserId = table.Column(type: "uuid", nullable: false), - CustomUsername = table.Column(type: "text", nullable: false), - IsBanned = table.Column(type: "boolean", nullable: false), - IsMuted = table.Column(type: "boolean", nullable: false), - BannedUntil = table.Column(type: "timestamp with time zone", nullable: true), - MutedUntil = table.Column(type: "timestamp with time zone", nullable: true), - AvatarUrl = table.Column(type: "text", nullable: false), - CustomAvatarUrl = table.Column(type: "text", nullable: true), - BanReason = table.Column(type: "text", nullable: true), - MuteReason = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_UsersToServerRelations", x => x.Id); - table.ForeignKey( - name: "FK_UsersToServerRelations_Servers_ServerId", - column: x => x.ServerId, - principalTable: "Servers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_UsersToServerRelations_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Channels_ServerId", - table: "Channels", - column: "ServerId"); - - migrationBuilder.CreateIndex( - name: "IX_UsersToServerRelations_ServerId", - table: "UsersToServerRelations", - column: "ServerId"); - - migrationBuilder.CreateIndex( - name: "IX_UsersToServerRelations_UserId", - table: "UsersToServerRelations", - column: "UserId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Channels"); - - migrationBuilder.DropTable( - name: "UsersToServerRelations"); - - migrationBuilder.DropTable( - name: "Servers"); - - migrationBuilder.DropTable( - name: "Users"); - } - } -} \ No newline at end of file diff --git a/src/Argon.Api/Migrations/20241106102428_updateUserModel.Designer.cs b/src/Argon.Api/Migrations/20241106102428_updateUserModel.Designer.cs deleted file mode 100644 index c8c5f8a..0000000 --- a/src/Argon.Api/Migrations/20241106102428_updateUserModel.Designer.cs +++ /dev/null @@ -1,248 +0,0 @@ -// -using System; -using Argon.Api.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Argon.Api.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20241106102428_updateUserModel")] - partial class updateUserModel - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AccessLevel") - .HasColumnType("integer"); - - b.Property("ChannelType") - .HasColumnType("integer"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.ToTable("Channels"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("Servers"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarFileId") - .HasMaxLength(1023) - .HasColumnType("character varying(1023)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("OtpHash") - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("PasswordDigest") - .HasMaxLength(511) - .HasColumnType("character varying(511)"); - - b.Property("PhoneNumber") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .IsRequired() - .HasColumnType("text"); - - b.Property("BanReason") - .HasColumnType("text"); - - b.Property("BannedUntil") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CustomAvatarUrl") - .HasColumnType("text"); - - b.Property("CustomUsername") - .IsRequired() - .HasColumnType("text"); - - b.Property("IsBanned") - .HasColumnType("boolean"); - - b.Property("IsMuted") - .HasColumnType("boolean"); - - b.Property("Joined") - .HasColumnType("timestamp with time zone"); - - b.Property("MuteReason") - .HasColumnType("text"); - - b.Property("MutedUntil") - .HasColumnType("timestamp with time zone"); - - b.Property("Role") - .HasColumnType("integer"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.HasIndex("UserId"); - - b.ToTable("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.HasOne("Argon.Api.Entities.Server", null) - .WithMany("Channels") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.HasOne("Argon.Api.Entities.Server", "Server") - .WithMany("UsersToServerRelations") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Argon.Api.Entities.User", "User") - .WithMany("UsersToServerRelations") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Server"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Navigation("Channels"); - - b.Navigation("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Navigation("UsersToServerRelations"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Argon.Api/Migrations/20241106102428_updateUserModel.cs b/src/Argon.Api/Migrations/20241106102428_updateUserModel.cs deleted file mode 100644 index 3df809e..0000000 --- a/src/Argon.Api/Migrations/20241106102428_updateUserModel.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Argon.Api.Migrations -{ - /// - public partial class updateUserModel : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "OTP", - table: "Users"); - - migrationBuilder.RenameColumn( - name: "AvatarUrl", - table: "Users", - newName: "AvatarFileId"); - - migrationBuilder.AddColumn( - name: "OtpHash", - table: "Users", - type: "character varying(128)", - maxLength: 128, - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "OtpHash", - table: "Users"); - - migrationBuilder.RenameColumn( - name: "AvatarFileId", - table: "Users", - newName: "AvatarUrl"); - - migrationBuilder.AddColumn( - name: "OTP", - table: "Users", - type: "character varying(7)", - maxLength: 7, - nullable: true); - } - } -} diff --git a/src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.Designer.cs b/src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.Designer.cs deleted file mode 100644 index 78ce0b8..0000000 --- a/src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.Designer.cs +++ /dev/null @@ -1,289 +0,0 @@ -// -using System; -using Argon.Api.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Argon.Api.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20241111204036_DisplayNameAndAgreements")] - partial class DisplayNameAndAgreements - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AccessLevel") - .HasColumnType("integer"); - - b.Property("ChannelType") - .HasColumnType("integer"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.ToTable("Channels"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("Servers"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarFileId") - .HasMaxLength(1023) - .HasColumnType("character varying(1023)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("OtpHash") - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("PasswordDigest") - .HasMaxLength(511) - .HasColumnType("character varying(511)"); - - b.Property("PhoneNumber") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AgreeTOS") - .HasColumnType("boolean"); - - b.Property("AllowedSendOptionalEmails") - .HasColumnType("boolean"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("UserAgreements"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .HasColumnType("text"); - - b.Property("BanReason") - .HasColumnType("text"); - - b.Property("BannedUntil") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CustomAvatarUrl") - .HasColumnType("text"); - - b.Property("CustomUsername") - .HasColumnType("text"); - - b.Property("IsBanned") - .HasColumnType("boolean"); - - b.Property("IsMuted") - .HasColumnType("boolean"); - - b.Property("Joined") - .HasColumnType("timestamp with time zone"); - - b.Property("MuteReason") - .HasColumnType("text"); - - b.Property("MutedUntil") - .HasColumnType("timestamp with time zone"); - - b.Property("Role") - .HasColumnType("integer"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.HasIndex("UserId"); - - b.ToTable("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.HasOne("Argon.Api.Entities.Server", null) - .WithMany("Channels") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => - { - b.HasOne("Argon.Api.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.HasOne("Argon.Api.Entities.Server", "Server") - .WithMany("UsersToServerRelations") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Argon.Api.Entities.User", "User") - .WithMany("UsersToServerRelations") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Server"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Navigation("Channels"); - - b.Navigation("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Navigation("UsersToServerRelations"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.cs b/src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.cs deleted file mode 100644 index 8224160..0000000 --- a/src/Argon.Api/Migrations/20241111204036_DisplayNameAndAgreements.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Argon.Api.Migrations -{ - /// - public partial class DisplayNameAndAgreements : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "CustomUsername", - table: "UsersToServerRelations", - type: "text", - nullable: true, - oldClrType: typeof(string), - oldType: "text"); - - migrationBuilder.AlterColumn( - name: "AvatarUrl", - table: "UsersToServerRelations", - type: "text", - nullable: true, - oldClrType: typeof(string), - oldType: "text"); - - migrationBuilder.AddColumn( - name: "DisplayName", - table: "Users", - type: "character varying(30)", - maxLength: 30, - nullable: true); - - migrationBuilder.CreateTable( - name: "UserAgreements", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - AllowedSendOptionalEmails = table.Column(type: "boolean", nullable: false), - AgreeTOS = table.Column(type: "boolean", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UserId = table.Column(type: "uuid", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_UserAgreements", x => x.Id); - table.ForeignKey( - name: "FK_UserAgreements_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_UserAgreements_UserId", - table: "UserAgreements", - column: "UserId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "UserAgreements"); - - migrationBuilder.DropColumn( - name: "DisplayName", - table: "Users"); - - migrationBuilder.AlterColumn( - name: "CustomUsername", - table: "UsersToServerRelations", - type: "text", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "text", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "AvatarUrl", - table: "UsersToServerRelations", - type: "text", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "text", - oldNullable: true); - } - } -} diff --git a/src/Argon.Api/Migrations/20241112184733_changesUserRelation.Designer.cs b/src/Argon.Api/Migrations/20241112184733_changesUserRelation.Designer.cs deleted file mode 100644 index 855327c..0000000 --- a/src/Argon.Api/Migrations/20241112184733_changesUserRelation.Designer.cs +++ /dev/null @@ -1,262 +0,0 @@ -// -using System; -using Argon.Api.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Argon.Api.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20241112184733_changesUserRelation")] - partial class changesUserRelation - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AccessLevel") - .HasColumnType("integer"); - - b.Property("ChannelType") - .HasColumnType("integer"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.ToTable("Channels"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("Servers"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AvatarFileId") - .HasMaxLength(1023) - .HasColumnType("character varying(1023)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.Property("OtpHash") - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("PasswordDigest") - .HasMaxLength(511) - .HasColumnType("character varying(511)"); - - b.Property("PhoneNumber") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AgreeTOS") - .HasColumnType("boolean"); - - b.Property("AllowedSendOptionalEmails") - .HasColumnType("boolean"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("UserAgreements"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Joined") - .HasColumnType("timestamp with time zone"); - - b.Property("Role") - .HasColumnType("integer"); - - b.Property("ServerId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ServerId"); - - b.HasIndex("UserId"); - - b.ToTable("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Channel", b => - { - b.HasOne("Argon.Api.Entities.Server", null) - .WithMany("Channels") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => - { - b.HasOne("Argon.Api.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => - { - b.HasOne("Argon.Api.Entities.Server", "Server") - .WithMany("UsersToServerRelations") - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Argon.Api.Entities.User", "User") - .WithMany("UsersToServerRelations") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Server"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Argon.Api.Entities.Server", b => - { - b.Navigation("Channels"); - - b.Navigation("UsersToServerRelations"); - }); - - modelBuilder.Entity("Argon.Api.Entities.User", b => - { - b.Navigation("UsersToServerRelations"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Argon.Api/Migrations/20241112184733_changesUserRelation.cs b/src/Argon.Api/Migrations/20241112184733_changesUserRelation.cs deleted file mode 100644 index 78dbb20..0000000 --- a/src/Argon.Api/Migrations/20241112184733_changesUserRelation.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Argon.Api.Migrations -{ - /// - public partial class changesUserRelation : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "AvatarUrl", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "BanReason", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "BannedUntil", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "CustomAvatarUrl", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "CustomUsername", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "IsBanned", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "IsMuted", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "MuteReason", - table: "UsersToServerRelations"); - - migrationBuilder.DropColumn( - name: "MutedUntil", - table: "UsersToServerRelations"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "AvatarUrl", - table: "UsersToServerRelations", - type: "text", - nullable: true); - - migrationBuilder.AddColumn( - name: "BanReason", - table: "UsersToServerRelations", - type: "text", - nullable: true); - - migrationBuilder.AddColumn( - name: "BannedUntil", - table: "UsersToServerRelations", - type: "timestamp with time zone", - nullable: true); - - migrationBuilder.AddColumn( - name: "CustomAvatarUrl", - table: "UsersToServerRelations", - type: "text", - nullable: true); - - migrationBuilder.AddColumn( - name: "CustomUsername", - table: "UsersToServerRelations", - type: "text", - nullable: true); - - migrationBuilder.AddColumn( - name: "IsBanned", - table: "UsersToServerRelations", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "IsMuted", - table: "UsersToServerRelations", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "MuteReason", - table: "UsersToServerRelations", - type: "text", - nullable: true); - - migrationBuilder.AddColumn( - name: "MutedUntil", - table: "UsersToServerRelations", - type: "timestamp with time zone", - nullable: true); - } - } -} diff --git a/src/Argon.Api/Migrations/20241123160114_initial.Designer.cs b/src/Argon.Api/Migrations/20241123160114_initial.Designer.cs new file mode 100644 index 0000000..2490067 --- /dev/null +++ b/src/Argon.Api/Migrations/20241123160114_initial.Designer.cs @@ -0,0 +1,554 @@ +// +using System; +using Argon.Api.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Argon.Api.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20241123160114_initial")] + partial class initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AgreeTOS") + .HasColumnType("boolean"); + + b.Property("AllowedSendOptionalEmails") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserAgreements"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ArchetypeModel.Archetype", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Colour") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Entitlement") + .HasColumnType("numeric(20,0)"); + + b.Property("IconFileId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("IsHidden") + .HasColumnType("boolean"); + + b.Property("IsLocked") + .HasColumnType("boolean"); + + b.Property("IsMentionable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ServerId"); + + b.ToTable("Archetypes"); + + b.HasData( + new + { + Id = new Guid("11111111-3333-0000-1111-111111111111"), + Colour = -8355712, + CreatedAt = new DateTime(2024, 11, 23, 16, 1, 14, 205, DateTimeKind.Utc).AddTicks(8382), + CreatorId = new Guid("11111111-2222-1111-2222-111111111111"), + Description = "Default role for everyone in this server", + Entitlement = 15760355m, + IsDeleted = false, + IsHidden = false, + IsLocked = false, + IsMentionable = true, + Name = "everyone", + ServerId = new Guid("11111111-0000-1111-1111-111111111111"), + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("11111111-4444-0000-1111-111111111111"), + Colour = -8355712, + CreatedAt = new DateTime(2024, 11, 23, 16, 1, 14, 205, DateTimeKind.Utc).AddTicks(8411), + CreatorId = new Guid("11111111-2222-1111-2222-111111111111"), + Description = "Default role for owner in this server", + Entitlement = -1m, + IsDeleted = false, + IsHidden = true, + IsLocked = true, + IsMentionable = false, + Name = "owner", + ServerId = new Guid("11111111-0000-1111-1111-111111111111"), + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Channel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChannelType") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Id", "ServerId"); + + b.ToTable("Channels"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ChannelEntitlementOverwrite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Allow") + .HasColumnType("numeric(20,0)"); + + b.Property("ArchetypeId") + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Deny") + .HasColumnType("numeric(20,0)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("Scope") + .HasColumnType("integer"); + + b.Property("ServerMemberId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ArchetypeId"); + + b.HasIndex("ChannelId"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ServerMemberId"); + + b.ToTable("ChannelEntitlementOverwrites"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarFileId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.ToTable("Servers"); + + b.HasData( + new + { + Id = new Guid("11111111-0000-1111-1111-111111111111"), + AvatarFileId = "", + CreatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatorId = new Guid("11111111-2222-1111-2222-111111111111"), + Description = "", + IsDeleted = false, + Name = "system_server", + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ServerMember", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ServerId"); + + b.HasIndex("UserId"); + + b.ToTable("UsersToServerRelations"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ServerMemberArchetype", b => + { + b.Property("ServerMemberId") + .HasColumnType("uuid"); + + b.Property("ArchetypeId") + .HasColumnType("uuid"); + + b.HasKey("ServerMemberId", "ArchetypeId"); + + b.HasIndex("ArchetypeId"); + + b.ToTable("ServerMemberArchetypes"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarFileId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("OtpHash") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("PasswordDigest") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("PhoneNumber") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("11111111-2222-1111-2222-111111111111"), + CreatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DisplayName = "System", + Email = "system@argon.gl", + IsDeleted = false, + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Username = "system" + }); + }); + + modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => + { + b.HasOne("Argon.Contracts.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ArchetypeModel.Archetype", b => + { + b.HasOne("Argon.Contracts.Models.Server", "Server") + .WithMany("Archetypes") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Channel", b => + { + b.HasOne("Argon.Contracts.Models.Server", "Server") + .WithMany("Channels") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ChannelEntitlementOverwrite", b => + { + b.HasOne("Argon.Contracts.Models.ArchetypeModel.Archetype", "Archetype") + .WithMany() + .HasForeignKey("ArchetypeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Argon.Contracts.Models.Channel", "Channel") + .WithMany("EntitlementOverwrites") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Argon.Contracts.Models.ServerMember", "ServerMember") + .WithMany() + .HasForeignKey("ServerMemberId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Archetype"); + + b.Navigation("Channel"); + + b.Navigation("ServerMember"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ServerMember", b => + { + b.HasOne("Argon.Contracts.Models.Server", "Server") + .WithMany("Users") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Argon.Contracts.Models.User", "User") + .WithMany("ServerMembers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Server"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ServerMemberArchetype", b => + { + b.HasOne("Argon.Contracts.Models.ArchetypeModel.Archetype", "Archetype") + .WithMany("ServerMemberRoles") + .HasForeignKey("ArchetypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Argon.Contracts.Models.ServerMember", "ServerMember") + .WithMany("ServerMemberArchetypes") + .HasForeignKey("ServerMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Archetype"); + + b.Navigation("ServerMember"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ArchetypeModel.Archetype", b => + { + b.Navigation("ServerMemberRoles"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Channel", b => + { + b.Navigation("EntitlementOverwrites"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Server", b => + { + b.Navigation("Archetypes"); + + b.Navigation("Channels"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ServerMember", b => + { + b.Navigation("ServerMemberArchetypes"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.User", b => + { + b.Navigation("ServerMembers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Argon.Api/Migrations/20241123160114_initial.cs b/src/Argon.Api/Migrations/20241123160114_initial.cs new file mode 100644 index 0000000..a352593 --- /dev/null +++ b/src/Argon.Api/Migrations/20241123160114_initial.cs @@ -0,0 +1,360 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Argon.Api.Migrations +{ + /// + public partial class initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + var sql = System.IO.File.ReadAllText("Migrations/orleans_up.sql"); + migrationBuilder.Sql(sql); + + migrationBuilder.CreateTable( + name: "Servers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Description = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + AvatarFileId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + DeletedAt = table.Column(type: "timestamp with time zone", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Servers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Email = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + Username = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DisplayName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + PhoneNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + PasswordDigest = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + AvatarFileId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + OtpHash = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + DeletedAt = table.Column(type: "timestamp with time zone", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Archetypes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ServerId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: false), + Entitlement = table.Column(type: "numeric(20,0)", nullable: false), + IsMentionable = table.Column(type: "boolean", nullable: false), + IsLocked = table.Column(type: "boolean", nullable: false), + IsHidden = table.Column(type: "boolean", nullable: false), + Colour = table.Column(type: "integer", nullable: false), + IconFileId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + DeletedAt = table.Column(type: "timestamp with time zone", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Archetypes", x => x.Id); + table.ForeignKey( + name: "FK_Archetypes_Servers_ServerId", + column: x => x.ServerId, + principalTable: "Servers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Channels", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ChannelType = table.Column(type: "integer", nullable: false), + ServerId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Description = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + DeletedAt = table.Column(type: "timestamp with time zone", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Channels", x => x.Id); + table.ForeignKey( + name: "FK_Channels_Servers_ServerId", + column: x => x.ServerId, + principalTable: "Servers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserAgreements", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + AllowedSendOptionalEmails = table.Column(type: "boolean", nullable: false), + AgreeTOS = table.Column(type: "boolean", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UserId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserAgreements", x => x.Id); + table.ForeignKey( + name: "FK_UserAgreements_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UsersToServerRelations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ServerId = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + JoinedAt = table.Column(type: "timestamp with time zone", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + DeletedAt = table.Column(type: "timestamp with time zone", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UsersToServerRelations", x => x.Id); + table.ForeignKey( + name: "FK_UsersToServerRelations_Servers_ServerId", + column: x => x.ServerId, + principalTable: "Servers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UsersToServerRelations_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ChannelEntitlementOverwrites", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ChannelId = table.Column(type: "uuid", nullable: false), + Scope = table.Column(type: "integer", nullable: false), + ArchetypeId = table.Column(type: "uuid", nullable: true), + ServerMemberId = table.Column(type: "uuid", nullable: true), + Allow = table.Column(type: "numeric(20,0)", nullable: false), + Deny = table.Column(type: "numeric(20,0)", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + DeletedAt = table.Column(type: "timestamp with time zone", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ChannelEntitlementOverwrites", x => x.Id); + table.ForeignKey( + name: "FK_ChannelEntitlementOverwrites_Archetypes_ArchetypeId", + column: x => x.ArchetypeId, + principalTable: "Archetypes", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_ChannelEntitlementOverwrites_Channels_ChannelId", + column: x => x.ChannelId, + principalTable: "Channels", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ChannelEntitlementOverwrites_UsersToServerRelations_ServerM~", + column: x => x.ServerMemberId, + principalTable: "UsersToServerRelations", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "ServerMemberArchetypes", + columns: table => new + { + ServerMemberId = table.Column(type: "uuid", nullable: false), + ArchetypeId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServerMemberArchetypes", x => new { x.ServerMemberId, x.ArchetypeId }); + table.ForeignKey( + name: "FK_ServerMemberArchetypes_Archetypes_ArchetypeId", + column: x => x.ArchetypeId, + principalTable: "Archetypes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ServerMemberArchetypes_UsersToServerRelations_ServerMemberId", + column: x => x.ServerMemberId, + principalTable: "UsersToServerRelations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.InsertData( + table: "Servers", + columns: new[] { "Id", "AvatarFileId", "CreatedAt", "CreatorId", "DeletedAt", "Description", "IsDeleted", "Name", "UpdatedAt" }, + values: new object[] { new Guid("11111111-0000-1111-1111-111111111111"), "", new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("11111111-2222-1111-2222-111111111111"), null, "", false, "system_server", new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) }); + + migrationBuilder.InsertData( + table: "Users", + columns: new[] { "Id", "AvatarFileId", "CreatedAt", "DeletedAt", "DisplayName", "Email", "IsDeleted", "OtpHash", "PasswordDigest", "PhoneNumber", "UpdatedAt", "Username" }, + values: new object[] { new Guid("11111111-2222-1111-2222-111111111111"), null, new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), null, "System", "system@argon.gl", false, null, null, null, new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), "system" }); + + migrationBuilder.InsertData( + table: "Archetypes", + columns: new[] { "Id", "Colour", "CreatedAt", "CreatorId", "DeletedAt", "Description", "Entitlement", "IconFileId", "IsDeleted", "IsHidden", "IsLocked", "IsMentionable", "Name", "ServerId", "UpdatedAt" }, + values: new object[,] + { + { new Guid("11111111-3333-0000-1111-111111111111"), -8355712, new DateTime(2024, 11, 23, 16, 1, 14, 205, DateTimeKind.Utc).AddTicks(8382), new Guid("11111111-2222-1111-2222-111111111111"), null, "Default role for everyone in this server", 15760355m, null, false, false, false, true, "everyone", new Guid("11111111-0000-1111-1111-111111111111"), new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) }, + { new Guid("11111111-4444-0000-1111-111111111111"), -8355712, new DateTime(2024, 11, 23, 16, 1, 14, 205, DateTimeKind.Utc).AddTicks(8411), new Guid("11111111-2222-1111-2222-111111111111"), null, "Default role for owner in this server", -1m, null, false, true, true, false, "owner", new Guid("11111111-0000-1111-1111-111111111111"), new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) } + }); + + migrationBuilder.CreateIndex( + name: "IX_Archetypes_CreatorId", + table: "Archetypes", + column: "CreatorId"); + + migrationBuilder.CreateIndex( + name: "IX_Archetypes_ServerId", + table: "Archetypes", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_ChannelEntitlementOverwrites_ArchetypeId", + table: "ChannelEntitlementOverwrites", + column: "ArchetypeId"); + + migrationBuilder.CreateIndex( + name: "IX_ChannelEntitlementOverwrites_ChannelId", + table: "ChannelEntitlementOverwrites", + column: "ChannelId"); + + migrationBuilder.CreateIndex( + name: "IX_ChannelEntitlementOverwrites_CreatorId", + table: "ChannelEntitlementOverwrites", + column: "CreatorId"); + + migrationBuilder.CreateIndex( + name: "IX_ChannelEntitlementOverwrites_ServerMemberId", + table: "ChannelEntitlementOverwrites", + column: "ServerMemberId"); + + migrationBuilder.CreateIndex( + name: "IX_Channels_CreatorId", + table: "Channels", + column: "CreatorId"); + + migrationBuilder.CreateIndex( + name: "IX_Channels_Id_ServerId", + table: "Channels", + columns: new[] { "Id", "ServerId" }); + + migrationBuilder.CreateIndex( + name: "IX_Channels_ServerId", + table: "Channels", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_ServerMemberArchetypes_ArchetypeId", + table: "ServerMemberArchetypes", + column: "ArchetypeId"); + + migrationBuilder.CreateIndex( + name: "IX_Servers_CreatorId", + table: "Servers", + column: "CreatorId"); + + migrationBuilder.CreateIndex( + name: "IX_UserAgreements_UserId", + table: "UserAgreements", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UsersToServerRelations_CreatorId", + table: "UsersToServerRelations", + column: "CreatorId"); + + migrationBuilder.CreateIndex( + name: "IX_UsersToServerRelations_ServerId", + table: "UsersToServerRelations", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_UsersToServerRelations_UserId", + table: "UsersToServerRelations", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + var sql = System.IO.File.ReadAllText("Migrations/orleans_down.sql"); + migrationBuilder.Sql(sql); + + migrationBuilder.DropTable( + name: "ChannelEntitlementOverwrites"); + + migrationBuilder.DropTable( + name: "ServerMemberArchetypes"); + + migrationBuilder.DropTable( + name: "UserAgreements"); + + migrationBuilder.DropTable( + name: "Channels"); + + migrationBuilder.DropTable( + name: "Archetypes"); + + migrationBuilder.DropTable( + name: "UsersToServerRelations"); + + migrationBuilder.DropTable( + name: "Servers"); + + migrationBuilder.DropTable( + name: "Users"); + } + } +} diff --git a/src/Argon.Api/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Argon.Api/Migrations/ApplicationDbContextModelSnapshot.cs index d8d91a3..2c448eb 100644 --- a/src/Argon.Api/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Argon.Api/Migrations/ApplicationDbContextModelSnapshot.cs @@ -22,30 +22,80 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Argon.Api.Entities.Channel", b => + modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("AccessLevel") - .HasColumnType("integer"); + b.Property("AgreeTOS") + .HasColumnType("boolean"); - b.Property("ChannelType") + b.Property("AllowedSendOptionalEmails") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserAgreements"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ArchetypeModel.Archetype", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Colour") .HasColumnType("integer"); b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + b.Property("Description") .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Entitlement") + .HasColumnType("numeric(20,0)"); + + b.Property("IconFileId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("IsHidden") + .HasColumnType("boolean"); + + b.Property("IsLocked") + .HasColumnType("boolean"); + + b.Property("IsMentionable") + .HasColumnType("boolean"); b.Property("Name") .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + .HasMaxLength(64) + .HasColumnType("character varying(64)"); b.Property("ServerId") .HasColumnType("uuid"); @@ -53,110 +103,226 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); - b.Property("UserId") - .HasColumnType("uuid"); - b.HasKey("Id"); + b.HasIndex("CreatorId"); + b.HasIndex("ServerId"); - b.ToTable("Channels"); + b.ToTable("Archetypes"); + + b.HasData( + new + { + Id = new Guid("11111111-3333-0000-1111-111111111111"), + Colour = -8355712, + CreatedAt = new DateTime(2024, 11, 23, 16, 1, 14, 205, DateTimeKind.Utc).AddTicks(8382), + CreatorId = new Guid("11111111-2222-1111-2222-111111111111"), + Description = "Default role for everyone in this server", + Entitlement = 15760355m, + IsDeleted = false, + IsHidden = false, + IsLocked = false, + IsMentionable = true, + Name = "everyone", + ServerId = new Guid("11111111-0000-1111-1111-111111111111"), + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("11111111-4444-0000-1111-111111111111"), + Colour = -8355712, + CreatedAt = new DateTime(2024, 11, 23, 16, 1, 14, 205, DateTimeKind.Utc).AddTicks(8411), + CreatorId = new Guid("11111111-2222-1111-2222-111111111111"), + Description = "Default role for owner in this server", + Entitlement = -1m, + IsDeleted = false, + IsHidden = true, + IsLocked = true, + IsMentionable = false, + Name = "owner", + ServerId = new Guid("11111111-0000-1111-1111-111111111111"), + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); }); - modelBuilder.Entity("Argon.Api.Entities.Server", b => + modelBuilder.Entity("Argon.Contracts.Models.Channel", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("AvatarUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + b.Property("ChannelType") + .HasColumnType("integer"); b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + b.Property("Description") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); b.Property("Name") .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ServerId") + .HasColumnType("uuid"); b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); b.HasKey("Id"); - b.ToTable("Servers"); + b.HasIndex("CreatorId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Id", "ServerId"); + + b.ToTable("Channels"); }); - modelBuilder.Entity("Argon.Api.Entities.User", b => + modelBuilder.Entity("Argon.Contracts.Models.ChannelEntitlementOverwrite", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("AvatarFileId") - .HasMaxLength(1023) - .HasColumnType("character varying(1023)"); + b.Property("Allow") + .HasColumnType("numeric(20,0)"); + + b.Property("ArchetypeId") + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("uuid"); b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); + b.Property("CreatorId") + .HasColumnType("uuid"); + b.Property("DeletedAt") .HasColumnType("timestamp with time zone"); - b.Property("DisplayName") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); + b.Property("Deny") + .HasColumnType("numeric(20,0)"); - b.Property("Email") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + b.Property("IsDeleted") + .HasColumnType("boolean"); - b.Property("OtpHash") + b.Property("Scope") + .HasColumnType("integer"); + + b.Property("ServerMemberId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ArchetypeId"); + + b.HasIndex("ChannelId"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ServerMemberId"); + + b.ToTable("ChannelEntitlementOverwrites"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarFileId") .HasMaxLength(128) .HasColumnType("character varying(128)"); - b.Property("PasswordDigest") - .HasMaxLength(511) - .HasColumnType("character varying(511)"); + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); - b.Property("PhoneNumber") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); + b.Property("CreatorId") + .HasColumnType("uuid"); - b.Property("UpdatedAt") + b.Property("DeletedAt") .HasColumnType("timestamp with time zone"); - b.Property("Username") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); b.HasKey("Id"); - b.ToTable("Users"); + b.HasIndex("CreatorId"); + + b.ToTable("Servers"); + + b.HasData( + new + { + Id = new Guid("11111111-0000-1111-1111-111111111111"), + AvatarFileId = "", + CreatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatorId = new Guid("11111111-2222-1111-2222-111111111111"), + Description = "", + IsDeleted = false, + Name = "system_server", + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); }); - modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => + modelBuilder.Entity("Argon.Contracts.Models.ServerMember", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("AgreeTOS") - .HasColumnType("boolean"); + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); - b.Property("AllowedSendOptionalEmails") + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsDeleted") .HasColumnType("boolean"); - b.Property("CreatedAt") + b.Property("JoinedAt") .HasColumnType("timestamp with time zone"); + b.Property("ServerId") + .HasColumnType("uuid"); + b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); @@ -165,74 +331,164 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); + b.HasIndex("CreatorId"); + + b.HasIndex("ServerId"); + b.HasIndex("UserId"); - b.ToTable("UserAgreements"); + b.ToTable("UsersToServerRelations"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ServerMemberArchetype", b => + { + b.Property("ServerMemberId") + .HasColumnType("uuid"); + + b.Property("ArchetypeId") + .HasColumnType("uuid"); + + b.HasKey("ServerMemberId", "ArchetypeId"); + + b.HasIndex("ArchetypeId"); + + b.ToTable("ServerMemberArchetypes"); }); - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => + modelBuilder.Entity("Argon.Contracts.Models.User", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("AvatarFileId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); - b.Property("Joined") + b.Property("DeletedAt") .HasColumnType("timestamp with time zone"); - b.Property("Role") - .HasColumnType("integer"); + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); - b.Property("ServerId") - .HasColumnType("uuid"); + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("OtpHash") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("PasswordDigest") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("PhoneNumber") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); - b.Property("UserId") - .HasColumnType("uuid"); + b.Property("Username") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); b.HasKey("Id"); - b.HasIndex("ServerId"); + b.ToTable("Users"); - b.HasIndex("UserId"); + b.HasData( + new + { + Id = new Guid("11111111-2222-1111-2222-111111111111"), + CreatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DisplayName = "System", + Email = "system@argon.gl", + IsDeleted = false, + UpdatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Username = "system" + }); + }); - b.ToTable("UsersToServerRelations"); + modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => + { + b.HasOne("Argon.Contracts.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ArchetypeModel.Archetype", b => + { + b.HasOne("Argon.Contracts.Models.Server", "Server") + .WithMany("Archetypes") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Server"); }); - modelBuilder.Entity("Argon.Api.Entities.Channel", b => + modelBuilder.Entity("Argon.Contracts.Models.Channel", b => { - b.HasOne("Argon.Api.Entities.Server", null) + b.HasOne("Argon.Contracts.Models.Server", "Server") .WithMany("Channels") .HasForeignKey("ServerId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("Server"); }); - modelBuilder.Entity("Argon.Api.Entities.UserAgreements", b => + modelBuilder.Entity("Argon.Contracts.Models.ChannelEntitlementOverwrite", b => { - b.HasOne("Argon.Api.Entities.User", "User") + b.HasOne("Argon.Contracts.Models.ArchetypeModel.Archetype", "Archetype") .WithMany() - .HasForeignKey("UserId") + .HasForeignKey("ArchetypeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Argon.Contracts.Models.Channel", "Channel") + .WithMany("EntitlementOverwrites") + .HasForeignKey("ChannelId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("User"); + b.HasOne("Argon.Contracts.Models.ServerMember", "ServerMember") + .WithMany() + .HasForeignKey("ServerMemberId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Archetype"); + + b.Navigation("Channel"); + + b.Navigation("ServerMember"); }); - modelBuilder.Entity("Argon.Api.Entities.UsersToServerRelation", b => + modelBuilder.Entity("Argon.Contracts.Models.ServerMember", b => { - b.HasOne("Argon.Api.Entities.Server", "Server") - .WithMany("UsersToServerRelations") + b.HasOne("Argon.Contracts.Models.Server", "Server") + .WithMany("Users") .HasForeignKey("ServerId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Argon.Api.Entities.User", "User") - .WithMany("UsersToServerRelations") + b.HasOne("Argon.Contracts.Models.User", "User") + .WithMany("ServerMembers") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -242,16 +498,52 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("Argon.Api.Entities.Server", b => + modelBuilder.Entity("Argon.Contracts.Models.ServerMemberArchetype", b => + { + b.HasOne("Argon.Contracts.Models.ArchetypeModel.Archetype", "Archetype") + .WithMany("ServerMemberRoles") + .HasForeignKey("ArchetypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Argon.Contracts.Models.ServerMember", "ServerMember") + .WithMany("ServerMemberArchetypes") + .HasForeignKey("ServerMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Archetype"); + + b.Navigation("ServerMember"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ArchetypeModel.Archetype", b => + { + b.Navigation("ServerMemberRoles"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Channel", b => { + b.Navigation("EntitlementOverwrites"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.Server", b => + { + b.Navigation("Archetypes"); + b.Navigation("Channels"); - b.Navigation("UsersToServerRelations"); + b.Navigation("Users"); + }); + + modelBuilder.Entity("Argon.Contracts.Models.ServerMember", b => + { + b.Navigation("ServerMemberArchetypes"); }); - modelBuilder.Entity("Argon.Api.Entities.User", b => + modelBuilder.Entity("Argon.Contracts.Models.User", b => { - b.Navigation("UsersToServerRelations"); + b.Navigation("ServerMembers"); }); #pragma warning restore 612, 618 }