using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Timeline.Entities; using Timeline.Helpers; namespace Timeline.Services.User.RegisterCode { public class RegisterCodeService : IRegisterCodeService, IDisposable { private readonly DatabaseContext _databaseContext; private readonly IUserService _userService; private readonly IClock _clock; private readonly RandomNumberGenerator _randomNumberGenerator; public RegisterCodeService(DatabaseContext databaseContext, IUserService userService, IClock clock) { _databaseContext = databaseContext; _userService = userService; _clock = clock; _randomNumberGenerator = RandomNumberGenerator.Create(); } public async Task CreateNewCodeAsync(long userId) { await _userService.CheckUserExistenceAsync(userId); var oldEntity = await _databaseContext.RegisterCodes.Where(r => r.OwnerId == userId && r.Enabled).SingleOrDefaultAsync(); if (oldEntity is not null) { oldEntity.Enabled = false; } var newEntity = new Entities.RegisterCode() { Code = _randomNumberGenerator.GenerateAlphaDigitString(6), OwnerId = userId, Enabled = true }; _databaseContext.RegisterCodes.Add(newEntity); await _databaseContext.SaveChangesAsync(); return newEntity.Code; } public async Task CreateRegisterInfoAsync(long userId, string registerCode, DateTime registerTime) { await _userService.CheckUserExistenceAsync(userId); var introducerId = await GetCodeOwnerAsync(registerCode, false); var entity = new UserRegisterInfo() { UserId = userId, IntroducerId = introducerId, RegisterCode = registerCode, RegisterTime = registerTime }; _databaseContext.UserRegisterInfos.Add(entity); await _databaseContext.SaveChangesAsync(); return entity; } public void Dispose() { _randomNumberGenerator.Dispose(); } public async Task GetCodeOwnerAsync(string code, bool onlyEnabled = true) { var entity = await _databaseContext.RegisterCodes.Where(r => r.Code == code).SingleOrDefaultAsync(); if (entity is null) return null; if (onlyEnabled && !entity.Enabled) return null; return entity.OwnerId; } public async Task GetCurrentCodeAsync(long userId) { await _userService.CheckUserExistenceAsync(userId); var entity = await _databaseContext.RegisterCodes.Where(r => r.OwnerId == userId && r.Enabled).SingleOrDefaultAsync(); return entity?.Code; } public async Task GetUserRegisterInfoAsync(long userId) { await _userService.CheckUserExistenceAsync(userId); return await _databaseContext.UserRegisterInfos.Where(i => i.UserId == userId).SingleOrDefaultAsync(); } public Task> GetUserRegisterInfoOfIntroducerAsync(long introducerId) { throw new NotImplementedException(); } public async Task RegisterUserWithCode(CreateUserParams userParams, string registerCode) { var registerCodeOwner = await GetCodeOwnerAsync(registerCode); if (registerCodeOwner is null) { throw new InvalidRegisterCodeException("Register code is invalid."); } var user = await _userService.CreateUserAsync(userParams); await CreateRegisterInfoAsync(user.Id, registerCode, _clock.GetCurrentTime()); return user; } } }