public InteractionResultStatus Handle(string data) { var startsWithSpace = data.StartsWith(" "); data = data.TrimStart(' '); _viewport.Log("> " + data); try { foreach (var interaction in _interactions) { string @alias; string text; if (interaction.WillProcess(data, out @alias, out text)) { if (startsWithSpace) { _viewport.Clear(); } var request = new InteractionRequest(text, CurrentStoryId, data, _viewport.LookupRef, CurrentStoryName); var response = new InteractionResponse(_viewport, (l, s) => { CurrentStoryId = l; CurrentStoryName = s; }, _sender); var context = new InteractionContext(request, _storage, response); var result = interaction.Handle(context); if (result.Status == InteractionResultStatus.Error) { _viewport.Error(result.OptionalError); } return result.Status; } } } catch (Exception ex) { _viewport.Error("Error: {0}", ex.Message); return InteractionResultStatus.Error; } _viewport.Error("Unknown command sequence: {0}", data); return InteractionResultStatus.Error; }
public InteractionContext(InteractionRequest request, NuclearStorage storage, InteractionResponse response) { Request = request; Storage = storage; Response = response; }
public async Task<InteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, UserConsent consent) { if (request.PromptMode == Constants.PromptModes.Consent || await _consent.RequiresConsentAsync(request.Client, request.Subject, request.RequestedScopes)) { var response = new InteractionResponse(); // did user provide consent if (consent == null) { // user was not yet shown conset screen response.IsConsent = true; } else { request.WasConsentShown = true; // user was shown consent -- did they say yes or no if (consent.WasConsentGranted == false) { // no need to show consent screen again // build access denied error to return to client response.IsError = true; response.Error = new AuthorizeError { ErrorType = ErrorTypes.Client, Error = Constants.AuthorizeErrors.AccessDenied, ResponseMode = request.ResponseMode, ErrorUri = request.RedirectUri, State = request.State }; } else { // they said yes, set scopes they chose request.ValidatedScopes.SetConsentedScopes(consent.ScopedConsented); if (!request.ValidatedScopes.GrantedScopes.Any()) { // they said yes, but didn't pick any scopes // show consent again and provide error message response.IsConsent = true; response.ConsentError = "Must select at least one permission."; } if (request.Client.AllowRememberConsent) { // remember consent var scopes = Enumerable.Empty<string>(); if (consent.RememberConsent) { // remember what user actually selected scopes = request.ValidatedScopes.GrantedScopes.Select(x => x.Name); } await _consent.UpdateConsentAsync(request.Client, request.Subject, scopes); } } } return response; } return new InteractionResponse(); }
/// <inheritdoc /> public async Task <Result> RespondAsync ( IInteractionCreate?gatewayEvent, CancellationToken ct = default ) { if (gatewayEvent is null) { return(Result.FromSuccess()); } if (!gatewayEvent.Data.HasValue) { return(Result.FromSuccess()); } if (!gatewayEvent.ChannelID.HasValue) { return(Result.FromSuccess()); } var user = gatewayEvent.User.HasValue ? gatewayEvent.User.Value : gatewayEvent.Member.HasValue ? gatewayEvent.Member.Value.User.HasValue ? gatewayEvent.Member.Value.User.Value : null : null; if (user is null) { return(Result.FromSuccess()); } // Signal Discord that we'll be handling this one asynchronously var response = new InteractionResponse(InteractionCallbackType.DeferredChannelMessageWithSource); var interactionResponse = await _interactionAPI.CreateInteractionResponseAsync ( gatewayEvent.ID, gatewayEvent.Token, response, ct ); if (!interactionResponse.IsSuccess) { return(interactionResponse); } var interactionData = gatewayEvent.Data.Value !; interactionData.UnpackInteraction(out var command, out var parameters); var context = new InteractionContext ( gatewayEvent.GuildID, gatewayEvent.ChannelID.Value, user, gatewayEvent.Member, gatewayEvent.Token, gatewayEvent.ID, gatewayEvent.ApplicationID, interactionData.Resolved ); // Provide the created context to any services inside this scope _contextInjection.Context = context; // Run any user-provided pre execution events var preExecution = await _eventCollector.RunPreExecutionEvents(context, ct); if (!preExecution.IsSuccess) { return(preExecution); } // Run the actual command var searchOptions = new TreeSearchOptions(StringComparison.OrdinalIgnoreCase); var executeResult = await _commandService.TryExecuteAsync ( command, parameters, _services, searchOptions : searchOptions, ct : ct ); if (!executeResult.IsSuccess) { return(Result.FromError(executeResult)); } // Run any user-provided post execution events return(await _eventCollector.RunPostExecutionEvents ( context, executeResult.Entity, ct )); }
/// <summary> /// Processes the consent logic. /// </summary> /// <param name="request">The request.</param> /// <param name="consent">The consent.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException">Invalid PromptMode</exception> protected internal virtual async Task <InteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (request.PromptModes.Any() && !request.PromptModes.Contains(OidcConstants.PromptModes.None) && !request.PromptModes.Contains(OidcConstants.PromptModes.Consent)) { Logger.LogError("Invalid prompt mode: {promptMode}", request.PromptModes.ToSpaceSeparatedString()); throw new ArgumentException("Invalid PromptMode"); } var consentRequired = await Consent.RequiresConsentAsync(request.Subject, request.Client, request.ValidatedResources.ParsedScopes); if (consentRequired && request.PromptModes.Contains(OidcConstants.PromptModes.None)) { Logger.LogInformation("Error: prompt=none requested, but consent is required."); return(new InteractionResponse { Error = OidcConstants.AuthorizeErrors.ConsentRequired }); } if (request.PromptModes.Contains(OidcConstants.PromptModes.Consent) || consentRequired) { var response = new InteractionResponse(); // did user provide consent if (consent == null) { // user was not yet shown conset screen response.IsConsent = true; Logger.LogInformation("Showing consent: User has not yet consented"); } else { request.WasConsentShown = true; Logger.LogTrace("Consent was shown to user"); // user was shown consent -- did they say yes or no if (consent.Granted == false) { // no need to show consent screen again // build error to return to client Logger.LogInformation("Error: User consent result: {error}", consent.Error); var error = consent.Error switch { AuthorizationError.AccountSelectionRequired => OidcConstants.AuthorizeErrors.AccountSelectionRequired, AuthorizationError.ConsentRequired => OidcConstants.AuthorizeErrors.ConsentRequired, AuthorizationError.InteractionRequired => OidcConstants.AuthorizeErrors.InteractionRequired, AuthorizationError.LoginRequired => OidcConstants.AuthorizeErrors.LoginRequired, _ => OidcConstants.AuthorizeErrors.AccessDenied }; response.Error = error; response.ErrorDescription = consent.ErrorDescription; } else { // double check that required scopes are in the list of consented scopes var requiredScopes = request.ValidatedResources.GetRequiredScopeValues(); var valid = requiredScopes.All(x => consent.ScopesValuesConsented.Contains(x)); if (valid == false) { response.Error = OidcConstants.AuthorizeErrors.AccessDenied; Logger.LogInformation("Error: User denied consent to required scopes"); } else { // they said yes, set scopes they chose request.Description = consent.Description; request.ValidatedResources = request.ValidatedResources.Filter(consent.ScopesValuesConsented); Logger.LogInformation("User consented to scopes: {scopes}", consent.ScopesValuesConsented); if (request.Client.AllowRememberConsent) { // remember consent var parsedScopes = Enumerable.Empty <ParsedScopeValue>(); if (consent.RememberConsent) { // remember what user actually selected parsedScopes = request.ValidatedResources.ParsedScopes; Logger.LogDebug("User indicated to remember consent for scopes: {scopes}", request.ValidatedResources.RawScopeValues); } await Consent.UpdateConsentAsync(request.Subject, request.Client, parsedScopes); } } } } return(response); } return(new InteractionResponse()); }
internal async Task <InteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null) { if (request == null) { throw new ArgumentNullException("request"); } if (request.PromptMode != null && request.PromptMode != OidcConstants.PromptModes.None && request.PromptMode != OidcConstants.PromptModes.Consent) { throw new ArgumentException("Invalid PromptMode"); } var consentRequired = await _consent.RequiresConsentAsync(request.Client, request.Subject, request.RequestedScopes); if (consentRequired && request.PromptMode == OidcConstants.PromptModes.None) { _logger.LogInformation("Prompt=none requested, but consent is required."); return(new InteractionResponse { Error = new AuthorizeError { ErrorType = ErrorTypes.Client, Error = OidcConstants.AuthorizeErrors.ConsentRequired, ResponseMode = request.ResponseMode, ErrorUri = request.RedirectUri, State = request.State } }); } if (request.PromptMode == OidcConstants.PromptModes.Consent || consentRequired) { var response = new InteractionResponse(); // did user provide consent if (consent == null) { // user was not yet shown conset screen response.IsConsent = true; } else { request.WasConsentShown = true; // user was shown consent -- did they say yes or no if (consent.Granted == false) { // no need to show consent screen again // build access denied error to return to client response.Error = new AuthorizeError { ErrorType = ErrorTypes.Client, Error = OidcConstants.AuthorizeErrors.AccessDenied, ResponseMode = request.ResponseMode, ErrorUri = request.RedirectUri, State = request.State }; } else { // double check that required scopes are in the list of consented scopes var valid = request.ValidatedScopes.ValidateRequiredScopes(consent.ScopesConsented); if (valid == false) { response.Error = new AuthorizeError { ErrorType = ErrorTypes.Client, Error = OidcConstants.AuthorizeErrors.AccessDenied, ResponseMode = request.ResponseMode, ErrorUri = request.RedirectUri, State = request.State }; } else { // they said yes, set scopes they chose request.ValidatedScopes.SetConsentedScopes(consent.ScopesConsented); if (request.Client.AllowRememberConsent) { // remember consent var scopes = Enumerable.Empty <string>(); if (consent.RememberConsent) { // remember what user actually selected scopes = request.ValidatedScopes.GrantedScopes.Select(x => x.Name); } await _consent.UpdateConsentAsync(request.Client, request.Subject, scopes); } } } } return(response); } return(new InteractionResponse()); }
public static async Task SendInteractionResponseAsync(BaseDiscordClient client, InteractionResponse response, IDiscordInteraction interaction, IMessageChannel channel = null, RequestOptions options = null) { await client.ApiClient.CreateInteractionResponseAsync(response, interaction.Id, interaction.Token, options).ConfigureAwait(false); }