Move projects to src; add Neutrino secret

This commit is contained in:
Holden
2026-06-19 22:52:38 -05:00
parent 2cfc5e7369
commit 95751904fa
90 changed files with 32 additions and 10 deletions
@@ -0,0 +1,20 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using RecNet.Domain.GameVersions;
namespace RecNet.Infrastructure.Persistence.Configurations;
public class GameVersionConfiguration : IEntityTypeConfiguration<GameVersion>
{
public void Configure(EntityTypeBuilder<GameVersion> builder)
{
builder.HasKey(x => x.Version);
builder.Property(x => x.Version)
.HasMaxLength(32)
.IsRequired();
builder.Property(x => x.IsValid)
.IsRequired();
}
}
@@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using RecNet.Domain.Profiles;
namespace RecNet.Infrastructure.Persistence.Configurations;
public class ProfileConfiguration : IEntityTypeConfiguration<Profile>
{
public void Configure(EntityTypeBuilder<Profile> builder)
{
builder.HasKey(x => x.ProfileId);
builder.Property(x => x.Name)
.HasMaxLength(Profile.MaxNameLength)
.IsRequired();
builder.Property(x => x.Platform)
.HasConversion<string>()
.HasMaxLength(50)
.IsRequired();
builder.Property(x => x.PlatformId)
.HasMaxLength(50)
.IsRequired();
builder.Property(x => x.DeviceIds)
.HasColumnType("jsonb");
builder.Property(x => x.CreatedAt)
.IsRequired();
builder.HasIndex(x => new { x.Platform, x.PlatformId })
.IsUnique();
}
}
@@ -0,0 +1,21 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using RecNet.Domain.Configuration;
namespace RecNet.Infrastructure.Persistence.Configurations;
public class ServerConfigConfiguration : IEntityTypeConfiguration<ServerConfig>
{
public void Configure(EntityTypeBuilder<ServerConfig> builder)
{
builder.HasKey(x => x.Key);
builder.Property(x => x.Key)
.HasMaxLength(128)
.IsRequired();
builder.Property(x => x.Value)
.HasColumnType("jsonb")
.IsRequired();
}
}
@@ -0,0 +1,18 @@
using Microsoft.EntityFrameworkCore;
using RecNet.Domain.Configuration;
using RecNet.Domain.GameVersions;
using RecNet.Domain.Profiles;
namespace RecNet.Infrastructure.Persistence;
public class DatabaseContext(DbContextOptions<DatabaseContext> options) : DbContext(options)
{
public DbSet<Profile> Profiles => Set<Profile>();
public DbSet<GameVersion> GameVersions => Set<GameVersion>();
public DbSet<ServerConfig> ServerConfigs => Set<ServerConfig>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(typeof(DatabaseContext).Assembly);
}
}
@@ -0,0 +1,66 @@
// <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("20260618180145_Initial")]
partial class Initial
{
/// <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.Entities.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<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");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,44 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace RecNet.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Profiles",
columns: table => new
{
ProfileId = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
Platform = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
PlatformId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
DeviceIds = table.Column<string>(type: "jsonb", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Profiles", x => x.ProfileId);
});
migrationBuilder.CreateIndex(
name: "IX_Profiles_Platform_PlatformId",
table: "Profiles",
columns: new[] { "Platform", "PlatformId" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Profiles");
}
}
}
@@ -0,0 +1,81 @@
// <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("20260618183916_ServerConfigs")]
partial class ServerConfigs
{
/// <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.Entities.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.Entities.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<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");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace RecNet.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class ServerConfigs : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ServerConfigs",
columns: table => new
{
Key = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
Value = table.Column<string>(type: "jsonb", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerConfigs", x => x.Key);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ServerConfigs");
}
}
}
@@ -0,0 +1,87 @@
// <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("20260619025601_ProfileToggles")]
partial class ProfileToggles
{
/// <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.Entities.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.Entities.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>("IsModerator")
.HasColumnType("boolean");
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");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace RecNet.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class ProfileToggles : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsBanned",
table: "Profiles",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<bool>(
name: "IsModerator",
table: "Profiles",
type: "boolean",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsBanned",
table: "Profiles");
migrationBuilder.DropColumn(
name: "IsModerator",
table: "Profiles");
}
}
}
@@ -0,0 +1,101 @@
// <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("20260619201140_GameVersion")]
partial class GameVersion
{
/// <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.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>("IsModerator")
.HasColumnType("boolean");
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");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace RecNet.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class GameVersion : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "GameVersions",
columns: table => new
{
Version = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
IsValid = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GameVersions", x => x.Version);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "GameVersions");
}
}
}
@@ -0,0 +1,98 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using RecNet.Infrastructure.Persistence;
#nullable disable
namespace RecNet.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(DatabaseContext))]
partial class DatabaseContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(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.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>("IsModerator")
.HasColumnType("boolean");
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");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,11 @@
using Microsoft.EntityFrameworkCore;
using RecNet.Domain.GameVersions;
namespace RecNet.Infrastructure.Persistence.Repositories;
public class GameVersionRepository(DatabaseContext dbContext) : IGameVersionRepository
{
public Task<GameVersion?> GetAsync(string version, CancellationToken ct = default)
=> dbContext.GameVersions
.FirstOrDefaultAsync(x => x.Version == version, ct);
}
@@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore;
using RecNet.Domain.Common;
using RecNet.Domain.Profiles;
namespace RecNet.Infrastructure.Persistence.Repositories;
public class ProfileRepository(DatabaseContext dbContext) : IProfileRepository
{
public Task<Profile?> GetByIdAsync(
Guid profileId,
CancellationToken ct = default)
=> dbContext.Profiles
.FirstOrDefaultAsync(x => x.ProfileId == profileId, ct);
public async Task<IReadOnlyList<Profile>> GetByIdsAsync(
List<Guid> profileIds,
CancellationToken ct = default)
=> await dbContext.Profiles
.Where(x => profileIds.Contains(x.ProfileId))
.ToListAsync(ct);
public Task<Profile?> GetByPlatform(
PlatformType platform,
string platformId,
CancellationToken ct = default)
=> dbContext.Profiles
.FirstOrDefaultAsync(x =>
x.Platform == platform &&
x.PlatformId == platformId,
ct);
public async Task AddAsync(
Profile profile,
CancellationToken ct = default)
=> await dbContext.Profiles.AddAsync(profile, ct);
public Task SaveChangesAsync(CancellationToken ct = default)
=> dbContext.SaveChangesAsync(ct);
}
@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using RecNet.Domain.Configuration;
namespace RecNet.Infrastructure.Persistence.Repositories;
public class ServerConfigRepository(DatabaseContext dbContext) : IServerConfigRepository
{
public Task<ServerConfig?> GetAsync(string key, CancellationToken ct = default)
=> dbContext.ServerConfigs
.FirstOrDefaultAsync(x => x.Key == key, ct);
public async Task SetAsync(string key, string value, CancellationToken ct = default)
{
var config = await GetAsync(key, ct);
if (config is null)
{
config = ServerConfig.Create(key, value);
await dbContext.ServerConfigs.AddAsync(config, ct);
return;
}
config.SetValue(value);
}
public Task SaveChangesAsync(CancellationToken ct = default)
=> dbContext.SaveChangesAsync(ct);
}