From faa8a87c59202472a09ac1d4cb5ee0941672d4e7 Mon Sep 17 00:00:00 2001 From: Fergal Moran Date: Fri, 27 Apr 2018 02:22:05 +0100 Subject: [PATCH] Temp image fix --- client/src/app/app.module.ts | 4 +- client/src/app/app.router.ts | 2 - .../callback/callback.component.css | 0 .../callback/callback.component.html | 3 - .../components/callback/callback.component.ts | 17 - client/src/app/effects/entries.effects.ts | 4 +- server/Controllers/EntryController.cs | 11 +- server/Controllers/ImageUploadController.cs | 3 +- ...20180427010607_ImageUrlUpdates.Designer.cs | 365 ++++++++++++++++++ .../20180427010607_ImageUrlUpdates.cs | 25 ++ .../PodnomsDbContextModelSnapshot.cs | 4 +- server/Models/Podcast.cs | 8 +- server/Persistence/PodcastRepository.cs | 2 +- server/Providers/MappingProvider.cs | 6 +- 14 files changed, 413 insertions(+), 41 deletions(-) delete mode 100644 client/src/app/components/callback/callback.component.css delete mode 100644 client/src/app/components/callback/callback.component.html delete mode 100644 client/src/app/components/callback/callback.component.ts create mode 100644 server/Migrations/20180427010607_ImageUrlUpdates.Designer.cs create mode 100644 server/Migrations/20180427010607_ImageUrlUpdates.cs diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts index abaaacb..ce01ca8 100644 --- a/client/src/app/app.module.ts +++ b/client/src/app/app.module.ts @@ -1,5 +1,4 @@ import { GlobalsService } from './services/globals.service'; -import { CallbackComponent } from './components/callback/callback.component'; import { PodcastUploadFormComponent } from './components/podcast/podcast-upload-form/podcast-upload-form.component'; import { PodcastAddUrlFormComponent } from './components/podcast/podcast-add-url-form/podcast-add-url-form.component'; import { PodcastAddFormComponent } from './components/podcast/podcast-add-form/podcast-add-form.component'; @@ -70,7 +69,7 @@ import { PodNomsApiInterceptor } from './interceptors/podnoms-api.interceptor'; import { SideOverlayComponent } from './components/side-overlay/side-overlay.component'; import { UiStateService } from './services/ui-state.service'; -let config = new AuthServiceConfig([ +const config = new AuthServiceConfig([ { id: GoogleLoginProvider.PROVIDER_ID, provider: new GoogleLoginProvider('357461672895-2mevm3b10b4bd3gjdvugl00up8ba2n4m.apps.googleusercontent.com') @@ -101,7 +100,6 @@ export function provideConfig() { PodcastAddUrlFormComponent, DebugComponent, SidebarComponent, - CallbackComponent, RegisterComponent, ResetComponent, ProfileComponent, diff --git a/client/src/app/app.router.ts b/client/src/app/app.router.ts index e073f98..8175a1d 100644 --- a/client/src/app/app.router.ts +++ b/client/src/app/app.router.ts @@ -1,7 +1,6 @@ import { ProfileComponent } from 'app/components/profile/profile.component'; import { ResetComponent } from 'app/components/reset/reset.component'; import { RegisterComponent } from 'app/components/register/register.component'; -import { CallbackComponent } from 'app/components/callback/callback.component'; import { LoginComponent } from 'app/components/login/login.component'; import { DebugComponent } from 'app/components/debug/debug.component'; import { NgModule } from '@angular/core'; @@ -18,7 +17,6 @@ const routes: Routes = [ { path: 'about', component: AboutComponent }, { path: 'register', component: RegisterComponent }, { path: 'reset', component: ResetComponent, pathMatch: 'full' }, - { path: 'callback', component: CallbackComponent }, { path: 'debug', component: DebugComponent, canActivate: [AuthGuard] }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] }, { path: 'podcasts', component: PodcastComponent, canActivate: [AuthGuard] }, diff --git a/client/src/app/components/callback/callback.component.css b/client/src/app/components/callback/callback.component.css deleted file mode 100644 index e69de29..0000000 diff --git a/client/src/app/components/callback/callback.component.html b/client/src/app/components/callback/callback.component.html deleted file mode 100644 index c725f56..0000000 --- a/client/src/app/components/callback/callback.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- Loading...... -
\ No newline at end of file diff --git a/client/src/app/components/callback/callback.component.ts b/client/src/app/components/callback/callback.component.ts deleted file mode 100644 index facbb9c..0000000 --- a/client/src/app/components/callback/callback.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { PodnomsAuthService } from 'app/services/podnoms-auth.service'; -import { Router } from '@angular/router'; - -@Component({ - selector: 'app-callback', - templateUrl: './callback.component.html', - styleUrls: ['./callback.component.css'] -}) -export class CallbackComponent implements OnInit { - constructor(private _authService: PodnomsAuthService, private _router: Router) {} - - ngOnInit() { - debugger; - this._router.navigate(['/podcasts']); - } -} diff --git a/client/src/app/effects/entries.effects.ts b/client/src/app/effects/entries.effects.ts index 11738e2..aa25e85 100644 --- a/client/src/app/effects/entries.effects.ts +++ b/client/src/app/effects/entries.effects.ts @@ -33,8 +33,8 @@ export class EntriesEffects { add$ = this.actions$ .ofType(entries.ADD) .switchMap((action: entries.AddAction) => - //this is probably (definitely) superfluous as we've now moved - //the addEntry into the component + // this is probably (definitely) superfluous as we've now moved + // the addEntry into the component this._service.updateEntry(action.payload) .map(res => { console.log('EntriesEffects', 'add$', res); diff --git a/server/Controllers/EntryController.cs b/server/Controllers/EntryController.cs index e96abba..849a60a 100644 --- a/server/Controllers/EntryController.cs +++ b/server/Controllers/EntryController.cs @@ -8,6 +8,7 @@ using Hangfire; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using PodNoms.Api.Models; @@ -25,6 +26,9 @@ namespace PodNoms.Api.Controllers { public class EntryController : BaseAuthController { private readonly IPodcastRepository _podcastRepository; private readonly IEntryRepository _repository; + + public IConfiguration _options { get; } + private readonly IUnitOfWork _unitOfWork; private readonly IMapper _mapper; private readonly IUrlProcessService _processor; @@ -36,12 +40,14 @@ namespace PodNoms.Api.Controllers { IPodcastRepository podcastRepository, IUnitOfWork unitOfWork, IMapper mapper, IOptions storageSettings, IOptions audioFileStorageSettings, + IConfiguration options, IUrlProcessService processor, ILoggerFactory logger, UserManager userManager, IHttpContextAccessor contextAccessor) : base(contextAccessor, userManager) { this._logger = logger.CreateLogger(); this._podcastRepository = podcastRepository; this._repository = repository; + this._options = options; this._storageSettings = storageSettings.Value; this._unitOfWork = unitOfWork; this._audioFileStorageSettings = audioFileStorageSettings.Value; @@ -57,7 +63,10 @@ namespace PodNoms.Api.Controllers { extractJobId, service => service.UploadAudio(entry.Id, entry.AudioUrl)); var notify = BackgroundJob.ContinueWith( uploadJobId, service => service.NotifyUser(entry.Podcast.AppUser.Id, "PodNoms", $"{entry.Title} has finished processing", - entry.Podcast.ImageUrl)); + entry.Podcast.GetThumbnailUrl( + this._options.GetSection("Storage")["CdnUrl"], + this._options.GetSection("ImageFileStorageSettings")["ContainerName"]) + )); } catch (InvalidOperationException ex) { _logger.LogError($"Failed submitting job to processor\n{ex.Message}"); entry.ProcessingStatus = ProcessingStatus.Failed; diff --git a/server/Controllers/ImageUploadController.cs b/server/Controllers/ImageUploadController.cs index bd79137..4863f27 100644 --- a/server/Controllers/ImageUploadController.cs +++ b/server/Controllers/ImageUploadController.cs @@ -63,7 +63,6 @@ namespace PodNoms.Api.Controllers { var destinationFile = $"{podcast.Uid}.{extension}"; var destinationFileThumbnail = $"{podcast.Uid}-32x32.{extension}"; - podcast.ImageUrl = destinationFile; await _fileUploader.UploadFile(finishedFile, _imageFileStorageSettings.ContainerName, destinationFile, "image/png", (p, t) => _logger.LogDebug($"Uploading image: {p} - {t}")); @@ -72,7 +71,7 @@ namespace PodNoms.Api.Controllers { destinationFileThumbnail, "image/png", (p, t) => _logger.LogDebug($"Uploading image: {p} - {t}")); await _repository.AddOrUpdateAsync(podcast); - + podcast.TemporaryImageUrl = string.Empty; await this._unitOfWork.CompleteAsync(); return new OkObjectResult(_mapper.Map(podcast)); diff --git a/server/Migrations/20180427010607_ImageUrlUpdates.Designer.cs b/server/Migrations/20180427010607_ImageUrlUpdates.Designer.cs new file mode 100644 index 0000000..7e9e4b5 --- /dev/null +++ b/server/Migrations/20180427010607_ImageUrlUpdates.Designer.cs @@ -0,0 +1,365 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Migrations; +using PodNoms.Api.Persistence; + +namespace PodNoms.Api.Migrations +{ + [DbContext(typeof(PodnomsDbContext))] + [Migration("20180427010607_ImageUrlUpdates")] + partial class ImageUrlUpdates + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.0-preview2-30571") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("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", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("PodNoms.Api.Models.Playlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreateDate"); + + b.Property("PodcastId"); + + b.Property("SourceUrl"); + + b.Property("UpdateDate"); + + b.HasKey("Id"); + + b.HasIndex("PodcastId"); + + b.ToTable("Playlists"); + }); + + modelBuilder.Entity("PodNoms.Api.Models.Podcast", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AppUserId"); + + b.Property("CreateDate") + .ValueGeneratedOnAdd() + .HasDefaultValueSql("getdate()"); + + b.Property("Description"); + + b.Property("Slug") + .IsUnicode(true); + + b.Property("TemporaryImageUrl"); + + b.Property("Title"); + + b.Property("Uid"); + + b.Property("UpdateDate"); + + b.HasKey("Id"); + + b.HasIndex("AppUserId"); + + b.ToTable("Podcasts"); + }); + + modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AudioFileSize"); + + b.Property("AudioLength"); + + b.Property("AudioUrl"); + + b.Property("Author"); + + b.Property("CreateDate") + .ValueGeneratedOnAdd() + .HasDefaultValueSql("getdate()"); + + b.Property("Description"); + + b.Property("ImageUrl"); + + b.Property("PlaylistId"); + + b.Property("PodcastId"); + + b.Property("Processed"); + + b.Property("ProcessingPayload"); + + b.Property("ProcessingStatus"); + + b.Property("SourceUrl"); + + b.Property("Title"); + + b.Property("Uid"); + + b.Property("UpdateDate"); + + b.HasKey("Id"); + + b.HasIndex("PlaylistId"); + + b.HasIndex("PodcastId"); + + b.ToTable("PodcastEntries"); + }); + + modelBuilder.Entity("PodNoms.Api.Services.Auth.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("FacebookId"); + + b.Property("FirstName"); + + b.Property("LastName"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("PictureUrl"); + + b.Property("SecurityStamp"); + + b.Property("Slug"); + + b.Property("TwoFactorEnabled"); + + b.Property("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", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", b => + { + b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .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 + } + } +} diff --git a/server/Migrations/20180427010607_ImageUrlUpdates.cs b/server/Migrations/20180427010607_ImageUrlUpdates.cs new file mode 100644 index 0000000..377032b --- /dev/null +++ b/server/Migrations/20180427010607_ImageUrlUpdates.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace PodNoms.Api.Migrations +{ + public partial class ImageUrlUpdates : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "ImageUrl", + table: "Podcasts", + newName: "TemporaryImageUrl"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "TemporaryImageUrl", + table: "Podcasts", + newName: "ImageUrl"); + } + } +} diff --git a/server/Migrations/PodnomsDbContextModelSnapshot.cs b/server/Migrations/PodnomsDbContextModelSnapshot.cs index a0ba407..3bd4e5b 100644 --- a/server/Migrations/PodnomsDbContextModelSnapshot.cs +++ b/server/Migrations/PodnomsDbContextModelSnapshot.cs @@ -160,11 +160,11 @@ namespace PodNoms.Api.Migrations b.Property("Description"); - b.Property("ImageUrl"); - b.Property("Slug") .IsUnicode(true); + b.Property("TemporaryImageUrl"); + b.Property("Title"); b.Property("Uid"); diff --git a/server/Models/Podcast.cs b/server/Models/Podcast.cs index 1665705..5273a8f 100644 --- a/server/Models/Podcast.cs +++ b/server/Models/Podcast.cs @@ -11,17 +11,17 @@ namespace PodNoms.Api.Models { public string Title { get; set; } public string Description { get; set; } public string Slug { get; set; } - public string ImageUrl { get; set; } + public string TemporaryImageUrl { get; set; } public List PodcastEntries { get; set; } public Podcast() { PodcastEntries = new List(); } public string GetImageUrl(string cdnUrl, string containerName) { - return $"{cdnUrl}{containerName}/{this.ImageUrl}"; + return string.IsNullOrEmpty(TemporaryImageUrl) ? $"{cdnUrl}{containerName}/{this.Uid}.png" : TemporaryImageUrl; } - public string GetThumnnailUrl(string cdnUrl, string containerName) { - return $"{cdnUrl}{containerName}/{this.Uid}-32x32.png"; + public string GetThumbnailUrl(string cdnUrl, string containerName) { + return string.IsNullOrEmpty(TemporaryImageUrl) ? $"{cdnUrl}{containerName}/{this.Uid}-32x32.png" : TemporaryImageUrl; } } } \ No newline at end of file diff --git a/server/Persistence/PodcastRepository.cs b/server/Persistence/PodcastRepository.cs index 99cde34..09e79c8 100644 --- a/server/Persistence/PodcastRepository.cs +++ b/server/Persistence/PodcastRepository.cs @@ -54,7 +54,7 @@ namespace PodNoms.Api.Persistence { from p in _context.Podcasts select p.Slug); } - item.ImageUrl = $"standard/podcast-image-{Randomisers.RandomInteger(1, 16)}.png"; + item.TemporaryImageUrl = $"standard/podcast-image-{Randomisers.RandomInteger(1, 16)}.png"; _context.Podcasts.Add(item); } diff --git a/server/Providers/MappingProvider.cs b/server/Providers/MappingProvider.cs index 38238ba..e1ac2fa 100644 --- a/server/Providers/MappingProvider.cs +++ b/server/Providers/MappingProvider.cs @@ -24,7 +24,7 @@ namespace PodNoms.Api.Providers { this._options.GetSection("ImageFileStorageSettings")["ContainerName"]))) .ForMember( v => v.ThumbnailUrl, - e => e.MapFrom(m => m.GetThumnnailUrl( + e => e.MapFrom(m => m.GetThumbnailUrl( this._options.GetSection("Storage")["CdnUrl"], this._options.GetSection("ImageFileStorageSettings")["ContainerName"]))); @@ -42,9 +42,7 @@ namespace PodNoms.Api.Providers { map => map.MapFrom(s => s.PictureUrl)); //API Resource to Domain - CreateMap() - .ForMember(v => v.ImageUrl, map => map.Ignore()) - ; + CreateMap(); CreateMap() .ForMember( e => e.ImageUrl,