aboutsummaryrefslogtreecommitdiff
path: root/BackEnd/Timeline/Controllers
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-04-16 22:11:29 +0800
committercrupest <crupest@outlook.com>2022-04-16 22:11:29 +0800
commitb4f783c20aa47cb601dc81e0dad07aa92517c229 (patch)
tree5555a97984df994910c26b3d5f2fc897cfbdfd28 /BackEnd/Timeline/Controllers
parent750785728f57af11dfc682ee9ee870e4dc191981 (diff)
downloadtimeline-b4f783c20aa47cb601dc81e0dad07aa92517c229.tar.gz
timeline-b4f783c20aa47cb601dc81e0dad07aa92517c229.tar.bz2
timeline-b4f783c20aa47cb601dc81e0dad07aa92517c229.zip
...
Diffstat (limited to 'BackEnd/Timeline/Controllers')
-rw-r--r--BackEnd/Timeline/Controllers/TokenController.cs4
-rw-r--r--BackEnd/Timeline/Controllers/V2/TokenV2Controller.cs132
2 files changed, 134 insertions, 2 deletions
diff --git a/BackEnd/Timeline/Controllers/TokenController.cs b/BackEnd/Timeline/Controllers/TokenController.cs
index 9ee5a09f..7fba0bc5 100644
--- a/BackEnd/Timeline/Controllers/TokenController.cs
+++ b/BackEnd/Timeline/Controllers/TokenController.cs
@@ -1,4 +1,4 @@
-using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
@@ -77,7 +77,7 @@ namespace Timeline.Controllers
[AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
- public async Task<ActionResult<HttpVerifyTokenResponse>> Verify([FromBody] HttpVerifyTokenRequest request)
+ public async Task<ActionResult<HttpVerifyTokenResponse>> Verify([FromBody] HttpVerifyOrRevokeTokenRequest request)
{
try
{
diff --git a/BackEnd/Timeline/Controllers/V2/TokenV2Controller.cs b/BackEnd/Timeline/Controllers/V2/TokenV2Controller.cs
new file mode 100644
index 00000000..b129758a
--- /dev/null
+++ b/BackEnd/Timeline/Controllers/V2/TokenV2Controller.cs
@@ -0,0 +1,132 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Threading.Tasks;
+using Timeline.Models.Http;
+using Timeline.Services;
+using Timeline.Services.Token;
+using Timeline.Services.User;
+
+namespace Timeline.Controllers.V2
+{
+ [ApiController]
+ [Route("v2/token")]
+ public class TokenV2Controller : V2ControllerBase
+ {
+ private readonly IUserService _userService;
+ private readonly IUserTokenService _userTokenService;
+ private readonly IClock _clock;
+
+ public TokenV2Controller(IUserService userService, IUserTokenService userTokenService, IClock clock)
+ {
+ _userService = userService;
+ _userTokenService = userTokenService;
+ _clock = clock;
+ }
+
+ private const string BadCredentialMessage = "Username or password is wrong.";
+
+ /// <summary>
+ /// Create a new token for a user.
+ /// </summary>
+ /// <returns>Result of token creation.</returns>
+ [HttpPost("create")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult<HttpCreateTokenResponse>> CreateAsync([FromBody] HttpCreateTokenRequestV2 request)
+ {
+
+ try
+ {
+ DateTime? expireTime = null;
+ if (request.ValidDays is not null)
+ expireTime = _clock.GetCurrentTime().AddDays(request.ValidDays.Value);
+
+ var userId = await _userService.VerifyCredential(request.Username, request.Password);
+ var token = await _userTokenService.CreateTokenAsync(userId, expireTime);
+ var user = await _userService.GetUserAsync(userId);
+
+ return new HttpCreateTokenResponse
+ {
+ Token = token,
+ User = await MapAsync<HttpUser>(user)
+ };
+ }
+ catch (EntityNotExistException)
+ {
+ return UnprocessableEntity(new ErrorResponse(ErrorResponse.InvalidRequest, BadCredentialMessage));
+ }
+ catch (BadPasswordException)
+ {
+ return UnprocessableEntity(new ErrorResponse(ErrorResponse.InvalidRequest, BadCredentialMessage));
+ }
+ }
+
+ private const string TokenExpiredMessage = "The token has expired.";
+ private const string TokenInvalidMessage = "The token is invalid.";
+
+ /// <summary>
+ /// Verify a token.
+ /// </summary>
+ /// <returns>Result of token verification.</returns>
+ [HttpPost("verify")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult<HttpVerifyTokenResponseV2>> VerifyAsync([FromBody] HttpVerifyOrRevokeTokenRequest request)
+ {
+ try
+ {
+ var tokenInfo = await _userTokenService.ValidateTokenAsync(request.Token);
+ var user = await _userService.GetUserAsync(tokenInfo.UserId);
+ return new HttpVerifyTokenResponseV2
+ {
+ User = await MapAsync<HttpUser>(user),
+ ExpireAt = tokenInfo.ExpireAt
+ };
+ }
+ catch (UserTokenExpiredException)
+ {
+ return UnprocessableEntity(new ErrorResponse(ErrorResponse.InvalidRequest, TokenExpiredMessage));
+ }
+ catch (UserTokenException)
+ {
+ return UnprocessableEntity(new ErrorResponse(ErrorResponse.InvalidRequest, TokenInvalidMessage));
+ }
+ }
+
+ [HttpPost("revoke")]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ [Authorize]
+ public async Task<ActionResult> RevokeAsync([FromBody] HttpVerifyOrRevokeTokenRequest body)
+ {
+ UserTokenInfo userTokenInfo;
+ try
+ {
+ userTokenInfo = await _userTokenService.ValidateTokenAsync(body.Token, false);
+ }
+ catch (UserTokenException)
+ {
+ return UnprocessableEntity(new ErrorResponse(ErrorResponse.InvalidRequest, TokenInvalidMessage));
+ }
+
+ if (userTokenInfo.UserId != GetAuthUserId())
+ return UnprocessableEntity(new ErrorResponse(ErrorResponse.InvalidRequest, TokenInvalidMessage));
+
+ await _userTokenService.RevokeTokenAsync(body.Token);
+
+ return NoContent();
+ }
+
+ [HttpPost("revokeall")]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [Authorize]
+ public async Task<ActionResult> RevokeAllAsync()
+ {
+ await _userTokenService.RevokeAllTokenByUserIdAsync(GetAuthUserId());
+ return NoContent();
+ }
+ }
+}
+