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
This commit is contained in:
Sojan Jose
2023-06-09 15:32:24 +05:30
committed by GitHub
parent c715e396f0
commit 48f2e58e59
12 changed files with 94 additions and 3 deletions

View File

@@ -75,6 +75,7 @@ gem 'jwt'
gem 'pundit' gem 'pundit'
# super admin # super admin
gem 'administrate' gem 'administrate'
gem 'administrate-field-active_storage'
##--- gems for pubsub service ---## ##--- gems for pubsub service ---##
# https://karolgalanciak.com/blog/2019/11/30/from-activerecord-callbacks-to-publish-slash-subscribe-pattern-and-event-driven-design/ # https://karolgalanciak.com/blog/2019/11/30/from-activerecord-callbacks-to-publish-slash-subscribe-pattern-and-event-driven-design/

View File

@@ -113,6 +113,9 @@ GEM
kaminari (>= 1.0) kaminari (>= 1.0)
sassc-rails (~> 2.1) sassc-rails (~> 2.1)
selectize-rails (~> 0.6) selectize-rails (~> 0.6)
administrate-field-active_storage (0.4.2)
administrate (>= 0.2.2)
rails (>= 7.0)
annotate (3.2.0) annotate (3.2.0)
activerecord (>= 3.2, < 8.0) activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0) rake (>= 10.4, < 14.0)
@@ -798,6 +801,7 @@ DEPENDENCIES
activerecord-import activerecord-import
acts-as-taggable-on acts-as-taggable-on
administrate administrate
administrate-field-active_storage
annotate annotate
attr_extras attr_extras
audited (~> 5.3) audited (~> 5.3)

View File

@@ -1,5 +1,6 @@
//= link_tree ../images //= link_tree ../images
//= link administrate/application.css //= link administrate/application.css
//= link administrate/application.js //= link administrate/application.js
//= link administrate-field-active_storage/application.css
//= link dashboardChart.js //= link dashboardChart.js
//= link secretField.js //= link secretField.js

View File

@@ -41,4 +41,14 @@ class SuperAdmin::AgentBotsController < SuperAdmin::ApplicationController
# See https://administrate-prototype.herokuapp.com/customizing_controller_actions # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
# for more information # 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 end

View File

@@ -45,6 +45,17 @@ class SuperAdmin::UsersController < SuperAdmin::ApplicationController
# empty values into nil values. It uses other APIs such as `resource_class` # empty values into nil values. It uses other APIs such as `resource_class`
# and `dashboard`: # 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 def resource_params
permitted_params = super permitted_params = super
permitted_params.delete(:password) if permitted_params[:password].blank? permitted_params.delete(:password) if permitted_params[:password].blank?

View File

@@ -10,6 +10,11 @@ class AgentBotDashboard < Administrate::BaseDashboard
ATTRIBUTE_TYPES = { ATTRIBUTE_TYPES = {
access_token: Field::HasOne, access_token: Field::HasOne,
avatar_url: AvatarField, 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, id: Field::Number,
name: Field::String, name: Field::String,
account: Field::BelongsTo.with_options(searchable: true, searchable_field: 'name', order: 'id DESC'), 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. # an array of attributes that will be displayed on the model's show page.
SHOW_PAGE_ATTRIBUTES = %i[ SHOW_PAGE_ATTRIBUTES = %i[
id id
avatar_url
account account
name name
description description
@@ -47,6 +53,7 @@ class AgentBotDashboard < Administrate::BaseDashboard
# on the model's form (`new` and `edit`) pages. # on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = %i[ FORM_ATTRIBUTES = %i[
name name
avatar
account account
description description
outgoing_url outgoing_url

View File

@@ -11,6 +11,11 @@ class UserDashboard < Administrate::BaseDashboard
account_users: Field::HasMany, account_users: Field::HasMany,
id: Field::Number, id: Field::Number,
avatar_url: AvatarField, 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, provider: Field::String,
uid: Field::String, uid: Field::String,
password: Field::Password, password: Field::Password,
@@ -69,6 +74,7 @@ class UserDashboard < Administrate::BaseDashboard
# on the model's form (`new` and `edit`) pages. # on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = %i[ FORM_ATTRIBUTES = %i[
name name
avatar
display_name display_name
email email
password password

View File

@@ -399,10 +399,15 @@ Rails.application.routes.draw do
post :seed, on: :member post :seed, on: :member
post :reset_cache, on: :member post :reset_cache, on: :member
end 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 :access_tokens, only: [:index, :show]
resources :installation_configs, only: [:index, :new, :create, :show, :edit, :update] 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] resources :platform_apps, only: [:index, :new, :create, :show, :edit, :update]
resource :instance_status, only: [:show] resource :instance_status, only: [:show]

View File

@@ -22,4 +22,25 @@ RSpec.describe 'Super Admin agent-bots API', type: :request do
end end
end 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 end

View File

@@ -45,4 +45,25 @@ RSpec.describe 'Super Admin Users API', type: :request do
end end
end 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 end

View File

@@ -9,5 +9,9 @@ FactoryBot.define do
trait :skip_validate do trait :skip_validate do
to_create { |instance| instance.save(validate: false) } to_create { |instance| instance.save(validate: false) }
end end
trait :with_avatar do
avatar { fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png') }
end
end end
end end

View File

@@ -26,7 +26,7 @@ FactoryBot.define do
end end
trait :with_avatar do 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 end
trait :administrator do trait :administrator do