Summary

Class:ProjectX.Services.AuthService
Assembly:ProjectX
File(s):C:\private\projects\projectx\backend\src\ProjectX\Services\UserService.cs
Covered lines:47
Uncovered lines:1
Coverable lines:48
Total lines:112
Line coverage:97.9%
Branch coverage:75%

History

Metrics

MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
.ctor(...)10100100
CreateUserAsync()11494.7460
ConfirmUserAsync()74100100

File(s)

C:\private\projects\projectx\backend\src\ProjectX\Services\UserService.cs

#LineLine coverage
 1using System;
 2using System.Threading.Tasks;
 3using Microsoft.Extensions.Logging;
 4using ProjectX.Entities;
 5using ProjectX.Exceptions;
 6using ProjectX.Stores;
 7using ServiceBase;
 8using ServiceBase.Notification.Sms;
 9
 10namespace ProjectX.Services
 11{
 12    public class AuthService
 13    {
 14        private readonly ILogger<AuthService> _logger;
 15        private readonly IUserStore _userStore;
 16        private readonly CryptoService _crypto;
 17        private readonly ISmsService _smsService;
 18        private readonly IDateTimeAccessor _dateTimeAccessor;
 19
 420        public AuthService(
 421            ILogger<AuthService> logger,
 422            IUserStore userStore,
 423            CryptoService crypto,
 424            ISmsService smsService,
 425            IDateTimeAccessor dateTimeAccessor)
 26        {
 427            this._logger = logger;
 428            this._userStore = userStore;
 429            this._crypto = crypto;
 430            this._smsService = smsService;
 431            this._dateTimeAccessor = dateTimeAccessor;
 432        }
 33
 34        public async Task<User> CreateUserAsync(
 35            string phone,
 36            ClientOS clientOs,
 37            string locale)
 38        {
 39            // Check if user already exists
 140            User user = await this._userStore.LoadUserByPhoneAsync(phone);
 141            bool isNew = false;
 42
 143             if (user != null)
 44            {
 45                // TODO: do throttling
 46            }
 47            else
 48            {
 149                isNew = true;
 150                user = new Entities.User
 151                {
 152                    Phone = phone
 153                };
 54            }
 55
 156            user.Code = this._crypto.GenerateCode();
 157            user.ClientOS = clientOs;
 58
 59            // TODO: Check a list of supported locales
 160            user.Locale = locale;
 61
 62            // Default information
 163            user.Age = 18;
 164            user.Perimeter = 50;
 165            user.AgeFrom = 18;
 166            user.AgeTo = 100;
 67
 68            // Persist user information
 169             if (isNew)
 70            {
 171                user = await this._userStore.CreateUserAsync(user);
 172            }
 73            else
 74            {
 075                user = await this._userStore.UpdateUserAsync(user);
 76            }
 77
 78            // Send SMS
 179            await this._smsService.SendSmsAsync("Code_en", phone, user);
 80
 181            return user;
 182        }
 83
 84        public async Task<User> ConfirmUserAsync(Guid userId, string code)
 85        {
 386            User user = await this._userStore.LoadUserByIdAsync(userId);
 87
 388             if (user == null)
 89            {
 190                throw new EntityNotFoundException(
 191                    $"User with id {userId} not found");
 92            }
 93
 294             if (!code.Equals(user.Code))
 95            {
 196                throw new CodeNotMatchException($"Confirmation code {code} " +
 197                    $"for user {userId} does not match");
 98            }
 99
 100            // Generate hash
 1101            string hash = this._crypto.GenerateHash();
 102
 1103            user.Code = null;
 1104            user.Hash = hash;
 1105            user.ConfirmedAt = this._dateTimeAccessor.UtcNow;
 106
 1107            await this._userStore.UpdateUserAsync(user);
 108
 1109            return user;
 1110        }
 111    }
 112}