diff --git a/client/src/app/services/base.service.ts b/client/src/app/services/base.service.ts index 95efc39..51cbc63 100644 --- a/client/src/app/services/base.service.ts +++ b/client/src/app/services/base.service.ts @@ -12,7 +12,7 @@ export abstract class BaseService { } let modelStateErrors: string = ''; - const serverError = error.json(); + const serverError = error; if (!serverError.type) { for (let key in serverError) { diff --git a/server/Controllers/ImageUploadController.cs b/server/Controllers/ImageUploadController.cs index 17146ae..3c29f6d 100644 --- a/server/Controllers/ImageUploadController.cs +++ b/server/Controllers/ImageUploadController.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using AutoMapper; -using SixLabors.ImageSharp; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -16,12 +15,14 @@ using PodNoms.Api.Persistence; using PodNoms.Api.Services; using PodNoms.Api.Services.Storage; using PodNoms.Api.Utils; -using SixLabors.ImageSharp.PixelFormats; +using Microsoft.AspNetCore.Identity; +using PodNoms.Api.Services.Auth; +using System.Drawing; namespace PodNoms.Api.Controllers { [Authorize] [Route("/podcast/{slug}/imageupload")] - public class ImageUploadController : Controller { + public class ImageUploadController : BaseAuthController { private readonly IPodcastRepository _repository; private readonly IUnitOfWork _unitOfWork; private readonly IMapper _mapper; @@ -31,7 +32,9 @@ namespace PodNoms.Api.Controllers { public ImageUploadController(IPodcastRepository repository, IUnitOfWork unitOfWork, IFileUploader fileUploader, IOptions imageFileStorageSettings, - ILoggerFactory loggerFactory, IMapper mapper) { + ILoggerFactory loggerFactory, IMapper mapper, UserManager userManager, IHttpContextAccessor contextAccessor) + : base(contextAccessor, userManager) { + this._fileUploader = fileUploader; this._imageFileStorageSettings = imageFileStorageSettings.Value; this._repository = repository; @@ -42,42 +45,33 @@ namespace PodNoms.Api.Controllers { [HttpPost] public async Task Upload(string slug, IFormFile file) { _logger.LogDebug("Uploading new image"); - var email = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; - if (!string.IsNullOrEmpty(email)) { - if (file == null || file.Length == 0) return BadRequest("No file found in stream"); - if (file.Length > _imageFileStorageSettings.MaxUploadFileSize) return BadRequest("Maximum file size exceeded"); - if (!_imageFileStorageSettings.IsSupported(file.FileName)) return BadRequest("Invalid file type"); + if (file == null || file.Length == 0) return BadRequest("No file found in stream"); + if (file.Length > _imageFileStorageSettings.MaxUploadFileSize) return BadRequest("Maximum file size exceeded"); + if (!_imageFileStorageSettings.IsSupported(file.FileName)) return BadRequest("Invalid file type"); - var podcast = await _repository.GetAsync(email, slug); - if (podcast == null) - return NotFound(); + var podcast = await _repository.GetAsync(_applicationUser.Id, slug); + if (podcast == null) + return NotFound(); - var cacheFile = await CachedFormFileStorage.CacheItem(file); - (var finishedFile, var extension) = __todo_convert_cache_file(cacheFile, podcast.Uid); + var cacheFile = await CachedFormFileStorage.CacheItem(file); + (var finishedFile, var extension) = __todo_convert_cache_file(cacheFile, podcast.Uid); - var destinationFile = $"{System.Guid.NewGuid().ToString()}.{extension}"; - podcast.ImageUrl = destinationFile; + var destinationFile = $"{System.Guid.NewGuid().ToString()}.{extension}"; + podcast.ImageUrl = destinationFile; - var imageUrl = await _fileUploader.UploadFile(finishedFile, _imageFileStorageSettings.ContainerName, - destinationFile, (p, t) => _logger.LogDebug($"Uploading image: {p} - {t}")); + var imageUrl = await _fileUploader.UploadFile(finishedFile, _imageFileStorageSettings.ContainerName, + destinationFile, (p, t) => _logger.LogDebug($"Uploading image: {p} - {t}")); - await _repository.AddOrUpdateAsync(podcast); + await _repository.AddOrUpdateAsync(podcast); - await this._unitOfWork.CompleteAsync(); + await this._unitOfWork.CompleteAsync(); - return new OkObjectResult(_mapper.Map(podcast)); - } - return Unauthorized(); + return new OkObjectResult(_mapper.Map(podcast)); } //TODO: Refactor this to service private (string, string) __todo_convert_cache_file(string cacheFile, string prefix) { - var outputFile = Path.Combine(Path.GetTempPath(), $"{prefix}.jpg"); - using (Image image = Image.Load(cacheFile)) { - image.Save(outputFile); - } - - return (outputFile, "jpg"); + return (cacheFile, "jpg"); } } } diff --git a/server/Controllers/PodcastController.cs b/server/Controllers/PodcastController.cs index 9a23e17..7a412d3 100644 --- a/server/Controllers/PodcastController.cs +++ b/server/Controllers/PodcastController.cs @@ -62,6 +62,7 @@ namespace PodNoms.Api.Controllers { public async Task Post([FromBody] PodcastViewModel vm) { if (ModelState.IsValid) { var item = _mapper.Map(vm); + item.AppUser = _applicationUser; var ret = await _repository.AddOrUpdateAsync(item); await _uow.CompleteAsync(); return new OkObjectResult(_mapper.Map(ret)); diff --git a/server/Persistence/PodcastRepository.cs b/server/Persistence/PodcastRepository.cs index 0510af5..99cde34 100644 --- a/server/Persistence/PodcastRepository.cs +++ b/server/Persistence/PodcastRepository.cs @@ -48,17 +48,14 @@ namespace PodNoms.Api.Persistence { if (item.Id != 0) { _context.Entry(item).State = EntityState.Modified; } else { - var localFile = await HttpUtils.DownloadFile($"http://lorempixel.com/1400/1400/?{System.Guid.NewGuid().ToString()}"); item.Uid = System.Guid.NewGuid().ToString(); if (string.IsNullOrEmpty(item.Slug) && !string.IsNullOrEmpty(item.Title)) { item.Slug = item.Title.Slugify( from p in _context.Podcasts select p.Slug); } - item.ImageUrl = $"{item.Uid}.jpg"; + item.ImageUrl = $"standard/podcast-image-{Randomisers.RandomInteger(1, 16)}.png"; _context.Podcasts.Add(item); - var file = await _fileUploader.UploadFile( - localFile, _imageStorageSettings.ContainerName, item.ImageUrl, null); } return item; diff --git a/server/PodNoms.Api.csproj b/server/PodNoms.Api.csproj index 482f783..23e7316 100644 --- a/server/PodNoms.Api.csproj +++ b/server/PodNoms.Api.csproj @@ -28,7 +28,7 @@ - + diff --git a/server/Services/Auth/PodNomsUserManager.cs b/server/Services/Auth/PodNomsUserManager.cs new file mode 100644 index 0000000..9b97a63 --- /dev/null +++ b/server/Services/Auth/PodNomsUserManager.cs @@ -0,0 +1,42 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using PodNoms.Api.Persistence; +using PodNoms.Api.Services.Auth; +using PodNoms.Api.Utils.Extensions; + +namespace PodNoms.Api.Services.Auth { + public class PodNomsUserManager : UserManager { + private readonly PodnomsDbContext _context; + + public PodNomsUserManager(IUserStore store, IOptions optionsAccessor, + IPasswordHasher passwordHasher, IEnumerable> userValidators, + IEnumerable> passwordValidators, ILookupNormalizer keyNormalizer, + IdentityErrorDescriber errors, IServiceProvider services, ILogger> logger) : + base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger) { + } + public override Task CreateAsync(ApplicationUser user) { + _slugify(user); + return base.CreateAsync(user); + } + public override Task UpdateAsync(ApplicationUser user) { + _slugify(user); + return base.UpdateAsync(user); + } + + private void _slugify(ApplicationUser user) { + if (string.IsNullOrEmpty(user.Slug)) { + var name = $"{user.FirstName} {user.LastName}"; + var c = name ?? user.Email?.Split('@')[0] ?? string.Empty; + if (!string.IsNullOrEmpty(c)) { + user.Slug = c.Slugify( + from u in Users select u.Slug); + } + } + } + } +} \ No newline at end of file diff --git a/server/Startup.cs b/server/Startup.cs index d46cca1..c4bd871 100644 --- a/server/Startup.cs +++ b/server/Startup.cs @@ -153,7 +153,7 @@ namespace PodNoms.Api { context.Token = token; } return Task.CompletedTask; - }; + }; }); services.AddAuthorization(j => { @@ -171,7 +171,8 @@ namespace PodNoms.Api { }); identityBuilder = new IdentityBuilder(identityBuilder.UserType, typeof(IdentityRole), identityBuilder.Services); identityBuilder.AddEntityFrameworkStores().AddDefaultTokenProviders(); - + identityBuilder.AddUserManager(); + services.AddMvc(options => { options.OutputFormatters.Add(new XmlSerializerOutputFormatter()); options.OutputFormatters @@ -206,6 +207,7 @@ namespace PodNoms.Api { .AllowCredentials()); }); + services.AddTransient(); services.AddTransient(); services.TryAddTransient(); diff --git a/server/Utils/HttpUtils.cs b/server/Utils/HttpUtils.cs index 9654cf6..d17572e 100644 --- a/server/Utils/HttpUtils.cs +++ b/server/Utils/HttpUtils.cs @@ -1,21 +1,15 @@ using System.Net.Http; using System.Threading.Tasks; -namespace PodNoms.Api.Utils -{ - public class HttpUtils - { - public static async Task DownloadFile(string url, string file="") - { +namespace PodNoms.Api.Utils { + public class HttpUtils { + public static async Task DownloadFile(string url, string file = "") { if (string.IsNullOrEmpty(file)) file = System.IO.Path.GetTempFileName(); - using (var client = new HttpClient()) - { - using (var response = await client.GetAsync(url)) - { - using (var content = response.Content) - { + using (var client = new HttpClient()) { + using (var response = await client.GetAsync(url)) { + using (var content = response.Content) { byte[] result = await content.ReadAsByteArrayAsync(); System.IO.File.WriteAllBytes(file, result); }