diff --git a/src/GroundsForSupport.Server/Data/Context.cs b/src/GroundsForSupport.Server/Data/Context.cs new file mode 100644 index 0000000..5672d7d --- /dev/null +++ b/src/GroundsForSupport.Server/Data/Context.cs @@ -0,0 +1,32 @@ +using GroundsForSupport.Server.Payments; + +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; + +namespace GroundsForSupport.Server.Data; + +internal sealed class Context( + IOptions ctxOptions, + DbContextOptions options +) : DbContext(options) +{ + private const string DataSourceKey = "Data Source="; + private readonly ContextOptions _ctxOptions = ctxOptions.Value; + + public DbSet Payments => Set(); + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + var dbPath = _ctxOptions.GetFullyQualifiedDatabasePath(); + var dbDirectory = Path.GetDirectoryName(dbPath) ?? throw new InvalidOperationException("Database directory path could not be determined."); + + if (Directory.Exists(dbDirectory) is false) + { + Directory.CreateDirectory(dbDirectory); + } + + var connectionString = $"{DataSourceKey}{dbPath}"; + + optionsBuilder.UseSqlite(connectionString); + } +} \ No newline at end of file diff --git a/src/GroundsForSupport.Server/Data/ContextOptions.cs b/src/GroundsForSupport.Server/Data/ContextOptions.cs new file mode 100644 index 0000000..1413737 --- /dev/null +++ b/src/GroundsForSupport.Server/Data/ContextOptions.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.Options; + +namespace GroundsForSupport.Server.Data; + +internal sealed record ContextOptions +{ + public string DatabaseFilePath { get; init; } = string.Empty; + public string GetFullyQualifiedDatabasePath() + { + return Path.GetFullPath(DatabaseFilePath, AppContext.BaseDirectory); + } +} + +internal sealed record ContextOptionsSetup : IConfigureOptions +{ + private const string SectionName = nameof(ContextOptions); + private readonly IConfiguration _configuration; + + public ContextOptionsSetup(IConfiguration configuration) + { + _configuration = configuration; + } + + public void Configure(ContextOptions options) + { + _configuration.GetSection(SectionName).Bind(options); + } +} \ No newline at end of file diff --git a/src/GroundsForSupport.Server/Data/MigrationService.cs b/src/GroundsForSupport.Server/Data/MigrationService.cs new file mode 100644 index 0000000..94714f2 --- /dev/null +++ b/src/GroundsForSupport.Server/Data/MigrationService.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore; + +namespace GroundsForSupport.Server.Data; + +internal sealed class MigrationService( + IServiceProvider serviceProvider, + ILogger logger +) : IHostedService +{ + private readonly IServiceProvider _serviceProvider = serviceProvider; + + public async Task StartAsync(CancellationToken cancellationToken) + { + logger.LogInformation("Applying database migrations..."); + + using var scope = _serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + await context.Database.MigrateAsync(cancellationToken); + + logger.LogInformation("Database migrations applied."); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/GroundsForSupport.Server/GroundsForSupport.Server.csproj b/src/GroundsForSupport.Server/GroundsForSupport.Server.csproj index 7b6b496..74aa631 100644 --- a/src/GroundsForSupport.Server/GroundsForSupport.Server.csproj +++ b/src/GroundsForSupport.Server/GroundsForSupport.Server.csproj @@ -8,6 +8,11 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + diff --git a/src/GroundsForSupport.Server/Migrations/20251230125831_AddPaymentsModel.Designer.cs b/src/GroundsForSupport.Server/Migrations/20251230125831_AddPaymentsModel.Designer.cs new file mode 100644 index 0000000..29df42f --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20251230125831_AddPaymentsModel.Designer.cs @@ -0,0 +1,34 @@ +// +using GroundsForSupport.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + [DbContext(typeof(Context))] + [Migration("20251230125831_AddPaymentsModel")] + partial class AddPaymentsModel + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.1"); + + modelBuilder.Entity("GroundsForSupport.Server.Payments.Payment", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Payments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/GroundsForSupport.Server/Migrations/20251230125831_AddPaymentsModel.cs b/src/GroundsForSupport.Server/Migrations/20251230125831_AddPaymentsModel.cs new file mode 100644 index 0000000..92aae8d --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20251230125831_AddPaymentsModel.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + /// + public partial class AddPaymentsModel : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Payments", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Payments", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Payments"); + } + } +} diff --git a/src/GroundsForSupport.Server/Migrations/20251231131814_AddAmountToPaymentModel.Designer.cs b/src/GroundsForSupport.Server/Migrations/20251231131814_AddAmountToPaymentModel.Designer.cs new file mode 100644 index 0000000..a0b15d4 --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20251231131814_AddAmountToPaymentModel.Designer.cs @@ -0,0 +1,37 @@ +// +using GroundsForSupport.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + [DbContext(typeof(Context))] + [Migration("20251231131814_AddAmountToPaymentModel")] + partial class AddAmountToPaymentModel + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.1"); + + modelBuilder.Entity("GroundsForSupport.Server.Payments.Payment", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Payments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/GroundsForSupport.Server/Migrations/20251231131814_AddAmountToPaymentModel.cs b/src/GroundsForSupport.Server/Migrations/20251231131814_AddAmountToPaymentModel.cs new file mode 100644 index 0000000..1cb7a51 --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20251231131814_AddAmountToPaymentModel.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + /// + public partial class AddAmountToPaymentModel : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Amount", + table: "Payments", + type: "INTEGER", + nullable: false, + defaultValue: 0L); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Amount", + table: "Payments"); + } + } +} diff --git a/src/GroundsForSupport.Server/Migrations/20260102131600_AddNameMessagePropertiesToPaymentModel.Designer.cs b/src/GroundsForSupport.Server/Migrations/20260102131600_AddNameMessagePropertiesToPaymentModel.Designer.cs new file mode 100644 index 0000000..d9618c6 --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20260102131600_AddNameMessagePropertiesToPaymentModel.Designer.cs @@ -0,0 +1,44 @@ +// +using GroundsForSupport.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + [DbContext(typeof(Context))] + [Migration("20260102131600_AddNameMessagePropertiesToPaymentModel")] + partial class AddNameMessagePropertiesToPaymentModel + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.1"); + + modelBuilder.Entity("GroundsForSupport.Server.Payments.Payment", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Payments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/GroundsForSupport.Server/Migrations/20260102131600_AddNameMessagePropertiesToPaymentModel.cs b/src/GroundsForSupport.Server/Migrations/20260102131600_AddNameMessagePropertiesToPaymentModel.cs new file mode 100644 index 0000000..b1ac7d1 --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20260102131600_AddNameMessagePropertiesToPaymentModel.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + /// + public partial class AddNameMessagePropertiesToPaymentModel : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Message", + table: "Payments", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "Name", + table: "Payments", + type: "TEXT", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Message", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "Name", + table: "Payments"); + } + } +} diff --git a/src/GroundsForSupport.Server/Migrations/20260102140326_AddCreatedAtTimeStampToPaymentsModel.Designer.cs b/src/GroundsForSupport.Server/Migrations/20260102140326_AddCreatedAtTimeStampToPaymentsModel.Designer.cs new file mode 100644 index 0000000..5dfccda --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20260102140326_AddCreatedAtTimeStampToPaymentsModel.Designer.cs @@ -0,0 +1,47 @@ +// +using GroundsForSupport.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + [DbContext(typeof(Context))] + [Migration("20260102140326_AddCreatedAtTimeStampToPaymentsModel")] + partial class AddCreatedAtTimeStampToPaymentsModel + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.1"); + + modelBuilder.Entity("GroundsForSupport.Server.Payments.Payment", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("CreatedAtUnix") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Payments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/GroundsForSupport.Server/Migrations/20260102140326_AddCreatedAtTimeStampToPaymentsModel.cs b/src/GroundsForSupport.Server/Migrations/20260102140326_AddCreatedAtTimeStampToPaymentsModel.cs new file mode 100644 index 0000000..d693557 --- /dev/null +++ b/src/GroundsForSupport.Server/Migrations/20260102140326_AddCreatedAtTimeStampToPaymentsModel.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GroundsForSupport.Server.Migrations +{ + /// + public partial class AddCreatedAtTimeStampToPaymentsModel : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatedAtUnix", + table: "Payments", + type: "INTEGER", + nullable: false, + defaultValue: 0L); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CreatedAtUnix", + table: "Payments"); + } + } +}