Skip to content

Commit

Permalink
User auth stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
fergalmoran committed Oct 4, 2023
1 parent 67ead7e commit fdeab9f
Show file tree
Hide file tree
Showing 31 changed files with 39,457 additions and 630 deletions.
2 changes: 1 addition & 1 deletion .dotnetenv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
DOTNET_PROJ=mixyboos-api
export DOTNET_PROJ=mixyboos-api
8 changes: 7 additions & 1 deletion mixyboos-api/Controllers/DebugController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ public class DebugController : _Controller {
private readonly IConfiguration _configuration;
private readonly IHubContext<DebugHub> _hub;

public DebugController(ILogger<DebugController> logger) : base(logger) { }
public DebugController(IConfiguration configuration, ILogger<DebugController> logger, IHubContext<DebugHub> hub,
UserManager<MixyBoosUser> userManager) :
base(logger) {
_configuration = configuration;
_hub = hub;
_userManager = userManager;
}

[HttpGet("ping")]
public ActionResult Ping() {
Expand Down
183 changes: 89 additions & 94 deletions mixyboos-api/Controllers/ProfileController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,116 +18,111 @@ namespace MixyBoos.Api.Controllers;
[Authorize]
[Route("[controller]")]
public class ProfileController : _Controller {
private readonly UserManager<MixyBoosUser> _userManager;
private readonly MixyBoosContext _context;

public ProfileController(
UserManager<MixyBoosUser> userManager,
MixyBoosContext context,
ILogger<ProfileController> logger) : base(logger) {
_userManager = userManager;
_context = context;
private readonly UserManager<MixyBoosUser> _userManager;
private readonly MixyBoosContext _context;

public ProfileController(
UserManager<MixyBoosUser> userManager,
MixyBoosContext context,
ILogger<ProfileController> logger) : base(logger) {
_userManager = userManager;
_context = context;
}

[HttpGet]
public async Task<ActionResult<ProfileDTO>> GetProfile() {
var user = await _userManager.FindByNameWithFollowingAsync(User.Identity.Name);
if (user is null) {
return Unauthorized();
}

[HttpGet("me")]
public async Task<ActionResult<ProfileDTO>> GetProfile() {
var user = await _userManager.FindByNameWithFollowingAsync(User.Identity.Name);
if (user is null) {
return Unauthorized();
}
return Ok(user.ToDto());
}

return Ok(user.Adapt<ProfileDTO>());

[HttpPost]
[Authorize]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<ProfileDTO>> UpdateProfile([FromBody] ProfileDTO incoming) {
if (!ModelState.IsValid) {
return BadRequest();
}

var user = await _userManager.FindByIdAsync(incoming.Id);
if (user is null) {
return NotFound();
}

[HttpPost("follow")]
public async Task<IActionResult> FollowUser([FromQuery] string userId) {
var userToFollow = await _userManager.FindByIdAsync(userId);
var me = await _userManager.FindByNameWithFollowingAsync(User.Identity.Name);
user.FromDto(incoming);

if (userToFollow is null && me is not null) {
return BadRequest();
}
await _userManager.UpdateAsync(user);

if (!me.Following.Any(f => f.Id.Equals(userToFollow.Id))) {
me.Following.Add(userToFollow);
userToFollow.Followers.Add(me);
await _context.SaveChangesAsync();
}
return Ok(user.ToDto());
}

return Ok();
[HttpPost("follow")]
public async Task<IActionResult> FollowUser([FromQuery] string userId) {
var userToFollow = await _userManager.FindByIdAsync(userId);
var me = await _userManager.FindByNameWithFollowingAsync(User.Identity.Name);

if (userToFollow is null && me is not null) {
return BadRequest();
}

[HttpPost("togglefollow")]
public async Task<IActionResult> ToggleFollow([FromQuery] string slug) {
var userToFollow = await _userManager.FindBySlugWithFollowingAsync(slug);
var me = await _userManager.FindByNameWithFollowingAsync(User.Identity.Name);

if (userToFollow is null && me is not null) {
return BadRequest();
}

if (!me.Following.Any(f => f.Id.Equals(userToFollow.Id))) {
me.Following.Add(userToFollow);
userToFollow.Followers.Add(me);
} else {
me.Following.Remove(userToFollow);
userToFollow.Followers.Remove(userToFollow);
}

await _context.SaveChangesAsync();
return Ok();
if (!me.Following.Any(f => f.Id.Equals(userToFollow.Id))) {
me.Following.Add(userToFollow);
userToFollow.Followers.Add(me);
await _context.SaveChangesAsync();
}

[HttpGet("apikey")]
public async Task<ActionResult<GetApiKeyDTO>> GetApiKey() {
var user = await _userManager.FindByNameAsync(User.Identity.Name);
if (string.IsNullOrEmpty(user.StreamKey)) {
user.StreamKey = KeyGenerator.GenerateRandomCryptoString(32);
await _context.SaveChangesAsync();
}

return Ok(new GetApiKeyDTO {
UserId = User.Identity.Name,
ApiKey = user.StreamKey
});
return Ok();
}

[HttpPost("togglefollow")]
public async Task<IActionResult> ToggleFollow([FromQuery] string slug) {
var userToFollow = await _userManager.FindBySlugWithFollowingAsync(slug);
var me = await _userManager.FindByNameWithFollowingAsync(User.Identity.Name);

if (userToFollow is null && me is not null) {
return BadRequest();
}

if (!me.Following.Any(f => f.Id.Equals(userToFollow.Id))) {
me.Following.Add(userToFollow);
userToFollow.Followers.Add(me);
} else {
me.Following.Remove(userToFollow);
userToFollow.Followers.Remove(userToFollow);
}

[HttpGet]
public async Task<ActionResult<ProfileDTO>> GetBySlug([FromQuery] string slug) {
var user = await _userManager.FindBySlugAsync(slug);
if (user is null) {
return NotFound();
}
await _context.SaveChangesAsync();
return Ok();
}

return Ok(user.Adapt<ProfileDTO>());
[HttpGet("apikey")]
public async Task<ActionResult<GetApiKeyDTO>> GetApiKey() {
var user = await _userManager.FindByNameAsync(User.Identity.Name);
if (string.IsNullOrEmpty(user.StreamKey)) {
user.StreamKey = KeyGenerator.GenerateRandomCryptoString(32);
await _context.SaveChangesAsync();
}

[HttpPost]
[Authorize]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<ProfileDTO>> UpdateBySlug([FromBody] ProfileDTO incoming) {
if (!ModelState.IsValid) {
return BadRequest();
}

var user = await _userManager.FindByIdAsync(incoming.Id);
if (user is null) {
return NotFound();
}

user.UserName = incoming.UserName;
user.Title = incoming.Title;
user.DisplayName = incoming.DisplayName;
user.City = incoming.City;
user.Country = incoming.Country;
user.Biography = incoming.Biography;
user.PhoneNumber = incoming.PhoneNumber;

await _userManager.UpdateAsync(user);

return Ok(user.Adapt<ProfileDTO>());
return Ok(new GetApiKeyDTO {
UserId = User.Identity.Name,
ApiKey = user.StreamKey
});
}

[HttpGet("{slug}")]
public async Task<ActionResult<ProfileDTO>> GetBySlug(string slug) {
var user = await _userManager.FindBySlugAsync(slug);
if (user is null) {
return NotFound();
}

return Ok(user.Adapt<ProfileDTO>());
}
}
2 changes: 1 addition & 1 deletion mixyboos-api/Data/DTO/ProfileDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public class FollowDTO {

public class ProfileDTO {
public string Id { get; set; }
public string UserName { get; set; }
public string Title { get; set; }
public string ProfileImage { get; set; }
public string HeaderImage { get; set; }
Expand All @@ -21,5 +20,6 @@ public class ProfileDTO {

public List<FollowDTO> Followers { get; set; }
public List<FollowDTO> Following { get; set; }

}
}
14 changes: 9 additions & 5 deletions mixyboos-api/Data/MixyBoosContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MixyBoos.Api.Data.Models;
using MixyBoos.Api.Data.Options;
using MixyBoos.Api.Data.Utils;
using MixyBoos.Api.Services.Extensions;

#nullable disable

namespace MixyBoos.Api.Data;

public class MixyBoosContext : IdentityDbContext<MixyBoosUser, IdentityRole<Guid>, Guid> {
private readonly DbScaffoldOptions _settings;
private readonly ILogger<MixyBoosContext> _logger;
public DbSet<Mix> Mixes { get; set; }

Expand All @@ -30,8 +31,10 @@ public class MixyBoosContext : IdentityDbContext<MixyBoosUser, IdentityRole<Guid
public DbSet<ShowChat> ShowChat { get; set; }


public MixyBoosContext(DbContextOptions<MixyBoosContext> options, ILogger<MixyBoosContext> logger)
public MixyBoosContext(DbContextOptions<MixyBoosContext> options, IOptions<DbScaffoldOptions> settings,
ILogger<MixyBoosContext> logger)
: base(options) {
_settings = settings.Value;
_logger = logger;
}

Expand Down Expand Up @@ -60,6 +63,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {

protected override void OnModelCreating(ModelBuilder mb) {
base.OnModelCreating(mb);

mb.HasDefaultSchema("mixyboos");
mb.UseIdentityByDefaultColumns();

Expand Down Expand Up @@ -97,8 +101,6 @@ protected override void OnModelCreating(ModelBuilder mb) {
}

foreach (var pb in __getColumns(mb, "Id")) {
_logger.LogDebug("Creating value generators for {GeneratorName}",
pb.Metadata.DeclaringEntityType.Name);
pb.IsRequired()
.HasConversion<string>()
.ValueGeneratedOnAdd();
Expand Down Expand Up @@ -159,6 +161,8 @@ protected override void OnModelCreating(ModelBuilder mb) {
mb.Entity<Mix>()
.Navigation(m => m.User)
.AutoInclude();

mb.SeedAuthenticationUsers(_settings);
}

public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
Expand Down
3 changes: 1 addition & 2 deletions mixyboos-api/Data/Models/MixActivity.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#nullable enable
using System;
using System.ComponentModel.DataAnnotations;

namespace MixyBoos.Api.Data.Models;

public class MixActivity : BaseEntity {
public Guid MixId { get; set; }
public virtual Mix Mix { get; set; }
public virtual required Mix Mix { get; set; }

public Guid? UserId { get; set; }
public virtual MixyBoosUser? User { get; set; }
Expand Down
65 changes: 36 additions & 29 deletions mixyboos-api/Data/Models/MixyBoosUser.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,48 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Channels;
using Mapster;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using MixyBoos.Api.Data.DTO;
using MixyBoos.Api.Data.Utils;

namespace MixyBoos.Api.Data.Models;

[Index(nameof(Slug), IsUnique = true)]
public class MixyBoosUser : IdentityUser<Guid>, ISluggedEntity {
public MixyBoosUser() {
this.Followers = new List<MixyBoosUser>();
this.Following = new List<MixyBoosUser>();
this.Likes = new List<MixLike>();
this.Plays = new List<MixPlay>();
this.Shares = new List<MixShare>();
this.Downloads = new List<MixDownload>();
}

[MaxLength(50)] public string Title { get; set; }
[MaxLength(30)] public string DisplayName { get; set; }
public string ProfileImage { get; set; }
public string HeaderImage { get; set; }

[SlugField(SourceField = "UserName")]
public string Slug { get; set; }

[MaxLength(100)] public string City { get; set; }
[MaxLength(100)] public string Country { get; set; }
[MaxLength(2048)] public string Biography { get; set; }
public string StreamKey { get; set; }

public ICollection<MixyBoosUser> Followers { get; set; }
public ICollection<MixyBoosUser> Following { get; set; }

public ICollection<MixPlay> Plays { get; set; }
public ICollection<MixLike>? Likes { get; set; }
public ICollection<MixShare>? Shares { get; set; }
public ICollection<MixDownload>? Downloads { get; set; }
[MaxLength(50)] public string Title { get; set; }
[MaxLength(30)] public string DisplayName { get; set; }
public string ProfileImage { get; set; }
public string HeaderImage { get; set; }

[SlugField(SourceField = "UserName")]
public string Slug { get; set; }

[MaxLength(100)] public string City { get; set; }
[MaxLength(100)] public string Country { get; set; }
[MaxLength(2048)] public string Biography { get; set; }
public string StreamKey { get; set; }

public ICollection<MixyBoosUser> Followers { get; set; } = new List<MixyBoosUser>();
public ICollection<MixyBoosUser> Following { get; set; } = new List<MixyBoosUser>();

public ICollection<MixPlay> Plays { get; set; } = new List<MixPlay>();
public ICollection<MixLike> Likes { get; set; } = new List<MixLike>();
public ICollection<MixShare> Shares { get; set; } = new List<MixShare>();
public ICollection<MixDownload> Downloads { get; set; } = new List<MixDownload>();


public void FromDto(ProfileDTO profile) {
Slug = profile.Slug;
Title = profile.Title;
DisplayName = profile.DisplayName;
City = profile.City;
Country = profile.Country;
Biography = profile.Biography;
PhoneNumber = profile.PhoneNumber;
}

public ProfileDTO ToDto() => this.Adapt<ProfileDTO>();
}
Loading

0 comments on commit fdeab9f

Please sign in to comment.