From 9bc49a37f8b19344da538db17cb3dd948dea7a7b Mon Sep 17 00:00:00 2001 From: Fergal Moran Date: Wed, 25 Apr 2018 18:50:29 +0100 Subject: [PATCH] Removed outdated user repo stuff --- .../app/components/login/login.component.ts | 3 +- client/src/environments/environment.prod.ts | 3 - client/src/environments/environment.ts | 1 - server/Controllers/AccountsController.cs | 4 +- server/Controllers/BaseAuthController.cs | 20 + server/Controllers/ChatterController.cs | 15 +- server/Controllers/DebugController.cs | 16 +- server/Controllers/EntryController.cs | 12 +- server/Controllers/ExternalAuthController.cs | 4 +- server/Controllers/PodcastController.cs | 37 +- server/Controllers/ProfileController.cs | 51 +-- server/Controllers/RssController.cs | 37 +- server/Controllers/UserController.cs | 33 -- server/Controllers/WebPushController.cs | 12 +- .../20180425154651_SlugUser.Designer.cs | 365 ++++++++++++++++++ server/Migrations/20180425154651_SlugUser.cs | 88 +++++ .../PodnomsDbContextModelSnapshot.cs | 53 +-- server/Models/Podcast.cs | 1 - server/Models/User.cs | 37 -- server/Persistence/EntryRepository.cs | 2 +- server/Persistence/IPodcastRepository.cs | 10 +- server/Persistence/IUserRepository.cs | 14 - server/Persistence/PlaylistRepository.cs | 2 +- server/Persistence/PodcastRepository.cs | 13 +- server/Persistence/PodnomsContext.cs | 5 - server/Persistence/UserRepository.cs | 90 ----- server/Providers/MappingProvider.cs | 7 +- server/Services/Auth/ApplicationUser.cs | 1 + .../Services/Auth/AuthenticationMiddleware.cs | 61 --- server/Services/Auth/UserManagerExtensions.cs | 12 + .../Processor/AudioUploadProcessService.cs | 44 +-- server/Services/Processor/ProcessService.cs | 2 +- .../Services/Processor/UrlProcessService.cs | 6 +- server/Startup.cs | 1 - 34 files changed, 599 insertions(+), 463 deletions(-) create mode 100644 server/Controllers/BaseAuthController.cs delete mode 100644 server/Controllers/UserController.cs create mode 100644 server/Migrations/20180425154651_SlugUser.Designer.cs create mode 100644 server/Migrations/20180425154651_SlugUser.cs delete mode 100644 server/Models/User.cs delete mode 100644 server/Persistence/IUserRepository.cs delete mode 100644 server/Persistence/UserRepository.cs delete mode 100644 server/Services/Auth/AuthenticationMiddleware.cs create mode 100644 server/Services/Auth/UserManagerExtensions.cs diff --git a/client/src/app/components/login/login.component.ts b/client/src/app/components/login/login.component.ts index c793e27..5f8c337 100644 --- a/client/src/app/components/login/login.component.ts +++ b/client/src/app/components/login/login.component.ts @@ -43,8 +43,7 @@ export class LoginComponent implements OnInit { this.isRequesting = true; if (provider === 'facebook') { const options: LoginOpt = { - scope: 'email public_profile', - redirect_uri: 'http://localhost:5000/facebook-auth.html' + scope: 'email public_profile' }; this._socialAuthService.signIn( FacebookLoginProvider.PROVIDER_ID, options) .then(user => { diff --git a/client/src/environments/environment.prod.ts b/client/src/environments/environment.prod.ts index f49137b..14fc101 100644 --- a/client/src/environments/environment.prod.ts +++ b/client/src/environments/environment.prod.ts @@ -1,12 +1,9 @@ export const environment = { production: true, - // API_HOST: 'https://api.podnoms.com', API_HOST: 'https://api.podnoms.com', SIGNALR_HOST: 'https://rt.podnoms.com', - AUTH0_REDIRECT_URL: 'https://podnoms.com/callback', BASE_URL: 'https://podnoms.com', appInsights: { instrumentationKey: '020b002a-bd3d-4b25-8a74-cab16fd39dfc' } }; - diff --git a/client/src/environments/environment.ts b/client/src/environments/environment.ts index fa526a0..44e62c8 100644 --- a/client/src/environments/environment.ts +++ b/client/src/environments/environment.ts @@ -5,7 +5,6 @@ export const environment = { production: false, API_HOST: ROOT_URL, SIGNALR_HOST: ROOT_URL, - AUTH0_REDIRECT_URL: `${ROOT_URL}/callback`, BASE_URL: 'http://localhost:4200/', appInsights: { instrumentationKey: '020b002a-bd3d-4b25-8a74-cab16fd39dfc' diff --git a/server/Controllers/AccountsController.cs b/server/Controllers/AccountsController.cs index 99677c0..2c4e29d 100644 --- a/server/Controllers/AccountsController.cs +++ b/server/Controllers/AccountsController.cs @@ -10,12 +10,10 @@ namespace PodNoms.Api.Controllers { [Route("[controller]")] public class AccountsController : Controller { - private readonly IUserRepository _userRepository; private readonly UserManager _userManager; private readonly IMapper _mapper; - public AccountsController(IUserRepository userRepository, UserManager userManager, IMapper mapper) { - this._userRepository = userRepository; + public AccountsController(UserManager userManager, IMapper mapper) { this._userManager = userManager; this._mapper = mapper; } diff --git a/server/Controllers/BaseAuthController.cs b/server/Controllers/BaseAuthController.cs new file mode 100644 index 0000000..5d4ac9d --- /dev/null +++ b/server/Controllers/BaseAuthController.cs @@ -0,0 +1,20 @@ +using System.Linq; +using System.Security.Claims; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using PodNoms.Api.Services.Auth; + +public class BaseAuthController : Controller { + private readonly ClaimsPrincipal _caller; + protected readonly UserManager _userManager; + protected readonly string _userId; + protected readonly ApplicationUser _applicationUser; + + public BaseAuthController(IHttpContextAccessor contextAccessor, UserManager userManager) { + _caller = contextAccessor.HttpContext.User; + _userManager = userManager; + _userId = _caller.Claims.Single(c => c.Type == "id").Value; + _applicationUser = userManager.FindByIdAsync(_userId).Result; + } +} \ No newline at end of file diff --git a/server/Controllers/ChatterController.cs b/server/Controllers/ChatterController.cs index 60a320d..99ea63c 100644 --- a/server/Controllers/ChatterController.cs +++ b/server/Controllers/ChatterController.cs @@ -2,28 +2,27 @@ using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using PodNoms.Api.Persistence; +using PodNoms.Api.Services.Auth; using PodNoms.Api.Services.Hubs; namespace PodNoms.Api.Controllers { [Authorize] [Route("[controller]")] - public class ChatterController : Controller { - private readonly IUserRepository _repository; + public class ChatterController : BaseAuthController { private readonly HubLifetimeManager _chatterHub; - public ChatterController(IUserRepository repository, HubLifetimeManager chatterHub) { + public ChatterController(HubLifetimeManager chatterHub, UserManager userManager, IHttpContextAccessor contextAccessor) + : base(contextAccessor, userManager) { this._chatterHub = chatterHub; - this._repository = repository; } [HttpPost("ping")] public async Task> Ping([FromBody] string message) { - var email = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; - - var user = await this._repository.GetAsync(email); await _chatterHub.SendAllAsync( - $"{user.Uid}_chatter", + $"{_applicationUser.Id}_chatter", new object[] { message }); return Ok(message); } diff --git a/server/Controllers/DebugController.cs b/server/Controllers/DebugController.cs index dffcc81..fcdd9cd 100644 --- a/server/Controllers/DebugController.cs +++ b/server/Controllers/DebugController.cs @@ -3,12 +3,15 @@ using System.Security.Claims; using System.Threading.Tasks; using Hangfire; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using PodNoms.Api.Models; using PodNoms.Api.Persistence; +using PodNoms.Api.Services.Auth; using PodNoms.Api.Services.Downloader; using PodNoms.Api.Services.Hubs; using PodNoms.Api.Services.Jobs; @@ -18,7 +21,7 @@ using WebPush = Lib.Net.Http.WebPush; namespace PodNoms.Api.Controllers { [Route("[controller]")] - public class DebugController : UserController { + public class DebugController : BaseAuthController { private readonly StorageSettings _storageSettings; private readonly AudioFileStorageSettings _audioFileStorageSettings; private readonly ApplicationsSettings _applicationsSettings; @@ -30,12 +33,14 @@ namespace PodNoms.Api.Controllers { public AppSettings _appSettings { get; } public DebugController(IOptions settings, IOptions appSettings, - HubLifetimeManager hubManager, IUserRepository userRepository, + HubLifetimeManager hubManager, IOptions applicationsSettings, IOptions audioFileStorageSettings, IOptions imageFileStorageSettings, IPushSubscriptionStore subscriptionStore, - IPushNotificationService notificationService) : base(userRepository) { + UserManager userManager, + IPushNotificationService notificationService, + IHttpContextAccessor contextAccessor) : base(contextAccessor, userManager) { this._appSettings = appSettings.Value; this._storageSettings = settings.Value; this._applicationsSettings = applicationsSettings.Value; @@ -75,12 +80,9 @@ namespace PodNoms.Api.Controllers { Topic = "Debug", Urgency = WebPush.PushMessageUrgency.Normal }; - var uid = await GetUserUidAsync(); - - await _subscriptionStore.ForEachSubscriptionAsync(uid, (subscription) => { + await _subscriptionStore.ForEachSubscriptionAsync(_applicationUser.Id, (subscription) => { _notificationService.SendNotificationAsync(subscription, pushMessage); }); - return "Hello Sailor!"; } } diff --git a/server/Controllers/EntryController.cs b/server/Controllers/EntryController.cs index a5b63b0..7f8837c 100644 --- a/server/Controllers/EntryController.cs +++ b/server/Controllers/EntryController.cs @@ -5,6 +5,8 @@ using System.Linq; using System.Threading.Tasks; using AutoMapper; using Hangfire; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -12,6 +14,7 @@ using PodNoms.Api.Models; using PodNoms.Api.Models.ViewModels; using PodNoms.Api.Persistence; using PodNoms.Api.Services; +using PodNoms.Api.Services.Auth; using PodNoms.Api.Services.Jobs; using PodNoms.Api.Services.Processor; using PodNoms.Api.Services.Storage; @@ -19,7 +22,7 @@ using PodNoms.Api.Services.Storage; namespace PodNoms.Api.Controllers { [Route("[controller]")] - public class EntryController : UserController { + public class EntryController : BaseAuthController { private readonly IPodcastRepository _podcastRepository; private readonly IEntryRepository _repository; private readonly IUnitOfWork _unitOfWork; @@ -30,11 +33,12 @@ namespace PodNoms.Api.Controllers { private readonly StorageSettings _storageSettings; public EntryController(IEntryRepository repository, - IUserRepository userRepository, IPodcastRepository podcastRepository, IUnitOfWork unitOfWork, IMapper mapper, IOptions storageSettings, IOptions audioFileStorageSettings, - IUrlProcessService processor, ILoggerFactory logger) : base(userRepository) { + IUrlProcessService processor, ILoggerFactory logger, + UserManager userManager, + IHttpContextAccessor contextAccessor) : base(contextAccessor, userManager) { this._logger = logger.CreateLogger(); this._podcastRepository = podcastRepository; this._repository = repository; @@ -52,7 +56,7 @@ namespace PodNoms.Api.Controllers { var uploadJobId = BackgroundJob.ContinueWith( extractJobId, service => service.UploadAudio(entry.Id, entry.AudioUrl)); var notify = BackgroundJob.ContinueWith( - uploadJobId, service => service.NotifyUser(entry.Podcast.User.Uid, "PodNoms", $"{entry.Title} has finished processing", + uploadJobId, service => service.NotifyUser(entry.Podcast.AppUser.Id, "PodNoms", $"{entry.Title} has finished processing", entry.Podcast.ImageUrl)); } catch (InvalidOperationException ex) { _logger.LogError($"Failed submitting job to processor\n{ex.Message}"); diff --git a/server/Controllers/ExternalAuthController.cs b/server/Controllers/ExternalAuthController.cs index 8c3574e..438f30b 100644 --- a/server/Controllers/ExternalAuthController.cs +++ b/server/Controllers/ExternalAuthController.cs @@ -62,13 +62,13 @@ namespace PodNoms.Api.Controllers { FirstName = payload.GivenName, LastName = payload.FamilyName, Name = payload.Name, - Picture = new FacebookPictureData { + Picture = new FacebookPictureData { Data = new FacebookPicture { Url = payload.Picture } } }); - } catch (Exception ex) { + } catch (Exception) { return BadRequest(Errors.AddErrorToModelState("login_failure", "Invalid google token.", ModelState)); } } diff --git a/server/Controllers/PodcastController.cs b/server/Controllers/PodcastController.cs index 6492288..9a23e17 100644 --- a/server/Controllers/PodcastController.cs +++ b/server/Controllers/PodcastController.cs @@ -21,21 +21,19 @@ using PodNoms.Api.Utils.Extensions; namespace PodNoms.Api.Controllers { [Authorize] [Route("[controller]")] - public class PodcastController : Controller { + public class PodcastController : BaseAuthController { private readonly IPodcastRepository _repository; - private readonly IUserRepository _userRepository; private readonly UserManager _userManager; private readonly IOptions _settings; private readonly IMapper _mapper; - private ClaimsPrincipal _caller; private readonly IUnitOfWork _uow; - public PodcastController(IPodcastRepository repository, IUserRepository userRepository, UserManager userManager, - IOptions options, IMapper mapper, IUnitOfWork unitOfWork, IHttpContextAccessor httpContextAccessor) { - this._caller = httpContextAccessor.HttpContext.User; + public PodcastController(IPodcastRepository repository, IOptions options, + IMapper mapper, IUnitOfWork unitOfWork, + UserManager userManager, IHttpContextAccessor contextAccessor) + : base(contextAccessor, userManager) { this._uow = unitOfWork; this._repository = repository; - this._userRepository = userRepository; this._userManager = userManager; this._settings = options; this._mapper = mapper; @@ -43,11 +41,9 @@ namespace PodNoms.Api.Controllers { [HttpGet] public async Task> Get() { - var userId = _caller.Claims.Single(c => c.Type == "id"); - var podcasts = await _repository.GetAllAsync(userId.Value); + var podcasts = await _repository.GetAllAsync(_applicationUser.Id); var ret = _mapper.Map, List>(podcasts.ToList()); return ret; - throw new Exception("No local user stored!"); } [HttpGet("{slug}")] @@ -64,22 +60,13 @@ namespace PodNoms.Api.Controllers { [HttpPost] public async Task Post([FromBody] PodcastViewModel vm) { - var userId = _caller.Claims.Single(c => c.Type == "id"); - var user = await this._userManager.FindByIdAsync(userId.Value); - if (user != null) { - if (ModelState.IsValid) { - var item = _mapper.Map(vm); - - //remove once we're ready - item.User = _userRepository.Get("fergal.moran@gmail.com"); - item.AppUser = user; - - var ret = await _repository.AddOrUpdateAsync(item); - await _uow.CompleteAsync(); - return new OkObjectResult(_mapper.Map(ret)); - } + if (ModelState.IsValid) { + var item = _mapper.Map(vm); + var ret = await _repository.AddOrUpdateAsync(item); + await _uow.CompleteAsync(); + return new OkObjectResult(_mapper.Map(ret)); } - return BadRequest("Invalid request data"); + return BadRequest("Invalid podcast model"); } [HttpPut] diff --git a/server/Controllers/ProfileController.cs b/server/Controllers/ProfileController.cs index fbf7d33..148fb41 100644 --- a/server/Controllers/ProfileController.cs +++ b/server/Controllers/ProfileController.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using AutoMapper; @@ -14,68 +15,32 @@ using PodNoms.Api.Services.Auth; namespace PodNoms.Api.Controllers { [Authorize] [Route("[controller]")] - public class ProfileController : Controller { - private IUserRepository _userRepository; - private readonly UserManager _userManager; + public class ProfileController : BaseAuthController { public IUnitOfWork _unitOfWork { get; } - private readonly ClaimsPrincipal _caller; public IMapper _mapper { get; } - public ProfileController(IUserRepository userRepository, IMapper mapper, IUnitOfWork unitOfWork, - UserManager userManager, IHttpContextAccessor httpContextAccessor) { - this._caller = httpContextAccessor.HttpContext.User; + public ProfileController(IMapper mapper, IUnitOfWork unitOfWork, + UserManager userManager, IHttpContextAccessor contextAccessor) + : base(contextAccessor, userManager) { this._mapper = mapper; this._unitOfWork = unitOfWork; - this._userManager = userManager; - this._userRepository = userRepository; } [HttpGet] public async Task> Get() { - var userId = _caller.Claims.Single(c => c.Type == "id"); - var user = await this._userManager.FindByIdAsync(userId.Value); - - var result = _mapper.Map(user); + var result = _mapper.Map(_applicationUser); return new OkObjectResult(result); } [HttpPost] public async Task Post([FromBody] ProfileViewModel item) { - /* TODO: Update this to the new model - var email = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; - var user = _userRepository.Get(email); - - user.Id = item.Id; - user.EmailAddress = item.Email; - user.FullName = item.Name; - user.ProfileImage = item.ProfileImage; - user.ApiKey = item.ApiKey; - - _userRepository.AddOrUpdate(user); - await _unitOfWork.CompleteAsync(); - */ - return new OkObjectResult(item); + throw new InvalidOperationException("THis has not been setup yet"); } - [HttpPost("updateapikey")] - public async Task UpdateApiKey() { - var email = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; - var user = _userRepository.Get(email); - if (user != null) { - var newKey = _userRepository.UpdateApiKey(user); - await _unitOfWork.CompleteAsync(); - return new OkObjectResult(newKey); - } - return new NotFoundResult(); - } [HttpGet("checkslug/{slug}")] public async Task CheckSlug(string slug) { - var result = await _userRepository.GetBySlugAsync(slug); - if (result != null) { - return "Found"; - } return "NotFound"; } } diff --git a/server/Controllers/RssController.cs b/server/Controllers/RssController.cs index 8eb2340..ae89799 100644 --- a/server/Controllers/RssController.cs +++ b/server/Controllers/RssController.cs @@ -4,36 +4,35 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Xml; using HandlebarsDotNet; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using PodNoms.Api.Models; using PodNoms.Api.Models.ViewModels.RssViewModels; using PodNoms.Api.Persistence; +using PodNoms.Api.Services.Auth; using PodNoms.Api.Utils; using PodNoms.Api.Utils.Extensions; -namespace PodNoms.Api.Controllers -{ +namespace PodNoms.Api.Controllers { [Route("[controller]")] - public class RssController : Controller - { + public class RssController : Controller { private readonly IPodcastRepository _podcastRepository; - private readonly IUserRepository _userRepository; + private readonly UserManager _userManager; private readonly ILogger _logger; private readonly AppSettings _appOptions; private readonly StorageSettings _storageOptions; private readonly ImageFileStorageSettings _imageOptions; public RssController(IPodcastRepository podcastRespository, - IUserRepository userRepository, IOptions appOptions, IOptions imageOptions, IOptions storageOptions, - ILoggerFactory loggerFactory) - { + UserManager userManager, + ILoggerFactory loggerFactory) { _podcastRepository = podcastRespository; - _userRepository = userRepository; + _userManager = userManager; _appOptions = appOptions.Value; _imageOptions = imageOptions.Value; _storageOptions = storageOptions.Value; @@ -42,19 +41,16 @@ namespace PodNoms.Api.Controllers [HttpGet("{slug}/{entry}")] [Produces("application/xml")] - public async Task Get(string slug, string entry) - { + public async Task Get(string slug, string entry) { _logger.LogDebug("RSS: Retrieving podcast"); - var user = await _userRepository.GetBySlugAsync(slug); - if (user != null) - { - var podcast = await _podcastRepository.GetAsync(user.EmailAddress, entry); - if (podcast != null) - { + + var user = await _userManager.FindBySlugAsync(slug); + if (user != null) { + var podcast = await _podcastRepository.GetAsync(user.Id, entry); + if (podcast != null) { string xml = ResourceReader.ReadResource("podcast.xml", _logger); var template = Handlebars.Compile(xml); - var compiled = new PodcastEnclosureViewModel - { + var compiled = new PodcastEnclosureViewModel { Title = podcast.Title, Description = podcast.Description, Author = "PodNoms Podcasts", @@ -65,8 +61,7 @@ namespace PodNoms.Api.Controllers Copyright = $"© {DateTime.Now.Year} PodNoms", Items = ( from e in podcast.PodcastEntries - select new PodcastEnclosureItemViewModel - { + select new PodcastEnclosureItemViewModel { Title = e.Title.StripNonXMLChars(), Description = e.Description.StripNonXMLChars(), Author = e.Author.StripNonXMLChars(), diff --git a/server/Controllers/UserController.cs b/server/Controllers/UserController.cs deleted file mode 100644 index 3505278..0000000 --- a/server/Controllers/UserController.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using PodNoms.Api.Models; -using PodNoms.Api.Persistence; - -namespace PodNoms.Api.Controllers { - [Authorize] - [Obsolete("This should be superceded by the new identity stuff")] - public class UserController : Controller { - protected IUserRepository _userRepository { get; } - - public UserController(IUserRepository repository) { - this._userRepository = repository; - } - protected async Task GetUserAsync() { - var identifier = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; - var user = await this._userRepository.GetAsync(identifier); - return user; - } - protected async Task GetUserUidAsync() { - var user = await GetUserAsync(); - return user.Uid; - } - protected async Task GetUserIdAsync() { - var user = await GetUserAsync(); - return user.Id; - } - } -} \ No newline at end of file diff --git a/server/Controllers/WebPushController.cs b/server/Controllers/WebPushController.cs index fc7c66c..7b985d8 100644 --- a/server/Controllers/WebPushController.cs +++ b/server/Controllers/WebPushController.cs @@ -5,24 +5,28 @@ using Microsoft.AspNetCore.Mvc; using PodNoms.Api.Services.Push; using PodNoms.Api.Services.Push.Models; using PodNoms.Api.Persistence; +using Microsoft.AspNetCore.Identity; +using PodNoms.Api.Services.Auth; +using Microsoft.AspNetCore.Http; namespace PodNoms.Api.Controllers { // [Authorize] [Route("[controller]")] - public class WebPushController : UserController { + public class WebPushController : BaseAuthController { private readonly IPushSubscriptionStore _subscriptionStore; public readonly IPushNotificationService _notificationService; - public WebPushController(IUserRepository userRepository, IPushSubscriptionStore subscriptionStore, - IPushNotificationService notificationService) : base(userRepository) { + public WebPushController(IPushSubscriptionStore subscriptionStore, IPushNotificationService notificationService, + UserManager userManager, + IHttpContextAccessor contextAccessor) : base(contextAccessor, userManager) { this._subscriptionStore = subscriptionStore; this._notificationService = notificationService; } [HttpPost("subscribe")] public async Task StoreSubscription([FromBody]WebPush.PushSubscription subscription) { - subscription.Keys["auth"] = $"{await this.GetUserUidAsync()}"; + subscription.Keys["auth"] = _applicationUser.Id; await _subscriptionStore.StoreSubscriptionAsync(subscription); return NoContent(); } diff --git a/server/Migrations/20180425154651_SlugUser.Designer.cs b/server/Migrations/20180425154651_SlugUser.Designer.cs new file mode 100644 index 0000000..fbda905 --- /dev/null +++ b/server/Migrations/20180425154651_SlugUser.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("20180425154651_SlugUser")] + partial class SlugUser + { + 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("ImageUrl"); + + b.Property("Slug") + .IsUnicode(true); + + 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/20180425154651_SlugUser.cs b/server/Migrations/20180425154651_SlugUser.cs new file mode 100644 index 0000000..79ac1a6 --- /dev/null +++ b/server/Migrations/20180425154651_SlugUser.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace PodNoms.Api.Migrations +{ + public partial class SlugUser : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Podcasts_UserDetails_UserId", + table: "Podcasts"); + + migrationBuilder.DropTable( + name: "UserDetails"); + + migrationBuilder.DropIndex( + name: "IX_Podcasts_UserId", + table: "Podcasts"); + + migrationBuilder.DropColumn( + name: "UserId", + table: "Podcasts"); + + migrationBuilder.AddColumn( + name: "Slug", + table: "AspNetUsers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Slug", + table: "AspNetUsers"); + + migrationBuilder.AddColumn( + name: "UserId", + table: "Podcasts", + nullable: true); + + migrationBuilder.CreateTable( + name: "UserDetails", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + ApiKey = table.Column(maxLength: 50, nullable: true), + CreateDate = table.Column(nullable: false), + EmailAddress = table.Column(maxLength: 100, nullable: true), + FullName = table.Column(maxLength: 100, nullable: true), + ProfileImage = table.Column(nullable: true), + ProviderId = table.Column(maxLength: 50, nullable: true), + RefreshToken = table.Column(nullable: true), + Sid = table.Column(maxLength: 50, nullable: true), + Slug = table.Column(maxLength: 50, nullable: true), + Uid = table.Column(maxLength: 50, nullable: true), + UpdateDate = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserDetails", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Podcasts_UserId", + table: "Podcasts", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserDetails_Slug", + table: "UserDetails", + column: "Slug", + unique: true, + filter: "[Slug] IS NOT NULL"); + + migrationBuilder.AddForeignKey( + name: "FK_Podcasts_UserDetails_UserId", + table: "Podcasts", + column: "UserId", + principalTable: "UserDetails", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/server/Migrations/PodnomsDbContextModelSnapshot.cs b/server/Migrations/PodnomsDbContextModelSnapshot.cs index 6d10001..a0ba407 100644 --- a/server/Migrations/PodnomsDbContextModelSnapshot.cs +++ b/server/Migrations/PodnomsDbContextModelSnapshot.cs @@ -171,14 +171,10 @@ namespace PodNoms.Api.Migrations b.Property("UpdateDate"); - b.Property("UserId"); - b.HasKey("Id"); b.HasIndex("AppUserId"); - b.HasIndex("UserId"); - b.ToTable("Podcasts"); }); @@ -230,49 +226,6 @@ namespace PodNoms.Api.Migrations b.ToTable("PodcastEntries"); }); - modelBuilder.Entity("PodNoms.Api.Models.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApiKey") - .HasMaxLength(50); - - b.Property("CreateDate"); - - b.Property("EmailAddress") - .HasMaxLength(100); - - b.Property("FullName") - .HasMaxLength(100); - - b.Property("ProfileImage"); - - b.Property("ProviderId") - .HasMaxLength(50); - - b.Property("RefreshToken"); - - b.Property("Sid") - .HasMaxLength(50); - - b.Property("Slug") - .HasMaxLength(50); - - b.Property("Uid") - .HasMaxLength(50); - - b.Property("UpdateDate"); - - b.HasKey("Id"); - - b.HasIndex("Slug") - .IsUnique() - .HasFilter("[Slug] IS NOT NULL"); - - b.ToTable("UserDetails"); - }); - modelBuilder.Entity("PodNoms.Api.Services.Auth.ApplicationUser", b => { b.Property("Id") @@ -314,6 +267,8 @@ namespace PodNoms.Api.Migrations b.Property("SecurityStamp"); + b.Property("Slug"); + b.Property("TwoFactorEnabled"); b.Property("UserName") @@ -390,10 +345,6 @@ namespace PodNoms.Api.Migrations b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "AppUser") .WithMany() .HasForeignKey("AppUserId"); - - b.HasOne("PodNoms.Api.Models.User", "User") - .WithMany() - .HasForeignKey("UserId"); }); modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b => diff --git a/server/Models/Podcast.cs b/server/Models/Podcast.cs index 855e7a3..5e2ab30 100644 --- a/server/Models/Podcast.cs +++ b/server/Models/Podcast.cs @@ -7,7 +7,6 @@ namespace PodNoms.Api.Models { public class Podcast : BaseModel { public int Id { get; set; } public string Uid { get; set; } - public User User { get; set; } public ApplicationUser AppUser { get; set; } public string Title { get; set; } public string Description { get; set; } diff --git a/server/Models/User.cs b/server/Models/User.cs deleted file mode 100644 index 2437f18..0000000 --- a/server/Models/User.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; - -namespace PodNoms.Api.Models { - public class User : BaseModel { - public int Id { get; set; } - - [MaxLength(50)] - public string Slug { get; set; } - - [MaxLength(100)] - public string EmailAddress { get; set; } - - [MaxLength(100)] - public string FullName { get; set; } - - public string ProfileImage { get; set; } - - [MaxLength(50)] - public string Uid { get; set; } - - [MaxLength(50)] - public string Sid { get; set; } - - [MaxLength(50)] - public string ProviderId { get; set; } - - [MaxLength(50)] - public string ApiKey { get; set; } - - public string RefreshToken { get; set; } - internal string GetUserId() { - //TODO: Sort this when signalr uses correct id - return FullName; - } - } -} \ No newline at end of file diff --git a/server/Persistence/EntryRepository.cs b/server/Persistence/EntryRepository.cs index 1d78cbc..a78abff 100644 --- a/server/Persistence/EntryRepository.cs +++ b/server/Persistence/EntryRepository.cs @@ -15,7 +15,7 @@ namespace PodNoms.Api.Persistence { public async Task GetAsync(int id) { var entry = await _context.PodcastEntries .Include(e => e.Podcast) - .Include(e => e.Podcast.User) + .Include(e => e.Podcast.AppUser) .SingleOrDefaultAsync(e => e.Id == id); return entry; } diff --git a/server/Persistence/IPodcastRepository.cs b/server/Persistence/IPodcastRepository.cs index 1e8ba07..6953f4b 100644 --- a/server/Persistence/IPodcastRepository.cs +++ b/server/Persistence/IPodcastRepository.cs @@ -2,13 +2,11 @@ using System.Collections.Generic; using System.Threading.Tasks; using PodNoms.Api.Models; -namespace PodNoms.Api.Persistence -{ - public interface IPodcastRepository - { +namespace PodNoms.Api.Persistence { + public interface IPodcastRepository { Task GetAsync(int id); - Task GetAsync(string emailAddress, string slug); - Task> GetAllAsync(string emailAddress); + Task GetAsync(string id, string slug); + Task> GetAllAsync(string id); Task AddOrUpdateAsync(Podcast item); Task DeleteAsync(int id); } diff --git a/server/Persistence/IUserRepository.cs b/server/Persistence/IUserRepository.cs deleted file mode 100644 index 72c2b85..0000000 --- a/server/Persistence/IUserRepository.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Threading.Tasks; -using PodNoms.Api.Models; - -namespace PodNoms.Api.Persistence { - public interface IUserRepository { - User Get(int id); - User Get(string email); - Task GetAsync(string id); - Task GetBySlugAsync(string slug); - User UpdateRegistration(string email, string name, string sid, string providerId, string profileImage, string refreshToken); - string UpdateApiKey(User user); - User AddOrUpdate(User user); - } -} \ No newline at end of file diff --git a/server/Persistence/PlaylistRepository.cs b/server/Persistence/PlaylistRepository.cs index c44d211..12d0179 100644 --- a/server/Persistence/PlaylistRepository.cs +++ b/server/Persistence/PlaylistRepository.cs @@ -13,7 +13,7 @@ namespace PodNoms.Api.Persistence { public async Task GetAsync(int id) { var entry = await _context.Playlists .Include(e => e.Podcast) - .Include(e => e.Podcast.User) + .Include(e => e.Podcast.AppUser) .SingleOrDefaultAsync(e => e.Id == id); return entry; } diff --git a/server/Persistence/PodcastRepository.cs b/server/Persistence/PodcastRepository.cs index 0d5b738..0510af5 100644 --- a/server/Persistence/PodcastRepository.cs +++ b/server/Persistence/PodcastRepository.cs @@ -23,24 +23,23 @@ namespace PodNoms.Api.Persistence { public async Task GetAsync(int id) { var ret = await _context.Podcasts .Where(p => p.Id == id) - .Include(p => p.User) + .Include(p => p.AppUser) .FirstOrDefaultAsync(); return ret; } - public async Task GetAsync(string emailAddress, string slug) { + public async Task GetAsync(string id, string slug) { var ret = await _context.Podcasts - .Where(p => p.Slug == slug && p.User.EmailAddress == emailAddress) + .Where(p => p.Slug == slug && p.AppUser.Id == id) .Include(p => p.PodcastEntries) - .Include(p => p.User) + .Include(p => p.AppUser) .FirstOrDefaultAsync(); return ret; } - public async Task> GetAllAsync(string userId) { + public async Task> GetAllAsync(string id) { var ret = _context.Podcasts - .Where(u => u.AppUser.Id == userId) - .Include(p => p.User) + .Where(u => u.AppUser.Id == id) .Include(p => p.AppUser) .OrderByDescending(p => p.Id); return await ret.ToListAsync(); diff --git a/server/Persistence/PodnomsContext.cs b/server/Persistence/PodnomsContext.cs index c8d7df7..8baf0b6 100644 --- a/server/Persistence/PodnomsContext.cs +++ b/server/Persistence/PodnomsContext.cs @@ -29,15 +29,10 @@ namespace PodNoms.Api.Persistence { .Property(b => b.CreateDate) .HasDefaultValueSql("getdate()"); - modelBuilder.Entity() - .HasIndex(e => e.Slug) - .IsUnique(true); - } public DbSet Podcasts { get; set; } public DbSet PodcastEntries { get; set; } public DbSet Playlists { get; set; } - public DbSet UserDetails { get; set; } } } \ No newline at end of file diff --git a/server/Persistence/UserRepository.cs b/server/Persistence/UserRepository.cs deleted file mode 100644 index b6f0bf1..0000000 --- a/server/Persistence/UserRepository.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using PodNoms.Api.Models; -using PodNoms.Api.Persistence; -using PodNoms.Api.Utils; -using PodNoms.Api.Utils.Extensions; - -namespace PodNoms.Api.Persistence { - public class UserRepository : IUserRepository { - private readonly PodnomsDbContext _context; - - public UserRepository(PodnomsDbContext context) { - _context = context; - } - - public User Get(int id) { - return _context.UserDetails.FirstOrDefault(u => u.Id == id); - } - - public User Get(string email) { - return _context.UserDetails.FirstOrDefault(u => u.EmailAddress == email); - } - public async Task GetAsync(string email) { - return await _context.UserDetails - .Where(u => u.EmailAddress == email) - .FirstOrDefaultAsync(); - } - public async Task GetBySlugAsync(string slug) { - var user = await _context.UserDetails - .Where(u => u.Slug == slug) - .FirstOrDefaultAsync(); - - return user; - } - - public User AddOrUpdate(User user) { - if (user.Id != 0) { - _context.UserDetails.Attach(user); - } else { - _context.UserDetails.Add(user); - - } - return user; - } - - public User UpdateRegistration(string email, string name, string sid, string providerId, string profileImage, - string refreshToken) { - var user = _context.UserDetails.FirstOrDefault(u => u.EmailAddress == email); - - if (user == null) { - user = new User(); - user.EmailAddress = email; - } - user.FullName = string.IsNullOrEmpty(user.FullName) ? name : user.FullName; - if (string.IsNullOrEmpty(user.Slug)) { - var c = user.FullName ?? email?.Split('@')[0] ?? string.Empty; - if (!string.IsNullOrEmpty(c)) { - user.Slug = c.Slugify( - from u in _context.UserDetails select u.Slug); - } - } - if (string.IsNullOrEmpty(user.Uid)) { - user.Uid = System.Guid.NewGuid().ToString(); - } - if (!string.IsNullOrEmpty(refreshToken)) { - user.RefreshToken = refreshToken; - } - user.Sid = sid; - user.ProfileImage = profileImage; - - if (string.IsNullOrEmpty(user.ApiKey)) - UpdateApiKey(user); - - AddOrUpdate(user); - return user; - } - - public string UpdateApiKey(User user) { - var newKey = ""; - if (user != null) { - do { - newKey = Randomisers.RandomString(16); - } while (_context.UserDetails.FirstOrDefault(u => u.ApiKey == newKey) != null); - } - user.ApiKey = newKey; - return newKey; - } - } -} \ No newline at end of file diff --git a/server/Providers/MappingProvider.cs b/server/Providers/MappingProvider.cs index 433b07b..72a3e3b 100644 --- a/server/Providers/MappingProvider.cs +++ b/server/Providers/MappingProvider.cs @@ -16,7 +16,7 @@ namespace PodNoms.Api.Providers { CreateMap() .ForMember( v => v.RssUrl, - e => e.MapFrom(m => $"{this._options.GetSection("App")["RssUrl"]}{m.User.Slug}/{m.Slug}")) + e => e.MapFrom(m => $"{this._options.GetSection("App")["RssUrl"]}{m.AppUser.Slug}/{m.Slug}")) .ForMember( v => v.ImageUrl, e => e.MapFrom(m => m.GetImageUrl( @@ -28,11 +28,6 @@ namespace PodNoms.Api.Providers { src => src.AudioUrl, e => e.MapFrom(m => $"{this._options.GetSection("Storage")["CdnUrl"]}{m.AudioUrl}")); - CreateMap() - .ForMember( - src => src.Name, - e => e.MapFrom(m => m.FullName)); - CreateMap() .ForMember( src => src.Name, diff --git a/server/Services/Auth/ApplicationUser.cs b/server/Services/Auth/ApplicationUser.cs index 8dd848f..63cf101 100644 --- a/server/Services/Auth/ApplicationUser.cs +++ b/server/Services/Auth/ApplicationUser.cs @@ -7,5 +7,6 @@ namespace PodNoms.Api.Services.Auth { public string LastName { get; set; } public long? FacebookId { get; set; } public string PictureUrl { get; set; } + public string Slug { get; set; } } } \ No newline at end of file diff --git a/server/Services/Auth/AuthenticationMiddleware.cs b/server/Services/Auth/AuthenticationMiddleware.cs deleted file mode 100644 index 722cc05..0000000 --- a/server/Services/Auth/AuthenticationMiddleware.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.Logging; -using PodNoms.Api.Models; -using PodNoms.Api.Persistence; -using RestSharp; - -namespace PodNoms.Api.Services.Auth { - public class AuthenticationMiddleware { - public async static Task OnTokenValidated(TokenValidatedContext context) { - var userRepository = (IUserRepository)context.HttpContext.RequestServices.GetService(typeof(IUserRepository)); - var unitOfWork = (IUnitOfWork)context.HttpContext.RequestServices.GetService(typeof(IUnitOfWork)); - var claimsIdentity = context.Principal.Identity as ClaimsIdentity; - if (claimsIdentity != null && context.Request.Headers.ContainsKey("Authorization")) { - var claimToken = context.Request.Headers["Authorization"][0].Substring(context.Scheme.Name.Length + 1); - claimsIdentity.AddClaim(new Claim("id_token", claimToken)); - - var picture = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "picture")?.Value; - var name = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "name")?.Value; - - var data = new { - Name = name, - EmailAddress = claimsIdentity.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value, - Sid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid)?.Value, - UserId = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "subject")?.Value, - ProfileImage = picture - }; - var refreshToken = await _getRefreshToken(); - userRepository.UpdateRegistration(data.EmailAddress, data.Name, data.Sid, data.UserId, - data.ProfileImage, refreshToken); - - await unitOfWork.CompleteAsync(); - return true; - } - return false; - } - - private static async Task _getRefreshToken() { - var client = new RestClient("https://podnoms.eu.auth0.com/oauth/token"); - var request = new RestRequest(Method.POST); - request.AddHeader("content-type", "application/json"); - request.AddParameter( - "application/json", - "{\"grant_type\":\"authorization_code\"," + - "\"client_id\": \"Fx6Z3kZoheEpXhZO97ioAg1asbHDdCtr\"," + - "\"client_secret\": \"g9wwXHppw7eNOIpD_r9z-7ttcvuzYz-8QlxXd_n6l8QiSW5VpIrlSwTn7w5uflP_\"," + - "\"code\": \"YOUR_AUTHORIZATION_CODE\"," + - "\"redirect_uri\": \"http://localhost:4200/callback\"}", - ParameterType.RequestBody); - - IRestResponse response = await client.ExecuteTaskAsync(request); - if (response.IsSuccessful) { - return response.Content; - } - - return string.Empty; - } - } -} \ No newline at end of file diff --git a/server/Services/Auth/UserManagerExtensions.cs b/server/Services/Auth/UserManagerExtensions.cs new file mode 100644 index 0000000..65f44d6 --- /dev/null +++ b/server/Services/Auth/UserManagerExtensions.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using System.Linq; +using Microsoft.AspNetCore.Identity; + +namespace PodNoms.Api.Services.Auth { + public static class UserManagerExtensions { + public static async Task FindBySlugAsync(this UserManager userManager, string slug){ + var user = await Task.Run(() => userManager.Users.SingleOrDefault(x => x.Slug == slug)); + return user; + } + } +} \ No newline at end of file diff --git a/server/Services/Processor/AudioUploadProcessService.cs b/server/Services/Processor/AudioUploadProcessService.cs index f68715f..c8f5fda 100644 --- a/server/Services/Processor/AudioUploadProcessService.cs +++ b/server/Services/Processor/AudioUploadProcessService.cs @@ -18,62 +18,62 @@ namespace PodNoms.Api.Services.Processor { private readonly IFileUploader _fileUploader; private readonly AudioFileStorageSettings _audioStorageSettings; - public AudioUploadProcessService (IEntryRepository repository, IUnitOfWork unitOfWork, + public AudioUploadProcessService(IEntryRepository repository, IUnitOfWork unitOfWork, IFileUploader fileUploader, IOptions audioStorageSettings, - ILoggerFactory logger, IMapper mapper, IRealTimeUpdater realtimeUpdater) : base (logger, mapper, realtimeUpdater) { + ILoggerFactory logger, IMapper mapper, IRealTimeUpdater realtimeUpdater) : base(logger, mapper, realtimeUpdater) { this._repository = repository; this._unitOfWork = unitOfWork; this._fileUploader = fileUploader; this._audioStorageSettings = audioStorageSettings.Value; } - public async Task UploadAudio (int entryId, string localFile) { - var entry = await _repository.GetAsync (entryId); + public async Task UploadAudio(int entryId, string localFile) { + var entry = await _repository.GetAsync(entryId); if (entry == null) { - _logger.LogError ($"Unable to find entry with id: {entryId}"); + _logger.LogError($"Unable to find entry with id: {entryId}"); return false; } entry.ProcessingStatus = ProcessingStatus.Uploading; - await _unitOfWork.CompleteAsync (); + await _unitOfWork.CompleteAsync(); try { // bit messy but can't figure how to pass youtube-dl job result to this job // so using AudioUrl as a proxy - if (string.IsNullOrEmpty (localFile)) + if (string.IsNullOrEmpty(localFile)) localFile = entry.AudioUrl; - if (File.Exists (localFile)) { - var fileName = new FileInfo (localFile).Name; - await _fileUploader.UploadFile (localFile, _audioStorageSettings.ContainerName, fileName, + if (File.Exists(localFile)) { + var fileName = new FileInfo(localFile).Name; + await _fileUploader.UploadFile(localFile, _audioStorageSettings.ContainerName, fileName, async (p, t) => { if (p % 1 == 0) { - await _sendProgressUpdate ( - entry.Podcast.User.GetUserId (), + await _sendProgressUpdate( + entry.Podcast.AppUser.Id, entry.Uid, new ProcessProgressEvent { Percentage = p, - CurrentSpeed = string.Empty, - TotalSize = t.ToString () + CurrentSpeed = string.Empty, + TotalSize = t.ToString() }); } }); entry.Processed = true; entry.ProcessingStatus = ProcessingStatus.Processed; entry.AudioUrl = $"{_audioStorageSettings.ContainerName}/{fileName}"; - await _unitOfWork.CompleteAsync (); - await _sendProcessCompleteMessage (entry); + await _unitOfWork.CompleteAsync(); + await _sendProcessCompleteMessage(entry); return true; } else { - _logger.LogError ($"Error uploading audio file: {entry.AudioUrl} does not exist"); + _logger.LogError($"Error uploading audio file: {entry.AudioUrl} does not exist"); entry.ProcessingStatus = ProcessingStatus.Failed; entry.ProcessingPayload = $"Unable to find {entry.AudioUrl}"; - await _unitOfWork.CompleteAsync (); - await _sendProcessCompleteMessage (entry); + await _unitOfWork.CompleteAsync(); + await _sendProcessCompleteMessage(entry); } } catch (Exception ex) { - _logger.LogError ($"Error uploading audio file: {ex.Message}"); + _logger.LogError($"Error uploading audio file: {ex.Message}"); entry.ProcessingStatus = ProcessingStatus.Failed; entry.ProcessingPayload = ex.Message; - await _unitOfWork.CompleteAsync (); - await _sendProcessCompleteMessage (entry); + await _unitOfWork.CompleteAsync(); + await _sendProcessCompleteMessage(entry); } return false; } diff --git a/server/Services/Processor/ProcessService.cs b/server/Services/Processor/ProcessService.cs index 8c5fdbc..89fa45d 100644 --- a/server/Services/Processor/ProcessService.cs +++ b/server/Services/Processor/ProcessService.cs @@ -27,7 +27,7 @@ namespace PodNoms.Api.Services.Processor { protected async Task _sendProcessCompleteMessage(PodcastEntry entry) { var result = _mapper.Map(entry); - return await _sendProcessUpdate(entry.Podcast.User.GetUserId(), entry.Uid, "info_processed", result); + return await _sendProcessUpdate(entry.Podcast.AppUser.Id, entry.Uid, "info_processed", result); } protected async Task _sendProgressUpdate(string userId, string itemUid, ProcessProgressEvent data) { return await _realtime.SendProcessUpdate(userId, itemUid, "progress_update", data); diff --git a/server/Services/Processor/UrlProcessService.cs b/server/Services/Processor/UrlProcessService.cs index d6ef27c..a95d6c8 100644 --- a/server/Services/Processor/UrlProcessService.cs +++ b/server/Services/Processor/UrlProcessService.cs @@ -85,7 +85,7 @@ namespace PodNoms.Api.Services.Processor { var outputFile = Path.Combine(System.IO.Path.GetTempPath(), $"{System.Guid.NewGuid().ToString()}.mp3"); - downloader.DownloadProgress += async (s, e) => await __downloader_progress(entry.Podcast.User.GetUserId(), entry.Uid, e); + downloader.DownloadProgress += async (s, e) => await __downloader_progress(entry.Podcast.AppUser.Id, entry.Uid, e); downloader.PostProcessing += (s, e) => { Console.WriteLine(e); @@ -98,7 +98,7 @@ namespace PodNoms.Api.Services.Processor { await _sendProcessCompleteMessage(entry); await _unitOfWork.CompleteAsync(); await _chatterHub.SendAllAsync( - $"{entry.Podcast.User.Uid}_chatter", + $"{entry.Podcast.AppUser.Id}_chatter", new object[] { $"{entry.Title} has succesfully been processed" }); } @@ -109,7 +109,7 @@ namespace PodNoms.Api.Services.Processor { await _unitOfWork.CompleteAsync(); await _sendProcessCompleteMessage(entry); await _chatterHub.SendAllAsync( - $"{entry.Podcast.User.Uid}_chatter", + $"{entry.Podcast.AppUser.Id}_chatter", new object[] { $"Error processing {entry.Title}" }); } return false; diff --git a/server/Startup.cs b/server/Startup.cs index cb96505..d46cca1 100644 --- a/server/Startup.cs +++ b/server/Startup.cs @@ -214,7 +214,6 @@ namespace PodNoms.Api { services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped();