Added endpoint for registering a user locally after successful logon from Auth0
This commit is contained in:
40
YABA.API/Controllers/UsersController.cs
Normal file
40
YABA.API/Controllers/UsersController.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Net;
|
||||||
|
using YABA.API.Extensions;
|
||||||
|
using YABA.API.ViewModels;
|
||||||
|
using YABA.Service.Interfaces;
|
||||||
|
|
||||||
|
namespace YABA.API.Controllers
|
||||||
|
{
|
||||||
|
[ApiVersion("1")]
|
||||||
|
[Authorize, Route("api/v{version:apiVersion}/[controller]")]
|
||||||
|
public class UsersController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IUserService _userService;
|
||||||
|
|
||||||
|
public UsersController(IUserService userService)
|
||||||
|
{
|
||||||
|
_userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("Register")]
|
||||||
|
[ProducesResponseType(typeof(UserResponse), (int)HttpStatusCode.OK)]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
||||||
|
public IActionResult Register()
|
||||||
|
{
|
||||||
|
var authProviderId = this.GetAuthProviderId();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authProviderId)) return NotFound();
|
||||||
|
|
||||||
|
var isRegistered = _userService.IsUserRegistered(authProviderId);
|
||||||
|
|
||||||
|
if (isRegistered) return NoContent();
|
||||||
|
|
||||||
|
var registedUser = _userService.RegisterUser(authProviderId);
|
||||||
|
return Ok(new UserResponse(registedUser));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,35 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace YABA.API.Controllers
|
|
||||||
{
|
|
||||||
[ApiController]
|
|
||||||
[ApiVersion("1")]
|
|
||||||
[Authorize, Route("api/v{version:apiVersion}/[controller]")]
|
|
||||||
public class WeatherForecastController : ControllerBase
|
|
||||||
{
|
|
||||||
private static readonly string[] Summaries = new[]
|
|
||||||
{
|
|
||||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly ILogger<WeatherForecastController> _logger;
|
|
||||||
|
|
||||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet(Name = "GetWeatherForecast")]
|
|
||||||
public IEnumerable<WeatherForecast> Get()
|
|
||||||
{
|
|
||||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
|
||||||
{
|
|
||||||
Date = DateTime.Now.AddDays(index),
|
|
||||||
TemperatureC = Random.Shared.Next(-20, 55),
|
|
||||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
35
YABA.API/Extensions/ControllerExtensions.cs
Normal file
35
YABA.API/Extensions/ControllerExtensions.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using YABA.Common.Extensions;
|
||||||
|
using YABA.Common.Lookups;
|
||||||
|
|
||||||
|
namespace YABA.API.Extensions
|
||||||
|
{
|
||||||
|
public static class ControllerExtensions
|
||||||
|
{
|
||||||
|
public static string GetAuthProviderId(this ControllerBase controller)
|
||||||
|
{
|
||||||
|
return GetCustomClaim(controller, ClaimsLookup.AuthProviderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetUserId(this ControllerBase controller)
|
||||||
|
{
|
||||||
|
var isValidUserId = int.TryParse(GetCustomClaim(controller, ClaimsLookup.UserId), out int userId);
|
||||||
|
return isValidUserId ? userId : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetCustomClaim(this ControllerBase controller, ClaimsLookup claim)
|
||||||
|
{
|
||||||
|
var claimsIdentity = controller.User.Identity as ClaimsIdentity;
|
||||||
|
return claimsIdentity.FindFirst(claim.GetClaimName())?.Value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetIpAddress(this ControllerBase controller)
|
||||||
|
{
|
||||||
|
if (controller.Request.Headers.ContainsKey("X-Forwarded-For"))
|
||||||
|
return controller.Request.Headers["X-Forwarded-For"];
|
||||||
|
|
||||||
|
return controller.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
YABA.API/ViewModels/UserResponse.cs
Normal file
20
YABA.API/ViewModels/UserResponse.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using YABA.Service.DTO;
|
||||||
|
|
||||||
|
namespace YABA.API.ViewModels
|
||||||
|
{
|
||||||
|
public class UserResponse
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
public DateTimeOffset CreatedOn { get; set; }
|
||||||
|
public DateTimeOffset LastModified { get; set; }
|
||||||
|
|
||||||
|
public UserResponse(UserDTO value)
|
||||||
|
{
|
||||||
|
Id = value.Id;
|
||||||
|
IsDeleted = value.IsDeleted;
|
||||||
|
CreatedOn = value.CreatedOn;
|
||||||
|
LastModified = value.LastModified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,6 +23,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\YABA.Common\YABA.Common.csproj" />
|
||||||
<ProjectReference Include="..\YABA.Data\YABA.Data.csproj" />
|
<ProjectReference Include="..\YABA.Data\YABA.Data.csproj" />
|
||||||
<ProjectReference Include="..\YABA.Service\YABA.Service.csproj" />
|
<ProjectReference Include="..\YABA.Service\YABA.Service.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
14
YABA.Common/Attributes/ClaimNameAttribute.cs
Normal file
14
YABA.Common/Attributes/ClaimNameAttribute.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace YABA.Common.Attributes
|
||||||
|
{
|
||||||
|
public class ClaimNameAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public ClaimNameAttribute(string name)
|
||||||
|
{
|
||||||
|
this.Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
YABA.Common/Extensions/EnumExtensions.cs
Normal file
29
YABA.Common/Extensions/EnumExtensions.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using YABA.Common.Attributes;
|
||||||
|
using YABA.Common.Lookups;
|
||||||
|
|
||||||
|
namespace YABA.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class EnumExtensions
|
||||||
|
{
|
||||||
|
public static TAttribute GetAttribute<TAttribute>(this Enum value) where TAttribute : Attribute
|
||||||
|
{
|
||||||
|
var enumType = value.GetType();
|
||||||
|
var name = Enum.GetName(enumType, value);
|
||||||
|
return enumType.GetField(name).GetCustomAttributes(false).OfType<TAttribute>().SingleOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDisplayName(this Enum enumValue)
|
||||||
|
{
|
||||||
|
return enumValue.GetAttribute<DisplayAttribute>().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetClaimName(this ClaimsLookup claimLookup)
|
||||||
|
{
|
||||||
|
return claimLookup.GetAttribute<ClaimNameAttribute>().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
22
YABA.Common/Lookups/ClaimsLookup.cs
Normal file
22
YABA.Common/Lookups/ClaimsLookup.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using YABA.Common.Attributes;
|
||||||
|
|
||||||
|
namespace YABA.Common.Lookups
|
||||||
|
{
|
||||||
|
public enum ClaimsLookup
|
||||||
|
{
|
||||||
|
[ClaimNameAttribute("https://dev.iwanaga.moe/api/auth_provider_id")]
|
||||||
|
AuthProviderId = 1,
|
||||||
|
|
||||||
|
[ClaimNameAttribute("https://dev.iwanaga.moe/api/email_address")]
|
||||||
|
UserEmail = 2,
|
||||||
|
|
||||||
|
[ClaimNameAttribute("https://dev.iwanaga.moe/api/email_verified")]
|
||||||
|
IsEmailConfirmed = 3,
|
||||||
|
|
||||||
|
[ClaimNameAttribute("https://dev.iwanaga.moe/api/username")]
|
||||||
|
Username = 4,
|
||||||
|
|
||||||
|
[ClaimNameAttribute("https://dev.iwanaga.moe/api/id")]
|
||||||
|
UserId = 5
|
||||||
|
}
|
||||||
|
}
|
||||||
12
YABA.Common/YABA.Common.csproj
Normal file
12
YABA.Common/YABA.Common.csproj
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -1,9 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace YABA.Service
|
|
||||||
{
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using YABA.Service.Interfaces;
|
||||||
|
|
||||||
namespace YABA.Service.Configuration
|
namespace YABA.Service.Configuration
|
||||||
{
|
{
|
||||||
@ -7,7 +8,7 @@ namespace YABA.Service.Configuration
|
|||||||
{
|
{
|
||||||
public static void AddServiceProjectDependencyInjectionConfiguration(this IServiceCollection services, IConfiguration configuration)
|
public static void AddServiceProjectDependencyInjectionConfiguration(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
|
services.AddScoped<IUserService, UserService>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
YABA.Service/DTO/UserDTO.cs
Normal file
23
YABA.Service/DTO/UserDTO.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using YABA.Models;
|
||||||
|
|
||||||
|
namespace YABA.Service.DTO
|
||||||
|
{
|
||||||
|
public class UserDTO
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
public DateTimeOffset CreatedOn { get; set; }
|
||||||
|
public DateTimeOffset LastModified { get; set; }
|
||||||
|
|
||||||
|
public UserDTO(User value)
|
||||||
|
{
|
||||||
|
Id = value.Id;
|
||||||
|
IsDeleted = value.IsDeleted;
|
||||||
|
CreatedOn = value.CreatedOn;
|
||||||
|
LastModified = value.LastModified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
YABA.Service/Interfaces/IUserService.cs
Normal file
13
YABA.Service/Interfaces/IUserService.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using YABA.Service.DTO;
|
||||||
|
|
||||||
|
namespace YABA.Service.Interfaces
|
||||||
|
{
|
||||||
|
public interface IUserService
|
||||||
|
{
|
||||||
|
public bool IsUserRegistered(string authProviderId);
|
||||||
|
public UserDTO RegisterUser(string authProviderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
42
YABA.Service/UserService.cs
Normal file
42
YABA.Service/UserService.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using YABA.Data.Context;
|
||||||
|
using YABA.Models;
|
||||||
|
using YABA.Service.DTO;
|
||||||
|
using YABA.Service.Interfaces;
|
||||||
|
|
||||||
|
namespace YABA.Service
|
||||||
|
{
|
||||||
|
public class UserService : IUserService
|
||||||
|
{
|
||||||
|
private readonly YABAReadOnlyContext _roContext;
|
||||||
|
private readonly YABAReadWriteContext _context;
|
||||||
|
|
||||||
|
public UserService (YABAReadOnlyContext roContext, YABAReadWriteContext context)
|
||||||
|
{
|
||||||
|
_roContext = roContext;
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsUserRegistered(string authProviderId)
|
||||||
|
{
|
||||||
|
return _roContext.Users.Any(x => x.Auth0Id == authProviderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDTO RegisterUser(string authProviderId)
|
||||||
|
{
|
||||||
|
if(IsUserRegistered(authProviderId))
|
||||||
|
{
|
||||||
|
var user = _roContext.Users.FirstOrDefault(x => x.Auth0Id == authProviderId);
|
||||||
|
return new UserDTO(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
var userToRegister = new User
|
||||||
|
{
|
||||||
|
Auth0Id = authProviderId
|
||||||
|
};
|
||||||
|
|
||||||
|
var registedUser = _context.Users.Add(userToRegister);
|
||||||
|
return _context.SaveChanges() > 0 ? new UserDTO(registedUser.Entity) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,4 +10,10 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\YABA.Common\YABA.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\YABA.Data\YABA.Data.csproj" />
|
||||||
|
<ProjectReference Include="..\YABA.Models\YABA.Models.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
10
YABA.sln
10
YABA.sln
@ -7,9 +7,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YABA.API", "YABA.API\YABA.A
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YABA.Models", "YABA.Models\YABA.Models.csproj", "{DDA30925-F844-426B-8B90-3E6E258BD407}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YABA.Models", "YABA.Models\YABA.Models.csproj", "{DDA30925-F844-426B-8B90-3E6E258BD407}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YABA.Data", "YABA.Data\YABA.Data.csproj", "{461E9D5A-3C06-4CCB-A466-76BBB9BB7BF5}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YABA.Data", "YABA.Data\YABA.Data.csproj", "{461E9D5A-3C06-4CCB-A466-76BBB9BB7BF5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YABA.Service", "YABA.Service\YABA.Service.csproj", "{0098D0A8-0273-46F1-9FE7-B0409442251A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YABA.Service", "YABA.Service\YABA.Service.csproj", "{0098D0A8-0273-46F1-9FE7-B0409442251A}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YABA.Common", "YABA.Common\YABA.Common.csproj", "{CA107B5D-4B8E-4515-8380-CB474C57F79C}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -33,6 +35,10 @@ Global
|
|||||||
{0098D0A8-0273-46F1-9FE7-B0409442251A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{0098D0A8-0273-46F1-9FE7-B0409442251A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{0098D0A8-0273-46F1-9FE7-B0409442251A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{0098D0A8-0273-46F1-9FE7-B0409442251A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{0098D0A8-0273-46F1-9FE7-B0409442251A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{0098D0A8-0273-46F1-9FE7-B0409442251A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{CA107B5D-4B8E-4515-8380-CB474C57F79C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{CA107B5D-4B8E-4515-8380-CB474C57F79C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CA107B5D-4B8E-4515-8380-CB474C57F79C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{CA107B5D-4B8E-4515-8380-CB474C57F79C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
Reference in New Issue
Block a user