diff options
author | crupest <crupest@outlook.com> | 2020-11-26 23:43:11 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-11-26 23:43:11 +0800 |
commit | c2ca954fc8bc0f12ad2ece715cb6c4a633a23119 (patch) | |
tree | e095e0583b927472d04af4e9546a7e78277a04d2 | |
parent | 43ac8b704e47e05d259f35d0a9cdb4de6c787ee5 (diff) | |
download | timeline-c2ca954fc8bc0f12ad2ece715cb6c4a633a23119.tar.gz timeline-c2ca954fc8bc0f12ad2ece715cb6c4a633a23119.tar.bz2 timeline-c2ca954fc8bc0f12ad2ece715cb6c4a633a23119.zip |
refactor: ...
-rw-r--r-- | BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs | 6 | ||||
-rw-r--r-- | BackEnd/Timeline/Controllers/TokenController.cs | 4 | ||||
-rw-r--r-- | BackEnd/Timeline/Controllers/UserController.cs | 6 | ||||
-rw-r--r-- | BackEnd/Timeline/Services/TimelinePostService.cs | 4 | ||||
-rw-r--r-- | BackEnd/Timeline/Services/TimelineService.cs | 3 | ||||
-rw-r--r-- | BackEnd/Timeline/Services/UserCredentialService.cs | 104 | ||||
-rw-r--r-- | BackEnd/Timeline/Services/UserService.cs | 68 | ||||
-rw-r--r-- | BackEnd/Timeline/Services/UserTokenManager.cs | 7 | ||||
-rw-r--r-- | BackEnd/Timeline/Startup.cs | 2 |
9 files changed, 120 insertions, 84 deletions
diff --git a/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs b/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs index 950fa974..a4cd983d 100644 --- a/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs +++ b/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs @@ -1,8 +1,4 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Timeline.Services;
+using Timeline.Services;
namespace Timeline.Tests.Services
{
diff --git a/BackEnd/Timeline/Controllers/TokenController.cs b/BackEnd/Timeline/Controllers/TokenController.cs index 8f2ca600..41ec21e6 100644 --- a/BackEnd/Timeline/Controllers/TokenController.cs +++ b/BackEnd/Timeline/Controllers/TokenController.cs @@ -22,6 +22,7 @@ namespace Timeline.Controllers [ProducesErrorResponseType(typeof(CommonResponse))]
public class TokenController : Controller
{
+ private readonly IUserCredentialService _userCredentialService;
private readonly IUserTokenManager _userTokenManager;
private readonly ILogger<TokenController> _logger;
private readonly IClock _clock;
@@ -29,8 +30,9 @@ namespace Timeline.Controllers private readonly IMapper _mapper;
/// <summary></summary>
- public TokenController(IUserTokenManager userTokenManager, ILogger<TokenController> logger, IClock clock, IMapper mapper)
+ public TokenController(IUserCredentialService userCredentialService, IUserTokenManager userTokenManager, ILogger<TokenController> logger, IClock clock, IMapper mapper)
{
+ _userCredentialService = userCredentialService;
_userTokenManager = userTokenManager;
_logger = logger;
_clock = clock;
diff --git a/BackEnd/Timeline/Controllers/UserController.cs b/BackEnd/Timeline/Controllers/UserController.cs index 8edae139..626a116f 100644 --- a/BackEnd/Timeline/Controllers/UserController.cs +++ b/BackEnd/Timeline/Controllers/UserController.cs @@ -26,15 +26,17 @@ namespace Timeline.Controllers {
private readonly ILogger<UserController> _logger;
private readonly IUserService _userService;
+ private readonly IUserCredentialService _userCredentialService;
private readonly IUserPermissionService _userPermissionService;
private readonly IUserDeleteService _userDeleteService;
private readonly IMapper _mapper;
/// <summary></summary>
- public UserController(ILogger<UserController> logger, IUserService userService, IUserPermissionService userPermissionService, IUserDeleteService userDeleteService, IMapper mapper)
+ public UserController(ILogger<UserController> logger, IUserService userService, IUserCredentialService userCredentialService, IUserPermissionService userPermissionService, IUserDeleteService userDeleteService, IMapper mapper)
{
_logger = logger;
_userService = userService;
+ _userCredentialService = userCredentialService;
_userPermissionService = userPermissionService;
_userDeleteService = userDeleteService;
_mapper = mapper;
@@ -190,7 +192,7 @@ namespace Timeline.Controllers {
try
{
- await _userService.ChangePassword(this.GetUserId(), request.OldPassword, request.NewPassword);
+ await _userCredentialService.ChangePassword(this.GetUserId(), request.OldPassword, request.NewPassword);
return Ok();
}
catch (BadPasswordException e)
diff --git a/BackEnd/Timeline/Services/TimelinePostService.cs b/BackEnd/Timeline/Services/TimelinePostService.cs index 36fcdbca..a1176a68 100644 --- a/BackEnd/Timeline/Services/TimelinePostService.cs +++ b/BackEnd/Timeline/Services/TimelinePostService.cs @@ -1,4 +1,6 @@ using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using SixLabors.ImageSharp;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -8,9 +10,7 @@ using Timeline.Entities; using Timeline.Helpers;
using Timeline.Models;
using Timeline.Services.Exceptions;
-using SixLabors.ImageSharp;
using static Timeline.Resources.Services.TimelineService;
-using Microsoft.Extensions.Logging;
namespace Timeline.Services
{
diff --git a/BackEnd/Timeline/Services/TimelineService.cs b/BackEnd/Timeline/Services/TimelineService.cs index f943f8b4..b8ec354a 100644 --- a/BackEnd/Timeline/Services/TimelineService.cs +++ b/BackEnd/Timeline/Services/TimelineService.cs @@ -1,13 +1,10 @@ using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Logging;
-using SixLabors.ImageSharp;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
-using Timeline.Helpers;
using Timeline.Models;
using Timeline.Models.Validation;
using Timeline.Services.Exceptions;
diff --git a/BackEnd/Timeline/Services/UserCredentialService.cs b/BackEnd/Timeline/Services/UserCredentialService.cs new file mode 100644 index 00000000..e5c3581b --- /dev/null +++ b/BackEnd/Timeline/Services/UserCredentialService.cs @@ -0,0 +1,104 @@ +using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Timeline.Entities;
+using Timeline.Helpers;
+using Timeline.Models;
+using Timeline.Models.Validation;
+using Timeline.Services.Exceptions;
+
+namespace Timeline.Services
+{
+ public interface IUserCredentialService
+ {
+ /// <summary>
+ /// Try to verify the given username and password.
+ /// </summary>
+ /// <param name="username">The username of the user to verify.</param>
+ /// <param name="password">The password of the user to verify.</param>
+ /// <returns>User id.</returns>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="username"/> or <paramref name="password"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="username"/> is of bad format or <paramref name="password"/> is empty.</exception>
+ /// <exception cref="UserNotExistException">Thrown when the user with given username does not exist.</exception>
+ /// <exception cref="BadPasswordException">Thrown when password is wrong.</exception>
+ Task<long> VerifyCredential(string username, string password);
+
+ /// <summary>
+ /// Try to change a user's password with old password.
+ /// </summary>
+ /// <param name="id">The id of user to change password of.</param>
+ /// <param name="oldPassword">Old password.</param>
+ /// <param name="newPassword">New password.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="oldPassword"/> or <paramref name="newPassword"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown if <paramref name="oldPassword"/> or <paramref name="newPassword"/> is empty.</exception>
+ /// <exception cref="UserNotExistException">Thrown if the user with given username does not exist.</exception>
+ /// <exception cref="BadPasswordException">Thrown if the old password is wrong.</exception>
+ Task ChangePassword(long id, string oldPassword, string newPassword);
+ }
+
+ public class UserCredentialService : IUserCredentialService
+ {
+ private readonly ILogger<UserCredentialService> _logger;
+ private readonly DatabaseContext _database;
+ private readonly IPasswordService _passwordService;
+
+ private readonly UsernameValidator _usernameValidator = new UsernameValidator();
+
+ public UserCredentialService(ILogger<UserCredentialService> logger, DatabaseContext database, IPasswordService passwordService)
+ {
+ _logger = logger;
+ _database = database;
+ _passwordService = passwordService;
+ }
+
+ public async Task<long> VerifyCredential(string username, string password)
+ {
+ if (username == null)
+ throw new ArgumentNullException(nameof(username));
+ if (password == null)
+ throw new ArgumentNullException(nameof(password));
+ if (!_usernameValidator.Validate(username, out var message))
+ throw new ArgumentException(message);
+ if (password.Length == 0)
+ throw new ArgumentException("Password can't be empty.");
+
+ var entity = await _database.Users.Where(u => u.Username == username).Select(u => new { u.Id, u.Password }).SingleOrDefaultAsync();
+
+ if (entity == null)
+ throw new UserNotExistException(username);
+
+ if (!_passwordService.VerifyPassword(entity.Password, password))
+ throw new BadPasswordException(password);
+
+ return entity.Id;
+ }
+
+ public async Task ChangePassword(long id, string oldPassword, string newPassword)
+ {
+ if (oldPassword == null)
+ throw new ArgumentNullException(nameof(oldPassword));
+ if (newPassword == null)
+ throw new ArgumentNullException(nameof(newPassword));
+ if (oldPassword.Length == 0)
+ throw new ArgumentException("Old password can't be empty.");
+ if (newPassword.Length == 0)
+ throw new ArgumentException("New password can't be empty.");
+
+ var entity = await _database.Users.Where(u => u.Id == id).SingleOrDefaultAsync();
+
+ if (entity == null)
+ throw new UserNotExistException(id);
+
+ if (!_passwordService.VerifyPassword(entity.Password, oldPassword))
+ throw new BadPasswordException(oldPassword);
+
+ entity.Password = _passwordService.HashPassword(newPassword);
+ entity.Version += 1;
+ await _database.SaveChangesAsync();
+ _logger.LogInformation(Log.Format(Resources.Services.UserService.LogDatabaseUpdate, ("Id", id), ("Operation", "Change password")));
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/UserService.cs b/BackEnd/Timeline/Services/UserService.cs index cded3ff1..9395cc52 100644 --- a/BackEnd/Timeline/Services/UserService.cs +++ b/BackEnd/Timeline/Services/UserService.cs @@ -27,19 +27,6 @@ namespace Timeline.Services public interface IUserService : IBasicUserService
{
/// <summary>
- /// Try to verify the given username and password.
- /// </summary>
- /// <param name="username">The username of the user to verify.</param>
- /// <param name="password">The password of the user to verify.</param>
- /// <returns>The user info and auth info.</returns>
- /// <exception cref="ArgumentNullException">Thrown when <paramref name="username"/> or <paramref name="password"/> is null.</exception>
- /// <exception cref="ArgumentException">Thrown when <paramref name="username"/> is of bad format or <paramref name="password"/> is empty.</exception>
- /// <exception cref="UserNotExistException">Thrown when the user with given username does not exist.</exception>
- /// <exception cref="BadPasswordException">Thrown when password is wrong.</exception>
- Task<User> VerifyCredential(string username, string password);
-
-
- /// <summary>
/// Try to get a user by id.
/// </summary>
/// <param name="id">The id of the user.</param>
@@ -47,7 +34,6 @@ namespace Timeline.Services /// <exception cref="UserNotExistException">Thrown when the user with given id does not exist.</exception>
Task<User> GetUser(long id);
-
/// <summary>
/// List all users.
/// </summary>
@@ -77,18 +63,6 @@ namespace Timeline.Services /// Version will increase if password is changed.
/// </remarks>
Task<User> ModifyUser(long id, ModifyUserParams? param);
-
- /// <summary>
- /// Try to change a user's password with old password.
- /// </summary>
- /// <param name="id">The id of user to change password of.</param>
- /// <param name="oldPassword">Old password.</param>
- /// <param name="newPassword">New password.</param>
- /// <exception cref="ArgumentNullException">Thrown if <paramref name="oldPassword"/> or <paramref name="newPassword"/> is null.</exception>
- /// <exception cref="ArgumentException">Thrown if <paramref name="oldPassword"/> or <paramref name="newPassword"/> is empty.</exception>
- /// <exception cref="UserNotExistException">Thrown if the user with given username does not exist.</exception>
- /// <exception cref="BadPasswordException">Thrown if the old password is wrong.</exception>
- Task ChangePassword(long id, string oldPassword, string newPassword);
}
public class UserService : BasicUserService, IUserService
@@ -159,26 +133,7 @@ namespace Timeline.Services };
}
- public async Task<User> VerifyCredential(string username, string password)
- {
- if (username == null)
- throw new ArgumentNullException(nameof(username));
- if (password == null)
- throw new ArgumentNullException(nameof(password));
-
- CheckUsernameFormat(username, nameof(username));
- CheckPasswordFormat(password, nameof(password));
-
- var entity = await _databaseContext.Users.Where(u => u.Username == username).SingleOrDefaultAsync();
-
- if (entity == null)
- throw new UserNotExistException(username);
- if (!_passwordService.VerifyPassword(entity.Password, password))
- throw new BadPasswordException(password);
-
- return await CreateUserFromEntity(entity);
- }
public async Task<User> GetUser(long id)
{
@@ -288,28 +243,5 @@ namespace Timeline.Services return await CreateUserFromEntity(entity);
}
-
- public async Task ChangePassword(long id, string oldPassword, string newPassword)
- {
- if (oldPassword == null)
- throw new ArgumentNullException(nameof(oldPassword));
- if (newPassword == null)
- throw new ArgumentNullException(nameof(newPassword));
- CheckPasswordFormat(oldPassword, nameof(oldPassword));
- CheckPasswordFormat(newPassword, nameof(newPassword));
-
- var entity = await _databaseContext.Users.Where(u => u.Id == id).SingleOrDefaultAsync();
-
- if (entity == null)
- throw new UserNotExistException(id);
-
- if (!_passwordService.VerifyPassword(entity.Password, oldPassword))
- throw new BadPasswordException(oldPassword);
-
- entity.Password = _passwordService.HashPassword(newPassword);
- entity.Version += 1;
- await _databaseContext.SaveChangesAsync();
- _logger.LogInformation(Log.Format(LogDatabaseUpdate, ("Id", id), ("Operation", "Change password")));
- }
}
}
diff --git a/BackEnd/Timeline/Services/UserTokenManager.cs b/BackEnd/Timeline/Services/UserTokenManager.cs index 09ecd19c..831329e6 100644 --- a/BackEnd/Timeline/Services/UserTokenManager.cs +++ b/BackEnd/Timeline/Services/UserTokenManager.cs @@ -45,13 +45,15 @@ namespace Timeline.Services {
private readonly ILogger<UserTokenManager> _logger;
private readonly IUserService _userService;
+ private readonly IUserCredentialService _userCredentialService;
private readonly IUserTokenService _userTokenService;
private readonly IClock _clock;
- public UserTokenManager(ILogger<UserTokenManager> logger, IUserService userService, IUserTokenService userTokenService, IClock clock)
+ public UserTokenManager(ILogger<UserTokenManager> logger, IUserService userService, IUserCredentialService userCredentialService, IUserTokenService userTokenService, IClock clock)
{
_logger = logger;
_userService = userService;
+ _userCredentialService = userCredentialService;
_userTokenService = userTokenService;
_clock = clock;
}
@@ -65,7 +67,8 @@ namespace Timeline.Services if (password == null)
throw new ArgumentNullException(nameof(password));
- var user = await _userService.VerifyCredential(username, password);
+ var userId = await _userCredentialService.VerifyCredential(username, password);
+ var user = await _userService.GetUser(userId);
var token = _userTokenService.GenerateToken(new UserTokenInfo { Id = user.Id, Version = user.Version, ExpireAt = expireAt });
return new UserTokenCreateResult { Token = token, User = user };
diff --git a/BackEnd/Timeline/Startup.cs b/BackEnd/Timeline/Startup.cs index 63e2a0dd..bf34f9e2 100644 --- a/BackEnd/Timeline/Startup.cs +++ b/BackEnd/Timeline/Startup.cs @@ -90,6 +90,7 @@ namespace Timeline services.AddTransient<IPasswordService, PasswordService>();
services.AddScoped<IBasicUserService, BasicUserService>();
services.AddScoped<IUserService, UserService>();
+ services.AddScoped<IUserCredentialService, UserCredentialService>();
services.AddScoped<IUserDeleteService, UserDeleteService>();
services.AddScoped<IUserTokenService, JwtUserTokenService>();
services.AddScoped<IUserTokenManager, UserTokenManager>();
@@ -100,7 +101,6 @@ namespace Timeline services.AddScoped<ITimelineService, TimelineService>();
services.AddScoped<ITimelinePostService, TimelinePostService>();
-
services.AddDbContext<DatabaseContext>((services, options) =>
{
var pathProvider = services.GetRequiredService<IPathProvider>();
|