Add relationships feature and EF migration
This commit is contained in:
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RecNet.Application.Common.Security;
|
||||
using RecNet.Application.Profiles;
|
||||
using RecNet.Application.Profiles.Avatar;
|
||||
using AvatarEntity = RecNet.Domain.Profiles.Avatar;
|
||||
|
||||
namespace API.Controllers.Avatar.V1;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using API.Contracts.Profiles.Responses;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RecNet.Application.Profiles;
|
||||
using RecNet.Application.Profiles.Login;
|
||||
using LoginRequest = API.Contracts.Profiles.Requests.LoginRequest;
|
||||
|
||||
namespace API.Controllers.Profiles.V1;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RecNet.Application.Common.Security;
|
||||
using RecNet.Application.Profiles;
|
||||
using RecNet.Application.Profiles.Relationships;
|
||||
|
||||
namespace API.Controllers.Relationships.V1;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]/v1")]
|
||||
public class RelationshipsController(IRelationshipService relationshipService) : ControllerBase
|
||||
{
|
||||
[HttpGet("get")]
|
||||
public async Task<IReadOnlyList<RelationshipDTO>> GetRelationships(CancellationToken ct)
|
||||
{
|
||||
var profileId = User.GetProfileId();
|
||||
|
||||
return await relationshipService.GetRelationshipsAsync(profileId, ct);
|
||||
}
|
||||
|
||||
[HttpPost("update")]
|
||||
public async Task<ActionResult<RelationshipDTO>> UpdateRelationship(
|
||||
[FromBody] RelationshipDTO request,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var profileId = User.GetProfileId();
|
||||
|
||||
return Ok(
|
||||
await relationshipService.UpdateRelationshipAsync
|
||||
(
|
||||
profileId: profileId,
|
||||
command: new UpdateRelationshipCommand(request.ProfileId, request.Muted, request.Ignored),
|
||||
ct: ct
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RecNet.Application.Common.Security;
|
||||
using RecNet.Application.Profiles;
|
||||
using RecNet.Application.Profiles.Settings;
|
||||
|
||||
namespace API.Controllers.Settings.V1;
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using AutoMapper;
|
||||
using RecNet.Application.Profiles;
|
||||
using RecNet.Application.Profiles.Avatar;
|
||||
using RecNet.Application.Profiles.Relationships;
|
||||
using RecNet.Application.Profiles.Settings;
|
||||
|
||||
namespace RecNet.Application.Common.Mapping;
|
||||
|
||||
@@ -9,6 +12,7 @@ public class ApplicationMappingProfile : Profile
|
||||
{
|
||||
CreateMap<Domain.Profiles.Profile, ProfileDTO>();
|
||||
CreateMap<Domain.Profiles.Avatar, AvatarDTO>();
|
||||
CreateMap<Domain.Profiles.Relationship, RelationshipDTO>();
|
||||
CreateMap<Domain.Profiles.PlayerSetting, PlayerSettingDTO>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using RecNet.Application.Neutrino;
|
||||
using RecNet.Application.Profiles;
|
||||
using RecNet.Application.Profiles.Login;
|
||||
using RecNet.Application.Profiles.Relationships;
|
||||
|
||||
namespace RecNet.Application;
|
||||
|
||||
@@ -13,6 +15,7 @@ public static class DependencyInjection
|
||||
services.AddScoped<NameGenerator>();
|
||||
|
||||
services.AddScoped<IProfileService, ProfileService>();
|
||||
services.AddScoped<IRelationshipService, RelationshipService>();
|
||||
services.AddScoped<INeutrinoAuthorizationService, NeutrinoAuthorizationService>();
|
||||
|
||||
return services;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace RecNet.Application.Profiles;
|
||||
namespace RecNet.Application.Profiles.Avatar;
|
||||
|
||||
public class AvatarDTO
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace RecNet.Application.Profiles;
|
||||
namespace RecNet.Application.Profiles.Avatar;
|
||||
|
||||
public sealed record UpdateAvatarCommand(
|
||||
string? OutfitSelections,
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
using RecNet.Application.Profiles.Avatar;
|
||||
using RecNet.Application.Profiles.Login;
|
||||
using RecNet.Application.Profiles.Settings;
|
||||
|
||||
namespace RecNet.Application.Profiles;
|
||||
|
||||
public interface IProfileService
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using RecNet.Domain.Common;
|
||||
|
||||
namespace RecNet.Application.Profiles;
|
||||
namespace RecNet.Application.Profiles.Login;
|
||||
|
||||
public sealed record LoginProfileCommand(
|
||||
string AppVersion,
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace RecNet.Application.Profiles;
|
||||
namespace RecNet.Application.Profiles.Login;
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using RecNet.Application.Common.Interfaces;
|
||||
using RecNet.Domain.Profiles.Names;
|
||||
|
||||
namespace RecNet.Application.Profiles;
|
||||
namespace RecNet.Application.Profiles.Login;
|
||||
|
||||
public class NameGenerator(IConfigService configService)
|
||||
{
|
||||
@@ -1,10 +1,14 @@
|
||||
using AutoMapper;
|
||||
using RecNet.Application.Common.Interfaces;
|
||||
using RecNet.Application.Common.Security;
|
||||
using RecNet.Application.Profiles.Avatar;
|
||||
using RecNet.Application.Profiles.Login;
|
||||
using RecNet.Application.Profiles.Settings;
|
||||
using RecNet.Domain.Common;
|
||||
using RecNet.Domain.GameVersions;
|
||||
using RecNet.Domain.Profiles;
|
||||
using ProfileEntity = RecNet.Domain.Profiles.Profile;
|
||||
using AvatarEntity = RecNet.Domain.Profiles.Avatar;
|
||||
|
||||
namespace RecNet.Application.Profiles;
|
||||
|
||||
@@ -45,7 +49,7 @@ public class ProfileService(
|
||||
return null;
|
||||
|
||||
profile.SetAvatar(
|
||||
Avatar.Create(
|
||||
AvatarEntity.Create(
|
||||
command.OutfitSelections,
|
||||
command.SkinColor,
|
||||
command.HairColor
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace RecNet.Application.Profiles.Relationships;
|
||||
|
||||
public interface IRelationshipService
|
||||
{
|
||||
Task<IReadOnlyList<RelationshipDTO>> GetRelationshipsAsync(Guid profileId, CancellationToken ct = default);
|
||||
Task<RelationshipDTO> UpdateRelationshipAsync(Guid profileId, UpdateRelationshipCommand command, CancellationToken ct = default);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace RecNet.Application.Profiles.Relationships;
|
||||
|
||||
public class RelationshipDTO
|
||||
{
|
||||
[JsonPropertyName("ProfileId")]
|
||||
public Guid ProfileId { get; set; }
|
||||
|
||||
[JsonPropertyName("Muted")]
|
||||
public bool Muted { get; set; }
|
||||
|
||||
[JsonPropertyName("Ignored")]
|
||||
public bool Ignored { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using AutoMapper;
|
||||
using RecNet.Domain.Profiles;
|
||||
|
||||
namespace RecNet.Application.Profiles.Relationships;
|
||||
|
||||
public class RelationshipService(IRelationshipRepository repository, IMapper mapper) : IRelationshipService
|
||||
{
|
||||
public async Task<IReadOnlyList<RelationshipDTO>> GetRelationshipsAsync(
|
||||
Guid profileId,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var relationships = await repository.GetAllOwnedRelationships(profileId, ct);
|
||||
|
||||
return mapper.Map<List<RelationshipDTO>>(relationships);
|
||||
}
|
||||
|
||||
public async Task<RelationshipDTO> UpdateRelationshipAsync(Guid profileId, UpdateRelationshipCommand command, CancellationToken ct = default)
|
||||
{
|
||||
var relationship = await repository.GetAsync(profileId, command.ProfileId, ct);
|
||||
if (relationship == null)
|
||||
{
|
||||
|
||||
relationship = Relationship.Create(profileId, command.ProfileId);
|
||||
await repository.AddAsync(relationship, ct);
|
||||
}
|
||||
|
||||
relationship.Mutate(command.Muted, command.Ignored);
|
||||
|
||||
await repository.SaveChangesAsync(ct);
|
||||
|
||||
return mapper.Map<RelationshipDTO>(relationship);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace RecNet.Application.Profiles.Relationships;
|
||||
|
||||
public record UpdateRelationshipCommand(
|
||||
Guid ProfileId,
|
||||
bool Muted,
|
||||
bool Ignored);
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace RecNet.Application.Profiles;
|
||||
namespace RecNet.Application.Profiles.Settings;
|
||||
|
||||
public class PlayerSettingDTO
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace RecNet.Application.Profiles;
|
||||
namespace RecNet.Application.Profiles.Settings;
|
||||
|
||||
public sealed record UpdatePlayerSettingCommand(
|
||||
string Key,
|
||||
10
src/RecNet.Domain/Profiles/IRelationshipRepository.cs
Normal file
10
src/RecNet.Domain/Profiles/IRelationshipRepository.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace RecNet.Domain.Profiles;
|
||||
|
||||
public interface IRelationshipRepository
|
||||
{
|
||||
Task<Relationship?> GetAsync(Guid ownerId, Guid profileId, CancellationToken ct = default);
|
||||
Task<IReadOnlyList<Relationship>> GetAllOwnedRelationships(Guid ownerId, CancellationToken ct = default);
|
||||
|
||||
Task AddAsync(Relationship relationship, CancellationToken ct = default);
|
||||
Task SaveChangesAsync(CancellationToken ct = default);
|
||||
}
|
||||
@@ -39,6 +39,7 @@ public class Profile
|
||||
|
||||
public Avatar Avatar { get; private set; } = Avatar.Empty;
|
||||
public ICollection<PlayerSetting> Settings { get; } = [];
|
||||
public ICollection<Relationship> Relationships { get; } = [];
|
||||
|
||||
public static Profile Create(
|
||||
string name,
|
||||
|
||||
35
src/RecNet.Domain/Profiles/Relationship.cs
Normal file
35
src/RecNet.Domain/Profiles/Relationship.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using RecNet.Domain.Exceptions;
|
||||
|
||||
namespace RecNet.Domain.Profiles;
|
||||
|
||||
public class Relationship
|
||||
{
|
||||
public Guid OwnerProfileId { get; private set; }
|
||||
|
||||
public Guid ProfileId { get; private set; }
|
||||
|
||||
public bool Muted { get; private set; }
|
||||
public bool Ignored { get; private set; }
|
||||
|
||||
private Relationship()
|
||||
{
|
||||
}
|
||||
|
||||
public static Relationship Create(Guid ownerProfileId, Guid profileId)
|
||||
{
|
||||
if (ownerProfileId == Guid.Empty || profileId == Guid.Empty)
|
||||
throw new DomainException("Profile IDs cannot be null.");
|
||||
|
||||
return new Relationship
|
||||
{
|
||||
OwnerProfileId = ownerProfileId,
|
||||
ProfileId = profileId
|
||||
};
|
||||
}
|
||||
|
||||
public void Mutate(bool muted, bool ignored)
|
||||
{
|
||||
Muted = muted;
|
||||
Ignored = ignored;
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ public static class DependencyInjection
|
||||
|
||||
builder.Services.AddScoped<IGameVersionRepository, GameVersionRepository>();
|
||||
builder.Services.AddScoped<IProfileRepository, ProfileRepository>();
|
||||
builder.Services.AddScoped<IRelationshipRepository, RelationshipRepository>();
|
||||
builder.Services.AddScoped<IServerConfigRepository, ServerConfigRepository>();
|
||||
|
||||
builder.Services.AddScoped<IConfigService, ConfigService>();
|
||||
|
||||
@@ -35,6 +35,13 @@ public class ProfileConfiguration : IEntityTypeConfiguration<Profile>
|
||||
|
||||
builder.Navigation(x => x.Settings)
|
||||
.UsePropertyAccessMode(PropertyAccessMode.Field);
|
||||
|
||||
builder.HasMany(x => x.Relationships)
|
||||
.WithOne()
|
||||
.HasForeignKey(x => x.OwnerProfileId);
|
||||
|
||||
builder.Navigation(x => x.Relationships)
|
||||
.UsePropertyAccessMode(PropertyAccessMode.Field);
|
||||
|
||||
builder.OwnsOne(x => x.Avatar);
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using RecNet.Domain.Profiles;
|
||||
|
||||
namespace RecNet.Infrastructure.Persistence.Configurations;
|
||||
|
||||
public class RelationshipConfiguration : IEntityTypeConfiguration<Relationship>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Relationship> builder)
|
||||
{
|
||||
builder.HasKey(x => new { x.OwnerProfileId, x.ProfileId });
|
||||
|
||||
builder.Property(x => x.OwnerProfileId)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.ProfileId)
|
||||
.IsRequired();
|
||||
|
||||
builder.HasOne<Profile>()
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.ProfileId)
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ public class DatabaseContext(DbContextOptions<DatabaseContext> options) : DbCont
|
||||
{
|
||||
public DbSet<Profile> Profiles => Set<Profile>();
|
||||
public DbSet<PlayerSetting> PlayerSettings => Set<PlayerSetting>();
|
||||
public DbSet<Relationship> Relationships => Set<Relationship>();
|
||||
public DbSet<GameVersion> GameVersions => Set<GameVersion>();
|
||||
public DbSet<ServerConfig> ServerConfigs => Set<ServerConfig>();
|
||||
|
||||
|
||||
209
src/RecNet.Infrastructure/Persistence/Migrations/20260626215037_Relationships.Designer.cs
generated
Normal file
209
src/RecNet.Infrastructure/Persistence/Migrations/20260626215037_Relationships.Designer.cs
generated
Normal file
@@ -0,0 +1,209 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using RecNet.Infrastructure.Persistence;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace RecNet.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20260626215037_Relationships")]
|
||||
partial class Relationships
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Configuration.ServerConfig", b =>
|
||||
{
|
||||
b.Property<string>("Key")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.HasKey("Key");
|
||||
|
||||
b.ToTable("ServerConfigs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.GameVersions.GameVersion", b =>
|
||||
{
|
||||
b.Property<string>("Version")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)");
|
||||
|
||||
b.Property<bool>("IsValid")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.HasKey("Version");
|
||||
|
||||
b.ToTable("GameVersions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.PlayerSetting", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("UserId", "Key");
|
||||
|
||||
b.ToTable("PlayerSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Profile", b =>
|
||||
{
|
||||
b.Property<Guid>("ProfileId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.PrimitiveCollection<string>("DeviceIds")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<bool>("IsBanned")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsDeveloper")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsModerator")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<byte[]>("MetaAuthenticationSecret")
|
||||
.IsRequired()
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)");
|
||||
|
||||
b.Property<string>("Platform")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("PlatformId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.HasKey("ProfileId");
|
||||
|
||||
b.HasIndex("Platform", "PlatformId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Relationship", b =>
|
||||
{
|
||||
b.Property<Guid>("OwnerProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Ignored")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("Muted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.HasKey("OwnerProfileId", "ProfileId");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.ToTable("Relationships");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.PlayerSetting", b =>
|
||||
{
|
||||
b.HasOne("RecNet.Domain.Profiles.Profile", null)
|
||||
.WithMany("Settings")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Profile", b =>
|
||||
{
|
||||
b.OwnsOne("RecNet.Domain.Profiles.Avatar", "Avatar", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("ProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<string>("OutfitSelections")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.HasKey("ProfileId");
|
||||
|
||||
b1.ToTable("Profiles");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ProfileId");
|
||||
});
|
||||
|
||||
b.Navigation("Avatar")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Relationship", b =>
|
||||
{
|
||||
b.HasOne("RecNet.Domain.Profiles.Profile", null)
|
||||
.WithMany("Relationships")
|
||||
.HasForeignKey("OwnerProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("RecNet.Domain.Profiles.Profile", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Profile", b =>
|
||||
{
|
||||
b.Navigation("Relationships");
|
||||
|
||||
b.Navigation("Settings");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace RecNet.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Relationships : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Relationships",
|
||||
columns: table => new
|
||||
{
|
||||
OwnerProfileId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
ProfileId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Muted = table.Column<bool>(type: "boolean", nullable: false),
|
||||
Ignored = table.Column<bool>(type: "boolean", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Relationships", x => new { x.OwnerProfileId, x.ProfileId });
|
||||
table.ForeignKey(
|
||||
name: "FK_Relationships_Profiles_OwnerProfileId",
|
||||
column: x => x.OwnerProfileId,
|
||||
principalTable: "Profiles",
|
||||
principalColumn: "ProfileId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Relationships_Profiles_ProfileId",
|
||||
column: x => x.ProfileId,
|
||||
principalTable: "Profiles",
|
||||
principalColumn: "ProfileId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Relationships_ProfileId",
|
||||
table: "Relationships",
|
||||
column: "ProfileId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Relationships");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,6 +118,27 @@ namespace RecNet.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Relationship", b =>
|
||||
{
|
||||
b.Property<Guid>("OwnerProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ProfileId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Ignored")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("Muted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.HasKey("OwnerProfileId", "ProfileId");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.ToTable("Relationships");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.PlayerSetting", b =>
|
||||
{
|
||||
b.HasOne("RecNet.Domain.Profiles.Profile", null)
|
||||
@@ -158,8 +179,25 @@ namespace RecNet.Infrastructure.Persistence.Migrations
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Relationship", b =>
|
||||
{
|
||||
b.HasOne("RecNet.Domain.Profiles.Profile", null)
|
||||
.WithMany("Relationships")
|
||||
.HasForeignKey("OwnerProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("RecNet.Domain.Profiles.Profile", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RecNet.Domain.Profiles.Profile", b =>
|
||||
{
|
||||
b.Navigation("Relationships");
|
||||
|
||||
b.Navigation("Settings");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RecNet.Domain.Profiles;
|
||||
|
||||
namespace RecNet.Infrastructure.Persistence.Repositories;
|
||||
|
||||
public class RelationshipRepository(DatabaseContext dbContext) : IRelationshipRepository
|
||||
{
|
||||
public Task<Relationship?> GetAsync(
|
||||
Guid ownerId,
|
||||
Guid profileId,
|
||||
CancellationToken ct = default)
|
||||
=> dbContext.Relationships
|
||||
.FirstOrDefaultAsync(x =>
|
||||
x.OwnerProfileId == ownerId &&
|
||||
x.ProfileId == profileId,
|
||||
ct);
|
||||
|
||||
public async Task<IReadOnlyList<Relationship>> GetAllOwnedRelationships(Guid ownerId, CancellationToken ct = default)
|
||||
=> await dbContext.Relationships
|
||||
.AsNoTracking()
|
||||
.Where(x => x.OwnerProfileId == ownerId)
|
||||
.ToListAsync(ct);
|
||||
|
||||
public async Task AddAsync(
|
||||
Relationship relationship,
|
||||
CancellationToken ct = default)
|
||||
=> await dbContext.Relationships.AddAsync(relationship, ct);
|
||||
|
||||
public Task SaveChangesAsync(CancellationToken ct = default)
|
||||
=> dbContext.SaveChangesAsync(ct);
|
||||
}
|
||||
Reference in New Issue
Block a user