add-api-project #29
90
.vscode/launch.json
vendored
90
.vscode/launch.json
vendored
@ -1,36 +1,56 @@
|
||||
{
|
||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||
// Use hover for the description of the existing attributes
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (web)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Apps/Website/bin/Debug/net5.0/Website.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Apps/Website",
|
||||
"stopAtEntry": false,
|
||||
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
|
||||
"serverReadyAction": {
|
||||
"action": "openExternally",
|
||||
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
|
||||
},
|
||||
"env": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"sourceFileMap": {
|
||||
"/Views": "${workspaceFolder}/Views"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||
// Use hover for the description of the existing attributes
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (api)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/Apps/Api/bin/Debug/net5.0/Api.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Apps/Api",
|
||||
"stopAtEntry": false,
|
||||
"serverReadyAction": {
|
||||
"action": "openExternally",
|
||||
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
|
||||
},
|
||||
"env": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"sourceFileMap": {
|
||||
"/Views": "${workspaceFolder}/Views"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Launch (web)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Apps/Website/bin/Debug/net5.0/Website.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Apps/Website",
|
||||
"stopAtEntry": false,
|
||||
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
|
||||
"serverReadyAction": {
|
||||
"action": "openExternally",
|
||||
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
|
||||
},
|
||||
"env": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"sourceFileMap": {
|
||||
"/Views": "${workspaceFolder}/Views"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.1" />
|
||||
<PackageReference Include="NSwag.AspNetCore" Version="13.9.4" />
|
||||
<PackageReference Include="NSwag.MSBuild" Version="13.9.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
70
Apps/Api/Controllers/AccountsController.cs
Normal file
70
Apps/Api/Controllers/AccountsController.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Api.Models;
|
||||
using HN.Infrastructure.Identity;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public sealed class AccountsController : ControllerBase
|
||||
{
|
||||
private readonly UserManager<User> _usersManager;
|
||||
private readonly SignInManager<User> _signinManager;
|
||||
private readonly TokenValidationParameters _tokenParameters;
|
||||
|
||||
public AccountsController(UserManager<User> usersManager, SignInManager<User> signinManager, TokenValidationParameters tokenParameters)
|
||||
{
|
||||
_usersManager = usersManager;
|
||||
_signinManager = signinManager;
|
||||
_tokenParameters = tokenParameters;
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public IActionResult GetUsers()
|
||||
{
|
||||
return Ok(_usersManager.Users.ToArray());
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> Login(LoginViewModel command)
|
||||
{
|
||||
var user = await _usersManager.FindByNameAsync(command.Username);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var result = await _signinManager.CheckPasswordSignInAsync(user, command.Password, false);
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
Subject = new ClaimsIdentity(new Claim[]
|
||||
{
|
||||
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||
new Claim(ClaimTypes.Name, command.Username),
|
||||
}),
|
||||
|
||||
Expires = DateTime.UtcNow.AddDays(7),
|
||||
Issuer = _tokenParameters.ValidIssuer,
|
||||
Audience = _tokenParameters.ValidAudience,
|
||||
SigningCredentials = new SigningCredentials(_tokenParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256Signature)
|
||||
};
|
||||
|
||||
return Ok(new JwtSecurityTokenHandler().CreateEncodedJwt(tokenDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,7 +102,7 @@ namespace Api.Controllers
|
||||
{
|
||||
var result = await _bus.Send(command);
|
||||
|
||||
return CreatedAtAction(nameof(GetLinkById), new { id = result });
|
||||
return CreatedAtAction(nameof(GetLinkById), new { id = result }, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Apps/Api/Models/LoginViewModel.cs
Normal file
13
Apps/Api/Models/LoginViewModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Api.Models
|
||||
{
|
||||
public sealed class LoginViewModel
|
||||
{
|
||||
[Required]
|
||||
public string Username { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,19 @@
|
||||
using System;
|
||||
using HN.Application;
|
||||
using System.Text;
|
||||
using HN.Infrastructure;
|
||||
using HN.Infrastructure.Identity;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Api
|
||||
{
|
||||
public class MockExecutingContext : IExecutingUserProvider
|
||||
{
|
||||
public Guid GetCurrentUserId()
|
||||
{
|
||||
return Guid.NewGuid();
|
||||
}
|
||||
}
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
@ -32,7 +27,7 @@ namespace Api
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddHN(Configuration).ResolveConnectedUserWith<MockExecutingContext>();
|
||||
services.AddHN(Configuration).ResolveConnectedUserWith<HttpExecutingUserProvider>();
|
||||
services.AddHttpContextAccessor();
|
||||
|
||||
// Permet d'avoir des routes en lowercase
|
||||
@ -42,6 +37,31 @@ namespace Api
|
||||
options.LowercaseQueryStrings = true;
|
||||
});
|
||||
|
||||
// Ajout de l'authentification
|
||||
var tokenParams = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidIssuer = Configuration["JwtIssuer"],
|
||||
ValidAudience = Configuration["JwtAudience"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]))
|
||||
};
|
||||
|
||||
services.AddSingleton(tokenParams);
|
||||
|
||||
services.AddIdentityCore<User>()
|
||||
.AddRoles<Role>()
|
||||
.AddEntityFrameworkStores<HNDbContext>()
|
||||
.AddSignInManager();
|
||||
|
||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
o.TokenValidationParameters = tokenParams;
|
||||
});
|
||||
|
||||
services.AddControllers();
|
||||
services.AddSwaggerDocument(d =>
|
||||
{
|
||||
@ -66,6 +86,9 @@ namespace Api
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
|
||||
@ -9,5 +9,8 @@
|
||||
"ConnectionStrings": {
|
||||
"Default": "Data Source=../Website/hn.db"
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
"AllowedHosts": "*",
|
||||
"JwtIssuer": "http://localhost",
|
||||
"JwtAudience": "http://localhost",
|
||||
"JwtSecurityKey": "CTtgxbcSFbpJmdmLDnr3Y8h5RWseN7t5"
|
||||
}
|
||||
|
||||
@ -6,6 +6,60 @@
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/api/accounts": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Accounts"
|
||||
],
|
||||
"operationId": "Accounts_GetUsers",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/octet-stream": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/accounts/login": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Accounts"
|
||||
],
|
||||
"operationId": "Accounts_Login",
|
||||
"requestBody": {
|
||||
"x-name": "command",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/LoginViewModel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"x-position": 1
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/octet-stream": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/links": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -232,6 +286,24 @@
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"LoginViewModel": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"username",
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"LinkDto": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
@ -65,15 +65,7 @@ namespace Website.Controllers
|
||||
return View();
|
||||
}
|
||||
|
||||
var user = await _userManager.FindByNameAsync(command.Username);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
ModelState.AddModelError(nameof(LoginViewModel.Username), "Could not verify user identity");
|
||||
return View();
|
||||
}
|
||||
|
||||
var result = await _signInManager.PasswordSignInAsync(user, command.Password, true, false);
|
||||
var result = await _signInManager.PasswordSignInAsync(command.Username, command.Password, true, false);
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user