netcore-blueprint 1.0.27 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BlueprintTemplate/Blueprint.API/Blueprint.API.csproj +7 -0
- package/BlueprintTemplate/Blueprint.API/Controllers/AuthController.cs +46 -0
- package/BlueprintTemplate/Blueprint.API/Controllers/UserController.cs +3 -30
- package/BlueprintTemplate/Blueprint.API/Program.cs +35 -5
- package/BlueprintTemplate/Blueprint.API/appsettings.json +1 -1
- package/BlueprintTemplate/README.md +3 -2
- package/package.json +1 -1
- package/BlueprintTemplate/Blueprint.API/AsyncControllers/UserControllerAsync.cs +0 -51
- package/BlueprintTemplate/Blueprint.API/WeatherForecast.cs +0 -13
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
<ImplicitUsings>enable</ImplicitUsings>
|
|
7
7
|
</PropertyGroup>
|
|
8
8
|
|
|
9
|
+
<ItemGroup>
|
|
10
|
+
<Compile Remove="AsyncControllers\**" />
|
|
11
|
+
<Content Remove="AsyncControllers\**" />
|
|
12
|
+
<EmbeddedResource Remove="AsyncControllers\**" />
|
|
13
|
+
<None Remove="AsyncControllers\**" />
|
|
14
|
+
</ItemGroup>
|
|
15
|
+
|
|
9
16
|
<ItemGroup>
|
|
10
17
|
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
|
11
18
|
<PackageReference Include="AWSSDK.Extensions.NETCore.Setup" Version="3.7.301" />
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
using Microsoft.AspNetCore.Mvc;
|
|
2
|
+
using Microsoft.IdentityModel.Tokens;
|
|
3
|
+
using System.IdentityModel.Tokens.Jwt;
|
|
4
|
+
using System.Security.Claims;
|
|
5
|
+
using System.Text;
|
|
6
|
+
|
|
7
|
+
namespace Blueprint.API.Controllers
|
|
8
|
+
{
|
|
9
|
+
[Route("auth")]
|
|
10
|
+
[ApiController]
|
|
11
|
+
public class AuthController : ControllerBase
|
|
12
|
+
{
|
|
13
|
+
private readonly IConfiguration _config;
|
|
14
|
+
|
|
15
|
+
public AuthController(IConfiguration config)
|
|
16
|
+
{
|
|
17
|
+
_config = config;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
[HttpGet("token")]
|
|
21
|
+
public IActionResult GetToken(string role = "Admin")
|
|
22
|
+
{
|
|
23
|
+
var secret = _config["Jwt:Secret"];
|
|
24
|
+
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
|
|
25
|
+
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
|
26
|
+
|
|
27
|
+
var claims = new[]
|
|
28
|
+
{
|
|
29
|
+
new Claim(JwtRegisteredClaimNames.Sub, "test-user"),
|
|
30
|
+
new Claim(ClaimTypes.Role, role)
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
var token = new JwtSecurityToken(
|
|
34
|
+
issuer: _config["Jwt:Issuer"],
|
|
35
|
+
audience: _config["Jwt:Audience"],
|
|
36
|
+
claims: claims,
|
|
37
|
+
expires: DateTime.UtcNow.AddHours(1),
|
|
38
|
+
signingCredentials: creds
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
|
|
42
|
+
|
|
43
|
+
return Ok(new { token = tokenString });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -44,7 +44,7 @@ namespace Template.API.Controllers
|
|
|
44
44
|
/// <param name="pagingParams"></param>
|
|
45
45
|
/// <returns></returns>
|
|
46
46
|
[HttpGet]
|
|
47
|
-
|
|
47
|
+
[Authorize(Roles = "Admin")]
|
|
48
48
|
[ProducesResponseType(typeof(PagerData<UserResponseDto>), StatusCodes.Status200OK)]
|
|
49
49
|
public async Task<IActionResult> GetUsers([FromQuery] PagingParams pagingParams)
|
|
50
50
|
{
|
|
@@ -85,41 +85,13 @@ namespace Template.API.Controllers
|
|
|
85
85
|
return Ok(userResponseDto);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
/// <summary>
|
|
89
|
-
/// Checking user login
|
|
90
|
-
/// </summary>
|
|
91
|
-
/// <param name="token"></param>
|
|
92
|
-
/// <returns></returns>
|
|
93
|
-
[HttpGet("check-user-login")]
|
|
94
|
-
[ProducesResponseType(typeof(UserResponseDto), StatusCodes.Status200OK)]
|
|
95
|
-
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
96
|
-
public async Task<IActionResult> CheckUserLogin()
|
|
97
|
-
{
|
|
98
|
-
_logger.LogInformation($"Start checking user login");
|
|
99
|
-
var stopwatch = Stopwatch.StartNew();
|
|
100
|
-
|
|
101
|
-
string? authorizationHeader = Request.Headers["Authorization"].FirstOrDefault();
|
|
102
|
-
if (string.IsNullOrEmpty(authorizationHeader) || !authorizationHeader.StartsWith("Bearer "))
|
|
103
|
-
{
|
|
104
|
-
return Unauthorized("Authorization header missing or invalid.");
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
string token = authorizationHeader.Replace("Bearer ", string.Empty);
|
|
108
|
-
|
|
109
|
-
string newToken = await _userService.CheckUserLogin(token);
|
|
110
|
-
|
|
111
|
-
stopwatch.Stop();
|
|
112
|
-
_logger.LogInformation($"Checking user login done in {stopwatch.ElapsedMilliseconds}");
|
|
113
|
-
|
|
114
|
-
return Ok(newToken);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
88
|
/// <summary>
|
|
118
89
|
/// Update User
|
|
119
90
|
/// </summary>
|
|
120
91
|
/// <param name="userRequestDto"></param>
|
|
121
92
|
/// <returns></returns>
|
|
122
93
|
[HttpPut]
|
|
94
|
+
[Authorize(Roles = "Admin")]
|
|
123
95
|
[ProducesResponseType(typeof(UserResponseDto), StatusCodes.Status200OK)]
|
|
124
96
|
public async Task<IActionResult> UpdateUser([FromBody] UserRequestDto userRequestDto)
|
|
125
97
|
{
|
|
@@ -141,6 +113,7 @@ namespace Template.API.Controllers
|
|
|
141
113
|
/// <param name="userIds"></param>
|
|
142
114
|
/// <returns></returns>
|
|
143
115
|
[HttpDelete]
|
|
116
|
+
[Authorize(Roles = "Admin")]
|
|
144
117
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
145
118
|
public async Task<IActionResult> DeleteUser([FromBody] List<int> userIds)
|
|
146
119
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
1
|
+
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
2
2
|
using Microsoft.EntityFrameworkCore;
|
|
3
3
|
using Microsoft.IdentityModel.Tokens;
|
|
4
4
|
using Blueprint.Infra.Database;
|
|
@@ -21,6 +21,7 @@ using Amazon.SimpleSystemsManagement.Model;
|
|
|
21
21
|
using Amazon.SimpleSystemsManagement;
|
|
22
22
|
using Blueprint.Infra.Services.Mongo;
|
|
23
23
|
using Blueprint.Infra.Services.MySQL;
|
|
24
|
+
using System.Security.Claims;
|
|
24
25
|
|
|
25
26
|
var builder = WebApplication.CreateBuilder(args);
|
|
26
27
|
|
|
@@ -58,7 +59,36 @@ void ConfigureSwagger()
|
|
|
58
59
|
{
|
|
59
60
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
|
60
61
|
builder.Services.AddEndpointsApiExplorer();
|
|
61
|
-
builder.Services.AddSwaggerGen(
|
|
62
|
+
builder.Services.AddSwaggerGen(c =>
|
|
63
|
+
{
|
|
64
|
+
c.SwaggerDoc("v1", new() { Title = "My API", Version = "v1" });
|
|
65
|
+
|
|
66
|
+
// ✅ Add JWT Auth to Swagger
|
|
67
|
+
c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
|
68
|
+
{
|
|
69
|
+
Name = "Authorization",
|
|
70
|
+
Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
|
|
71
|
+
Scheme = "Bearer",
|
|
72
|
+
BearerFormat = "JWT",
|
|
73
|
+
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
|
|
74
|
+
Description = "Enter 'Bearer {your JWT token}'"
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
c.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
|
|
78
|
+
{
|
|
79
|
+
{
|
|
80
|
+
new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
|
81
|
+
{
|
|
82
|
+
Reference = new Microsoft.OpenApi.Models.OpenApiReference
|
|
83
|
+
{
|
|
84
|
+
Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
|
|
85
|
+
Id = "Bearer"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
new string[] {}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
62
92
|
}
|
|
63
93
|
|
|
64
94
|
void ConfigureServices()
|
|
@@ -87,12 +117,12 @@ void ConfigureServices()
|
|
|
87
117
|
options.SaveToken = true;
|
|
88
118
|
options.TokenValidationParameters = new TokenValidationParameters
|
|
89
119
|
{
|
|
90
|
-
ValidateIssuerSigningKey =
|
|
120
|
+
ValidateIssuerSigningKey = true,
|
|
91
121
|
ValidateIssuer = false,
|
|
92
122
|
ValidateAudience = false,
|
|
93
|
-
ValidateLifetime =
|
|
123
|
+
ValidateLifetime = true, // Ensure token expiration is checked
|
|
94
124
|
ClockSkew = TimeSpan.Zero, // Optional: Prevents automatic expiration buffer
|
|
95
|
-
RoleClaimType =
|
|
125
|
+
RoleClaimType = ClaimTypes.Role,
|
|
96
126
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Secret"]!))
|
|
97
127
|
};
|
|
98
128
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
0.
|
|
2
|
-
-
|
|
1
|
+
0. Files and folders can be delete when copy to other place (In each project folder):
|
|
2
|
+
- bin/
|
|
3
|
+
- obj/
|
|
3
4
|
1. Push the image to docker hub
|
|
4
5
|
- chmod +x build-and-push.sh
|
|
5
6
|
- run docker desktop as administrator
|
package/package.json
CHANGED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
using Blueprint.Core.Interfaces.SPI;
|
|
2
|
-
using Microsoft.AspNetCore.Mvc;
|
|
3
|
-
using System.Text.Json;
|
|
4
|
-
using Template.Core.Dtos.Requests;
|
|
5
|
-
|
|
6
|
-
namespace Blueprint.API.AsyncControllers
|
|
7
|
-
{
|
|
8
|
-
[Route("rest/v{version:apiVersion}/users-async")]
|
|
9
|
-
[ApiController]
|
|
10
|
-
public class UserControllerAsync : Controller
|
|
11
|
-
{
|
|
12
|
-
private readonly IRabbitMqService _rabbitMqService;
|
|
13
|
-
private readonly ILogger<UserControllerAsync> _logger;
|
|
14
|
-
|
|
15
|
-
public UserControllerAsync(IRabbitMqService rabbitMqService, ILogger<UserControllerAsync> logger)
|
|
16
|
-
{
|
|
17
|
-
_rabbitMqService = rabbitMqService;
|
|
18
|
-
_logger = logger;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
[HttpPost]
|
|
22
|
-
public IActionResult CreateUser([FromBody] UserRequestDto userRequestDto)
|
|
23
|
-
{
|
|
24
|
-
_logger.LogInformation($"Start queuing a user creation request.");
|
|
25
|
-
|
|
26
|
-
// Serialize the user data as a message
|
|
27
|
-
string message = JsonSerializer.Serialize(userRequestDto);
|
|
28
|
-
|
|
29
|
-
// Publish the message to RabbitMQ
|
|
30
|
-
_rabbitMqService.PublishMessage("user-creation-queue", message);
|
|
31
|
-
|
|
32
|
-
_logger.LogInformation($"User creation request queued successfully.");
|
|
33
|
-
return Accepted("User creation request is being processed.");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
[HttpDelete]
|
|
37
|
-
public IActionResult DeleteUser([FromBody] List<int> userIds)
|
|
38
|
-
{
|
|
39
|
-
_logger.LogInformation($"Start queuing a user deletion request.");
|
|
40
|
-
|
|
41
|
-
// Serialize the user IDs as a message
|
|
42
|
-
string message = JsonSerializer.Serialize(userIds);
|
|
43
|
-
|
|
44
|
-
// Publish the message to RabbitMQ
|
|
45
|
-
_rabbitMqService.PublishMessage("user-deletion-queue", message);
|
|
46
|
-
|
|
47
|
-
_logger.LogInformation($"User deletion request queued successfully.");
|
|
48
|
-
return Accepted("User deletion request is being processed.");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
namespace Blueprint.API
|
|
2
|
-
{
|
|
3
|
-
public class WeatherForecast
|
|
4
|
-
{
|
|
5
|
-
public DateOnly Date { get; set; }
|
|
6
|
-
|
|
7
|
-
public int TemperatureC { get; set; }
|
|
8
|
-
|
|
9
|
-
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
|
10
|
-
|
|
11
|
-
public string? Summary { get; set; }
|
|
12
|
-
}
|
|
13
|
-
}
|