From 48f2e58e595b9f4dc6887cdddaf9de0839ea8cdf Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Fri, 9 Jun 2023 15:32:24 +0530 Subject: [PATCH] feat: Ability to update avatars from super admin (#7264) - Ability to update user avatars from super admin - Ability to update bot avatars from super admin fixes: #7060 --- Gemfile | 1 + Gemfile.lock | 4 ++++ app/assets/config/manifest.js | 1 + .../super_admin/agent_bots_controller.rb | 10 +++++++++ .../super_admin/users_controller.rb | 11 ++++++++++ app/dashboards/agent_bot_dashboard.rb | 7 +++++++ app/dashboards/user_dashboard.rb | 6 ++++++ config/routes.rb | 9 ++++++-- .../super_admin/agent_bots_controller_spec.rb | 21 +++++++++++++++++++ .../super_admin/users_controller_spec.rb | 21 +++++++++++++++++++ spec/factories/agent_bots.rb | 4 ++++ spec/factories/users.rb | 2 +- 12 files changed, 94 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index d635d380960c..d49157502b82 100644 --- a/Gemfile +++ b/Gemfile @@ -75,6 +75,7 @@ gem 'jwt' gem 'pundit' # super admin gem 'administrate' +gem 'administrate-field-active_storage' ##--- gems for pubsub service ---## # https://karolgalanciak.com/blog/2019/11/30/from-activerecord-callbacks-to-publish-slash-subscribe-pattern-and-event-driven-design/ diff --git a/Gemfile.lock b/Gemfile.lock index 990d14bfb030..058176f5e315 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,6 +113,9 @@ GEM kaminari (>= 1.0) sassc-rails (~> 2.1) selectize-rails (~> 0.6) + administrate-field-active_storage (0.4.2) + administrate (>= 0.2.2) + rails (>= 7.0) annotate (3.2.0) activerecord (>= 3.2, < 8.0) rake (>= 10.4, < 14.0) @@ -798,6 +801,7 @@ DEPENDENCIES activerecord-import acts-as-taggable-on administrate + administrate-field-active_storage annotate attr_extras audited (~> 5.3) diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index 38da59e09457..2cc9549bcf68 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,5 +1,6 @@ //= link_tree ../images //= link administrate/application.css //= link administrate/application.js +//= link administrate-field-active_storage/application.css //= link dashboardChart.js //= link secretField.js diff --git a/app/controllers/super_admin/agent_bots_controller.rb b/app/controllers/super_admin/agent_bots_controller.rb index 8e094e7520af..29a3021ee499 100644 --- a/app/controllers/super_admin/agent_bots_controller.rb +++ b/app/controllers/super_admin/agent_bots_controller.rb @@ -41,4 +41,14 @@ class SuperAdmin::AgentBotsController < SuperAdmin::ApplicationController # See https://administrate-prototype.herokuapp.com/customizing_controller_actions # for more information + + def destroy_avatar + avatar = requested_resource.avatar + avatar.purge + redirect_back(fallback_location: super_admin_agent_bots_path) + end + + def scoped_resource + resource_class.with_attached_avatar + end end diff --git a/app/controllers/super_admin/users_controller.rb b/app/controllers/super_admin/users_controller.rb index fec4fb79031d..ff242030a615 100644 --- a/app/controllers/super_admin/users_controller.rb +++ b/app/controllers/super_admin/users_controller.rb @@ -45,6 +45,17 @@ def create # empty values into nil values. It uses other APIs such as `resource_class` # and `dashboard`: # + + def destroy_avatar + avatar = requested_resource.avatar + avatar.purge + redirect_back(fallback_location: super_admin_users_path) + end + + def scoped_resource + resource_class.with_attached_avatar + end + def resource_params permitted_params = super permitted_params.delete(:password) if permitted_params[:password].blank? diff --git a/app/dashboards/agent_bot_dashboard.rb b/app/dashboards/agent_bot_dashboard.rb index e97a64de8411..baeb6e814ed1 100644 --- a/app/dashboards/agent_bot_dashboard.rb +++ b/app/dashboards/agent_bot_dashboard.rb @@ -10,6 +10,11 @@ class AgentBotDashboard < Administrate::BaseDashboard ATTRIBUTE_TYPES = { access_token: Field::HasOne, avatar_url: AvatarField, + avatar: Field::ActiveStorage.with_options( + destroy_url: proc do |_namespace, _resource, attachment| + [:avatar_super_admin_agent_bot, { attachment_id: attachment.id }] + end + ), id: Field::Number, name: Field::String, account: Field::BelongsTo.with_options(searchable: true, searchable_field: 'name', order: 'id DESC'), @@ -36,6 +41,7 @@ class AgentBotDashboard < Administrate::BaseDashboard # an array of attributes that will be displayed on the model's show page. SHOW_PAGE_ATTRIBUTES = %i[ id + avatar_url account name description @@ -47,6 +53,7 @@ class AgentBotDashboard < Administrate::BaseDashboard # on the model's form (`new` and `edit`) pages. FORM_ATTRIBUTES = %i[ name + avatar account description outgoing_url diff --git a/app/dashboards/user_dashboard.rb b/app/dashboards/user_dashboard.rb index 1d59525f2895..9573d84477d7 100644 --- a/app/dashboards/user_dashboard.rb +++ b/app/dashboards/user_dashboard.rb @@ -11,6 +11,11 @@ class UserDashboard < Administrate::BaseDashboard account_users: Field::HasMany, id: Field::Number, avatar_url: AvatarField, + avatar: Field::ActiveStorage.with_options( + destroy_url: proc do |_namespace, _resource, attachment| + [:avatar_super_admin_user, { attachment_id: attachment.id }] + end + ), provider: Field::String, uid: Field::String, password: Field::Password, @@ -69,6 +74,7 @@ class UserDashboard < Administrate::BaseDashboard # on the model's form (`new` and `edit`) pages. FORM_ATTRIBUTES = %i[ name + avatar display_name email password diff --git a/config/routes.rb b/config/routes.rb index fe5196fdeecf..73eccd3eeb35 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -399,10 +399,15 @@ post :seed, on: :member post :reset_cache, on: :member end - resources :users, only: [:index, :new, :create, :show, :edit, :update, :destroy] + resources :users, only: [:index, :new, :create, :show, :edit, :update, :destroy] do + delete :avatar, on: :member, action: :destroy_avatar + end + resources :access_tokens, only: [:index, :show] resources :installation_configs, only: [:index, :new, :create, :show, :edit, :update] - resources :agent_bots, only: [:index, :new, :create, :show, :edit, :update] + resources :agent_bots, only: [:index, :new, :create, :show, :edit, :update] do + delete :avatar, on: :member, action: :destroy_avatar + end resources :platform_apps, only: [:index, :new, :create, :show, :edit, :update] resource :instance_status, only: [:show] diff --git a/spec/controllers/super_admin/agent_bots_controller_spec.rb b/spec/controllers/super_admin/agent_bots_controller_spec.rb index 63548e4412ae..4c514c0f0d55 100644 --- a/spec/controllers/super_admin/agent_bots_controller_spec.rb +++ b/spec/controllers/super_admin/agent_bots_controller_spec.rb @@ -22,4 +22,25 @@ end end end + + describe 'DELETE /super_admin/agent_bots/:id/destroy_avatar' do + let!(:agent_bot) { create(:agent_bot, :with_avatar) } + + context 'when it is an unauthenticated super admin' do + it 'returns unauthorized' do + delete "/super_admin/agent_bots/#{agent_bot.id}/avatar", params: { attachment_id: agent_bot.avatar.id } + expect(response).to have_http_status(:redirect) + expect(agent_bot.reload.avatar).to be_attached + end + end + + context 'when it is an authenticated super admin' do + it 'destroys the avatar' do + sign_in(super_admin, scope: :super_admin) + delete "/super_admin/agent_bots/#{agent_bot.id}/avatar", params: { attachment_id: agent_bot.avatar.id } + expect(response).to have_http_status(:redirect) + expect(agent_bot.reload.avatar).not_to be_attached + end + end + end end diff --git a/spec/controllers/super_admin/users_controller_spec.rb b/spec/controllers/super_admin/users_controller_spec.rb index 26e28bc1521b..12f1b69dc342 100644 --- a/spec/controllers/super_admin/users_controller_spec.rb +++ b/spec/controllers/super_admin/users_controller_spec.rb @@ -45,4 +45,25 @@ end end end + + describe 'DELETE /super_admin/users/:id/avatar' do + let!(:user) { create(:user, :with_avatar) } + + context 'when it is an unauthenticated super admin' do + it 'returns unauthorized' do + delete "/super_admin/users/#{user.id}/avatar", params: { attachment_id: user.avatar.id } + expect(response).to have_http_status(:redirect) + expect(user.reload.avatar).to be_attached + end + end + + context 'when it is an authenticated super admin' do + it 'destroys the avatar' do + sign_in(super_admin, scope: :super_admin) + delete "/super_admin/users/#{user.id}/avatar", params: { attachment_id: user.avatar.id } + expect(response).to have_http_status(:redirect) + expect(user.reload.avatar).not_to be_attached + end + end + end end diff --git a/spec/factories/agent_bots.rb b/spec/factories/agent_bots.rb index 87556709b1ad..8fc0a6bf483c 100644 --- a/spec/factories/agent_bots.rb +++ b/spec/factories/agent_bots.rb @@ -9,5 +9,9 @@ trait :skip_validate do to_create { |instance| instance.save(validate: false) } end + + trait :with_avatar do + avatar { fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png') } + end end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 9b613e5a1037..89ee68069846 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -26,7 +26,7 @@ end trait :with_avatar do - avatar { Rack::Test::UploadedFile.new('spec/assets/avatar.png', 'image/png') } + avatar { fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png') } end trait :administrator do