Navigation Items and Role access for Data Update Scripts (#12292)

* feat: add tech_menu_items to the admin helper

* feat: add the tech resources to /admin  if the user has the correct role

* feat: use a partial that will show the data update scripts in the navbar with the correct role

* chore: use a method

* test: chore

* feat: setup the data to need permission single_resource_admin with DataUpdateScript permissions

* chore: remove the if current_user.tech_admin?

* chore: remove line

* feat: add a DUS for single_resource_admin roles to be added to users with tech_admin roles

* fix: move all teh routes outside of the block where tech_admin is required.

* chore: use the constant and remove the method

* chore: add a comma

* Update config/routes.rb

Co-authored-by: rhymes <rhymes@hey.com>

* feat: add a tech admin role to the dropdown

* feat: add the tech admin role along with single_resource_admin

* chore: oops

* refactor: amend the spec to use let blocks

Co-authored-by: rhymes <rhymes@hey.com>
This commit is contained in:
Ridhwana 2021-02-09 17:41:14 +02:00 committed by GitHub
parent 56c50d87ac
commit 05e31971cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 100 additions and 11 deletions

View file

@ -67,7 +67,7 @@ within our community. ❤️
- [What is Forem?](#what-is-forem)
- [Table of Contents](#table-of-contents)
- [Community](#community)
- [Community](#community)
- [Contributing](#contributing)
- [Getting Started](#getting-started)
- [Prerequisites](#prerequisites)

View file

@ -16,5 +16,11 @@ module Admin
def force_run
DataUpdateWorker.perform_async(params[:id])
end
private
def authorize_admin
authorize DataUpdateScript, :access?, policy_class: InternalPolicy
end
end
end

View file

@ -37,6 +37,10 @@ module AdminHelper
PROFILE_ADMIN = { name: "config: profile setup", controller: "profile_fields" }.freeze
TECH_MENU_ITEMS = [
{ name: "data_update_scripts", controller: "data_update_scripts" },
].sort_by { |menu_item| menu_item[:name] }
def admin_menu_items
return MENU_ITEMS unless FeatureFlag.enabled?(:profile_admin)

View file

@ -9,6 +9,7 @@ module Constants
SPECIAL_ROLES = ["Admin",
"Super Admin",
"Tech Admin",
"Resource Admin: Article",
"Resource Admin: Comment",
"Resource Admin: BufferUpdate",
@ -20,6 +21,7 @@ module Constants
"Resource Admin: HtmlVariant",
"Resource Admin: DisplayAd",
"Resource Admin: ListingCategory",
"Resource Admin: Tag"].freeze
"Resource Admin: Tag",
"Resource Admin: DataUpdateScript"].freeze
end
end

View file

@ -2,6 +2,7 @@ class DataUpdateScript < ApplicationRecord
DIRECTORY = Rails.root.join("lib/data_update_scripts").freeze
NAMESPACE = "DataUpdateScripts".freeze
STATUSES = { enqueued: 0, working: 1, succeeded: 2, failed: 3 }.freeze
resourcify
enum status: STATUSES

View file

@ -78,6 +78,14 @@ module Moderator
check_super_admin
remove_negative_roles
user.add_role :super_admin
when "Tech Admin"
check_super_admin
remove_negative_roles
user.add_role :tech_admin
# DataUpdateScripts falls under the admin namespace
# and hence requires a single_resource_admin role to view
# this technical admin resource
user.add_role(:single_resource_admin, DataUpdateScript)
when /^(Resource Admin: )/
check_super_admin
remove_negative_roles

View file

@ -21,4 +21,20 @@
</div>
<% end %>
</div>
<div class="grid gap-2 m:gap-4 l:gap-6 m:grid-cols-2 l:grid-cols-3 px-2 m:px-0">
<div>
<div class="mt-6 mb-2"> Tech Resources </div>
<% AdminHelper::TECH_MENU_ITEMS.each do |tech_menu_item| %>
<div class="tag-card crayons-card branded-4 p-4 m:p-6 m:pt-4 flex flex-col relative">
<h3 class="crayons-tag crayons-tag--l mb-2">
<a href="/admin/<%= tech_menu_item[:controller] %>" class="crayons-link">
<%= tech_menu_item[:name].to_s.titleize %>
</a>
</h3>
</div>
<% end %>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
<% admin_menu_items.each do |menu_item| %>
<% menu_items.each do |menu_item| %>
<a class="crayons-link crayons-link--block <%= "crayons-link--current" if request.path.split("/")[2].match?(menu_item[:controller]) %>" href="/admin/<%= menu_item[:controller] %>">
<%= menu_item[:name].to_s.titleize %>
</a>

View file

@ -56,11 +56,13 @@
<div class="crayons-layout <%= controller_name == "admin_portals" ? "" : "crayons-layout--2-cols" %>">
<% unless controller_name == "admin_portals" %>
<div class="crayons-layout__left-sidebar">
<nav class="hidden m:block">
<%= render "admin/shared/navbar" %>
</nav>
</div>
<div class="crayons-layout__left-sidebar">
<nav class="hidden m:block">
<%= render "admin/shared/navbar", menu_items: admin_menu_items %>
<p class="crayons-field__description mt-4 mb-3">Tech Resources</p>
<%= render "admin/shared/navbar", menu_items: AdminHelper::TECH_MENU_ITEMS %>
</nav>
</div>
<% end %>
<main class="crayons-layout__content min-w-0">
<% flash.each do |type, message| %>

View file

@ -49,9 +49,6 @@ Rails.application.routes.draw do
{ rack_protection: { except: %i[authenticity_token form_token json_csrf
remote_token http_origin session_hijacking] } })
mount flipper_ui, at: "feature_flags"
resources :data_update_scripts, only: %i[index show]
post "/data_update_scripts/:id/force_run", to: "data_update_scripts#force_run"
end
namespace :users do
@ -66,6 +63,11 @@ Rails.application.routes.draw do
destroy], path: "listings/categories"
resources :comments, only: [:index]
resources :data_update_scripts, only: %i[index show] do
member do
post :force_run
end
end
resources :events, only: %i[index create update new edit]
resources :feedback_messages, only: %i[index show]
resources :invitations, only: %i[index new create destroy]

View file

@ -0,0 +1,10 @@
module DataUpdateScripts
class AddSingleResourceAdminRoleToUsersWithTechAdmin
def run
users_with_tech_admin_role = Role.find_by(name: "tech_admin").users
users_with_tech_admin_role.find_each do |user|
user.add_role(:single_resource_admin, DataUpdateScript)
end
end
end
end

View file

@ -0,0 +1,28 @@
require "rails_helper"
require Rails.root.join(
"lib/data_update_scripts/20210203104631_add_single_resource_admin_role_to_users_with_tech_admin.rb",
)
describe DataUpdateScripts::AddSingleResourceAdminRoleToUsersWithTechAdmin do
let!(:tech_admin1) { create(:user, :tech_admin) }
let!(:tech_admin2) { create(:user, :tech_admin) }
let!(:admin) { create(:user, :admin) }
it "adds single_resource_admin roles to users with tech_admin roles" do
described_class.new.run
expect(tech_admin1.reload.roles.pluck(:name)).to include("single_resource_admin")
expect(tech_admin2.reload.roles.pluck(:name)).to include("single_resource_admin")
end
it "sets the correct resource type for the single_resource_admin role" do
described_class.new.run
expect(tech_admin2.reload.roles.pluck(:resource_type)).to include("DataUpdateScript")
end
it "does not add single_resource_admin roles alongside other roles" do
described_class.new.run
expect(admin.reload.roles.pluck(:name)).not_to include("single_resource_admin")
end
end

View file

@ -34,6 +34,16 @@ RSpec.describe Moderator::ManageActivityAndRoles, type: :service do
expect(user.has_role?(:admin)).to be true
end
it "updates user to tech admin" do
described_class.handle_user_roles(
admin: admin,
user: user,
user_params: { note_for_current_role: "Upgrading to tech admin", user_status: "Tech Admin" },
)
expect(user.has_role?(:tech_admin)).to be true
expect(user.has_role?(:single_resource_admin, DataUpdateScript)).to be true
end
it "updates user to single resource admin" do
described_class.handle_user_roles(
admin: admin,