<commit_before>﻿// Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


#include "pch.h"

#if UWP_API
#include "user_impl.h"
#include "Utils_WinRT.h"
#if !XSAPI_CPP
#include "Macros_WinRT.h"
#include "XboxLiveContextSettings_WinRT.h"
#endif
#include "Event_WinRT.h"
#include "xsapi\presence.h"
#include "presence_internal.h"

using namespace pplx;
using namespace Platform;
using namespace Windows::Security::Authentication::Web::Core;
using namespace Windows::Security::Credentials;
using namespace Windows::System::Threading;
using namespace XBOX_LIVE_NAMESPACE;
#if BEAM_API
using namespace Microsoft::Xbox::Services::Beam;
using namespace Microsoft::Xbox::Services::Beam::System;
#else
using namespace Microsoft::Xbox::Services;
using namespace Microsoft::Xbox::Services::System;
using namespace XBOX_LIVE_NAMESPACE::presence;
#endif

NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_BEGIN

std::unordered_map<string_t, std::shared_ptr<user_impl_idp>> user_impl_idp::s_trackingUsers = std::unordered_map<string_t, std::shared_ptr<user_impl_idp>>();
Windows::System::UserWatcher^ user_impl_idp::s_userWatcher = nullptr;

pplx::task<xbox_live_result<sign_in_result>>
user_impl_idp::sign_in_impl(_In_ bool showUI, _In_ bool forceRefresh)
{
    UNREFERENCED_PARAMETER(forceRefresh);

    std::weak_ptr<user_impl_idp> thisWeakPtr = std::dynamic_pointer_cast<user_impl_idp>(shared_from_this());
    
    //Initiate user watcher
    if (is_multi_user_application())
    {
        std::lock_guard<std::mutex> lock(s_trackingUsersLock.get());

        if (s_userWatcher == nullptr)
        {
            s_userWatcher = Windows::System::User::CreateWatcher();
            s_userWatcher->Removed += ref new Windows::Foundation::TypedEventHandler<Windows::System::UserWatcher ^, Windows::System::UserChangedEventArgs ^>(&on_system_user_removed);
        }
    }

    auto task = initialize_provider()
    .then([thisWeakPtr, showUI](void)
    {
        std::shared_ptr<user_impl_idp> pThis(thisWeakPtr.lock());
        if (pThis == nullptr)
        {
            return xbox_live_result<sign_in_result>(xbox_live_error_code::runtime_error, "user_impl shutting down");
        }

        xbox_live_result<token_and_signature_result> result =  pThis->internal_get_token_and_signature_helper(
            _T("GET"),
            pThis->m_authConfig->xbox_live_endpoint(),
            string_t(),
            std::vector<unsigned char>(),
            showUI,
            false
            );

        if (result.err())
        {
            return xbox_live_result<sign_in_result>(result.err(), result.err_message());
        }
        else
        {
            const auto& payload = result.payload();

            if (!payload.xbox_user_id().empty())
            {
                // Hit presence service to validate the token.
                if (!payload.token().empty())
                {
                    const string_t& xboxUserId = payload.xbox_user_id();
                    string_t pathAndQuery = presence_service_impl::set_presence_sub_path(xboxUserId);

                    std::shared_ptr<http_call> httpCall = xbox_system_factory::get_factory()->create_http_call(
                        std::make_shared<xbox_live_context_settings>(),
                        _T("POST"),
                        utils::create_xboxlive_endpoint(_T("userpresence"), xbox_live_app_config::get_app_config_singleton()),
                        pathAndQuery,
                        xbox_live_api::set_presence_helper
                    );

                    presence_title_request request(true,presence_data());

                    httpCall->set_retry_allowed(false);
                    httpCall->set_request_body(request.serialize().serialize());
                    httpCall->set_xbox_contract_version_header_value(_T("3"));
                    httpCall->set_custom_header(AUTH_HEADER, payload.token());
                    if (!payload.signature().empty())
                    {
                        httpCall->set_custom_header(SIG_HEADER, payload.signature());
                    }

                    auto response = httpCall->get_response(http_call_response_body_type::json_body).get();

                    // If gettig 401, try to refresh token. If we succeeded or failed or any other reason, ignore the result and move on.
                    if (response->err_code().value() == (int)xbox_live_error_code::http_status_401_unauthorized)
                    {
                        auto refreshResult = pThis->internal_get_token_and_signature_helper(
                            _T("GET"),
                            pThis->m_authConfig->xbox_live_endpoint(),
                            string_t(),
                            std::vector<unsigned char>(),
                            showUI,
                            true
                        );

                        // if refresh fails, return the error.
                        if (refreshResult.err())
                        {
                            return xbox_live_result<sign_in_result>(refreshResult.err(), refreshResult.err_message());<commit_msg>Add more error handling for various sign in corner cases. (#112)<commit_after>﻿// Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


#include "pch.h"

#if UWP_API
#include "user_impl.h"
#include "Utils_WinRT.h"
#if !XSAPI_CPP
#include "Macros_WinRT.h"
#include "XboxLiveContextSettings_WinRT.h"
#endif
#include "Event_WinRT.h"
#include "xsapi\presence.h"
#include "presence_internal.h"

using namespace pplx;
using namespace Platform;
using namespace Windows::Security::Authentication::Web::Core;
using namespace Windows::Security::Credentials;
using namespace Windows::System::Threading;
using namespace XBOX_LIVE_NAMESPACE;
#if BEAM_API
using namespace Microsoft::Xbox::Services::Beam;
using namespace Microsoft::Xbox::Services::Beam::System;
#else
using namespace Microsoft::Xbox::Services;
using namespace Microsoft::Xbox::Services::System;
using namespace XBOX_LIVE_NAMESPACE::presence;
#endif

NAMESPACE_MICROSOFT_XBOX_SERVICES_SYSTEM_CPP_BEGIN

std::unordered_map<string_t, std::shared_ptr<user_impl_idp>> user_impl_idp::s_trackingUsers = std::unordered_map<string_t, std::shared_ptr<user_impl_idp>>();
Windows::System::UserWatcher^ user_impl_idp::s_userWatcher = nullptr;

pplx::task<xbox_live_result<sign_in_result>>
user_impl_idp::sign_in_impl(_In_ bool showUI, _In_ bool forceRefresh)
{
    UNREFERENCED_PARAMETER(forceRefresh);

    std::weak_ptr<user_impl_idp> thisWeakPtr = std::dynamic_pointer_cast<user_impl_idp>(shared_from_this());
    
    //Initiate user watcher
    if (is_multi_user_application())
    {
        std::lock_guard<std::mutex> lock(s_trackingUsersLock.get());

        if (s_userWatcher == nullptr)
        {
            s_userWatcher = Windows::System::User::CreateWatcher();
            s_userWatcher->Removed += ref new Windows::Foundation::TypedEventHandler<Windows::System::UserWatcher ^, Windows::System::UserChangedEventArgs ^>(&on_system_user_removed);
        }
    }

    auto task = initialize_provider()
    .then([thisWeakPtr, showUI](void)
    {
        std::shared_ptr<user_impl_idp> pThis(thisWeakPtr.lock());
        if (pThis == nullptr)
        {
            return xbox_live_result<sign_in_result>(xbox_live_error_code::runtime_error, "user_impl shutting down");
        }

        xbox_live_result<token_and_signature_result> result =  pThis->internal_get_token_and_signature_helper(
            _T("GET"),
            pThis->m_authConfig->xbox_live_endpoint(),
            string_t(),
            std::vector<unsigned char>(),
            showUI,
            false
            );

        if (result.err())
        {
            return xbox_live_result<sign_in_result>(result.err(), result.err_message());
        }
        else
        {
            const auto& payload = result.payload();

            if (!payload.xbox_user_id().empty())
            {
                // Hit presence service to validate the token.
                if (!payload.token().empty())
                {
                    const string_t& xboxUserId = payload.xbox_user_id();
                    string_t pathAndQuery = presence_service_impl::set_presence_sub_path(xboxUserId);

                    std::shared_ptr<http_call> httpCall = xbox_system_factory::get_factory()->create_http_call(
                        std::make_shared<xbox_live_context_settings>(),
                        _T("POST"),
                        utils::create_xboxlive_endpoint(_T("userpresence"), xbox_live_app_config::get_app_config_singleton()),
                        pathAndQuery,
                        xbox_live_api::set_presence_helper
                    );

                    presence_title_request request(true,presence_data());

                    httpCall->set_retry_allowed(false);
                    httpCall->set_request_body(request.serialize().serialize());
                    httpCall->set_xbox_contract_version_header_value(_T("3"));
                    httpCall->set_custom_header(AUTH_HEADER, payload.token());
                    if (!payload.signature().empty())
                    {
                        httpCall->set_custom_header(SIG_HEADER, payload.signature());
                    }

                    auto response = httpCall->get_response(http_call_response_body_type::json_body).get();

                    // If gettig 401, try to refresh token. If we succeeded or failed or any other reason, ignore the result and move on.
                    if (response->err_code().value() == (int)xbox_live_error_code::http_status_401_unauthorized)
                    {
                        auto refreshResult = pThis->internal_get_token_and_signature_helper(
                            _T("GET"),
                            pThis->m_authConfig->xbox_live_endpoint(),
                            string_t(),
                            std::vector<unsigned char>(),
                            showUI,
                            true
                        );

                        // if refresh fails, return the error.
                        if (refreshResult.err())
                        {
                            //if it's silent pass, give user interaction required.
                            if (!showUI)
                            {
                                return xbox_live_result<sign_in_result>(sign_in_status::user_interaction_required);
                            }
                            else
                            {
                                return xbox_live_result<sign_in_result>(refreshResult.err(), refreshResult.err_message());
                            }
                        }
                        else if (refreshResult.payload().xbox_user_id().empty())
                        {
                            return xbox_live_result<sign_in_result>(convert_web_token_request_status(refreshResult.payload().token_request_result()));
{'fraction_non_alphanumeric': 0.10193652501344809, 'fraction_numerical': 0.0015241169087322932, 'mean_word_length': 2.2789535567313344, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 73, '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': '7197022', 'n_tokens_mistral': 3123, 'n_tokens_neox': 3022, 'n_words': 505}