diff --git a/app/controllers/api/v1/application_controller.rb b/app/controllers/api/v1/application_controller.rb index 9e70a588..83e54646 100644 --- a/app/controllers/api/v1/application_controller.rb +++ b/app/controllers/api/v1/application_controller.rb @@ -44,7 +44,7 @@ def authenticate! @current_program = @current_token.application @current_scopes = @current_token.scopes unless @current_program&.active? - return render json: { error: "invalid_auth" }, status: :unauthorized + render json: { error: "invalid_auth" }, status: :unauthorized end else unless @current_token.hq_official? diff --git a/app/controllers/authorized_applications_controller.rb b/app/controllers/authorized_applications_controller.rb index 085c6354..09a6d334 100644 --- a/app/controllers/authorized_applications_controller.rb +++ b/app/controllers/authorized_applications_controller.rb @@ -2,24 +2,23 @@ class AuthorizedApplicationsController < ApplicationController include AhoyAnalytics def index - @access_tokens = current_identity.access_tokens - .includes(:application) - .order(created_at: :desc) - - render layout: request.headers["HX-Request"] ? "htmx" : false + @authorized_apps = load_apps + render layout: htmx? ? "htmx" : false end def destroy - token = current_identity.access_tokens.find(params[:id]) - track_event("oauth.revoked", program_name: token.application&.name, program_id: token.application&.id, scenario: token.application&.onboarding_scenario) - token.revoke - token.create_activity :revoke, owner: current_identity, recipient: current_identity + t = current_identity.access_tokens.find(params[:id]) + app = t.application + + track_event("oauth.revoked", program_name: app&.name, program_id: app&.id, scenario: app&.onboarding_scenario) - if request.headers["HX-Request"] - @access_tokens = current_identity.access_tokens - .includes(:application) - .order(created_at: :desc) + n = current_identity.all_access_tokens.where(application_id: app.id, revoked_at: nil).count + Program.revoke_tokens_and_grants_for(app.id, current_identity) + t.create_activity :revoke, owner: current_identity, recipient: current_identity, + parameters: { application_id: app.id, tokens_revoked: n } + if htmx? + @authorized_apps = load_apps flash.now[:success] = "Application access revoked successfully" render :index, layout: "htmx" else @@ -27,4 +26,25 @@ def destroy redirect_to security_path end end + + private + + def htmx? = request.headers["HX-Request"].present? + + def load_apps + current_identity.access_tokens.includes(:application).order(created_at: :desc).to_a + .group_by(&:application_id) + .filter_map { |_, toks| + tok = toks.first + next unless tok&.application + { + token: tok, + application: tok.application, + authorized_at: toks.map(&:created_at).min, + expires_at: toks.filter_map(&:expires_at).min, + scopes: toks.flat_map { |x| x.scopes.to_a }.uniq + } + } + .sort_by { |e| e[:authorized_at] }.reverse + end end diff --git a/app/controllers/identity_backup_codes_controller.rb b/app/controllers/identity_backup_codes_controller.rb index d1a06052..f8458a78 100644 --- a/app/controllers/identity_backup_codes_controller.rb +++ b/app/controllers/identity_backup_codes_controller.rb @@ -1,5 +1,5 @@ class IdentityBackupCodesController < ApplicationController - before_action -> { require_step_up("regenerate_backup_codes", return_to: identity_backup_codes_path) }, only: [:create, :confirm] + before_action -> { require_step_up("regenerate_backup_codes", return_to: identity_backup_codes_path) }, only: [ :create, :confirm ] def index @backup_codes = current_identity.backup_codes.active.order(created_at: :desc) diff --git a/app/controllers/identity_totps_controller.rb b/app/controllers/identity_totps_controller.rb index 8958360b..bd19824d 100644 --- a/app/controllers/identity_totps_controller.rb +++ b/app/controllers/identity_totps_controller.rb @@ -1,5 +1,5 @@ class IdentityTotpsController < ApplicationController - before_action -> { require_step_up("add_totp", return_to: security_path) }, only: [:new, :verify] + before_action -> { require_step_up("add_totp", return_to: security_path) }, only: [ :new, :verify ] def index @totp = current_identity.totp diff --git a/app/controllers/identity_webauthn_credentials_controller.rb b/app/controllers/identity_webauthn_credentials_controller.rb index b378b895..3fc3a066 100644 --- a/app/controllers/identity_webauthn_credentials_controller.rb +++ b/app/controllers/identity_webauthn_credentials_controller.rb @@ -1,7 +1,7 @@ class IdentityWebauthnCredentialsController < ApplicationController include WebauthnAuthenticatable - before_action -> { require_step_up("add_passkey", return_to: security_path) }, only: [:new, :options, :create] + before_action -> { require_step_up("add_passkey", return_to: security_path) }, only: [ :new, :options, :create ] def index @webauthn_credentials = current_identity.webauthn_credentials.order(created_at: :desc) diff --git a/app/controllers/step_up_controller.rb b/app/controllers/step_up_controller.rb index 0042bd36..6e9089a6 100644 --- a/app/controllers/step_up_controller.rb +++ b/app/controllers/step_up_controller.rb @@ -7,8 +7,8 @@ class StepUpController < ApplicationController VALID_ACTIONS = %w[remove_totp disable_2fa oidc_reauth email_change remove_passkey add_passkey regenerate_backup_codes add_totp].freeze ACTIONS_WITHOUT_EMAIL_FALLBACK = %w[email_change disable_2fa remove_passkey].freeze - before_action :validate_action_type, except: [:webauthn_options] - before_action :require_pending_step_up, only: [:send_email_code, :verify, :resend_email] + before_action :validate_action_type, except: [ :webauthn_options ] + before_action :require_pending_step_up, only: [ :send_email_code, :verify, :resend_email ] def new session[:pending_step_up_action] = params[:action_type] diff --git a/app/views/authorized_applications/_authorized_application.html.erb b/app/views/authorized_applications/_authorized_application.html.erb index cd484695..62a25d54 100644 --- a/app/views/authorized_applications/_authorized_application.html.erb +++ b/app/views/authorized_applications/_authorized_application.html.erb @@ -1,41 +1,39 @@ +<% app, tok, scopes = e.values_at(:application, :token, :scopes) %>