Add persistence
This commit is contained in:
parent
2721f57b9c
commit
c9da4cc805
@ -17,5 +17,13 @@
|
|||||||
<ItemGroup Label="Microsoft">
|
<ItemGroup Label="Microsoft">
|
||||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftVersion)" />
|
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftVersion)" />
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="$(MicrosoftVersion)" />
|
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="$(MicrosoftVersion)" />
|
||||||
|
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftVersion)" />
|
||||||
|
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup Label="EntityFramework">
|
||||||
|
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
|
||||||
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.3" />
|
||||||
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.3" />
|
||||||
|
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -16,6 +16,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Host", "src\Nocr
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Api.Contracts", "src\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj", "{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Api.Contracts", "src\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj", "{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Contracts", "Contracts", "{CA3AA87B-9217-4A2D-9EBA-BFC415B63818}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.Users.Persistence", "src\Nocr.Users.Persistence\Nocr.Users.Persistence.csproj", "{51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -38,5 +42,12 @@ Global
|
|||||||
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{51C01BA8-E3E1-45F4-9DDF-6E08DAF5BB46}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{4DDFB05F-DFC7-4BD6-B593-AD52CF1B002E} = {CA3AA87B-9217-4A2D-9EBA-BFC415B63818}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Nocr.Users.AppServices.Users.Repositories;
|
|
||||||
using Nocr.Users.AppServices.Users.Services;
|
using Nocr.Users.AppServices.Users.Services;
|
||||||
|
|
||||||
namespace Nocr.Users.AppServices;
|
namespace Nocr.Users.AppServices;
|
||||||
@ -11,8 +10,6 @@ public static class ServiceCollectionExtensions
|
|||||||
if (services == null)
|
if (services == null)
|
||||||
throw new ArgumentNullException(nameof(services));
|
throw new ArgumentNullException(nameof(services));
|
||||||
|
|
||||||
// Add registrations here
|
|
||||||
services.AddSingleton<IUsersRepository, InMemoryUsersRepository>();
|
|
||||||
services.AddScoped<IUsersService, UsersService>();
|
services.AddScoped<IUsersService, UsersService>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
using Nocr.Users.Api.Contracts.Users;
|
|
||||||
|
|
||||||
namespace Nocr.Users.AppServices.Users.Repositories;
|
|
||||||
|
|
||||||
public sealed class InMemoryUsersRepository : IUsersRepository
|
|
||||||
{
|
|
||||||
private long _id = 0;
|
|
||||||
|
|
||||||
private long _userIdentityId = 0;
|
|
||||||
|
|
||||||
private readonly List<User> _users = new();
|
|
||||||
|
|
||||||
public Task<long> Create(User user, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var id = Interlocked.Increment(ref _id);
|
|
||||||
user.Id = id;
|
|
||||||
_users.Add(user);
|
|
||||||
|
|
||||||
foreach (var identity in user.Identities)
|
|
||||||
{
|
|
||||||
identity.Id = Interlocked.Increment(ref _userIdentityId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.FromResult(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<User?> GetUserById(long id, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return Task.FromResult(_users.FirstOrDefault(x => x.Id == id));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<User?> GetByIdentity(UserIdentityType identityType, string identity,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var user = _users.SingleOrDefault(x => x.Identities.Any(i =>
|
|
||||||
i.Type == identityType && i.Identity.Equals(identity, StringComparison.OrdinalIgnoreCase)));
|
|
||||||
|
|
||||||
return Task.FromResult(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -10,6 +10,13 @@ public sealed class User
|
|||||||
|
|
||||||
public IReadOnlyCollection<UserIdentity> Identities => _identities;
|
public IReadOnlyCollection<UserIdentity> Identities => _identities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used by ef.
|
||||||
|
/// </summary>
|
||||||
|
private User()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private User(string username, params UserIdentity[] identities)
|
private User(string username, params UserIdentity[] identities)
|
||||||
{
|
{
|
||||||
Username = username;
|
Username = username;
|
||||||
|
|||||||
@ -8,6 +8,8 @@ public sealed class UserIdentity
|
|||||||
|
|
||||||
public string Identity { get; private set; }
|
public string Identity { get; private set; }
|
||||||
|
|
||||||
|
public long UserId { get; private set; }
|
||||||
|
|
||||||
public UserIdentityType Type { get; private set; }
|
public UserIdentityType Type { get; private set; }
|
||||||
|
|
||||||
private UserIdentity(string identity, UserIdentityType type)
|
private UserIdentity(string identity, UserIdentityType type)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Nocr.Users.AppServices;
|
using Nocr.Users.AppServices;
|
||||||
using Nocr.Users.Core.Dates;
|
using Nocr.Users.Core.Dates;
|
||||||
|
using Nocr.Users.Persistence;
|
||||||
|
|
||||||
namespace Nocr.Users.Host.Infrastructure;
|
namespace Nocr.Users.Host.Infrastructure;
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ public class Startup
|
|||||||
services.AddSwaggerGen();
|
services.AddSwaggerGen();
|
||||||
|
|
||||||
services.AddAppServices();
|
services.AddAppServices();
|
||||||
|
services.AddEfPersistence(Configuration.GetConnectionString(nameof(UsersContext))!);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" />
|
<PackageReference Include="Serilog.AspNetCore" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" />
|
<PackageReference Include="Swashbuckle.AspNetCore" />
|
||||||
@ -14,6 +15,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj" />
|
<ProjectReference Include="..\Nocr.Users.Api.Contracts\Nocr.Users.Api.Contracts.csproj" />
|
||||||
<ProjectReference Include="..\Nocr.Users.AppServices\Nocr.Users.AppServices.csproj" />
|
<ProjectReference Include="..\Nocr.Users.AppServices\Nocr.Users.AppServices.csproj" />
|
||||||
|
<ProjectReference Include="..\Nocr.Users.Persistence\Nocr.Users.Persistence.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -8,5 +8,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"UsersContext": "server=localhost;port=3307;database=nocr_users;uid=root;pwd=toor"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,5 +18,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"UsersContext": "server=nocr-users-db;port=3306;database=nocr_users;uid=root;pwd=toor"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence;
|
||||||
|
|
||||||
|
public class DesignTimeTextMatcherContextFactory : IDesignTimeDbContextFactory<UsersContext>
|
||||||
|
{
|
||||||
|
public UsersContext CreateDbContext(string[] args)
|
||||||
|
{
|
||||||
|
var optionsBuilder = new DbContextOptionsBuilder<UsersContext>();
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.json")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var connectionString = configuration.GetConnectionString("MariaLocal");
|
||||||
|
optionsBuilder.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion));
|
||||||
|
|
||||||
|
return new UsersContext(optionsBuilder.Options);
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.Designer.cs
generated
Normal file
93
src/Nocr.Users.Persistence/Migrations/20240330070727_InitialMigration.Designer.cs
generated
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Nocr.Users.Persistence;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(UsersContext))]
|
||||||
|
[Migration("20240330070727_InitialMigration")]
|
||||||
|
partial class InitialMigration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.3")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Username")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UX_users_username");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.UserIdentity", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Identity")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("UserId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("Identity", "Type")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UX_users_identity_identity_type");
|
||||||
|
|
||||||
|
b.ToTable("UserIdentity");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.UserIdentity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Nocr.Users.AppServices.Users.User", null)
|
||||||
|
.WithMany("Identities")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.NoAction)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Identities");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class InitialMigration : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterDatabase()
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Users",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Username = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Users", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "UserIdentity",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Identity = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||||
|
Type = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_UserIdentity", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_UserIdentity_Users_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id");
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_UserIdentity_UserId",
|
||||||
|
table: "UserIdentity",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "UX_users_identity_identity_type",
|
||||||
|
table: "UserIdentity",
|
||||||
|
columns: new[] { "Identity", "Type" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "UX_users_username",
|
||||||
|
table: "Users",
|
||||||
|
column: "Username",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "UserIdentity");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Nocr.Users.Persistence;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(UsersContext))]
|
||||||
|
partial class UsersContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.3")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Username")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UX_users_username");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.UserIdentity", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Identity")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("UserId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("Identity", "Type")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UX_users_identity_identity_type");
|
||||||
|
|
||||||
|
b.ToTable("UserIdentity");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.UserIdentity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Nocr.Users.AppServices.Users.User", null)
|
||||||
|
.WithMany("Identities")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.NoAction)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Nocr.Users.AppServices.Users.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Identities");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/Nocr.Users.Persistence/Nocr.Users.Persistence.csproj
Normal file
26
src/Nocr.Users.Persistence/Nocr.Users.Persistence.csproj
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
|
||||||
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Nocr.Users.AppServices\Nocr.Users.AppServices.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="appsettings.json" />
|
||||||
|
<Content Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
32
src/Nocr.Users.Persistence/ServiceCollectionExtensions.cs
Normal file
32
src/Nocr.Users.Persistence/ServiceCollectionExtensions.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Nocr.Users.AppServices.Users.Repositories;
|
||||||
|
using Nocr.Users.Persistence.Users;
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence;
|
||||||
|
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddEfPersistence(this IServiceCollection services, string connectionString)
|
||||||
|
{
|
||||||
|
if (services == null)
|
||||||
|
throw new ArgumentNullException(nameof(services));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(connectionString))
|
||||||
|
throw new ArgumentNullException(nameof(connectionString));
|
||||||
|
|
||||||
|
services.AddScoped<IUsersRepository, UsersRepository>();
|
||||||
|
|
||||||
|
services.AddDbContext<UsersContext>(
|
||||||
|
(ctx, context) =>
|
||||||
|
{
|
||||||
|
context.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion),
|
||||||
|
builder => builder.MigrationsAssembly(typeof(UsersContext).Assembly.FullName))
|
||||||
|
.UseLoggerFactory(ctx.GetRequiredService<ILoggerFactory>());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/Nocr.Users.Persistence/Users/UserConfiguration.cs
Normal file
39
src/Nocr.Users.Persistence/Users/UserConfiguration.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using Nocr.Users.AppServices.Users;
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence.Users;
|
||||||
|
|
||||||
|
public class UserConfiguration : IEntityTypeConfiguration<User>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<User> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(x => x.Id);
|
||||||
|
builder.Property(x => x.Username)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.HasIndex(x => x.Username)
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UX_users_username");
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasMany(u => u.Identities)
|
||||||
|
.WithOne()
|
||||||
|
.HasForeignKey(x => x.UserId)
|
||||||
|
.OnDelete(DeleteBehavior.NoAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserIdentityConfiguration : IEntityTypeConfiguration<UserIdentity>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<UserIdentity> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(x => x.Id);
|
||||||
|
builder.Property(x => x.Identity)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.HasIndex(x => new { x.Identity, x.Type })
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UX_users_identity_identity_type");
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/Nocr.Users.Persistence/Users/UsersRepository.cs
Normal file
38
src/Nocr.Users.Persistence/Users/UsersRepository.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Nocr.Users.Api.Contracts.Users;
|
||||||
|
using Nocr.Users.AppServices.Users;
|
||||||
|
using Nocr.Users.AppServices.Users.Repositories;
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence.Users;
|
||||||
|
|
||||||
|
public class UsersRepository : IUsersRepository
|
||||||
|
{
|
||||||
|
private readonly UsersContext _db;
|
||||||
|
|
||||||
|
public UsersRepository(UsersContext db)
|
||||||
|
{
|
||||||
|
_db = db ?? throw new ArgumentNullException(nameof(db));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<long> Create(User user, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var userId = await _db.Users.AddAsync(user, cancellationToken);
|
||||||
|
await _db.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
return userId.Entity.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<User?> GetUserById(long id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _db.Users.Include(x => x.Identities)
|
||||||
|
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<User?> GetByIdentity(UserIdentityType identityType, string identity,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _db.Users.Include(x => x.Identities)
|
||||||
|
.FirstOrDefaultAsync(x => x.Identities.Any(i => i.Type == identityType && i.Identity == identity),
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/Nocr.Users.Persistence/UsersContext.cs
Normal file
23
src/Nocr.Users.Persistence/UsersContext.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Nocr.Users.AppServices.Users;
|
||||||
|
using Nocr.Users.Persistence.Users;
|
||||||
|
|
||||||
|
namespace Nocr.Users.Persistence;
|
||||||
|
|
||||||
|
public class UsersContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<User> Users { get; set; }
|
||||||
|
|
||||||
|
public UsersContext(DbContextOptions options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.ApplyConfiguration(new UserConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new UserIdentityConfiguration());
|
||||||
|
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/Nocr.Users.Persistence/appsettings.json
Normal file
5
src/Nocr.Users.Persistence/appsettings.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"MariaLocal": "server=localhost;port=3307;database=nocr_users;uid=root;pwd=toor"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user