aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author杨宇千 <crupest@outlook.com>2019-08-04 15:46:31 +0800
committer杨宇千 <crupest@outlook.com>2019-08-04 15:46:31 +0800
commit36da221444807742a9e26f2ba636d9c6aef6155f (patch)
treedeace7e60ff91362572bf178004f3928175a340e
parenta17aa8770b0b4861849c6e01812b2ff686497f02 (diff)
downloadtimeline-36da221444807742a9e26f2ba636d9c6aef6155f.tar.gz
timeline-36da221444807742a9e26f2ba636d9c6aef6155f.tar.bz2
timeline-36da221444807742a9e26f2ba636d9c6aef6155f.zip
Continue to add unit tests for token. Fix a bug thanks to unit test.
-rw-r--r--Timeline.Tests/Helpers/TestClock.cs25
-rw-r--r--Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs6
-rw-r--r--Timeline.Tests/TokenUnitTest.cs58
-rw-r--r--Timeline/Controllers/TokenController.cs2
-rw-r--r--Timeline/Services/UserService.cs23
5 files changed, 92 insertions, 22 deletions
diff --git a/Timeline.Tests/Helpers/TestClock.cs b/Timeline.Tests/Helpers/TestClock.cs
new file mode 100644
index 00000000..fc200be9
--- /dev/null
+++ b/Timeline.Tests/Helpers/TestClock.cs
@@ -0,0 +1,25 @@
+using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using Timeline.Services;
+
+namespace Timeline.Tests.Helpers
+{
+ public class TestClock : IClock
+ {
+ DateTime? MockCurrentTime { get; set; } = null;
+
+ public DateTime GetCurrentTime()
+ {
+ return MockCurrentTime.GetValueOrDefault(DateTime.Now);
+ }
+ }
+
+ public static class TestClockWebApplicationFactoryExtensions
+ {
+ public static TestClock GetTestClock<T>(this WebApplicationFactory<T> factory) where T : class
+ {
+ return factory.Server.Host.Services.GetRequiredService<IClock>() as TestClock;
+ }
+ }
+}
diff --git a/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs b/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs
index a7616b41..aa005ba3 100644
--- a/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs
+++ b/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs
@@ -1,9 +1,11 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.AspNetCore.TestHost;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Timeline.Models;
+using Timeline.Services;
using Xunit.Abstractions;
namespace Timeline.Tests.Helpers
@@ -46,6 +48,10 @@ namespace Timeline.Tests.Helpers
db.Users.AddRange(TestMockUsers.MockUsers);
db.SaveChanges();
}
+ })
+ .ConfigureTestServices(services =>
+ {
+ services.AddSingleton<IClock, TestClock>();
});
});
}
diff --git a/Timeline.Tests/TokenUnitTest.cs b/Timeline.Tests/TokenUnitTest.cs
index 27c2ed32..d7df8797 100644
--- a/Timeline.Tests/TokenUnitTest.cs
+++ b/Timeline.Tests/TokenUnitTest.cs
@@ -1,10 +1,14 @@
using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System.Linq;
using System.Net;
using System.Net.Http;
using Timeline.Controllers;
+using Timeline.Entities;
using Timeline.Entities.Http;
+using Timeline.Models;
+using Timeline.Services;
using Timeline.Tests.Helpers;
using Timeline.Tests.Helpers.Authentication;
using Xunit;
@@ -80,23 +84,63 @@ namespace Timeline.Tests
{
var response = await client.PostAsJsonAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = "bad token hahaha" });
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+ var body = await response.ReadBodyAsJson<CommonResponse>();
+ Assert.Equal(TokenController.ErrorCodes.Verify_BadToken, body.Code);
}
}
[Fact]
- public async void VerifyTokenTest_GoodToken()
+ public async void VerifyTokenTest_BadVersion_AND_UserNotExist()
{
using (var client = _factory.CreateDefaultClient())
{
- var createTokenResult = await client.CreateUserTokenAsync("admin", "admin");
+ using (var scope = _factory.Server.Host.Services.CreateScope()) // UserService is scoped.
+ {
+ // create a user for test
+ var userService = scope.ServiceProvider.GetRequiredService<IUserService>();
+
+ const string username = "verifytokentest0";
+ const string password = "12345678";
+
+ await userService.PutUser(username, password, false);
+
+ // create a token
+ var token = (await client.CreateUserTokenAsync(username, password)).Token;
+ // increase version
+ await userService.PatchUser(username, null, null);
+
+ // test against bad version
+ var response = await client.PostAsJsonAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = token });
+ Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+ var body = await response.ReadBodyAsJson<CommonResponse>();
+ Assert.Equal(TokenController.ErrorCodes.Verify_BadVersion, body.Code);
+
+ // create another token
+ var token2 = (await client.CreateUserTokenAsync(username, password)).Token;
+
+ // delete user
+ await userService.DeleteUser(username);
+
+ // test against user not exist
+ var response2 = await client.PostAsJsonAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = token });
+ Assert.Equal(HttpStatusCode.BadRequest, response2.StatusCode);
+ var body2 = await response2.ReadBodyAsJson<CommonResponse>();
+ Assert.Equal(TokenController.ErrorCodes.Verify_UserNotExist, body2.Code);
+ }
+ }
+ }
+
+ [Fact]
+ public async void VerifyTokenTest_Success()
+ {
+ using (var client = _factory.CreateDefaultClient())
+ {
+ var createTokenResult = await client.CreateUserTokenAsync("admin", "admin");
var response = await client.PostAsJsonAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = createTokenResult.Token });
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- var result = JsonConvert.DeserializeObject<VerifyTokenResponse>(await response.Content.ReadAsStringAsync());
- Assert.NotNull(result.User);
- Assert.Equal(createTokenResult.User.Username, result.User.Username);
- Assert.Equal(createTokenResult.User.Administrator, result.User.Administrator);
+ var body = JsonConvert.DeserializeObject<VerifyTokenResponse>(await response.Content.ReadAsStringAsync());
+ Assert.Equal(TestMockUsers.MockUserInfos.Where(u => u.Username == "user").Single(), body.User, UserInfoComparers.EqualityComparer);
}
}
}
diff --git a/Timeline/Controllers/TokenController.cs b/Timeline/Controllers/TokenController.cs
index 66cf3dad..21f87ded 100644
--- a/Timeline/Controllers/TokenController.cs
+++ b/Timeline/Controllers/TokenController.cs
@@ -119,7 +119,7 @@ namespace Timeline.Controllers
}
catch (BadTokenVersionException e)
{
- var code = ErrorCodes.Verify_BadToken;
+ var code = ErrorCodes.Verify_BadVersion;
_logger.LogInformation(LoggingEventIds.VerifyFailed, e, "Attemp to verify a bad token because version is old. Code: {} Token: {}.", code, request.Token);
return BadRequest(new CommonResponse(code, "The token is expired. Try recreate a token."));
}
diff --git a/Timeline/Services/UserService.cs b/Timeline/Services/UserService.cs
index 328dbff0..65ac98d3 100644
--- a/Timeline/Services/UserService.cs
+++ b/Timeline/Services/UserService.cs
@@ -19,7 +19,7 @@ namespace Timeline.Services
[Serializable]
public class UserNotExistException : Exception
{
- public UserNotExistException(): base("The user does not exist.") { }
+ public UserNotExistException() : base("The user does not exist.") { }
public UserNotExistException(string message) : base(message) { }
public UserNotExistException(string message, Exception inner) : base(message, inner) { }
protected UserNotExistException(
@@ -30,7 +30,7 @@ namespace Timeline.Services
[Serializable]
public class BadPasswordException : Exception
{
- public BadPasswordException(): base("Password is wrong.") { }
+ public BadPasswordException() : base("Password is wrong.") { }
public BadPasswordException(string message) : base(message) { }
public BadPasswordException(string message, Exception inner) : base(message, inner) { }
protected BadPasswordException(
@@ -42,7 +42,7 @@ namespace Timeline.Services
[Serializable]
public class BadTokenVersionException : Exception
{
- public BadTokenVersionException(): base("Token version is expired.") { }
+ public BadTokenVersionException() : base("Token version is expired.") { }
public BadTokenVersionException(string message) : base(message) { }
public BadTokenVersionException(string message, Exception inner) : base(message, inner) { }
protected BadTokenVersionException(
@@ -105,6 +105,8 @@ namespace Timeline.Services
/// <summary>
/// Partially modify a user of given username.
+ ///
+ /// Note that whether actually modified or not, Version of the user will always increase.
/// </summary>
/// <param name="username">Username of the user to modify. Can't be null.</param>
/// <param name="password">New password. Null if not modify.</param>
@@ -309,27 +311,20 @@ namespace Timeline.Services
if (user == null)
throw new UserNotExistException();
- bool modified = false;
-
if (password != null)
{
- modified = true;
user.EncryptedPassword = _passwordService.HashPassword(password);
}
if (administrator != null)
{
- modified = true;
user.RoleString = IsAdminToRoleString(administrator.Value);
}
- if (modified)
- {
- user.Version += 1;
- await _databaseContext.SaveChangesAsync();
- //clear cache
- RemoveCache(user.Id);
- }
+ user.Version += 1;
+ await _databaseContext.SaveChangesAsync();
+ //clear cache
+ RemoveCache(user.Id);
}
public async Task DeleteUser(string username)