From def8e8dd78812c019a0d6e8e5a3e2de4e82ae3e4 Mon Sep 17 00:00:00 2001 From: 杨宇千 Date: Thu, 17 Oct 2019 20:46:57 +0800 Subject: ... --- Timeline/Models/Http/Token.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Timeline/Models/Http/Token.cs') diff --git a/Timeline/Models/Http/Token.cs b/Timeline/Models/Http/Token.cs index 68a66d0a..615b6d8a 100644 --- a/Timeline/Models/Http/Token.cs +++ b/Timeline/Models/Http/Token.cs @@ -10,7 +10,7 @@ namespace Timeline.Models.Http public string Password { get; set; } // in days, optional [Range(1, 365)] - public int? ExpireOffset { get; set; } + public int? Expire { get; set; } } public class CreateTokenResponse -- cgit v1.2.3 From b00cfa30a4f6a1c6d896d46da7dd063abf632cd3 Mon Sep 17 00:00:00 2001 From: 杨宇千 Date: Sat, 19 Oct 2019 21:37:15 +0800 Subject: ... --- Timeline.Tests/Controllers/TokenControllerTest.cs | 21 ++++++++++ Timeline.Tests/Timeline.Tests.csproj | 49 ++++++++++++----------- Timeline/Controllers/TokenController.cs | 6 +-- Timeline/Entities/DatabaseContext.cs | 10 ++--- Timeline/Entities/UserAvatar.cs | 6 +-- Timeline/Entities/UserDetail.cs | 10 ++--- Timeline/Helpers/InvalidModelResponseFactory.cs | 1 + Timeline/Helpers/Log.cs | 2 +- Timeline/Models/Http/Common.cs | 4 +- Timeline/Models/Http/Token.cs | 12 +++--- Timeline/Models/Http/User.cs | 12 +++--- Timeline/Models/UserDetail.cs | 12 +++--- Timeline/Services/JwtService.cs | 8 +++- Timeline/Startup.cs | 2 + Timeline/Timeline.csproj | 7 +++- 15 files changed, 99 insertions(+), 63 deletions(-) (limited to 'Timeline/Models/Http/Token.cs') diff --git a/Timeline.Tests/Controllers/TokenControllerTest.cs b/Timeline.Tests/Controllers/TokenControllerTest.cs index 60ba75dc..8b1cf071 100644 --- a/Timeline.Tests/Controllers/TokenControllerTest.cs +++ b/Timeline.Tests/Controllers/TokenControllerTest.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging.Abstractions; using Moq; using System; +using System.Collections.Generic; using System.Threading.Tasks; using Timeline.Controllers; using Timeline.Models.Http; @@ -90,6 +91,26 @@ namespace Timeline.Tests.Controllers .Which.User.Should().BeEquivalentTo(MockUser.User.Info); } + public static IEnumerable Verify_BadRequest_Data() + { + yield return new object[] { new JwtTokenVerifyException(JwtTokenVerifyException.ErrorCodes.Expired), Verify.Expired }; + yield return new object[] { new JwtTokenVerifyException(JwtTokenVerifyException.ErrorCodes.IdClaimBadFormat), Verify.BadFormat }; + yield return new object[] { new BadTokenVersionException(), Verify.OldVersion }; + yield return new object[] { new UserNotExistException(), Verify.UserNotExist }; + } + + [Theory] + [MemberData(nameof(Verify_BadRequest_Data))] + public async Task Verify_BadRequest(Exception e, int code) + { + const string token = "aaaaaaaaaaaaaa"; + _mockUserService.Setup(s => s.VerifyToken(token)).ThrowsAsync(e); + var action = await _controller.Verify(new VerifyTokenRequest { Token = token }); + action.Should().BeAssignableTo() + .Which.Value.Should().BeAssignableTo() + .Which.Code.Should().Be(code); + } + // TODO! Verify unit tests } } diff --git a/Timeline.Tests/Timeline.Tests.csproj b/Timeline.Tests/Timeline.Tests.csproj index 36bc03bc..3f88f174 100644 --- a/Timeline.Tests/Timeline.Tests.csproj +++ b/Timeline.Tests/Timeline.Tests.csproj @@ -1,28 +1,31 @@  - - netcoreapp3.0 - + + netcoreapp3.0 - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - + 8.0 + enable + - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + diff --git a/Timeline/Controllers/TokenController.cs b/Timeline/Controllers/TokenController.cs index 2e661695..ce5786ca 100644 --- a/Timeline/Controllers/TokenController.cs +++ b/Timeline/Controllers/TokenController.cs @@ -54,7 +54,7 @@ namespace Timeline.Controllers [AllowAnonymous] public async Task Create([FromBody] CreateTokenRequest request) { - void LogFailure(string reason, Exception e = null) + void LogFailure(string reason, Exception? e = null) { _logger.LogInformation(e, Log.Format("Attemp to login failed.", ("Reason", reason), @@ -100,7 +100,7 @@ namespace Timeline.Controllers [AllowAnonymous] public async Task Verify([FromBody] VerifyTokenRequest request) { - void LogFailure(string reason, Exception e = null, params (string, object)[] otherProperties) + void LogFailure(string reason, Exception? e = null, params (string, object?)[] otherProperties) { var properties = new (string, object)[2 + otherProperties.Length]; properties[0] = ("Reason", reason); @@ -125,7 +125,7 @@ namespace Timeline.Controllers { const string message = "Token is expired."; var innerException = e.InnerException as SecurityTokenExpiredException; - LogFailure(message, e, ("Expires", innerException.Expires), ("Current Time", _clock.GetCurrentTime())); + LogFailure(message, e, ("Expires", innerException?.Expires), ("Current Time", _clock.GetCurrentTime())); return BadRequest(new CommonResponse(ErrorCodes.Http.Token.Verify.Expired, message)); } else diff --git a/Timeline/Entities/DatabaseContext.cs b/Timeline/Entities/DatabaseContext.cs index d9815660..550db216 100644 --- a/Timeline/Entities/DatabaseContext.cs +++ b/Timeline/Entities/DatabaseContext.cs @@ -17,20 +17,20 @@ namespace Timeline.Entities public long Id { get; set; } [Column("name"), MaxLength(26), Required] - public string Name { get; set; } + public string Name { get; set; } = default!; [Column("password"), Required] - public string EncryptedPassword { get; set; } + public string EncryptedPassword { get; set; } = default!; [Column("roles"), Required] - public string RoleString { get; set; } + public string RoleString { get; set; } = default!; [Column("version"), Required] public long Version { get; set; } - public UserAvatar Avatar { get; set; } + public UserAvatar? Avatar { get; set; } - public UserDetailEntity Detail { get; set; } + public UserDetailEntity? Detail { get; set; } } public class DatabaseContext : DbContext diff --git a/Timeline/Entities/UserAvatar.cs b/Timeline/Entities/UserAvatar.cs index d549aea5..d47bb28b 100644 --- a/Timeline/Entities/UserAvatar.cs +++ b/Timeline/Entities/UserAvatar.cs @@ -11,13 +11,13 @@ namespace Timeline.Entities public long Id { get; set; } [Column("data")] - public byte[] Data { get; set; } + public byte[]? Data { get; set; } [Column("type")] - public string Type { get; set; } + public string? Type { get; set; } [Column("etag"), MaxLength(30)] - public string ETag { get; set; } + public string? ETag { get; set; } [Column("last_modified"), Required] public DateTime LastModified { get; set; } diff --git a/Timeline/Entities/UserDetail.cs b/Timeline/Entities/UserDetail.cs index bc14dbe6..e02d15c4 100644 --- a/Timeline/Entities/UserDetail.cs +++ b/Timeline/Entities/UserDetail.cs @@ -10,19 +10,19 @@ namespace Timeline.Entities public long Id { get; set; } [Column("nickname"), MaxLength(15)] - public string Nickname { get; set; } + public string? Nickname { get; set; } [Column("qq"), MaxLength(15)] - public string QQ { get; set; } + public string? QQ { get; set; } [Column("email"), MaxLength(50)] - public string Email { get; set; } + public string? Email { get; set; } [Column("phone_number"), MaxLength(15)] - public string PhoneNumber { get; set; } + public string? PhoneNumber { get; set; } [Column("description")] - public string Description { get; set; } + public string? Description { get; set; } public long UserId { get; set; } } diff --git a/Timeline/Helpers/InvalidModelResponseFactory.cs b/Timeline/Helpers/InvalidModelResponseFactory.cs index c792e845..643c99ac 100644 --- a/Timeline/Helpers/InvalidModelResponseFactory.cs +++ b/Timeline/Helpers/InvalidModelResponseFactory.cs @@ -6,6 +6,7 @@ namespace Timeline.Helpers { public static class InvalidModelResponseFactory { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods")] public static IActionResult Factory(ActionContext context) { var modelState = context.ModelState; diff --git a/Timeline/Helpers/Log.cs b/Timeline/Helpers/Log.cs index 64391cd1..8deebf1d 100644 --- a/Timeline/Helpers/Log.cs +++ b/Timeline/Helpers/Log.cs @@ -25,7 +25,7 @@ namespace Timeline.Helpers public static class Log { - public static string Format(string summary, params (string, object)[] properties) + public static string Format(string summary, params (string, object?)[] properties) { var builder = new StringBuilder(); builder.Append(summary); diff --git a/Timeline/Models/Http/Common.cs b/Timeline/Models/Http/Common.cs index 83e6a072..6f6dbc1e 100644 --- a/Timeline/Models/Http/Common.cs +++ b/Timeline/Models/Http/Common.cs @@ -38,8 +38,8 @@ namespace Timeline.Models.Http Message = message; } - public int? Code { get; set; } - public string Message { get; set; } + public int Code { get; set; } + public string? Message { get; set; } } public class CommonDataResponse : CommonResponse diff --git a/Timeline/Models/Http/Token.cs b/Timeline/Models/Http/Token.cs index 615b6d8a..ea8b59ed 100644 --- a/Timeline/Models/Http/Token.cs +++ b/Timeline/Models/Http/Token.cs @@ -5,9 +5,9 @@ namespace Timeline.Models.Http public class CreateTokenRequest { [Required] - public string Username { get; set; } + public string Username { get; set; } = default!; [Required] - public string Password { get; set; } + public string Password { get; set; } = default!; // in days, optional [Range(1, 365)] public int? Expire { get; set; } @@ -15,18 +15,18 @@ namespace Timeline.Models.Http public class CreateTokenResponse { - public string Token { get; set; } - public UserInfo User { get; set; } + public string Token { get; set; } = default!; + public UserInfo User { get; set; } = default!; } public class VerifyTokenRequest { [Required] - public string Token { get; set; } + public string Token { get; set; } = default!; } public class VerifyTokenResponse { - public UserInfo User { get; set; } + public UserInfo User { get; set; } = default!; } } diff --git a/Timeline/Models/Http/User.cs b/Timeline/Models/Http/User.cs index 4308a19c..98406fec 100644 --- a/Timeline/Models/Http/User.cs +++ b/Timeline/Models/Http/User.cs @@ -6,31 +6,31 @@ namespace Timeline.Models.Http public class UserPutRequest { [Required] - public string Password { get; set; } + public string Password { get; set; } = default!; [Required] public bool? Administrator { get; set; } } public class UserPatchRequest { - public string Password { get; set; } + public string? Password { get; set; } public bool? Administrator { get; set; } } public class ChangeUsernameRequest { [Required] - public string OldUsername { get; set; } + public string OldUsername { get; set; } = default!; [Required, ValidateWith(typeof(UsernameValidator))] - public string NewUsername { get; set; } + public string NewUsername { get; set; } = default!; } public class ChangePasswordRequest { [Required] - public string OldPassword { get; set; } + public string OldPassword { get; set; } = default!; [Required] - public string NewPassword { get; set; } + public string NewPassword { get; set; } = default!; } } diff --git a/Timeline/Models/UserDetail.cs b/Timeline/Models/UserDetail.cs index 1a6c0c6a..302e3bb1 100644 --- a/Timeline/Models/UserDetail.cs +++ b/Timeline/Models/UserDetail.cs @@ -8,21 +8,21 @@ namespace Timeline.Models public class UserDetail { [MaxLength(10)] - public string Nickname { get; set; } + public string? Nickname { get; set; } [ValidateWith(typeof(UserDetailValidators.QQValidator))] [JsonProperty(PropertyName = "qq")] - public string QQ { get; set; } + public string? QQ { get; set; } [ValidateWith(typeof(UserDetailValidators.EMailValidator))] - public string Email { get; set; } + public string? Email { get; set; } [ValidateWith(typeof(UserDetailValidators.PhoneNumberValidator))] - public string PhoneNumber { get; set; } + public string? PhoneNumber { get; set; } - public string Description { get; set; } + public string? Description { get; set; } - private static string CoerceEmptyToNull(string value) + private static string? CoerceEmptyToNull(string? value) { if (string.IsNullOrEmpty(value)) return null; diff --git a/Timeline/Services/JwtService.cs b/Timeline/Services/JwtService.cs index 350c5e80..90d0c217 100644 --- a/Timeline/Services/JwtService.cs +++ b/Timeline/Services/JwtService.cs @@ -33,6 +33,12 @@ namespace Timeline.Services public const int Expired = -2001; } + private const string message = "Jwt token is bad."; + + public JwtTokenVerifyException() : base(message) { } + public JwtTokenVerifyException(string message) : base(message) { } + public JwtTokenVerifyException(string message, Exception inner) : base(message, inner) { } + public JwtTokenVerifyException(int code) : base(GetErrorMessage(code)) { ErrorCode = code; } public JwtTokenVerifyException(string message, int code) : base(message) { ErrorCode = code; } public JwtTokenVerifyException(Exception inner, int code) : base(GetErrorMessage(code), inner) { ErrorCode = code; } @@ -41,7 +47,7 @@ namespace Timeline.Services System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } - public int ErrorCode { get; private set; } + public int ErrorCode { get; set; } private static string GetErrorMessage(int errorCode) { diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index fc570fdd..ddbe0840 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -13,6 +13,7 @@ using Timeline.Services; namespace Timeline { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static")] public class Startup { public Startup(IConfiguration configuration, IWebHostEnvironment environment) @@ -69,6 +70,7 @@ namespace Timeline services.AddMemoryCache(); } + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index 836dfb47..c634563a 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -4,6 +4,9 @@ false 1f6fb74d-4277-4bc0-aeea-b1fc5ffb0b43 crupest + + 8.0 + enable @@ -15,8 +18,8 @@ - all - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive -- cgit v1.2.3