< Summary

Class:SVETA.Api.Services.Implements.AuthenticationService
Assembly:SVETA.Api
File(s):/opt/dev/sveta_api_build/SVETA.Api/Services/Implements/AuthenticationService.cs
Covered lines:0
Uncovered lines:113
Coverable lines:113
Total lines:272
Line coverage:0% (0 of 113)
Covered branches:0
Total branches:92
Branch coverage:0% (0 of 92)

Metrics

MethodLine coverage Branch coverage
get_Roles()0%100%
.ctor(...)0%0%
CreateUser(...)0%0%
CreateClaims(...)0%0%
get_AnonymousUuid()0%100%
get_UserId()0%100%
get_UserEmail()0%100%
get_ContragentId()0%100%
get_ContragentKindId()0%100%
SwitchToServiceUser()0%100%
RevertUser()0%100%
SwitchToAnonymous()0%100%
IsOwner()0%0%
IsUserWholesaler()0%100%
IsUserRetailer()0%100%
IsUserManufacturer()0%100%
IsUserPlatform()0%100%
Confirmed()0%0%
Register()0%0%
CompanyAssigned()0%100%
IsAnonym()0%100%

File(s)

/opt/dev/sveta_api_build/SVETA.Api/Services/Implements/AuthenticationService.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Security.Claims;
 5using System.Threading.Tasks;
 6using CrmVtbc;
 7using IdentityServer4.Extensions;
 8using Microsoft.Extensions.Logging;
 9using Microsoft.Extensions.Options;
 10using SVETA.Api.Data.Domain;
 11using SVETA.Api.Helpers.Authorize;
 12using SVETA.Api.Services.Interfaces;
 13using WinSolutions.Sveta.Server.Data.DataModel.Entities;
 14using WinSolutions.Sveta.Server.Data.DataModel.Kinds;
 15using WinSolutions.Sveta.Common;
 16using Microsoft.AspNetCore.Http;
 17using Microsoft.EntityFrameworkCore;
 18using WinSolutions.Sveta.Server.Data.DataModel.Contexts;
 19using WinSolutions.Sveta.Server.Services.Interfaces;
 20using Elasticsearch.Net.Specification.CatApi;
 21using Microsoft.Extensions.Primitives;
 22using Newtonsoft.Json;
 23
 24namespace SVETA.Api.Services.Implements
 25{
 26    public class AuthenticationService : IAuthenticationService
 27    {
 28        User user;
 29        private User backUp;
 030        public List<string> Roles { get; }
 31        //private readonly AuthenticationSettings _authenticationSettings;
 32        private readonly ConfigurationsSettings _confsSettings;
 33        private readonly SvetaDbContext _db;
 34        private readonly ICommonUserService _commonUserService;
 35        private readonly IHttpContextAccessor _context;
 36        private readonly ICrmSyncWorker _crmSyncWorker;
 037        private string svetaDDistr = "svetaDDistr";
 38        private readonly bool hasCompany;
 39        private readonly bool hasUser;
 40        private readonly bool hasScope;
 41        private readonly bool hasConfirmed;
 042        private readonly int confirmed = 0;
 43        private Guid companyTid;
 44        private Guid userTid;
 45        private Guid anonymUser;
 46        private Guid serviceUser;
 47        private Guid anonymousUuid;
 48
 049        public AuthenticationService(IHttpContextAccessor context, SvetaDbContext db, ICommonUserService commonUserServi
 050            ILogger<AuthenticationService> logger, IOptions<AuthenticationSettings> options, IOptions<ConfigurationsSett
 051        {
 52            try
 053            {
 054                _db = db;
 055                _context = context;
 056                _confsSettings = optionsConf.Value;
 057                _commonUserService = commonUserService;
 58                //_authenticationSettings = options.Value;
 059                _crmSyncWorker = crmSyncWorker;
 060                Roles = new List<string>();
 061                if (!Guid.TryParse(_confsSettings.GetConfValue("AuthenticationSettings", "AnonymUserTID"), out anonymUse
 062                    throw new ArgumentException("Не удалось разобрать значение ключа AnonymUserTID в секции Authenticati
 063                if (!Guid.TryParse(_confsSettings.GetConfValue("AuthenticationSettings", "ServiceUserTID"), out serviceU
 064                    throw new ArgumentException("Не удалось разобрать значение ключа ServiceUserTID в секции Authenticat
 65
 66                StringValues anonymStringKey;
 067                if (context?.HttpContext?.Request?.Headers?.Keys?.Contains("Anonymous-UUID", StringComparer.OrdinalIgnor
 068                {
 069                    if (context?.HttpContext?.Request?.Headers?.TryGetValue("Anonymous-UUID", out anonymStringKey) ?? fa
 070                    {
 071                        Guid.TryParse(anonymStringKey, out anonymousUuid);
 072                    }
 073                }
 74
 075                if (context?.HttpContext?.User != null)
 076                {
 077                    var userClaims = context.HttpContext.User.Claims.IsNullOrEmpty() ? CreateClaims(anonymUser) : contex
 078                    Roles = userClaims.Claims.Where(claim => claim.Type.Contains("role", StringComparison.OrdinalIgnoreC
 079                        .Select(claim => claim.Value).ToList();
 080                    var dd_roles = _commonUserService.GetRoles().Result;
 081                    if (!Roles.Any(x => dd_roles.Any(e => e.Name == x)))
 082                        Roles.Add(Role.Anonym);
 083                    hasCompany = Guid.TryParse(userClaims.Claims.FirstOrDefault(claim => claim.Type.Contains("company_TI
 084                        .Value, out companyTid);
 085                    if (!hasCompany)
 086                    {
 087                        logger.LogError("Отсутствует company_TID в context claims");
 88                        //logger.LogError(JsonConvert.SerializeObject(userClaims.Claims.));
 089                        throw new ForbidException("В токене отсутствует company_TID");
 90                    }
 091                    hasUser = Guid.TryParse(userClaims.Claims.FirstOrDefault(claim => claim.Type.Contains("user_TID"))?
 092                                     .Value, out userTid);
 093                    if (!hasUser)
 094                    {
 095                        logger.LogError("Отсутствует user_TID в context claims");
 96                        //logger.LogError(JsonConvert.SerializeObject(userClaims.Claims));
 097                        throw new ForbidException("В токене отсутствует user_TID");
 98                    }
 099                    hasScope = userClaims.Claims.Where(claim => claim.Type.Contains("scope"))
 0100                        .Any(claim => claim.Value.Equals(svetaDDistr, StringComparison.Ordinal));
 0101                    if (!hasScope)
 0102                    {
 0103                        logger.LogError("Отсутствует scope ddistr в context claims");
 104                        //logger.LogError(JsonConvert.SerializeObject(context.HttpContext));
 0105                        throw new UnauthorizedAccessException();
 106                    }
 0107                    hasConfirmed = userClaims.Claims.Any(claim => claim.Type.Contains("confirmed"));
 0108                    confirmed = hasConfirmed ? Int32.Parse(userClaims.Claims.FirstOrDefault(claim => claim.Type.Contains
 0109                    CreateUser(userClaims);
 0110                }
 0111            }
 0112            catch (Exception e)
 0113            {
 0114                Console.WriteLine(e);
 0115                throw;
 116            }
 117
 0118        }
 119
 120        /// <summary>
 121        /// Создает сессию пользователя с указанным набором клаймсов
 122        /// </summary>
 123        /// <param name="claims">набор клаймсов</param>
 124        void CreateUser(ClaimsPrincipal claims)
 0125        {
 0126            userTid = claims.Claims.GetUserTID();
 0127            companyTid = claims.Claims.GetCompanyTID();
 128            try
 0129            {
 0130                if (_context?.HttpContext?.Request.Path.Value.ToLower().EndsWith("whoami") == true && userTid != anonymU
 0131                    && userTid != serviceUser)
 0132                    _crmSyncWorker.SyncWithCrm(userTid, companyTid).Wait();
 0133            }
 0134            catch (AggregateException ae)
 0135            {
 0136                if (ae.InnerException is SvetaException)
 0137                    throw new SvetaException($"Возникла ошибка при синхронизации с CRM. {ae.InnerException.Message}", (a
 0138                throw new SvetaException($"Возникла неизвестная ошибка при синхронизации с CRM. {ae.Message}", (int)Erro
 139            }
 140
 0141            user = _commonUserService.GetUser(userTid).Result;
 0142            if (user == null)
 0143            {
 0144                throw new ForbidException("Пользователь не найден.");
 145            }
 0146        }
 147
 148        /// <summary>
 149        /// Создает набор клаймсов для сервисного/анонимного пользователей
 150        /// </summary>
 151        /// <param name="tid">Гуид пользователя</param>
 152        /// <returns></returns>
 153        private ClaimsPrincipal CreateClaims(Guid tid)
 0154        {
 0155            var claims = new List<Claim>
 0156            {
 0157                new Claim("user_TID", tid.ToString()),
 0158                new Claim("scope", svetaDDistr)
 0159            };
 0160            if (tid == anonymUser)
 0161            {
 0162                claims.Add(new Claim("role", Role.Anonym));
 0163                claims.Add(new Claim("company_TID", Guid.NewGuid().ToString()));
 0164                claims.Add(new Claim("confirmed", "1"));
 0165            }
 0166            ClaimsIdentity id = new ClaimsIdentity(claims);
 0167            return new ClaimsPrincipal(id);
 0168        }
 169
 170        /// <summary>
 171        /// Возвращает GUID анонимного пользователя
 172        /// </summary>
 173        /// <returns></returns>
 174        public Guid AnonymousUuid
 175        {
 0176            get => anonymousUuid;
 177        }
 178
 179        /// <summary>
 180        /// Id текущего пользователя
 181        /// </summary>
 0182        public long UserId => user.Id;
 183
 184        /// <summary>
 185        /// Почта текущего пользователя
 186        /// </summary>
 0187        public string UserEmail => user.Email;
 188
 189        /// <summary>
 190        /// Id контрагента
 191        /// </summary>
 0192        public long ContragentId => user.Contragent.Id;
 193
 194        /// <summary>
 195        ///  Тип контрагента
 196        /// </summary>
 0197        public long ContragentKindId => user.Contragent.ContragentsKind.Id;
 198
 199        /// <summary>
 200        /// Переключает в контекст технического пользователя
 201        /// </summary>
 202        public void SwitchToServiceUser()
 0203        {
 0204            backUp = user;
 0205            CreateUser(CreateClaims(serviceUser));
 0206        }
 207
 208        /// <summary>
 209        /// Возвращает контекст сохраненного пользователя перед переключением
 210        /// </summary>
 0211        public void RevertUser() => user = backUp;
 212
 213        /// <summary>
 214        /// Переключает в контекст анонимного пользователя
 215        /// </summary>
 0216        public void SwitchToAnonymous() => CreateUser((CreateClaims((anonymUser))));
 217
 218        /// <summary>
 219        /// Проверяет, является ли пользователем владельцем контрагента
 220        /// </summary>
 221        /// <returns></returns>
 0222        public bool IsOwner() => user.Contragent?.Owner.Id == user.Id;
 223
 224        /// <summary>
 225        /// Проверяет, что контрагент авторизованного пользователя относится к группе Поставщики
 226        /// </summary>
 227        /// <returns>bool</returns>
 0228        public bool IsUserWholesaler() => user.Contragent.ContragentsKind.Id == (long)ContragentKind.Wholesaler;
 229
 230        /// <summary>
 231        /// Проверяет, что контрагент авторизованного пользователя относится к группе Магазины
 232        /// </summary>
 233        /// <returns>bool</returns>
 0234        public bool IsUserRetailer() => user.Contragent.ContragentsKind.Id == (long)ContragentKind.Retailer;
 235
 236        /// <summary>
 237        /// Проверяет, что контрагент авторизованного пользователя относится к группе Производители
 238        /// </summary>
 239        /// <returns>bool</returns>
 0240        public bool IsUserManufacturer() => user.Contragent.ContragentsKind.Id == (long)ContragentKind.Manufacturer;
 241
 242        /// <summary>
 243        /// Проверяет, что контрагент авторизованного пользователя относится к группе Платформа
 244        /// </summary>
 245        /// <returns>bool</returns>
 0246        public bool IsUserPlatform() => user.Contragent.ContragentsKind.Id == (long)ContragentKind.Platform;
 247
 248        /// <summary>
 249        /// Пользователь подтвердил почту или телефон в ЦРМ
 250        /// </summary>
 251        /// <returns></returns>
 0252        public bool Confirmed() => hasConfirmed && confirmed == 1;
 253
 254        /// <summary>
 255        /// Пользователь подтвердил данные в ЦРМ и получил userTID
 256        /// </summary>
 257        /// <returns></returns>
 0258        public bool Register() => hasConfirmed && confirmed == 1 && !userTid.IsDefaultValueOrNull();
 259
 260        /// <summary>
 261        /// Пользователь имеет прописанный companyTID
 262        /// </summary>
 263        /// <returns></returns>
 0264        public bool CompanyAssigned() => !companyTid.IsDefaultValueOrNull();
 265
 266        /// <summary>
 267        /// Проверяет авторизован ли текущий пользователь
 268        /// </summary>
 269        /// <returns></returns>
 0270        public bool IsAnonym() => user.ExternalKey.Equals(anonymUser);
 271    }
 272}