<commit_before>using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;
using System.Diagnostics;
using Newtonsoft.Json.Linq;
using CK.Auth;
using Microsoft.AspNetCore.Http;
using CK.Core;
using System.Linq;
using Microsoft.Extensions.Primitives;
using System.Security.Claims;
using CK.Text;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Authentication;

namespace CK.AspNet.Auth
{
    class WebFrontAuthHandler : AuthenticationHandler<WebFrontAuthOptions>, IAuthenticationRequestHandler
    {
        readonly static PathString _cSegmentPath = "/c";

        readonly WebFrontAuthService _authService;
        readonly IAuthenticationTypeSystem _typeSystem;
        readonly IWebFrontAuthLoginService _loginService;
        readonly IWebFrontAuthImpersonationService _impersonationService;
        readonly IWebFrontAuthUnsafeDirectLoginAllowService _unsafeDirectLoginAllower;

        public WebFrontAuthHandler(
            IOptionsMonitor<WebFrontAuthOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock,
            WebFrontAuthService authService,
            IAuthenticationTypeSystem typeSystem,
            IWebFrontAuthLoginService loginService,
            IWebFrontAuthImpersonationService impersonationService = null,
            IWebFrontAuthUnsafeDirectLoginAllowService unsafeDirectLoginAllower = null
            ) : base( options, logger, encoder, clock )
        {
            _authService = authService;
            _typeSystem = typeSystem;
            _loginService = loginService;
            _impersonationService = impersonationService;
            _unsafeDirectLoginAllower = unsafeDirectLoginAllower;
        }

        public Task<bool> HandleRequestAsync()
        {
            PathString remainder;
            if( Request.Path.StartsWithSegments( Options.EntryPath, out remainder ) )
            {
                Response.SetNoCacheAndDefaultStatus( StatusCodes.Status404NotFound );
                if( remainder.StartsWithSegments( _cSegmentPath, StringComparison.Ordinal, out PathString cBased ) )
                {
                    if( cBased.Value == "/refresh" )
                    {
                        return HandleRefresh();
                    }
                    else if( cBased.Value == "/basicLogin" )
                    {
                        if( _loginService.HasBasicLogin )
                        {
                            if( HttpMethods.IsPost( Request.Method ) ) return DirectBasicLogin( Context.GetRequestMonitor() );
                            Response.StatusCode = StatusCodes.Status405MethodNotAllowed;
                        }
                    }
                    else if( cBased.Value == "/startLogin" )
                    {
                        return HandleStartLogin();
                    }
                    else if( cBased.Value == "/unsafeDirectLogin" )
                    {
                        if( HttpMethods.IsPost( Request.Method ) ) return HandleUnsafeDirectLogin( Context.GetRequestMonitor() );
                        Response.StatusCode = StatusCodes.Status405MethodNotAllowed;
                    }
                    else if( cBased.Value == "/logout" )
                    {
                        return HandleLogout();
                    }
                    else if( cBased.Value == "/impersonate" )
                    {
                        if( _impersonationService != null )
                        {
                            if( HttpMethods.IsPost( Request.Method ) ) return HandleImpersonate( Context.GetRequestMonitor() );
                            Response.StatusCode = StatusCodes.Status405MethodNotAllowed;
                        }
                    }
                }
                else
                {
                    if( remainder.Value == "/token" ) return HandleToken();
                }
                return Task.FromResult( true );
            }
            return Task.FromResult( false );
        }

        Task<bool> HandleRefresh()
        {
            IAuthenticationInfo authInfo = _authService.EnsureAuthenticationInfo( Context );
            Debug.Assert( authInfo != null );
            JObject response = GetRefreshResponseAndSetCookies( authInfo, Request.Query.Keys.Contains( "schemes" ) );
            return WriteResponseAsync( response );
        }

        JObject GetRefreshResponseAndSetCookies( IAuthenticationInfo authInfo, bool addSchemes )
        {
            bool refreshable = false;
            if( authInfo.Level >= AuthLevel.Normal && Options.SlidingExpirationTime > TimeSpan.Zero )
            {
                refreshable = true;
                DateTime newExp = DateTime.UtcNow + Options.SlidingExpirationTime;
                if( newExp > authInfo.Expires.Value )
                {
                    authInfo = authInfo.SetExpires( newExp );
                }
            }
            JObject response = _authService.CreateAuthResponse( Context, authInfo, refreshable );
            if( addSchemes )
            {
                IReadOnlyList<string> list = Options.AvailableSchemes;
                if( list == null || list.Count == 0 ) list = _loginService.Providers;
                response.Add( "schemes", new JArray( _loginService.Providers ) );
            }
            _authService.SetCookies( Context, authInfo );
            return response;
        }

        Task<bool> HandleLogout()
        {
            _authService.Logout( Context );
            Context.Response.StatusCode = StatusCodes.Status200OK;
            return Task.FromResult( true );
        }

        async Task<bool> HandleStartLogin()
        {
            string scheme = Request.Query["scheme"];
            if( scheme == null )
            {
                Response.StatusCode = StatusCodes.Status400BadRequest;
                return true;
            }
            string returnUrl = Request.Query["returnUrl"];
            string callerOrigin = Request.Form["callerOrigin"];
            if( callerOrigin == null ) callerOrigin = Request.Query["callerOrigin"];

            IEnumerable<KeyValuePair<string, StringValues>> userData;
            if( HttpMethods.IsPost( Request.Method ) ) userData = Request.Form;
            else userData = Request.Query;<commit_msg>Fix. Stupid me.<commit_after>using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;
using System.Diagnostics;
using Newtonsoft.Json.Linq;
using CK.Auth;
using Microsoft.AspNetCore.Http;
using CK.Core;
using System.Linq;
using Microsoft.Extensions.Primitives;
using System.Security.Claims;
using CK.Text;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Authentication;

namespace CK.AspNet.Auth
{
    class WebFrontAuthHandler : AuthenticationHandler<WebFrontAuthOptions>, IAuthenticationRequestHandler
    {
        readonly static PathString _cSegmentPath = "/c";

        readonly WebFrontAuthService _authService;
        readonly IAuthenticationTypeSystem _typeSystem;
        readonly IWebFrontAuthLoginService _loginService;
        readonly IWebFrontAuthImpersonationService _impersonationService;
        readonly IWebFrontAuthUnsafeDirectLoginAllowService _unsafeDirectLoginAllower;

        public WebFrontAuthHandler(
            IOptionsMonitor<WebFrontAuthOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock,
            WebFrontAuthService authService,
            IAuthenticationTypeSystem typeSystem,
            IWebFrontAuthLoginService loginService,
            IWebFrontAuthImpersonationService impersonationService = null,
            IWebFrontAuthUnsafeDirectLoginAllowService unsafeDirectLoginAllower = null
            ) : base( options, logger, encoder, clock )
        {
            _authService = authService;
            _typeSystem = typeSystem;
            _loginService = loginService;
            _impersonationService = impersonationService;
            _unsafeDirectLoginAllower = unsafeDirectLoginAllower;
        }

        public Task<bool> HandleRequestAsync()
        {
            PathString remainder;
            if( Request.Path.StartsWithSegments( Options.EntryPath, out remainder ) )
            {
                Response.SetNoCacheAndDefaultStatus( StatusCodes.Status404NotFound );
                if( remainder.StartsWithSegments( _cSegmentPath, StringComparison.Ordinal, out PathString cBased ) )
                {
                    if( cBased.Value == "/refresh" )
                    {
                        return HandleRefresh();
                    }
                    else if( cBased.Value == "/basicLogin" )
                    {
                        if( _loginService.HasBasicLogin )
                        {
                            if( HttpMethods.IsPost( Request.Method ) ) return DirectBasicLogin( Context.GetRequestMonitor() );
                            Response.StatusCode = StatusCodes.Status405MethodNotAllowed;
                        }
                    }
                    else if( cBased.Value == "/startLogin" )
                    {
                        return HandleStartLogin();
                    }
                    else if( cBased.Value == "/unsafeDirectLogin" )
                    {
                        if( HttpMethods.IsPost( Request.Method ) ) return HandleUnsafeDirectLogin( Context.GetRequestMonitor() );
                        Response.StatusCode = StatusCodes.Status405MethodNotAllowed;
                    }
                    else if( cBased.Value == "/logout" )
                    {
                        return HandleLogout();
                    }
                    else if( cBased.Value == "/impersonate" )
                    {
                        if( _impersonationService != null )
                        {
                            if( HttpMethods.IsPost( Request.Method ) ) return HandleImpersonate( Context.GetRequestMonitor() );
                            Response.StatusCode = StatusCodes.Status405MethodNotAllowed;
                        }
                    }
                }
                else
                {
                    if( remainder.Value == "/token" ) return HandleToken();
                }
                return Task.FromResult( true );
            }
            return Task.FromResult( false );
        }

        Task<bool> HandleRefresh()
        {
            IAuthenticationInfo authInfo = _authService.EnsureAuthenticationInfo( Context );
            Debug.Assert( authInfo != null );
            JObject response = GetRefreshResponseAndSetCookies( authInfo, Request.Query.Keys.Contains( "schemes" ) );
            return WriteResponseAsync( response );
        }

        JObject GetRefreshResponseAndSetCookies( IAuthenticationInfo authInfo, bool addSchemes )
        {
            bool refreshable = false;
            if( authInfo.Level >= AuthLevel.Normal && Options.SlidingExpirationTime > TimeSpan.Zero )
            {
                refreshable = true;
                DateTime newExp = DateTime.UtcNow + Options.SlidingExpirationTime;
                if( newExp > authInfo.Expires.Value )
                {
                    authInfo = authInfo.SetExpires( newExp );
                }
            }
            JObject response = _authService.CreateAuthResponse( Context, authInfo, refreshable );
            if( addSchemes )
            {
                IReadOnlyList<string> list = Options.AvailableSchemes;
                if( list == null || list.Count == 0 ) list = _loginService.Providers;
                response.Add( "schemes", new JArray( _loginService.Providers ) );
            }
            _authService.SetCookies( Context, authInfo );
            return response;
        }

        Task<bool> HandleLogout()
        {
            _authService.Logout( Context );
            Context.Response.StatusCode = StatusCodes.Status200OK;
            return Task.FromResult( true );
        }

        async Task<bool> HandleStartLogin()
        {
            string scheme = Request.Query["scheme"];
            if( scheme == null )
            {
                Response.StatusCode = StatusCodes.Status400BadRequest;
                return true;
            }
            string returnUrl = Request.Query["returnUrl"];
            string callerOrigin = Request.Query["callerOrigin"];

            IEnumerable<KeyValuePair<string, StringValues>> userData;
            if( HttpMethods.IsPost( Request.Method ) )
            {
                if( callerOrigin == null ) callerOrigin = Request.Form["callerOrigin"];
                userData = Request.Form;
            }
            else userData = Request.Query;
{'fraction_non_alphanumeric': 0.0741541788969566, 'fraction_numerical': 0.002935269581337865, 'mean_word_length': 1.6967298479483441, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 27, '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': '5379068', 'n_tokens_mistral': 3067, 'n_tokens_neox': 2955, 'n_words': 605}