<commit_before>﻿using Bit.ViewModel.Contracts;
using IdentityModel.Client;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Auth;
using Xamarin.Auth.Presenters;

namespace Bit.ViewModel.Implementations
{
    public class DefaultSecurityService : ISecurityService
    {
        public DefaultSecurityService(AccountStore accountStore,
            IClientAppProfile clientAppProfile,
            BitOAuth2Authenticator bitOAuth2Authenticator,
            OAuthLoginPresenter oAuthLoginPresenter,
            IDateTimeProvider dateTimeProvider)
        {
            _clientAppProfile = clientAppProfile;
            _accountStore = accountStore;
            _dateTimeProvider = dateTimeProvider;
            OAuthAuthenticator = bitOAuth2Authenticator;
        }

        private readonly IClientAppProfile _clientAppProfile;
        private readonly AccountStore _accountStore;
        private readonly IDateTimeProvider _dateTimeProvider;

        public static BitOAuth2Authenticator OAuthAuthenticator { get; protected set; }

        public virtual bool IsLoggedIn()
        {
            Account account = GetAccount();

            if (account == null)
                return false;

            Token token = account;

            return (_dateTimeProvider.GetCurrentUtcDateTime() - token.login_date) < TimeSpan.FromSeconds(token.expires_in);
        }

        public virtual async Task<bool> IsLoggedInAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            Account account = await GetAccountAsync().ConfigureAwait(false);

            if (account == null)
                return false;

            Token token = account;

            return (_dateTimeProvider.GetCurrentUtcDateTime() - token.login_date) < TimeSpan.FromSeconds(token.expires_in);
        }

        private Account GetAccount()
        {
            return (_accountStore.FindAccountsForService(_clientAppProfile.AppName)).SingleOrDefault();
        }

        private async Task<Account> GetAccountAsync()
        {
            return (await _accountStore.FindAccountsForServiceAsync(_clientAppProfile.AppName).ConfigureAwait(false)).SingleOrDefault();
        }

        public virtual Task<Token> Login(object state = null, string client_id = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            return OAuthAuthenticator.Login(GetLoginUrl(state, client_id));
        }

        public virtual async Task<Token> LoginWithCredentials(string username, string password, string client_id, string client_secret, string[] scopes = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (scopes == null)
                scopes = "openid profile user_info".Split(' ');

            using (TokenClient tokenClient = new TokenClient(address: new Uri(_clientAppProfile.HostUri, "core/connect/token").ToString(), clientId: client_id, clientSecret: client_secret))
            {
                TokenResponse tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(username, password, scope: string.Join(" ", scopes), cancellationToken: cancellationToken).ConfigureAwait(false);

                if (tokenResponse.IsError)
                    throw tokenResponse.Exception ?? new Exception($"{tokenResponse.Error}");

                Account account = Token.FromTokenToAccount(tokenResponse);

                await _accountStore.SaveAsync(account, _clientAppProfile.AppName).ConfigureAwait(false);

                return account;
            }
        }

        public virtual async Task Logout(object state = null, string client_id = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            Account account = GetAccount();

            if (account != null)
            {
                Token token = account;
                await _accountStore.DeleteAsync(account, _clientAppProfile.AppName).ConfigureAwait(false);
                if (!string.IsNullOrEmpty(token.id_token))
                {
                    await OAuthAuthenticator.Logout(GetLogoutUrl(token.id_token, state, client_id));
                }
            }<commit_msg>Ability to customize http message handler of token client of security service of cs client<commit_after>﻿using Bit.ViewModel.Contracts;
using IdentityModel.Client;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Auth;
using Xamarin.Auth.Presenters;

namespace Bit.ViewModel.Implementations
{
    public class DefaultSecurityService : ISecurityService
    {
        public DefaultSecurityService(AccountStore accountStore,
            IClientAppProfile clientAppProfile,
            BitOAuth2Authenticator bitOAuth2Authenticator,
            OAuthLoginPresenter oAuthLoginPresenter,
            IDateTimeProvider dateTimeProvider)
        {
            _clientAppProfile = clientAppProfile;
            _accountStore = accountStore;
            _dateTimeProvider = dateTimeProvider;
            OAuthAuthenticator = bitOAuth2Authenticator;
        }

        private readonly IClientAppProfile _clientAppProfile;
        private readonly AccountStore _accountStore;
        private readonly IDateTimeProvider _dateTimeProvider;

        public static BitOAuth2Authenticator OAuthAuthenticator { get; protected set; }

        public virtual bool IsLoggedIn()
        {
            Account account = GetAccount();

            if (account == null)
                return false;

            Token token = account;

            return (_dateTimeProvider.GetCurrentUtcDateTime() - token.login_date) < TimeSpan.FromSeconds(token.expires_in);
        }

        public virtual async Task<bool> IsLoggedInAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            Account account = await GetAccountAsync().ConfigureAwait(false);

            if (account == null)
                return false;

            Token token = account;

            return (_dateTimeProvider.GetCurrentUtcDateTime() - token.login_date) < TimeSpan.FromSeconds(token.expires_in);
        }

        private Account GetAccount()
        {
            return (_accountStore.FindAccountsForService(_clientAppProfile.AppName)).SingleOrDefault();
        }

        private async Task<Account> GetAccountAsync()
        {
            return (await _accountStore.FindAccountsForServiceAsync(_clientAppProfile.AppName).ConfigureAwait(false)).SingleOrDefault();
        }

        public virtual Task<Token> Login(object state = null, string client_id = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            return OAuthAuthenticator.Login(GetLoginUrl(state, client_id));
        }

        public virtual async Task<Token> LoginWithCredentials(string username, string password, string client_id, string client_secret, string[] scopes = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (scopes == null)
                scopes = "openid profile user_info".Split(' ');

            using (TokenClient tokenClient = new TokenClient(address: new Uri(_clientAppProfile.HostUri, "core/connect/token").ToString(), clientId: client_id, clientSecret: client_secret, innerHttpMessageHandler: GetHttpMessageHandler()))
            {
                TokenResponse tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(username, password, scope: string.Join(" ", scopes), cancellationToken: cancellationToken).ConfigureAwait(false);

                if (tokenResponse.IsError)
                    throw tokenResponse.Exception ?? new Exception($"{tokenResponse.Error}");

                Account account = Token.FromTokenToAccount(tokenResponse);

                await _accountStore.SaveAsync(account, _clientAppProfile.AppName).ConfigureAwait(false);

                return account;
            }
        }

        protected virtual HttpMessageHandler GetHttpMessageHandler()
        {
            return new HttpClientHandler();
        }

        public virtual async Task Logout(object state = null, string client_id = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            Account account = GetAccount();

            if (account != null)
            {
                Token token = account;
                await _accountStore.DeleteAsync(account, _clientAppProfile.AppName).ConfigureAwait(false);
                if (!string.IsNullOrEmpty(token.id_token))
                {
                    await OAuthAuthenticator.Logout(GetLogoutUrl(token.id_token, state, client_id));
                }
            }
{'fraction_non_alphanumeric': 0.07440273037542662, 'fraction_numerical': 0.0009101251422070534, 'mean_word_length': 2.7014736842105265, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4268615', 'n_tokens_mistral': 2126, 'n_tokens_neox': 2106, 'n_words': 471}