From 401a5b74696c471e5168e421e3de0db1e5f946a8 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 12 Apr 2019 23:34:40 +0800 Subject: Add database connection. --- Timeline/Services/UserService.cs | 115 +++++++++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 10 deletions(-) (limited to 'Timeline/Services/UserService.cs') diff --git a/Timeline/Services/UserService.cs b/Timeline/Services/UserService.cs index 1da6922d..ad36c37b 100644 --- a/Timeline/Services/UserService.cs +++ b/Timeline/Services/UserService.cs @@ -1,31 +1,126 @@ -using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using System.Linq; +using System.Threading.Tasks; using Timeline.Entities; +using Timeline.Models; namespace Timeline.Services { + public class CreateTokenResult + { + public string Token { get; set; } + public UserInfo UserInfo { get; set; } + } + + public enum CreateUserResult + { + Success, + AlreadyExists + } + public interface IUserService { /// /// Try to anthenticate with the given username and password. + /// If success, create a token and return the user info. /// /// The username of the user to be anthenticated. /// The password of the user to be anthenticated. - /// null if anthentication failed. - /// An instance of if anthentication succeeded. - User Authenticate(string username, string password); + /// Return null if anthentication failed. An containing the created token and user info if anthentication succeeded. + Task CreateToken(string username, string password); + + /// + /// Verify the given token. + /// If success, return the user info. + /// + /// The token to verify. + /// Return null if verification failed. The user info if verification succeeded. + Task VerifyToken(string token); + + Task CreateUser(string username, string password, string[] roles); } public class UserService : IUserService { - private readonly IList _users = new List{ - new User { Id = 0, Username = "admin", Password = "admin", Roles = new string[] { "User", "Admin" } }, - new User { Id = 1, Username = "user", Password = "user", Roles = new string[] { "User"} } - }; + private readonly ILogger _logger; + private readonly DatabaseContext _databaseContext; + private readonly IJwtService _jwtService; + private readonly IPasswordService _passwordService; + + public UserService(ILogger logger, DatabaseContext databaseContext, IJwtService jwtService, IPasswordService passwordService) + { + _logger = logger; + _databaseContext = databaseContext; + _jwtService = jwtService; + _passwordService = passwordService; + } - public User Authenticate(string username, string password) + public async Task CreateToken(string username, string password) { - return _users.FirstOrDefault(user => user.Username == username && user.Password == password); + var users = _databaseContext.Users.ToList(); + + var user = await _databaseContext.Users.Where(u => u.Name == username).SingleOrDefaultAsync(); + + if (user == null) + { + _logger.LogInformation($"Create token failed with invalid username. Username = {username} Password = {password} ."); + return null; + } + + var verifyResult = _passwordService.VerifyPassword(user.EncryptedPassword, password); + + if (verifyResult) + { + var userInfo = new UserInfo(user); + + return new CreateTokenResult + { + Token = _jwtService.GenerateJwtToken(user.Id, userInfo.Roles), + UserInfo = userInfo + }; + } + else + { + _logger.LogInformation($"Create token failed with invalid password. Username = {username} Password = {password} ."); + return null; + } + } + + public async Task VerifyToken(string token) + { + var userId = _jwtService.VerifyJwtToken(token); + + if (userId == null) + { + _logger.LogInformation($"Verify token falied. Reason: invalid token. Token: {token} ."); + return null; + } + + var user = await _databaseContext.Users.Where(u => u.Id == userId.Value).SingleOrDefaultAsync(); + + if (user == null) + { + _logger.LogInformation($"Verify token falied. Reason: invalid user id. UserId: {userId} Token: {token} ."); + return null; + } + + return new UserInfo(user); + } + + public async Task CreateUser(string username, string password, string[] roles) + { + var exists = (await _databaseContext.Users.Where(u => u.Name == username).ToListAsync()).Count != 0; + + if (exists) + { + return CreateUserResult.AlreadyExists; + } + + await _databaseContext.Users.AddAsync(new User { Name = username, EncryptedPassword = _passwordService.HashPassword(password), RoleString = string.Join(',', roles) }); + await _databaseContext.SaveChangesAsync(); + + return CreateUserResult.Success; } } } -- cgit v1.2.3