diff --git a/.editorconfig b/.editorconfig index db19b724..cde44942 100644 --- a/.editorconfig +++ b/.editorconfig @@ -70,7 +70,6 @@ csharp_indent_case_contents = true csharp_indent_switch_labels = true # Modifiers dotnet_style_readonly_field = true:suggestion -csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion # Naming style dotnet_naming_symbols.privates.applicable_kinds = property,method,event,delegate diff --git a/docs/contributing/build.md b/docs/contributing/build.md index e24d12f2..4152cb5e 100644 --- a/docs/contributing/build.md +++ b/docs/contributing/build.md @@ -10,7 +10,7 @@ title: Build To develop for Kyoo, you will need the **.NET 5.0 SDK**, **node** and **npm** for the webapp. If you want to build the transcoder, you will also need a cmake compatible environment. ## Building -To run the development server, simply open the .sln file with your favorite C# IDE (like Jetbrain's Rider or Visual Studio) and press run or you can use the CLI and use the ```dotnet run dotnet run -p src/Kyoo.Host.Console --launch-profile "Console"``` command. +To run the development server, simply open the .sln file with your favorite C# IDE (like Jetbrain's Rider or Visual Studio) and press run or you can use the CLI and use the ```dotnet run --project src/Kyoo.Host.Console --launch-profile "Console"``` command. To pack the application, run the ```dotnet publish -c Release -o Kyoo.Host.Console``` command. This will build the server, the webapp and the transcoder and output files in the directory. ## Skipping parts diff --git a/src/Kyoo.Abstractions/Models/Resources/User.cs b/src/Kyoo.Abstractions/Models/Resources/User.cs index 69c7dfa4..17ad2591 100644 --- a/src/Kyoo.Abstractions/Models/Resources/User.cs +++ b/src/Kyoo.Abstractions/Models/Resources/User.cs @@ -17,6 +17,7 @@ // along with Kyoo. If not, see . using System.Collections.Generic; +using Kyoo.Abstractions.Models.Attributes; namespace Kyoo.Abstractions.Models { @@ -62,11 +63,13 @@ namespace Kyoo.Abstractions.Models /// /// The list of shows the user has finished. /// + [SerializeIgnore] public ICollection Watched { get; set; } /// /// The list of episodes the user is watching (stopped in progress or the next episode of the show) /// + [SerializeIgnore] public ICollection CurrentlyWatching { get; set; } } } diff --git a/src/Kyoo.Authentication/AuthenticationModule.cs b/src/Kyoo.Authentication/AuthenticationModule.cs index 64930085..b2dcfcdb 100644 --- a/src/Kyoo.Authentication/AuthenticationModule.cs +++ b/src/Kyoo.Authentication/AuthenticationModule.cs @@ -74,14 +74,16 @@ namespace Kyoo.Authentication public void Configure(ContainerBuilder builder) { builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); } /// public void Configure(IServiceCollection services) { Uri publicUrl = _configuration.GetPublicUrl(); - AuthenticationOption jwt = new(); - _configuration.GetSection(AuthenticationOption.Path).Bind(jwt); + AuthenticationOption jwt = ConfigurationBinder.Get( + _configuration.GetSection(AuthenticationOption.Path) + ); // TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) diff --git a/src/Kyoo.Authentication/Controllers/PermissionValidator.cs b/src/Kyoo.Authentication/Controllers/PermissionValidator.cs index 4af4d963..d3200d1c 100644 --- a/src/Kyoo.Authentication/Controllers/PermissionValidator.cs +++ b/src/Kyoo.Authentication/Controllers/PermissionValidator.cs @@ -72,7 +72,7 @@ namespace Kyoo.Authentication /// /// The permission to validate. /// - private readonly string _permission; + private readonly string? _permission; /// /// The kind of permission needed. @@ -133,7 +133,7 @@ namespace Kyoo.Authentication /// public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { - string permission = _permission; + string? permission = _permission; Kind? kind = _kind; if (permission == null || kind == null) diff --git a/src/Kyoo.Authentication/Controllers/TokenController.cs b/src/Kyoo.Authentication/Controllers/TokenController.cs index aa305b13..db841f89 100644 --- a/src/Kyoo.Authentication/Controllers/TokenController.cs +++ b/src/Kyoo.Authentication/Controllers/TokenController.cs @@ -31,119 +31,120 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; -namespace Kyoo.Authentication; - -/// -/// The service that controls jwt creation and validation. -/// -public class TokenController : ITokenController +namespace Kyoo.Authentication { /// - /// The options that this controller will use. + /// The service that controls jwt creation and validation. /// - private readonly IOptions _options; - - /// - /// The configuration used to retrieve the public URL of kyoo. - /// - private readonly IConfiguration _configuration; - - /// - /// Create a new . - /// - /// The options that this controller will use. - /// The configuration used to retrieve the public URL of kyoo. - public TokenController(IOptions options, IConfiguration configuration) + public class TokenController : ITokenController { - _options = options; - _configuration = configuration; - } + /// + /// The options that this controller will use. + /// + private readonly IOptions _options; - /// - public string CreateAccessToken(User user, out TimeSpan expireIn) - { - if (user == null) - throw new ArgumentNullException(nameof(user)); + /// + /// The configuration used to retrieve the public URL of kyoo. + /// + private readonly IConfiguration _configuration; - expireIn = new TimeSpan(1, 0, 0); - - SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); - SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature); - string permissions = user.Permissions != null - ? string.Join(',', user.Permissions) - : string.Empty; - List claims = new() + /// + /// Create a new . + /// + /// The options that this controller will use. + /// The configuration used to retrieve the public URL of kyoo. + public TokenController(IOptions options, IConfiguration configuration) { - new Claim(ClaimTypes.NameIdentifier, user.ID.ToString(CultureInfo.InvariantCulture)), - new Claim(ClaimTypes.Name, user.Username), - new Claim(ClaimTypes.Role, permissions), - new Claim("type", "access") - }; - if (user.Email != null) - claims.Add(new Claim(ClaimTypes.Email, user.Email)); - JwtSecurityToken token = new( - signingCredentials: credential, - issuer: _configuration.GetPublicUrl().ToString(), - audience: _configuration.GetPublicUrl().ToString(), - claims: claims, - expires: DateTime.UtcNow.Add(expireIn) - ); - return new JwtSecurityTokenHandler().WriteToken(token); - } + _options = options; + _configuration = configuration; + } - /// - public Task CreateRefreshToken(User user) - { - if (user == null) - throw new ArgumentNullException(nameof(user)); + /// + public string CreateAccessToken(User user, out TimeSpan expireIn) + { + if (user == null) + throw new ArgumentNullException(nameof(user)); - SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); - SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature); - JwtSecurityToken token = new( - signingCredentials: credential, - issuer: _configuration.GetPublicUrl().ToString(), - audience: _configuration.GetPublicUrl().ToString(), - claims: new[] + expireIn = new TimeSpan(1, 0, 0); + + SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); + SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature); + string permissions = user.Permissions != null + ? string.Join(',', user.Permissions) + : string.Empty; + List claims = new() { new Claim(ClaimTypes.NameIdentifier, user.ID.ToString(CultureInfo.InvariantCulture)), - new Claim("guid", Guid.NewGuid().ToString()), - new Claim("type", "refresh") - }, - expires: DateTime.UtcNow.AddYears(1) - ); - // TODO refresh keys are unique (thanks to the guid) but we could store them in DB to invalidate them if requested by the user. - return Task.FromResult(new JwtSecurityTokenHandler().WriteToken(token)); - } + new Claim(ClaimTypes.Name, user.Username), + new Claim(ClaimTypes.Role, permissions), + new Claim("type", "access") + }; + if (user.Email != null) + claims.Add(new Claim(ClaimTypes.Email, user.Email)); + JwtSecurityToken token = new( + signingCredentials: credential, + issuer: _configuration.GetPublicUrl().ToString(), + audience: _configuration.GetPublicUrl().ToString(), + claims: claims, + expires: DateTime.UtcNow.Add(expireIn) + ); + return new JwtSecurityTokenHandler().WriteToken(token); + } - /// - public int GetRefreshTokenUserID(string refreshToken) - { - SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); - JwtSecurityTokenHandler tokenHandler = new(); - ClaimsPrincipal principal; - try + /// + public Task CreateRefreshToken(User user) { - principal = tokenHandler.ValidateToken(refreshToken, new TokenValidationParameters + if (user == null) + throw new ArgumentNullException(nameof(user)); + + SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); + SigningCredentials credential = new(key, SecurityAlgorithms.HmacSha256Signature); + JwtSecurityToken token = new( + signingCredentials: credential, + issuer: _configuration.GetPublicUrl().ToString(), + audience: _configuration.GetPublicUrl().ToString(), + claims: new[] + { + new Claim(ClaimTypes.NameIdentifier, user.ID.ToString(CultureInfo.InvariantCulture)), + new Claim("guid", Guid.NewGuid().ToString()), + new Claim("type", "refresh") + }, + expires: DateTime.UtcNow.AddYears(1) + ); + // TODO refresh keys are unique (thanks to the guid) but we could store them in DB to invalidate them if requested by the user. + return Task.FromResult(new JwtSecurityTokenHandler().WriteToken(token)); + } + + /// + public int GetRefreshTokenUserID(string refreshToken) + { + SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Value.Secret)); + JwtSecurityTokenHandler tokenHandler = new(); + ClaimsPrincipal principal; + try { - ValidateIssuer = true, - ValidateAudience = true, - ValidateIssuerSigningKey = true, - ValidateLifetime = true, - ValidIssuer = _configuration.GetPublicUrl().ToString(), - ValidAudience = _configuration.GetPublicUrl().ToString(), - IssuerSigningKey = key - }, out SecurityToken _); - } - catch (Exception ex) - { - throw new SecurityTokenException(ex.Message); - } + principal = tokenHandler.ValidateToken(refreshToken, new TokenValidationParameters + { + ValidateIssuer = true, + ValidateAudience = true, + ValidateIssuerSigningKey = true, + ValidateLifetime = true, + ValidIssuer = _configuration.GetPublicUrl().ToString(), + ValidAudience = _configuration.GetPublicUrl().ToString(), + IssuerSigningKey = key + }, out SecurityToken _); + } + catch (Exception ex) + { + throw new SecurityTokenException(ex.Message); + } - if (principal.Claims.First(x => x.Type == "type").Value != "refresh") - throw new SecurityTokenException("Invalid token type. The token should be a refresh token."); - Claim identifier = principal.Claims.First(x => x.Type == ClaimTypes.NameIdentifier); - if (int.TryParse(identifier.Value, out int id)) - return id; - throw new SecurityTokenException("Token not associated to any user."); + if (principal.Claims.First(x => x.Type == "type").Value != "refresh") + throw new SecurityTokenException("Invalid token type. The token should be a refresh token."); + Claim identifier = principal.Claims.First(x => x.Type == ClaimTypes.NameIdentifier); + if (int.TryParse(identifier.Value, out int id)) + return id; + throw new SecurityTokenException("Token not associated to any user."); + } } } diff --git a/src/Kyoo.Authentication/Extensions.cs b/src/Kyoo.Authentication/Extensions.cs index 658da84e..369128d6 100644 --- a/src/Kyoo.Authentication/Extensions.cs +++ b/src/Kyoo.Authentication/Extensions.cs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; @@ -34,7 +35,8 @@ namespace Kyoo.Authentication /// The list of permissions public static ICollection GetPermissions(this ClaimsPrincipal user) { - return user.Claims.FirstOrDefault(x => x.Type == "permissions")?.Value.Split(','); + return user.Claims.FirstOrDefault(x => x.Type == "permissions")?.Value.Split(',') + ?? Array.Empty(); } } } diff --git a/src/Kyoo.Authentication/Kyoo.Authentication.csproj b/src/Kyoo.Authentication/Kyoo.Authentication.csproj index 0c3f072d..b34a7b42 100644 --- a/src/Kyoo.Authentication/Kyoo.Authentication.csproj +++ b/src/Kyoo.Authentication/Kyoo.Authentication.csproj @@ -2,6 +2,7 @@ ../Kyoo.WebLogin/ + enable diff --git a/src/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs b/src/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs deleted file mode 100644 index 8833f4cc..00000000 --- a/src/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System.ComponentModel.DataAnnotations; -using Microsoft.AspNetCore.Http; - -namespace Kyoo.Authentication.Models.DTO -{ - /// - /// A model only used on account update requests. - /// - public class AccountUpdateRequest - { - /// - /// The new email address of the user - /// - [EmailAddress(ErrorMessage = "The email is invalid.")] - public string Email { get; set; } - - /// - /// The new username of the user. - /// - [MinLength(4, ErrorMessage = "The username must have at least 4 characters")] - public string Username { get; set; } - - /// - /// The picture icon. - /// - public IFormFile Picture { get; set; } - } -} diff --git a/src/Kyoo.Authentication/Models/DTO/LoginRequest.cs b/src/Kyoo.Authentication/Models/DTO/LoginRequest.cs index 80159361..5e092fb5 100644 --- a/src/Kyoo.Authentication/Models/DTO/LoginRequest.cs +++ b/src/Kyoo.Authentication/Models/DTO/LoginRequest.cs @@ -34,13 +34,14 @@ namespace Kyoo.Authentication.Models.DTO public string Password { get; set; } /// - /// Should the user stay logged in? If true a cookie will be put. + /// Initializes a new instance of the class. /// - public bool StayLoggedIn { get; set; } - - /// - /// The return url of the login flow. - /// - public string ReturnURL { get; set; } + /// The user's username. + /// The user's password. + public LoginRequest(string username, string password) + { + Username = username; + Password = password; + } } } diff --git a/src/Kyoo.Authentication/Models/DTO/OtacRequest.cs b/src/Kyoo.Authentication/Models/DTO/OtacRequest.cs deleted file mode 100644 index c9794e81..00000000 --- a/src/Kyoo.Authentication/Models/DTO/OtacRequest.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -namespace Kyoo.Authentication.Models.DTO -{ - /// - /// A model to represent an otac request - /// - public class OtacRequest - { - /// - /// The One Time Access Code - /// - public string Otac { get; set; } - - /// - /// Should the user stay logged - /// - public bool StayLoggedIn { get; set; } - } -} diff --git a/src/Kyoo.Authentication/Models/DTO/OtacResponse.cs b/src/Kyoo.Authentication/Models/DTO/OtacResponse.cs deleted file mode 100644 index 13ff8aac..00000000 --- a/src/Kyoo.Authentication/Models/DTO/OtacResponse.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -namespace Kyoo.Authentication.Models.DTO -{ - /// - /// A one time access token - /// - public class OtacResponse - { - /// - /// The One Time Access Token that allow one to connect to an account without typing a password or without - /// any kind of verification. This is valid only one time and only for a short period of time. - /// - public string OTAC { get; set; } - - /// - /// Create a new . - /// - /// The one time access token. - public OtacResponse(string otac) - { - OTAC = otac; - } - } -} diff --git a/src/Kyoo.Authentication/Models/DTO/RegisterRequest.cs b/src/Kyoo.Authentication/Models/DTO/RegisterRequest.cs index 59cf66b1..e8e76750 100644 --- a/src/Kyoo.Authentication/Models/DTO/RegisterRequest.cs +++ b/src/Kyoo.Authentication/Models/DTO/RegisterRequest.cs @@ -44,9 +44,22 @@ namespace Kyoo.Authentication.Models.DTO /// /// The user's password. /// - [MinLength(8, ErrorMessage = "The password must have at least {1} characters")] + [MinLength(4, ErrorMessage = "The password must have at least {1} characters")] public string Password { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// The user email address. + /// The user's username. + /// The user's password. + public RegisterRequest(string email, string username, string password) + { + Email = email; + Username = username; + Password = password; + } + /// /// Convert this register request to a new class. /// diff --git a/src/Kyoo.Authentication/Models/JwtToken.cs b/src/Kyoo.Authentication/Models/JwtToken.cs index 5e885a17..c0dedc70 100644 --- a/src/Kyoo.Authentication/Models/JwtToken.cs +++ b/src/Kyoo.Authentication/Models/JwtToken.cs @@ -55,5 +55,18 @@ namespace Kyoo.Authentication [JsonProperty("expire_in")] [JsonPropertyName("expire_in")] public TimeSpan ExpireIn { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The access token used to authorize requests. + /// The refresh token to retrieve a new access token. + /// When the access token will expire. + public JwtToken(string accessToken, string refreshToken, TimeSpan expireIn) + { + AccessToken = accessToken; + RefreshToken = refreshToken; + ExpireIn = expireIn; + } } } diff --git a/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs b/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs index dc8209aa..2c2e6711 100644 --- a/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs +++ b/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs @@ -28,19 +28,24 @@ namespace Kyoo.Authentication.Models /// public const string Path = "authentication"; + /// + /// The default jwt secret. + /// + public const string DefaultSecret = "jwt-secret"; + /// /// The secret used to encrypt the jwt. /// - public string Secret { get; set; } + public string Secret { get; set; } = DefaultSecret; /// /// Options for permissions /// - public PermissionOption Permissions { get; set; } + public PermissionOption Permissions { get; set; } = new(); /// /// Root path of user's profile pictures. /// - public string ProfilePicturePath { get; set; } + public string ProfilePicturePath { get; set; } = "users/"; } } diff --git a/src/Kyoo.Authentication/Models/Options/PermissionOption.cs b/src/Kyoo.Authentication/Models/Options/PermissionOption.cs index 985a864d..5adca2de 100644 --- a/src/Kyoo.Authentication/Models/Options/PermissionOption.cs +++ b/src/Kyoo.Authentication/Models/Options/PermissionOption.cs @@ -31,11 +31,11 @@ namespace Kyoo.Authentication.Models /// /// The default permissions that will be given to a non-connected user. /// - public string[] Default { get; set; } + public string[] Default { get; set; } = new[] { "overall.read", "overall.write" }; /// /// Permissions applied to a new user. /// - public string[] NewUser { get; set; } + public string[] NewUser { get; set; } = new[] { "overall.read", "overall.write" }; } } diff --git a/src/Kyoo.Authentication/Views/AuthApi.cs b/src/Kyoo.Authentication/Views/AuthApi.cs index d6a47c01..9906fe8a 100644 --- a/src/Kyoo.Authentication/Views/AuthApi.cs +++ b/src/Kyoo.Authentication/Views/AuthApi.cs @@ -63,6 +63,16 @@ namespace Kyoo.Authentication.Views _token = token; } + /// + /// Create a new Forbidden result from an object. + /// + /// The json value to output on the response. + /// A new forbidden result with the given json object. + public static ObjectResult Forbid(object value) + { + return new ObjectResult(value) { StatusCode = StatusCodes.Status403Forbidden }; + } + /// /// Login. /// @@ -71,7 +81,7 @@ namespace Kyoo.Authentication.Views /// /// The body of the request. /// A new access and a refresh token. - /// The user and password does not match. + /// The user and password does not match. [HttpPost("login")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))] @@ -79,14 +89,13 @@ namespace Kyoo.Authentication.Views { User user = await _users.GetOrDefault(x => x.Username == request.Username); if (user == null || !BCryptNet.Verify(request.Password, user.Password)) - return BadRequest(new RequestError("The user and password does not match.")); + return Forbid(new RequestError("The user and password does not match.")); - return new JwtToken - { - AccessToken = _token.CreateAccessToken(user, out TimeSpan expireIn), - RefreshToken = await _token.CreateRefreshToken(user), - ExpireIn = expireIn - }; + return new JwtToken( + _token.CreateAccessToken(user, out TimeSpan expireIn), + await _token.CreateRefreshToken(user), + expireIn + ); } /// @@ -115,12 +124,11 @@ namespace Kyoo.Authentication.Views return Conflict(new RequestError("A user already exists with this username.")); } - return new JwtToken - { - AccessToken = _token.CreateAccessToken(user, out TimeSpan expireIn), - RefreshToken = await _token.CreateRefreshToken(user), - ExpireIn = expireIn - }; + return new JwtToken( + _token.CreateAccessToken(user, out TimeSpan expireIn), + await _token.CreateRefreshToken(user), + expireIn + ); } /// @@ -141,12 +149,11 @@ namespace Kyoo.Authentication.Views { int userId = _token.GetRefreshTokenUserID(token); User user = await _users.Get(userId); - return new JwtToken - { - AccessToken = _token.CreateAccessToken(user, out TimeSpan expireIn), - RefreshToken = await _token.CreateRefreshToken(user), - ExpireIn = expireIn - }; + return new JwtToken( + _token.CreateAccessToken(user, out TimeSpan expireIn), + await _token.CreateRefreshToken(user), + expireIn + ); } catch (ItemNotFoundException) { @@ -176,5 +183,7 @@ namespace Kyoo.Authentication.Views return Forbid(); return await _users.Get(userID); } + + // TODO: Add a put to edit the current user. } } diff --git a/src/Kyoo.Host.Generic/settings.json b/src/Kyoo.Host.Generic/settings.json index a5fcf254..778fb20a 100644 --- a/src/Kyoo.Host.Generic/settings.json +++ b/src/Kyoo.Host.Generic/settings.json @@ -61,8 +61,8 @@ "authentication": { "permissions": { - "default": ["overall.read", "overall.write", "overall.create", "overall.delete", "admin.read", "admin.write"], - "newUser": ["overall.read", "overall.write", "overall.create", "overall.delete", "admin.read", "admin.write"] + "default": ["overall.read", "overall.write"], + "newUser": ["overall.read", "overall.write"] }, "profilePicturePath": "users/", "secret": "jwt-secret" diff --git a/tests/robot/Authentication/auth.robot b/tests/robot/Authentication/auth.robot index 8ddab2da..623666bf 100644 --- a/tests/robot/Authentication/auth.robot +++ b/tests/robot/Authentication/auth.robot @@ -1,7 +1,18 @@ *** Settings *** Documentation Tests of the /auth route. ... Ensures that the user can authenticate on kyoo. -Resource ${RESOURCES}/rest.resource +Resource ../rest.resource *** Test Cases *** +BadAccount + [Documentation] Login fails if user does not exist + POST /auth/login {"username": "toto", "password": "tata"} + Output + Integer response status 403 + +Register + [Documentation] Create a new user and login in it + POST /auth/register {"username": "toto", "password": "tata", "email": "mail@kyoo.moe"} + Output + Integer response status 403 diff --git a/tests/robot/rest.resource b/tests/robot/rest.resource index 8d7f49cb..c0f31069 100644 --- a/tests/robot/rest.resource +++ b/tests/robot/rest.resource @@ -1,3 +1,4 @@ *** Settings *** -Documentation Common things to handle rest requests -Library REST +Documentation Common things to handle rest requests + +Library REST http://localhost:5000/api