class Services::RsAuthsController < Services::BaseController before_action :authenticate_user! before_action :require_service_enabled before_action :require_service_available before_action :find_rs_auth, only: [:destroy] def index @rs_apps = current_user.remote_storage_authorizations .includes(:web_app) .group_by(&:client_id) .values .map { |auths| auths.sort_by(&:created_at).reverse } .sort_by { |auths| app_name_for(auths.first).downcase } end def destroy client_id = @auth.client_id @auth.destroy! remaining = current_user.remote_storage_authorizations .where(client_id: client_id) .order(created_at: :desc) .includes(:web_app) .to_a respond_to do |format| format.json { head :no_content } format.html do redirect_to apps_services_storage_url, flash: { success: 'App authorization revoked' } end format.turbo_stream { revoke_stream(client_id, remaining) } end end def launch_app auth = current_user.remote_storage_authorizations .where(client_id: params[:client_id]) .order(created_at: :desc) .first http_status(:not_found) and return unless auth user_address = if Rails.env.development? "#{current_user.cn}@#{request.host_with_port}" else current_user.address end # Storage-first bearer token issuance (remoteStorage spec ยง11): the app # receives the address and runs the application-first flow itself. launch_url = "#{auth.launch_url}#remotestorage=#{user_address}" redirect_to launch_url, allow_other_host: true end private # Revoking one of several devices updates the open details modal in place. # Revoking the app's last device leaves nothing to show, so the dashboard # re-renders itself instead: that keeps grouping, sorting and the empty # state in one place. def revoke_stream(client_id, remaining) if remaining.empty? redirect_to apps_services_storage_url, flash: { success: 'App authorization revoked' } else render turbo_stream: [ turbo_stream.remove(helpers.rs_device_dom_id(@auth)), turbo_stream.replace(helpers.rs_app_dom_id(client_id, :card), RsAuthCardComponent.new(authorizations: remaining)), turbo_stream.replace(helpers.rs_app_dom_id(client_id, :access), RsAuthAccessComponent.new(authorizations: remaining)) ] end end def app_name_for(auth) auth.display_name end def require_service_enabled unless current_user.service_enabled?(:remotestorage) http_status :forbidden end end def require_service_available http_status :not_found unless Setting.remotestorage_enabled? end def find_rs_auth @auth = current_user.remote_storage_authorizations.find_by(id: params[:id]) http_status :not_found unless @auth end end