mirror of
https://github.com/fergalmoran/podnoms.git
synced 2025-12-22 09:18:08 +00:00
Generic slugify working (was it worth it? Fuck no)
This commit is contained in:
BIN
server/10 second countdown-OJ2wOKDzKyI.mkv
Normal file
BIN
server/10 second countdown-OJ2wOKDzKyI.mkv
Normal file
Binary file not shown.
@@ -113,11 +113,13 @@ namespace PodNoms.Api.Controllers {
|
||||
entry.Podcast = podcast;
|
||||
entry.Processed = false;
|
||||
_repository.AddOrUpdate(entry);
|
||||
await _unitOfWork.CompleteAsync();
|
||||
bool succeeded = await _unitOfWork.CompleteAsync();
|
||||
if (succeeded) {
|
||||
_processEntry(entry);
|
||||
var result = _mapper.Map<PodcastEntry, PodcastEntryViewModel>(entry);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if (status == AudioType.Playlist && YouTubeParser.ValidateUrl(item.SourceUrl)) {
|
||||
entry.ProcessingStatus = ProcessingStatus.Deferred;
|
||||
return Accepted(entry);
|
||||
|
||||
466
server/Migrations/20180511192735_AddUIDToBase.Designer.cs
generated
Normal file
466
server/Migrations/20180511192735_AddUIDToBase.Designer.cs
generated
Normal file
@@ -0,0 +1,466 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PodNoms.Api.Persistence;
|
||||
|
||||
namespace PodNoms.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(PodNomsDbContext))]
|
||||
[Migration("20180511192735_AddUIDToBase")]
|
||||
partial class AddUIDToBase
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.0-rc1-32029")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128)
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken();
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasName("RoleNameIndex")
|
||||
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("ClaimType");
|
||||
|
||||
b.Property<string>("ClaimValue");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("ClaimType");
|
||||
|
||||
b.Property<string>("ClaimValue");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider");
|
||||
|
||||
b.Property<string>("ProviderKey");
|
||||
|
||||
b.Property<string>("ProviderDisplayName");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId");
|
||||
|
||||
b.Property<string>("RoleId");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId");
|
||||
|
||||
b.Property<string>("LoginProvider");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("Value");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ChatMessage", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("FromUserId");
|
||||
|
||||
b.Property<DateTime?>("MessageSeen");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ToUserId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FromUserId");
|
||||
|
||||
b.HasIndex("ToUserId");
|
||||
|
||||
b.ToTable("ChatMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<bool>("IsProcessed");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("PlaylistId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("VideoId");
|
||||
|
||||
b.Property<string>("VideoType");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlaylistId");
|
||||
|
||||
b.ToTable("ParsedPlaylistItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("PodcastId");
|
||||
|
||||
b.Property<string>("SourceUrl");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("Playlists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("AppUserId");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Slug");
|
||||
|
||||
b.Property<string>("TemporaryImageUrl");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("Podcasts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long>("AudioFileSize");
|
||||
|
||||
b.Property<float>("AudioLength");
|
||||
|
||||
b.Property<string>("AudioUrl");
|
||||
|
||||
b.Property<string>("Author");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<string>("ImageUrl");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int?>("PlaylistId");
|
||||
|
||||
b.Property<int>("PodcastId");
|
||||
|
||||
b.Property<bool>("Processed");
|
||||
|
||||
b.Property<string>("ProcessingPayload");
|
||||
|
||||
b.Property<int>("ProcessingStatus");
|
||||
|
||||
b.Property<string>("SourceUrl");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlaylistId");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("PodcastEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Services.Auth.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("AccessFailedCount");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken();
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<bool>("EmailConfirmed");
|
||||
|
||||
b.Property<long?>("FacebookId");
|
||||
|
||||
b.Property<string>("FirstName");
|
||||
|
||||
b.Property<string>("LastName");
|
||||
|
||||
b.Property<bool>("LockoutEnabled");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("PasswordHash");
|
||||
|
||||
b.Property<string>("PhoneNumber");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed");
|
||||
|
||||
b.Property<string>("PictureUrl");
|
||||
|
||||
b.Property<string>("SecurityStamp");
|
||||
|
||||
b.Property<string>("Slug");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasName("UserNameIndex")
|
||||
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ChatMessage", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "FromUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("FromUserId");
|
||||
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "ToUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("ToUserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Models.Playlist", "Playlist")
|
||||
.WithMany("ParsedPlaylistItems")
|
||||
.HasForeignKey("PlaylistId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||
.WithMany()
|
||||
.HasForeignKey("PodcastId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "AppUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("AppUserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Models.Playlist")
|
||||
.WithMany("PodcastEntries")
|
||||
.HasForeignKey("PlaylistId");
|
||||
|
||||
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||
.WithMany("PodcastEntries")
|
||||
.HasForeignKey("PodcastId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
164
server/Migrations/20180511192735_AddUIDToBase.cs
Normal file
164
server/Migrations/20180511192735_AddUIDToBase.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace PodNoms.Api.Migrations {
|
||||
public partial class AddUIDToBase : Migration {
|
||||
protected override void Up(MigrationBuilder migrationBuilder) {
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "NewId",
|
||||
table: "Podcasts",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "NewId",
|
||||
table: "PodcastEntries",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "NewId",
|
||||
table: "Playlists",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Uid",
|
||||
table: "Playlists",
|
||||
nullable: false,
|
||||
defaultValue: System.Guid.NewGuid());
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "NewId",
|
||||
table: "ParsedPlaylistItems",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Uid",
|
||||
table: "ParsedPlaylistItems",
|
||||
nullable: false,
|
||||
defaultValue: System.Guid.NewGuid());
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "NewId",
|
||||
table: "ChatMessages",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Uid",
|
||||
table: "ChatMessages",
|
||||
nullable: false,
|
||||
defaultValue: System.Guid.NewGuid());
|
||||
|
||||
migrationBuilder.Sql("UPDATE Podcasts SET NewId = Uid WHERE NewId = '00000000-0000-0000-0000-000000000000' AND Uid IS NOT NULL");
|
||||
migrationBuilder.Sql("UPDATE PodcastEntries SET NewId = Uid WHERE NewId = '00000000-0000-0000-0000-000000000000' AND Uid IS NOT NULL");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreateDate",
|
||||
table: "Podcasts",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdateDate",
|
||||
table: "Podcasts",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreateDate",
|
||||
table: "PodcastEntries",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdateDate",
|
||||
table: "PodcastEntries",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreateDate",
|
||||
table: "Playlists",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdateDate",
|
||||
table: "Playlists",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreateDate",
|
||||
table: "ParsedPlaylistItems",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdateDate",
|
||||
table: "ParsedPlaylistItems",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "CreateDate",
|
||||
table: "ChatMessages",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "UpdateDate",
|
||||
table: "ChatMessages",
|
||||
type: "datetime2",
|
||||
nullable: false,
|
||||
defaultValueSql: "getdate()",
|
||||
oldClrType: typeof(DateTime));
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder) {
|
||||
migrationBuilder.DropColumn(
|
||||
name: "NewId",
|
||||
table: "Podcasts");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "NewId",
|
||||
table: "PodcastEntries");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "NewId",
|
||||
table: "Playlists");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Uid",
|
||||
table: "Playlists");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "NewId",
|
||||
table: "ParsedPlaylistItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Uid",
|
||||
table: "ParsedPlaylistItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "NewId",
|
||||
table: "ChatMessages");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Uid",
|
||||
table: "ChatMessages");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,15 +135,22 @@ namespace PodNoms.Api.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate");
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("FromUserId");
|
||||
|
||||
b.Property<DateTime?>("MessageSeen");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ToUserId");
|
||||
|
||||
b.Property<DateTime>("UpdateDate");
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
@@ -160,13 +167,20 @@ namespace PodNoms.Api.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate");
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<bool>("IsProcessed");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("PlaylistId");
|
||||
|
||||
b.Property<DateTime>("UpdateDate");
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("VideoId");
|
||||
|
||||
@@ -185,13 +199,20 @@ namespace PodNoms.Api.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate");
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("PodcastId");
|
||||
|
||||
b.Property<string>("SourceUrl");
|
||||
|
||||
b.Property<DateTime>("UpdateDate");
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
@@ -208,10 +229,14 @@ namespace PodNoms.Api.Migrations
|
||||
|
||||
b.Property<string>("AppUserId");
|
||||
|
||||
b.Property<DateTime>("CreateDate");
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Slug");
|
||||
|
||||
b.Property<string>("TemporaryImageUrl");
|
||||
@@ -220,7 +245,8 @@ namespace PodNoms.Api.Migrations
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate");
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
@@ -243,12 +269,16 @@ namespace PodNoms.Api.Migrations
|
||||
|
||||
b.Property<string>("Author");
|
||||
|
||||
b.Property<DateTime>("CreateDate");
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<string>("ImageUrl");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int?>("PlaylistId");
|
||||
|
||||
b.Property<int>("PodcastId");
|
||||
@@ -265,7 +295,8 @@ namespace PodNoms.Api.Migrations
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate");
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
|
||||
13
server/Models/Annotations/SlugFieldAttribute.cs
Normal file
13
server/Models/Annotations/SlugFieldAttribute.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
namespace PodNoms.Api.Models.Annotations {
|
||||
[System.AttributeUsage(System.AttributeTargets.Property)]
|
||||
public class SlugFieldAttribute : Attribute {
|
||||
private readonly string _sourceField;
|
||||
|
||||
public string SourceField => _sourceField;
|
||||
public SlugFieldAttribute(string sourceField) {
|
||||
this._sourceField = sourceField;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,26 +2,22 @@ using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace PodNoms.Api.Models {
|
||||
public class BaseModel : IEntity {
|
||||
public class BaseEntity : IEntity {
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
|
||||
//TODO: Remove once migration is complete
|
||||
public string Uid { get; set; }
|
||||
// TODO replace Id with below
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public Guid NewId { get; set; }
|
||||
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
|
||||
public DateTime CreateDate { get; set; }
|
||||
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
|
||||
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public DateTime UpdateDate { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public string ExposedUid { get => NewId.ToString(); }
|
||||
}
|
||||
|
||||
public interface IEntity {
|
||||
int Id { get; set; }
|
||||
DateTime CreateDate { get; set; }
|
||||
DateTime UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using Microsoft.Extensions.Options;
|
||||
using PodNoms.Api.Services.Auth;
|
||||
|
||||
namespace PodNoms.Api.Models {
|
||||
public class ChatMessage : BaseModel, IEntity {
|
||||
public class ChatMessage : BaseEntity, IEntity {
|
||||
|
||||
public ApplicationUser FromUser { get; set; }
|
||||
public ApplicationUser ToUser { get; set; }
|
||||
|
||||
9
server/Models/IEntity.cs
Normal file
9
server/Models/IEntity.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace PodNoms.Api.Models {
|
||||
public interface IEntity {
|
||||
int Id { get; set; }
|
||||
DateTime CreateDate { get; set; }
|
||||
DateTime UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
67
server/Models/ISluggedEntity.cs
Normal file
67
server/Models/ISluggedEntity.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Models.Annotations;
|
||||
using PodNoms.Api.Utils.Extensions;
|
||||
|
||||
namespace PodNoms.Api.Models {
|
||||
public interface ISluggedEntity {
|
||||
string Slug { get; set; }
|
||||
}
|
||||
|
||||
public static class SluggedEntityExtensions {
|
||||
private class ProxySluggedModel : ISluggedEntity {
|
||||
public string Slug { get; set; }
|
||||
}
|
||||
public static IEnumerable<T> Select<T>(this IDataReader reader,
|
||||
Func<IDataReader, T> projection) {
|
||||
while (reader.Read()) {
|
||||
yield return projection(reader);
|
||||
}
|
||||
}
|
||||
public static IEnumerable<T> ExecSQL<T>(this DbContext context, string query) where T : class, ISluggedEntity, new() {
|
||||
using (var command = context.Database.GetDbConnection().CreateCommand()) {
|
||||
command.CommandText = query;
|
||||
command.CommandType = CommandType.Text;
|
||||
context.Database.OpenConnection();
|
||||
|
||||
using (var reader = command.ExecuteReader()){
|
||||
var result = reader.Select<T>(r => new T {
|
||||
Slug = r["Slug"] is DBNull ? string.Empty : r["Slug"].ToString()
|
||||
});
|
||||
return result.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static string GetSlug(this ISluggedEntity entity, DbContext context, ILogger logger = null) {
|
||||
|
||||
try {
|
||||
var property = entity.GetType().GetProperties()
|
||||
.Where(prop => Attribute.IsDefined(prop, typeof(SlugFieldAttribute)))
|
||||
.FirstOrDefault();
|
||||
if (property != null) {
|
||||
var attribute = property.GetCustomAttributes(typeof(SlugFieldAttribute), false)
|
||||
.FirstOrDefault();
|
||||
|
||||
Type t = entity.GetType();
|
||||
var tableName = context.Model.FindEntityType(t).SqlServer().TableName;
|
||||
if (!string.IsNullOrEmpty(tableName)) {
|
||||
var sourceField = (attribute as SlugFieldAttribute).SourceField;
|
||||
var slugSource = entity.GetType().GetProperty("Title").GetValue(entity, null).ToString();
|
||||
var source = context.ExecSQL<ProxySluggedModel>($"SELECT Slug FROM {tableName}")
|
||||
.Select(m => m.Slug);
|
||||
return slugSource.Slugify(source);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger?.LogError($"Error slugifying {entity.GetType().Name} - {ex.Message}");
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PodNoms.Api.Models {
|
||||
public class Playlist : BaseModel {
|
||||
public class Playlist : BaseEntity {
|
||||
//TODO: Update this to use concrete model
|
||||
public int PodcastId { get; set; }
|
||||
public string SourceUrl { get; set; }
|
||||
@@ -12,7 +12,7 @@ namespace PodNoms.Api.Models {
|
||||
ParsedPlaylistItems = new List<ParsedPlaylistItem>();
|
||||
}
|
||||
}
|
||||
public class ParsedPlaylistItem : BaseModel {
|
||||
public class ParsedPlaylistItem : BaseEntity {
|
||||
public string VideoId { get; set; }
|
||||
public string VideoType { get; set; }
|
||||
public bool IsProcessed { get; set; }
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Microsoft.Extensions.Options;
|
||||
using PodNoms.Api.Models.Annotations;
|
||||
using PodNoms.Api.Services.Auth;
|
||||
|
||||
namespace PodNoms.Api.Models {
|
||||
public class Podcast : BaseModel {
|
||||
public class Podcast : BaseEntity, ISluggedEntity {
|
||||
public ApplicationUser AppUser { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
[SlugField(sourceField: "Title")]
|
||||
public string Slug { get; set; }
|
||||
public string TemporaryImageUrl { get; set; }
|
||||
public List<PodcastEntry> PodcastEntries { get; set; }
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace PodNoms.Api.Models {
|
||||
Failed, //5
|
||||
Deferred //6
|
||||
}
|
||||
public class PodcastEntry : BaseModel {
|
||||
public class PodcastEntry : BaseEntity {
|
||||
|
||||
public string Author { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
@@ -5,6 +5,6 @@ namespace PodNoms.Api.Persistence
|
||||
{
|
||||
public interface IUnitOfWork
|
||||
{
|
||||
Task CompleteAsync();
|
||||
Task<bool> CompleteAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Models;
|
||||
using PodNoms.Api.Models.Annotations;
|
||||
using PodNoms.Api.Services.Auth;
|
||||
using PodNoms.Api.Utils.Extensions;
|
||||
|
||||
namespace PodNoms.Api.Persistence {
|
||||
|
||||
public class PodNomsDbContext : IdentityDbContext<ApplicationUser> {
|
||||
public PodNomsDbContext(DbContextOptions<PodNomsDbContext> options) : base(options) { }
|
||||
private readonly ILogger<PodNomsDbContext> _logger;
|
||||
|
||||
public PodNomsDbContext(DbContextOptions<PodNomsDbContext> options, ILogger<PodNomsDbContext> logger) : base(options) {
|
||||
Database.SetCommandTimeout(360);
|
||||
this._logger = logger;
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
||||
base.OnModelCreating(modelBuilder);
|
||||
foreach (var pb in __getColumn(modelBuilder, "CreateDate")) {
|
||||
pb.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
}
|
||||
foreach (var pb in __getColumn(modelBuilder, "UpdateDate")) {
|
||||
pb.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
}
|
||||
foreach (var pb in __getColumn(modelBuilder, "NewId")) {
|
||||
pb.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private IEnumerable<PropertyBuilder> __getColumn(ModelBuilder modelBuilder, string columnName) {
|
||||
return modelBuilder.Model
|
||||
.GetEntityTypes()
|
||||
.SelectMany(t => t.GetProperties())
|
||||
.Where(p => p.Name == columnName)
|
||||
.Select(p => modelBuilder.Entity(p.DeclaringEntityType.ClrType).Property(p.Name));
|
||||
}
|
||||
|
||||
public override int SaveChanges() {
|
||||
_addTimestamps();
|
||||
return base.SaveChanges();
|
||||
}
|
||||
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(System.Threading.CancellationToken)) {
|
||||
_addTimestamps();
|
||||
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
|
||||
}
|
||||
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) {
|
||||
_addTimestamps();
|
||||
return base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
void _addTimestamps() {
|
||||
var modifiedEntries = ChangeTracker.Entries()
|
||||
.Where(x => (x.State == EntityState.Added || x.State == EntityState.Modified));
|
||||
|
||||
var now = DateTime.Now;
|
||||
foreach (var entry in modifiedEntries) {
|
||||
var entity = entry.Entity as BaseModel;
|
||||
if (entity != null) {
|
||||
if (entry.State == EntityState.Added) {
|
||||
entity.CreateDate = now;
|
||||
}
|
||||
entity.UpdateDate = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
public DbSet<Podcast> Podcasts { get; set; }
|
||||
public DbSet<PodcastEntry> PodcastEntries { get; set; }
|
||||
public DbSet<Playlist> Playlists { get; set; }
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Models;
|
||||
|
||||
namespace PodNoms.Api.Persistence {
|
||||
@@ -12,7 +13,7 @@ namespace PodNoms.Api.Persistence {
|
||||
Task<IEnumerable<ChatMessage>> GetAllChats(string userId);
|
||||
}
|
||||
public class ChatRepository : GenericRepository<ChatMessage>, IChatRepository {
|
||||
public ChatRepository(PodNomsDbContext context) : base(context) {
|
||||
public ChatRepository(PodNomsDbContext context, ILogger<ChatRepository> logger) : base(context, logger) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Models;
|
||||
|
||||
|
||||
@@ -12,7 +13,7 @@ namespace PodNoms.Api.Persistence {
|
||||
Task<PodcastEntry> GetByUidAsync(string uid);
|
||||
}
|
||||
public class EntryRepository : GenericRepository<PodcastEntry>, IEntryRepository {
|
||||
public EntryRepository(PodNomsDbContext context) : base(context) {
|
||||
public EntryRepository(PodNomsDbContext context, ILogger<EntryRepository> logger) : base(context, logger) {
|
||||
}
|
||||
public async Task<IEnumerable<PodcastEntry>> GetAllForSlugAsync(string podcastSlug) {
|
||||
var entries = await GetAll()
|
||||
|
||||
@@ -4,7 +4,9 @@ using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Models;
|
||||
using PodNoms.Api.Models.Annotations;
|
||||
|
||||
namespace PodNoms.Api.Persistence {
|
||||
public interface IRepository<TEntity> where TEntity : class, IEntity {
|
||||
@@ -18,9 +20,11 @@ namespace PodNoms.Api.Persistence {
|
||||
|
||||
public abstract class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity {
|
||||
private PodNomsDbContext _context;
|
||||
private readonly ILogger<GenericRepository<TEntity>> _logger;
|
||||
|
||||
public GenericRepository(PodNomsDbContext context) {
|
||||
public GenericRepository(PodNomsDbContext context, ILogger<GenericRepository<TEntity>> logger) {
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public PodNomsDbContext GetContext() {
|
||||
@@ -36,13 +40,16 @@ namespace PodNoms.Api.Persistence {
|
||||
}
|
||||
|
||||
public TEntity Create(TEntity entity) {
|
||||
if (entity is ISluggedEntity) {
|
||||
(entity as ISluggedEntity).Slug = (entity as ISluggedEntity).GetSlug(_context, _logger);
|
||||
}
|
||||
var ret = _context.Set<TEntity>().Add(entity);
|
||||
return ret as TEntity;
|
||||
return entity;
|
||||
}
|
||||
|
||||
public TEntity Update(TEntity entity) {
|
||||
var ret = _context.Set<TEntity>().Update(entity);
|
||||
return ret as TEntity;
|
||||
return entity;
|
||||
}
|
||||
|
||||
public TEntity AddOrUpdate(TEntity entity) {
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Models;
|
||||
|
||||
namespace PodNoms.Api.Persistence {
|
||||
@@ -10,7 +11,7 @@ namespace PodNoms.Api.Persistence {
|
||||
Task<List<ParsedPlaylistItem>> GetUnprocessedItems();
|
||||
}
|
||||
public class PlaylistRepository : GenericRepository<Playlist>, IPlaylistRepository {
|
||||
public PlaylistRepository(PodNomsDbContext context) : base(context) {
|
||||
public PlaylistRepository(PodNomsDbContext context, ILogger<PlaylistRepository> logger) : base(context, logger) {
|
||||
}
|
||||
|
||||
public async Task<ParsedPlaylistItem> GetParsedItem(string itemId, int playlistId) {
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Models;
|
||||
|
||||
namespace PodNoms.Api.Persistence {
|
||||
@@ -10,7 +11,7 @@ namespace PodNoms.Api.Persistence {
|
||||
Task<IEnumerable<Podcast>> GetAllForUserAsync(string userId);
|
||||
}
|
||||
public class PodcastRepository : GenericRepository<Podcast>, IPodcastRepository {
|
||||
public PodcastRepository(PodNomsDbContext context) : base(context) {
|
||||
public PodcastRepository(PodNomsDbContext context, ILogger<PodcastRepository> logger) : base(context, logger) {
|
||||
}
|
||||
public async Task<Podcast> GetAsync(string id, string slug) {
|
||||
var ret = await GetAll()
|
||||
|
||||
@@ -11,13 +11,15 @@ namespace PodNoms.Api.Persistence {
|
||||
this._logger = logger;
|
||||
this._context = context;
|
||||
}
|
||||
public async Task CompleteAsync() {
|
||||
public async Task<bool> CompleteAsync() {
|
||||
try {
|
||||
await Task.FromResult<object>(null);
|
||||
await _context.SaveChangesAsync();
|
||||
return true;
|
||||
} catch (DbUpdateException dbe) {
|
||||
this._logger.LogError($"Error completing unit of work: {dbe.Message}\n{dbe.InnerException.Message}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PodNoms.Api.Providers;
|
||||
|
||||
namespace PodNoms.Api {
|
||||
public class Program {
|
||||
@@ -15,21 +17,17 @@ namespace PodNoms.Api {
|
||||
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == EnvironmentName.Development;
|
||||
|
||||
public static void Main(string[] args) {
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
var host = BuildWebHost(args).Build();
|
||||
host.MigrateDatabase(isDevelopment);
|
||||
host.Run();
|
||||
}
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
public static IWebHostBuilder BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>()
|
||||
.UseUrls("http://0.0.0.0:5000")
|
||||
.UseKestrel(options => {
|
||||
options.Limits.MaxRequestBodySize = 1073741824; //1Gb
|
||||
// if (isDevelopment)
|
||||
// {
|
||||
// options.Listen(IPAddress.Any, 5001, listenOptions =>
|
||||
// {
|
||||
// listenOptions.UseHttps("certs/dev2.podnoms.com.pfx", "secret");
|
||||
// });
|
||||
// }
|
||||
options.Limits.MaxRequestBodySize = 1073741824;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
20
server/Providers/WebHostExtensions.cs
Normal file
20
server/Providers/WebHostExtensions.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using PodNoms.Api.Persistence;
|
||||
|
||||
namespace PodNoms.Api.Providers {
|
||||
public static class WebHostExtensions {
|
||||
public static IWebHost MigrateDatabase(this IWebHost webHost, bool isDevelopment) {
|
||||
if (isDevelopment) {
|
||||
var serviceScopeFactory = (IServiceScopeFactory)webHost.Services.GetService(typeof(IServiceScopeFactory));
|
||||
using (var scope = serviceScopeFactory.CreateScope()) {
|
||||
var services = scope.ServiceProvider;
|
||||
var dbContext = services.GetRequiredService<PodNomsDbContext>();
|
||||
// dbContext.Database.EnsureDeleted();
|
||||
dbContext.Database.EnsureCreated();
|
||||
}
|
||||
}
|
||||
return webHost;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System;
|
||||
using Hangfire;
|
||||
|
||||
namespace PodNoms.Api.Services.Processor {
|
||||
public class ServiceProviderActivator : JobActivator {
|
||||
public class HangfireActivator : JobActivator {
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public ServiceProviderActivator(IServiceProvider serviceProvider) {
|
||||
public HangfireActivator(IServiceProvider serviceProvider) {
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
@@ -49,11 +49,13 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using PodNoms.Api.Utils.RemoteParsers;
|
||||
using PodNoms.Api.Services.Slack;
|
||||
using System.Threading;
|
||||
|
||||
namespace PodNoms.Api {
|
||||
public class Startup {
|
||||
private const string SecretKey = "QGfaEMNASkNMGLKA3LjgPdkPfFEy3n40"; // todo: get this from somewhere secure
|
||||
private readonly SymmetricSecurityKey _signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey));
|
||||
private static Mutex mutex = new Mutex();
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
public Startup(IConfiguration configuration) {
|
||||
@@ -80,7 +82,7 @@ namespace PodNoms.Api {
|
||||
}
|
||||
public void ConfigureDevelopmentServices(IServiceCollection services) {
|
||||
services.AddDbContext<PodNomsDbContext>(options => {
|
||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
|
||||
options.UseSqlServer(Configuration.GetConnectionString("PlaygroundConnection"));
|
||||
options.EnableSensitiveDataLogging(true);
|
||||
});
|
||||
|
||||
@@ -117,9 +119,12 @@ namespace PodNoms.Api {
|
||||
options.MultipartBodyLengthLimit = long.MaxValue;
|
||||
});
|
||||
|
||||
mutex.WaitOne();
|
||||
Mapper.Reset();
|
||||
services.AddAutoMapper(e => {
|
||||
e.AddProfile(new MappingProvider(Configuration));
|
||||
});
|
||||
mutex.ReleaseMutex();
|
||||
|
||||
services.AddHttpClient("mixcloud", c => {
|
||||
c.BaseAddress = new Uri("https://api.mixcloud.com/");
|
||||
@@ -259,9 +264,20 @@ namespace PodNoms.Api {
|
||||
Encoding.RegisterProvider(instance);
|
||||
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
|
||||
ILoggerFactory loggerFactory, IServiceProvider serviceProvider) {
|
||||
ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IApplicationLifetime lifetime) {
|
||||
|
||||
lifetime.ApplicationStarted.Register(() => {
|
||||
if (env.IsDevelopment()) {
|
||||
var p = new System.Diagnostics.Process();
|
||||
p.StartInfo.UseShellExecute = false;
|
||||
p.StartInfo.RedirectStandardOutput = true;
|
||||
p.StartInfo.RedirectStandardError = true;
|
||||
p.StartInfo.FileName = "/usr/bin/play";
|
||||
p.StartInfo.Arguments = "/home/fergalm/dev/podnoms/server/.working/tada.mp3";
|
||||
p.Start();
|
||||
}
|
||||
});
|
||||
|
||||
if (env.IsDevelopment()) {
|
||||
app.UseDeveloperExceptionPage();
|
||||
@@ -273,13 +289,12 @@ namespace PodNoms.Api {
|
||||
// app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
|
||||
GlobalConfiguration.Configuration.UseActivator(new ServiceProviderActivator(serviceProvider));
|
||||
|
||||
if ((env.IsProduction() || true)) {
|
||||
app.UseHangfireServer();
|
||||
app.UseHangfireDashboard("/hangfire", new DashboardOptions {
|
||||
Authorization = new[] { new HangFireAuthorizationFilter() }
|
||||
});
|
||||
GlobalConfiguration.Configuration.UseActivator(new HangfireActivator(serviceProvider));
|
||||
}
|
||||
|
||||
app.UseForwardedHeaders(new ForwardedHeadersOptions {
|
||||
|
||||
@@ -3,12 +3,9 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PodNoms.Api.Utils.Extensions
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static string StripNonXMLChars(this string str, float xmlVersion = 1.1f)
|
||||
{
|
||||
namespace PodNoms.Api.Utils.Extensions {
|
||||
public static class StringExtensions {
|
||||
public static string StripNonXMLChars(this string str, float xmlVersion = 1.1f) {
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return string.Empty;
|
||||
const string patternVersion1_0 = @"&#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|7F|8[0-46-9A-F]9[0-9A-F]);";
|
||||
@@ -26,19 +23,16 @@ namespace PodNoms.Api.Utils.Extensions
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string RemoveNonAlphaChars(this string str)
|
||||
{
|
||||
public static string RemoveNonAlphaChars(this string str) {
|
||||
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
|
||||
return rgx.Replace(str, "");
|
||||
}
|
||||
public static string RemoveInvalidUrlChars(this string str)
|
||||
{
|
||||
public static string RemoveInvalidUrlChars(this string str) {
|
||||
string regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
|
||||
Regex r = new Regex(string.Format("[{0}]", Regex.Escape(regexSearch)));
|
||||
return r.Replace(str, "");
|
||||
}
|
||||
public static string Slugify(this string phrase, IEnumerable<string> source)
|
||||
{
|
||||
public static string Slugify(this string phrase, IEnumerable<string> source) {
|
||||
string str = phrase.RemoveAccent().ToLower().RemoveInvalidUrlChars().RemoveNonAlphaChars();
|
||||
// invalid chars
|
||||
str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
|
||||
@@ -51,26 +45,22 @@ namespace PodNoms.Api.Utils.Extensions
|
||||
|
||||
str = str.Replace(" ", "");
|
||||
var count = 1;
|
||||
|
||||
while (source != null &&
|
||||
!string.IsNullOrEmpty(source.Where(e => e == str).Select(e => e).DefaultIfEmpty("").FirstOrDefault()))
|
||||
{
|
||||
str = $"{str}_{count++}";
|
||||
var origStr = str;
|
||||
while (source != null && source.Count() != 0 &&
|
||||
!string.IsNullOrEmpty(source.Where(e => e == str).Select(e => e).DefaultIfEmpty("").FirstOrDefault())) {
|
||||
str = $"{origStr}-{count++}";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static string RemoveAccent(this string txt)
|
||||
{
|
||||
public static string RemoveAccent(this string txt) {
|
||||
byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt);
|
||||
return System.Text.Encoding.ASCII.GetString(bytes);
|
||||
}
|
||||
|
||||
public static string UrlParse(this string url, params string[] parts)
|
||||
{
|
||||
public static string UrlParse(this string url, params string[] parts) {
|
||||
url = url.TrimEnd('/');
|
||||
foreach (var u in parts)
|
||||
{
|
||||
foreach (var u in parts) {
|
||||
url = string.Format("{0}/{1}", url, u.TrimStart('/'));
|
||||
}
|
||||
return url;
|
||||
|
||||
Reference in New Issue
Block a user