diff --git a/src/tvnoms-server/TvNoms.ApiService/Endpoints/UserEndpoints.cs b/src/tvnoms-server/TvNoms.ApiService/Endpoints/UserEndpoints.cs index 90d83cb..35a8ba6 100644 --- a/src/tvnoms-server/TvNoms.ApiService/Endpoints/UserEndpoints.cs +++ b/src/tvnoms-server/TvNoms.ApiService/Endpoints/UserEndpoints.cs @@ -1,5 +1,6 @@ using System.Security.Claims; using Humanizer; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using TvNoms.Core.Entities; @@ -13,6 +14,7 @@ using TvNoms.Server.Services; namespace TvNoms.Server.ApiService.Endpoints; +[EnableCors("WebAppCors")] public class UserEndpoints : Shared.Endpoints { public UserEndpoints(IEndpointRouteBuilder endpointRouteBuilder) : base(endpointRouteBuilder) { @@ -59,10 +61,12 @@ public class UserEndpoints : Shared.Endpoints { return Results.Ok(); } + [EnableCors("WebAppCors")] public async Task SignInAsync([FromServices] IUserService userService, [FromBody] SignInForm form) { return Results.Ok(await userService.SignInAsync(form)); } + [EnableCors("WebAppCors")] public async Task SignInWithAsync( [FromServices] IUserService userService, [FromServices] SignInManager signInManager, @@ -99,6 +103,7 @@ public class UserEndpoints : Shared.Endpoints { return Results.Ok(await userService.SignInWithAsync(form)); } + [EnableCors("WebAppCors")] public IResult SignInWithRedirectAsync( [FromServices] SignInManager signInManager, [FromServices] IConfiguration configuration, diff --git a/src/tvnoms-server/TvNoms.ApiService/Program.cs b/src/tvnoms-server/TvNoms.ApiService/Program.cs index 469c2a9..b46dc1c 100644 --- a/src/tvnoms-server/TvNoms.ApiService/Program.cs +++ b/src/tvnoms-server/TvNoms.ApiService/Program.cs @@ -1,10 +1,14 @@ using System.Net; using System.Security.Claims; using System.Security.Cryptography.X509Certificates; +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using Serilog; +using Serilog.Settings.Configuration; using server.ServiceDefaults; using TvNoms.Core.Entities; using TvNoms.Core.Models; @@ -21,6 +25,19 @@ using TvNoms.Server.Data.Repositories; var builder = WebApplication.CreateBuilder(args); var assemblies = AssemblyHelper.GetAssemblies().ToArray(); +Log.Logger = new LoggerConfiguration() + .ReadFrom + .Configuration( + builder.Configuration, + new ConfigurationReaderOptions { SectionName = "SerilogOptions" }) + .Enrich + .FromLogContext() + .CreateLogger(); + +builder.Logging.ClearProviders(); +builder.Host.UseSerilog(Log.Logger); + + // Add service defaults & Aspire components. builder.AddServiceDefaults(); @@ -118,7 +135,23 @@ builder.Services.AddLocalFileStorage(options => { options.WebRootPath = "/uploads"; }); builder.Services.AddDocumentations(); -builder.Services.AddWebAppCors(); +builder.Services.AddWebAppCors(builder.Configuration); +builder.Services.AddDistributedMemoryCache(); +builder.Services.AddSession(options => { + options.IdleTimeout = TimeSpan.FromSeconds(10); + options.Cookie.HttpOnly = true; + options.Cookie.IsEssential = true; +}); +builder.Services.ConfigureHttpJsonOptions(options => { + options.SerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; + options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + options.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); + + options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; +}); + var app = builder.Build(); diff --git a/src/tvnoms-server/TvNoms.ApiService/TvNoms.ApiService.csproj b/src/tvnoms-server/TvNoms.ApiService/TvNoms.ApiService.csproj index 610b96e..d672e31 100644 --- a/src/tvnoms-server/TvNoms.ApiService/TvNoms.ApiService.csproj +++ b/src/tvnoms-server/TvNoms.ApiService/TvNoms.ApiService.csproj @@ -23,6 +23,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/src/tvnoms-server/TvNoms.ApiService/appsettings.Development.json b/src/tvnoms-server/TvNoms.ApiService/appsettings.Development.json index d6c1dc7..220f5fe 100644 --- a/src/tvnoms-server/TvNoms.ApiService/appsettings.Development.json +++ b/src/tvnoms-server/TvNoms.ApiService/appsettings.Development.json @@ -18,12 +18,13 @@ }, "AllowedHosts": "*", "AllowedOrigins": [ - "https://tvnoms.dev.fergl.ie:3000" + "https://tvnoms.dev.fergl.ie:3000", + "http://localhost:3000" ], "BearerAuthOptions": { "Secret": null, "Issuer": null, - "Audience": "https://tvnoms.dev.fergl.ie:5001", + "Audience": "https://tvnoms.dev.fergl.ie:3000", "AccessTokenExpiresIn": "60.00:00:00", "RefreshTokenExpiresIn": "60.00:00:00", "AllowMultipleSessions": true diff --git a/src/tvnoms-server/TvNoms.ApiService/appsettings.json b/src/tvnoms-server/TvNoms.ApiService/appsettings.json index 4d56694..faf2238 100644 --- a/src/tvnoms-server/TvNoms.ApiService/appsettings.json +++ b/src/tvnoms-server/TvNoms.ApiService/appsettings.json @@ -1,9 +1,51 @@ { - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } + "SerilogOptions": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft": "Debug", + "Microsoft.AspNetCore": "Debug", + "System": "Debug" + } + }, + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "WriteTo": [ + { + "Name": "Console", + "Args": { + "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Sixteen, Serilog.Sinks.Console", + "outputTemplate": "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "/tmp/tvnoms/logs/info-.txt", + "outputTemplate": "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}", + "rollingInterval": "Day", + "retainedFileCountLimit": 7, + "restrictedToMinimumLevel": "Information" + } + }, + { + "Name": "File", + "Args": { + "path": "/tmp/tvnoms/logs/error-.txt", + "outputTemplate": "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}", + "rollingInterval": "Day", + "retainedFileCountLimit": 7, + "restrictedToMinimumLevel": "Error" + } + } + ] }, "AllowedHosts": "*" } diff --git a/src/tvnoms-server/TvNoms.Core/Entities/IEntity.cs b/src/tvnoms-server/TvNoms.Core/Entities/IEntity.cs index 1b3f4e5..dd64e75 100644 --- a/src/tvnoms-server/TvNoms.Core/Entities/IEntity.cs +++ b/src/tvnoms-server/TvNoms.Core/Entities/IEntity.cs @@ -7,7 +7,7 @@ public interface IEntity { Guid Id { get; } } -public class BaseEntity : IEntity { +public abstract class BaseEntity : IEntity { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } diff --git a/src/tvnoms-server/TvNoms.Data/AppDbContext.cs b/src/tvnoms-server/TvNoms.Data/AppDbContext.cs index 0a2ab56..bd9d457 100644 --- a/src/tvnoms-server/TvNoms.Data/AppDbContext.cs +++ b/src/tvnoms-server/TvNoms.Data/AppDbContext.cs @@ -3,8 +3,6 @@ using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using TvNoms.Core.Entities; -using TvNoms.Core.Utilities; -using TvNoms.Server.Data.Extensions; namespace TvNoms.Server.Data; @@ -13,18 +11,19 @@ public class AppDbContext(IConfiguration configuration) : protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseNpgsql(configuration.GetConnectionString("DefaultConnection")); - protected override void OnModelCreating(ModelBuilder builder) { - base.OnModelCreating(builder); - var assemblies = AssemblyHelper.GetAssemblies(); + // protected override void OnModelCreating(ModelBuilder builder) { + // base.OnModelCreating(builder); + // var assemblies = AssemblyHelper.GetAssemblies(); + // + // builder.ApplyEntities(assemblies); + // builder.ApplyConfigurations(assemblies); + // } - builder.ApplyEntities(assemblies); - builder.ApplyConfigurations(assemblies); - } - - // public DbSet Users { get; set; } -// public DbSet UserRoles { get; set; } -// public DbSet Clients { get; set; } -// public DbSet Shows { get; set; } -// public DbSet Movies { get; set; } -// public DbSet Media { get; set; } + public DbSet Users { get; set; } + public DbSet UserSessions { get; set; } + public DbSet Roles { get; set; } + public DbSet Clients { get; set; } + public DbSet Shows { get; set; } + public DbSet Movies { get; set; } + public DbSet Media { get; set; } } diff --git a/src/tvnoms-server/TvNoms.Data/Extensions/DbContextExtensions.cs b/src/tvnoms-server/TvNoms.Data/Extensions/DbContextExtensions.cs index bb2a6dd..7692165 100644 --- a/src/tvnoms-server/TvNoms.Data/Extensions/DbContextExtensions.cs +++ b/src/tvnoms-server/TvNoms.Data/Extensions/DbContextExtensions.cs @@ -12,7 +12,8 @@ public static class DbContextExtensions { .SelectMany(_ => _.DefinedTypes) .Select(_ => _.AsType()) .Where(type => type is { IsClass: true, IsAbstract: false, IsGenericType: false } && - type.IsCompatibleWith(typeof(IEntity)) && (predicate?.Invoke(type) ?? true)); + (type.IsCompatibleWith(typeof(IEntity)) || type is BaseEntity) && + (predicate?.Invoke(type) ?? true)); foreach (var entityType in entityTypes) { modelBuilder.Entity(entityType); diff --git a/src/tvnoms-server/TvNoms.Data/Migrations/20240322200711_Initial.Designer.cs b/src/tvnoms-server/TvNoms.Data/Migrations/20240322213634_Initial.Designer.cs similarity index 90% rename from src/tvnoms-server/TvNoms.Data/Migrations/20240322200711_Initial.Designer.cs rename to src/tvnoms-server/TvNoms.Data/Migrations/20240322213634_Initial.Designer.cs index 8708210..8fd0eb6 100644 --- a/src/tvnoms-server/TvNoms.Data/Migrations/20240322200711_Initial.Designer.cs +++ b/src/tvnoms-server/TvNoms.Data/Migrations/20240322213634_Initial.Designer.cs @@ -12,7 +12,7 @@ using TvNoms.Server.Data; namespace TvNoms.Server.Data.Migrations { [DbContext(typeof(AppDbContext))] - [Migration("20240322200711_Initial")] + [Migration("20240322213634_Initial")] partial class Initial { /// @@ -164,7 +164,99 @@ namespace TvNoms.Server.Data.Migrations b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("TvNoms.Core.Entities.BaseEntity", b => + modelBuilder.Entity("TvNoms.Core.Entities.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ConnectionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConnectionTime") + .HasColumnType("timestamp with time zone"); + + b.Property("DateCreated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DateUpdated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("IpAddress") + .HasColumnType("text"); + + b.Property("UserAgent") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Clients"); + }); + + modelBuilder.Entity("TvNoms.Core.Entities.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DateCreated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DateUpdated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("Height") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Width") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("TvNoms.Core.Entities.Movie", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -178,18 +270,36 @@ namespace TvNoms.Server.Data.Migrations .ValueGeneratedOnAddOrUpdate() .HasColumnType("timestamp with time zone"); - b.Property("Discriminator") + b.Property("Title") .IsRequired() - .HasMaxLength(13) - .HasColumnType("character varying(13)"); + .HasColumnType("text"); b.HasKey("Id"); - b.ToTable("BaseEntity"); + b.ToTable("Movies"); + }); - b.HasDiscriminator("Discriminator").HasValue("BaseEntity"); + modelBuilder.Entity("TvNoms.Core.Entities.Show", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); - b.UseTphMappingStrategy(); + b.Property("DateCreated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DateUpdated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Shows"); }); modelBuilder.Entity("TvNoms.Core.Entities.User", b => @@ -315,7 +425,7 @@ namespace TvNoms.Server.Data.Migrations b.HasIndex("UserId"); - b.ToTable("UserSession"); + b.ToTable("UserSessions"); }); modelBuilder.Entity("TvNoms.Core.Entities.Role", b => @@ -325,102 +435,6 @@ namespace TvNoms.Server.Data.Migrations b.HasDiscriminator().HasValue("Role"); }); - modelBuilder.Entity("TvNoms.Core.Entities.Client", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("Active") - .HasColumnType("boolean"); - - b.Property("ConnectionId") - .IsRequired() - .HasColumnType("text"); - - b.Property("ConnectionTime") - .HasColumnType("timestamp with time zone"); - - b.Property("DeviceId") - .HasColumnType("text"); - - b.Property("IpAddress") - .HasColumnType("text"); - - b.Property("UserAgent") - .HasColumnType("text"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasIndex("UserId"); - - b.HasDiscriminator().HasValue("Client"); - }); - - modelBuilder.Entity("TvNoms.Core.Entities.Media", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("ContentType") - .IsRequired() - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Height") - .HasColumnType("integer"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text"); - - b.Property("Path") - .IsRequired() - .HasColumnType("text"); - - b.Property("Size") - .HasColumnType("bigint"); - - b.Property("Type") - .HasColumnType("integer"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Width") - .HasColumnType("integer"); - - b.HasDiscriminator().HasValue("Media"); - }); - - modelBuilder.Entity("TvNoms.Core.Entities.Movie", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("Title") - .IsRequired() - .HasColumnType("text"); - - b.HasDiscriminator().HasValue("Movie"); - }); - - modelBuilder.Entity("TvNoms.Core.Entities.Show", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("Title") - .IsRequired() - .HasColumnType("text"); - - b.ToTable("BaseEntity", t => - { - t.Property("Title") - .HasColumnName("Show_Title"); - }); - - b.HasDiscriminator().HasValue("Show"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -472,6 +486,15 @@ namespace TvNoms.Server.Data.Migrations .IsRequired(); }); + modelBuilder.Entity("TvNoms.Core.Entities.Client", b => + { + b.HasOne("TvNoms.Core.Entities.User", "User") + .WithMany("Clients") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + modelBuilder.Entity("TvNoms.Core.Entities.User", b => { b.HasOne("TvNoms.Core.Entities.Media", "Avatar") @@ -492,15 +515,6 @@ namespace TvNoms.Server.Data.Migrations b.Navigation("User"); }); - modelBuilder.Entity("TvNoms.Core.Entities.Client", b => - { - b.HasOne("TvNoms.Core.Entities.User", "User") - .WithMany("Clients") - .HasForeignKey("UserId"); - - b.Navigation("User"); - }); - modelBuilder.Entity("TvNoms.Core.Entities.User", b => { b.Navigation("Clients"); diff --git a/src/tvnoms-server/TvNoms.Data/Migrations/20240322200711_Initial.cs b/src/tvnoms-server/TvNoms.Data/Migrations/20240322213634_Initial.cs similarity index 76% rename from src/tvnoms-server/TvNoms.Data/Migrations/20240322200711_Initial.cs rename to src/tvnoms-server/TvNoms.Data/Migrations/20240322213634_Initial.cs index 6ee7119..aa2b2e1 100644 --- a/src/tvnoms-server/TvNoms.Data/Migrations/20240322200711_Initial.cs +++ b/src/tvnoms-server/TvNoms.Data/Migrations/20240322213634_Initial.cs @@ -27,6 +27,56 @@ namespace TvNoms.Server.Data.Migrations table.PrimaryKey("PK_AspNetRoles", x => x.Id); }); + migrationBuilder.CreateTable( + name: "Media", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Size = table.Column(type: "bigint", nullable: false), + Path = table.Column(type: "text", nullable: false), + ContentType = table.Column(type: "text", nullable: false), + Type = table.Column(type: "integer", nullable: false), + Width = table.Column(type: "integer", nullable: true), + Height = table.Column(type: "integer", nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + DateCreated = table.Column(type: "timestamp with time zone", nullable: false), + DateUpdated = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Media", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Movies", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Title = table.Column(type: "text", nullable: false), + DateCreated = table.Column(type: "timestamp with time zone", nullable: false), + DateUpdated = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Movies", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Shows", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Title = table.Column(type: "text", nullable: false), + DateCreated = table.Column(type: "timestamp with time zone", nullable: false), + DateUpdated = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Shows", x => x.Id); + }); + migrationBuilder.CreateTable( name: "AspNetRoleClaims", columns: table => new @@ -48,53 +98,6 @@ namespace TvNoms.Server.Data.Migrations onDelete: ReferentialAction.Cascade); }); - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - UserId = table.Column(type: "uuid", nullable: false), - ClaimType = table.Column(type: "text", nullable: true), - ClaimValue = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "text", nullable: false), - ProviderKey = table.Column(type: "text", nullable: false), - ProviderDisplayName = table.Column(type: "text", nullable: true), - UserId = table.Column(type: "uuid", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "uuid", nullable: false), - RoleId = table.Column(type: "uuid", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateTable( name: "AspNetUsers", columns: table => new @@ -127,6 +130,76 @@ namespace TvNoms.Server.Data.Migrations constraints: table => { table.PrimaryKey("PK_AspNetUsers", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUsers_Media_AvatarId", + column: x => x.AvatarId, + principalTable: "Media", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UserId = table.Column(type: "uuid", nullable: false), + ClaimType = table.Column(type: "text", nullable: true), + ClaimValue = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "text", nullable: false), + ProviderKey = table.Column(type: "text", nullable: false), + ProviderDisplayName = table.Column(type: "text", nullable: true), + UserId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -150,44 +223,32 @@ namespace TvNoms.Server.Data.Migrations }); migrationBuilder.CreateTable( - name: "BaseEntity", + name: "Clients", columns: table => new { Id = table.Column(type: "uuid", nullable: false), - DateCreated = table.Column(type: "timestamp with time zone", nullable: false), - DateUpdated = table.Column(type: "timestamp with time zone", nullable: false), - Discriminator = table.Column(type: "character varying(13)", maxLength: 13, nullable: false), - ConnectionId = table.Column(type: "text", nullable: true), - ConnectionTime = table.Column(type: "timestamp with time zone", nullable: true), + ConnectionId = table.Column(type: "text", nullable: false), + ConnectionTime = table.Column(type: "timestamp with time zone", nullable: false), IpAddress = table.Column(type: "text", nullable: true), DeviceId = table.Column(type: "text", nullable: true), UserId = table.Column(type: "uuid", nullable: true), UserAgent = table.Column(type: "text", nullable: true), - Active = table.Column(type: "boolean", nullable: true), - Name = table.Column(type: "text", nullable: true), - Size = table.Column(type: "bigint", nullable: true), - Path = table.Column(type: "text", nullable: true), - ContentType = table.Column(type: "text", nullable: true), - Type = table.Column(type: "integer", nullable: true), - Width = table.Column(type: "integer", nullable: true), - Height = table.Column(type: "integer", nullable: true), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: true), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true), - Title = table.Column(type: "text", nullable: true), - Show_Title = table.Column(type: "text", nullable: true) + Active = table.Column(type: "boolean", nullable: false), + DateCreated = table.Column(type: "timestamp with time zone", nullable: false), + DateUpdated = table.Column(type: "timestamp with time zone", nullable: false) }, constraints: table => { - table.PrimaryKey("PK_BaseEntity", x => x.Id); + table.PrimaryKey("PK_Clients", x => x.Id); table.ForeignKey( - name: "FK_BaseEntity_AspNetUsers_UserId", + name: "FK_Clients_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id"); }); migrationBuilder.CreateTable( - name: "UserSession", + name: "UserSessions", columns: table => new { Id = table.Column(type: "uuid", nullable: false), @@ -199,9 +260,9 @@ namespace TvNoms.Server.Data.Migrations }, constraints: table => { - table.PrimaryKey("PK_UserSession", x => x.Id); + table.PrimaryKey("PK_UserSessions", x => x.Id); table.ForeignKey( - name: "FK_UserSession_AspNetUsers_UserId", + name: "FK_UserSessions_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", @@ -251,54 +312,19 @@ namespace TvNoms.Server.Data.Migrations unique: true); migrationBuilder.CreateIndex( - name: "IX_BaseEntity_UserId", - table: "BaseEntity", + name: "IX_Clients_UserId", + table: "Clients", column: "UserId"); migrationBuilder.CreateIndex( - name: "IX_UserSession_UserId", - table: "UserSession", + name: "IX_UserSessions_UserId", + table: "UserSessions", column: "UserId"); - - migrationBuilder.AddForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - table: "AspNetUserClaims", - column: "UserId", - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - table: "AspNetUserLogins", - column: "UserId", - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - table: "AspNetUserRoles", - column: "UserId", - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_AspNetUsers_BaseEntity_AvatarId", - table: "AspNetUsers", - column: "AvatarId", - principalTable: "BaseEntity", - principalColumn: "Id"); } /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropForeignKey( - name: "FK_BaseEntity_AspNetUsers_UserId", - table: "BaseEntity"); - migrationBuilder.DropTable( name: "AspNetRoleClaims"); @@ -315,7 +341,16 @@ namespace TvNoms.Server.Data.Migrations name: "AspNetUserTokens"); migrationBuilder.DropTable( - name: "UserSession"); + name: "Clients"); + + migrationBuilder.DropTable( + name: "Movies"); + + migrationBuilder.DropTable( + name: "Shows"); + + migrationBuilder.DropTable( + name: "UserSessions"); migrationBuilder.DropTable( name: "AspNetRoles"); @@ -324,7 +359,7 @@ namespace TvNoms.Server.Data.Migrations name: "AspNetUsers"); migrationBuilder.DropTable( - name: "BaseEntity"); + name: "Media"); } } } diff --git a/src/tvnoms-server/TvNoms.Data/Migrations/AppDbContextModelSnapshot.cs b/src/tvnoms-server/TvNoms.Data/Migrations/AppDbContextModelSnapshot.cs index f682f9a..03e7e0c 100644 --- a/src/tvnoms-server/TvNoms.Data/Migrations/AppDbContextModelSnapshot.cs +++ b/src/tvnoms-server/TvNoms.Data/Migrations/AppDbContextModelSnapshot.cs @@ -161,7 +161,99 @@ namespace TvNoms.Server.Data.Migrations b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("TvNoms.Core.Entities.BaseEntity", b => + modelBuilder.Entity("TvNoms.Core.Entities.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ConnectionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConnectionTime") + .HasColumnType("timestamp with time zone"); + + b.Property("DateCreated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DateUpdated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("IpAddress") + .HasColumnType("text"); + + b.Property("UserAgent") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Clients"); + }); + + modelBuilder.Entity("TvNoms.Core.Entities.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DateCreated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DateUpdated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("Height") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Width") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("TvNoms.Core.Entities.Movie", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -175,18 +267,36 @@ namespace TvNoms.Server.Data.Migrations .ValueGeneratedOnAddOrUpdate() .HasColumnType("timestamp with time zone"); - b.Property("Discriminator") + b.Property("Title") .IsRequired() - .HasMaxLength(13) - .HasColumnType("character varying(13)"); + .HasColumnType("text"); b.HasKey("Id"); - b.ToTable("BaseEntity"); + b.ToTable("Movies"); + }); - b.HasDiscriminator("Discriminator").HasValue("BaseEntity"); + modelBuilder.Entity("TvNoms.Core.Entities.Show", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); - b.UseTphMappingStrategy(); + b.Property("DateCreated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("DateUpdated") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Shows"); }); modelBuilder.Entity("TvNoms.Core.Entities.User", b => @@ -312,7 +422,7 @@ namespace TvNoms.Server.Data.Migrations b.HasIndex("UserId"); - b.ToTable("UserSession"); + b.ToTable("UserSessions"); }); modelBuilder.Entity("TvNoms.Core.Entities.Role", b => @@ -322,102 +432,6 @@ namespace TvNoms.Server.Data.Migrations b.HasDiscriminator().HasValue("Role"); }); - modelBuilder.Entity("TvNoms.Core.Entities.Client", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("Active") - .HasColumnType("boolean"); - - b.Property("ConnectionId") - .IsRequired() - .HasColumnType("text"); - - b.Property("ConnectionTime") - .HasColumnType("timestamp with time zone"); - - b.Property("DeviceId") - .HasColumnType("text"); - - b.Property("IpAddress") - .HasColumnType("text"); - - b.Property("UserAgent") - .HasColumnType("text"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasIndex("UserId"); - - b.HasDiscriminator().HasValue("Client"); - }); - - modelBuilder.Entity("TvNoms.Core.Entities.Media", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("ContentType") - .IsRequired() - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Height") - .HasColumnType("integer"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text"); - - b.Property("Path") - .IsRequired() - .HasColumnType("text"); - - b.Property("Size") - .HasColumnType("bigint"); - - b.Property("Type") - .HasColumnType("integer"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Width") - .HasColumnType("integer"); - - b.HasDiscriminator().HasValue("Media"); - }); - - modelBuilder.Entity("TvNoms.Core.Entities.Movie", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("Title") - .IsRequired() - .HasColumnType("text"); - - b.HasDiscriminator().HasValue("Movie"); - }); - - modelBuilder.Entity("TvNoms.Core.Entities.Show", b => - { - b.HasBaseType("TvNoms.Core.Entities.BaseEntity"); - - b.Property("Title") - .IsRequired() - .HasColumnType("text"); - - b.ToTable("BaseEntity", t => - { - t.Property("Title") - .HasColumnName("Show_Title"); - }); - - b.HasDiscriminator().HasValue("Show"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -469,6 +483,15 @@ namespace TvNoms.Server.Data.Migrations .IsRequired(); }); + modelBuilder.Entity("TvNoms.Core.Entities.Client", b => + { + b.HasOne("TvNoms.Core.Entities.User", "User") + .WithMany("Clients") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + modelBuilder.Entity("TvNoms.Core.Entities.User", b => { b.HasOne("TvNoms.Core.Entities.Media", "Avatar") @@ -489,15 +512,6 @@ namespace TvNoms.Server.Data.Migrations b.Navigation("User"); }); - modelBuilder.Entity("TvNoms.Core.Entities.Client", b => - { - b.HasOne("TvNoms.Core.Entities.User", "User") - .WithMany("Clients") - .HasForeignKey("UserId"); - - b.Navigation("User"); - }); - modelBuilder.Entity("TvNoms.Core.Entities.User", b => { b.Navigation("Clients"); diff --git a/src/tvnoms-server/TvNoms.Infrastructure/Identity/ServiceCollectionExtensions.cs b/src/tvnoms-server/TvNoms.Infrastructure/Identity/ServiceCollectionExtensions.cs index 440e30d..3049405 100644 --- a/src/tvnoms-server/TvNoms.Infrastructure/Identity/ServiceCollectionExtensions.cs +++ b/src/tvnoms-server/TvNoms.Infrastructure/Identity/ServiceCollectionExtensions.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using TvNoms.Core.Entities; using TvNoms.Core.Extensions.Identity; @@ -9,14 +10,19 @@ using TvNoms.Server.Services; namespace TvNoms.Infrastructure.Identity; public static class ServiceCollectionExtensions { - public static IServiceCollection AddWebAppCors(this IServiceCollection services) { + public static IServiceCollection AddWebAppCors(this IServiceCollection services, IConfiguration config) { services.AddCors(options => { - options.AddPolicy("WebAppPolicy", builder => { - builder + options.AddPolicy("WebAppCors", policy => { + var allowedOrigins = + config.GetSection("AllowedOrigins")?.Get() ?? Array.Empty(); + + policy + .WithOrigins(allowedOrigins) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials() - .WithOrigins("https://tvnoms.dev.fergl.ie:3000/"); + .WithExposedHeaders("Content-Disposition") + .SetPreflightMaxAge(TimeSpan.FromMinutes(10)); }); }); return services;