diff --git a/.idea/.idea.Abyss/.idea/workspace.xml b/.idea/.idea.Abyss/.idea/workspace.xml index c49f6b9..fb33dea 100644 --- a/.idea/.idea.Abyss/.idea/workspace.xml +++ b/.idea/.idea.Abyss/.idea/workspace.xml @@ -11,6 +11,8 @@ + + diff --git a/Abyss/Components/Controllers/Security/UserController.cs b/Abyss/Components/Controllers/Security/UserController.cs index ba4f88b..c5664e1 100644 --- a/Abyss/Components/Controllers/Security/UserController.cs +++ b/Abyss/Components/Controllers/Security/UserController.cs @@ -20,110 +20,52 @@ public class UserController(UserService userService, ILogger log public async Task Challenge(string user) { var c = await userService.Challenge(user); - if (c == null) - return _403; - - return Ok(c); + return c != null ? Ok(c): _403; } [HttpPost("{user}")] public async Task Challenge(string user, [FromBody] ChallengeResponse response) { var r = await userService.Verify(user, response.Response, Ip); - if (r == null) - return _403; + if (r != null) + { + Response.Cookies.Append("token", r); + return Ok(r); + } - Response.Cookies.Append("token", r); - return Ok(r); + return _403; } [HttpPost("validate")] public IActionResult Validate(string token) { var u = userService.Validate(token, Ip); - if (u == -1) - { - return _401; - } - - return Ok(u); + return u == -1 ? _401 : Ok(u); } [HttpPost("destroy")] public IActionResult Destroy(string token) { var u = userService.Validate(token, Ip); - if (u == -1) + if (u != -1) { - return _401; + userService.Destroy(token); + return Ok("Success"); } - - userService.Destroy(token); - return Ok("Success"); + return _401; } [HttpPatch("{user}")] public async Task Create(string user, [FromBody] UserCreating creating) { - // Valid token - var r = await userService.Verify(user, creating.Response, Ip); - if (r == null) - return _403; - - // User exists ? - var cu = await userService.QueryUser(creating.Name); - if (cu != null) - return _403; - - // Valid username string - if (!IsAlphanumeric(creating.Name)) - return _403; - - // Valid parent && Privilege - var ou = await userService.QueryUser(userService.Validate(r, Ip)); - if (creating.Privilege > ou?.Privilege || ou == null) - return _403; - - await userService.CreateUser(new User - { - Username = creating.Name, - ParentId = ou.Uuid, - Privilege = creating.Privilege, - PublicKey = creating.PublicKey, - }); - - userService.Destroy(r); - return Ok("Success"); + bool r = await userService.CreateUserAsync(user, creating, Ip); + return r ? Ok("Success") : _403; } [HttpGet("{user}/open")] public async Task Open(string user, [FromQuery] string token, [FromQuery] string? bindIp = null) { - var caller = userService.Validate(token, Ip); - if (caller != 1) - { - return _403; - } - - var target = await userService.QueryUser(user); - if (target == null) - { - return _403; - } - - var ipToBind = string.IsNullOrWhiteSpace(bindIp) ? Ip : bindIp; - - var t = userService.CreateToken(target.Uuid, ipToBind, TimeSpan.FromHours(1)); - - logger.LogInformation("Root created 1h token for {User}, bound to {BindIp}, request from {ReqIp}", user, - ipToBind, Ip); - return Ok(new { token = t, user, boundIp = ipToBind }); - } - - public static bool IsAlphanumeric(string input) - { - if (string.IsNullOrEmpty(input)) - return false; - return Regex.IsMatch(input, @"^[a-zA-Z0-9]+$"); + string? r = await userService.OpenUserAsync(user, token, bindIp, Ip); + return r != null ? Ok(r) : _403; } } \ No newline at end of file diff --git a/Abyss/Components/Services/Security/UserService.cs b/Abyss/Components/Services/Security/UserService.cs index d42dcaa..d956c84 100644 --- a/Abyss/Components/Services/Security/UserService.cs +++ b/Abyss/Components/Services/Security/UserService.cs @@ -3,6 +3,7 @@ using System.Security.Cryptography; using System.Text; +using System.Text.RegularExpressions; using Abyss.Components.Services.Misc; using Abyss.Model.Security; using Microsoft.Extensions.Caching.Memory; @@ -17,7 +18,6 @@ public class UserService private readonly ILogger _logger; private readonly IMemoryCache _cache; private readonly SQLiteAsyncConnection _database; - public UserService(ILogger logger, ConfigureService config, IMemoryCache cache) { _logger = logger; @@ -59,6 +59,62 @@ public class UserService Console.ReadKey(); } } + + public async Task OpenUserAsync(string user, string token, string? bindIp, string ip) + { + var caller = Validate(token, ip); + if (caller != 1) + { + return null; + } + + var target = await QueryUser(user); + if (target == null) + { + return null; + } + + var ipToBind = string.IsNullOrWhiteSpace(bindIp) ? ip : bindIp; + + var t = CreateToken(target.Uuid, ipToBind, TimeSpan.FromHours(1)); + + _logger.LogInformation("Root created 1h token for {User}, bound to {BindIp}, request from {ReqIp}", user, + ipToBind, ip); + return t; + } + + public async Task CreateUserAsync(string user, UserCreating creating, string ip) + { + // Valid token + var r = await Verify(user, creating.Response, ip); + if (r == null) + return false; + + // User exists ? + var cu = await QueryUser(creating.Name); + if (cu != null) + return false; + + // Valid username string + if (!IsAlphanumeric(creating.Name)) + return false; + + // Valid parent && Privilege + var ou = await QueryUser(Validate(r, ip)); + if (creating.Privilege > ou?.Privilege || ou == null) + return false; + + await CreateUser(new User + { + Username = creating.Name, + ParentId = ou.Uuid, + Privilege = creating.Privilege, + PublicKey = creating.PublicKey, + }); + + Destroy(r); + return true; + } public async Task Challenge(string user) { var u = await _database.Table().Where(x => x.Username == user).FirstOrDefaultAsync(); @@ -226,4 +282,12 @@ public class UserService _logger.LogInformation($"Created token for {uid}@{ip}, valid {lifetime.TotalMinutes} minutes"); return token; } + + + public static bool IsAlphanumeric(string input) + { + if (string.IsNullOrEmpty(input)) + return false; + return Regex.IsMatch(input, @"^[a-zA-Z0-9]+$"); + } } \ No newline at end of file