aboutsummaryrefslogtreecommitdiffstats
path: root/src/Controllers/AccountController.cs
blob: 7f94711124417cabdd0cfb3a7583563e1ff8780e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IOL.WebApi.Template.Data.Database;
using IOL.WebApi.Template.Data.Dtos;
using IOL.WebApi.Template.Data.Result;
using IOL.Helpers;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace IOL.WebApi.Template.Controllers
{
	public class AccountController : AppControllerBase
	{
		private readonly AppDbContext _context;
		private readonly IAuthenticationService _authentication;

		public AccountController(
				AppDbContext context,
				IAuthenticationService authentication
		) {
			_context = context;
			_authentication = authentication;
		}

		[AllowAnonymous]
		[HttpPost("login")]
		public ActionResult Login(LoginRequestDto payload) {
			if (!ModelState.IsValid)
				return BadRequest(ModelState);
			var user = _context.Users.SingleOrDefault(u => u.Username == payload.Username);
			if (user == default || !user.VerifyPassword(payload.Password))
				return BadRequest(new ErrorResult("Invalid username or password"));

			var claims = new List<Claim> {
					new(ClaimTypes.NameIdentifier, user.Id.ToString()),
					new(ClaimTypes.Name, user.Username),
			};

			var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
			var principal = new ClaimsPrincipal(identity);
			var authenticationProperties = new AuthenticationProperties {
					AllowRefresh = true,
					IssuedUtc = DateTimeOffset.UtcNow,
			};

			if (payload.Persist) {
				authenticationProperties.ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(6);
				authenticationProperties.IsPersistent = true;
			}

			HttpContext.SignInAsync(principal, authenticationProperties);
			return Ok();
		}

		[HttpGet("logout")]
		[AllowAnonymous]
		public ActionResult Logout() {
			HttpContext.SignOutAsync();
			return Ok();
		}

		[AllowAnonymous]
		[HttpGet("create-initial")]
		public ActionResult CreateInitialUser(string username, string password) {
			if (_context.Users.Any()) {
				return NotFound();
			}

			var user = new User(username);
			user.HashAndSetPassword(password);
			_context.Users.Add(user);
			_context.SaveChanges();
			return Ok();
		}

		[AllowAnonymous]
		[HttpGet("me")]
		public async Task<ActionResult> GetLoggedInUser() {
			var authres =
					await _authentication.AuthenticateAsync(HttpContext, CookieAuthenticationDefaults.AuthenticationScheme);
			if (authres.Succeeded)
				return Ok(LoggedInUser);

			await HttpContext.SignOutAsync();
			return StatusCode(403);
		}

		[HttpPost("update-password")]
		public ActionResult UpdatePassword([FromBody] string newPassword) {
			if (newPassword.IsNullOrWhiteSpace()) {
				return BadRequest(new ErrorResult("Invalid request",
												  "The new password field is required"));
			}

			if (newPassword.Length < 6) {
				return BadRequest(new ErrorResult("Invalid request",
												  "The new password must contain atleast 6 characters"));
			}

			var user = _context.Users.SingleOrDefault(c => c.Id == LoggedInUser.Id);
			if (user == default) {
				HttpContext.SignOutAsync();
				return StatusCode(403);
			}

			user.HashAndSetPassword(newPassword);
			_context.SaveChanges();
			return Ok();
		}
	}
}