added ability to assign moderator role via admin/super admin (#17759)

* added ability to assign moderator role via admin/super admin

* create Mod User in seeds

* add Cypress specs

* fix failing Cypress tests

* fix failing specs by moving test Mod user to the end

* nudge Travis

* nudge Travis

Co-authored-by: Arit Amana <msarit@gmail.com>
This commit is contained in:
Dwight Scott 2022-05-26 10:57:08 -04:00 committed by GitHub
parent eced29ce68
commit 8b70e9e1f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 153 additions and 65 deletions

View file

@ -3,7 +3,9 @@ class Role < ApplicationRecord
admin
codeland_admin
comment_suspended
creator
mod_relations_admin
moderator
podcast_admin
restricted_liquid_tag
single_resource_admin
@ -15,7 +17,6 @@ class Role < ApplicationRecord
trusted
warned
workshop_pass
creator
].freeze
has_and_belongs_to_many :users, join_table: :users_roles # rubocop:disable Rails/HasAndBelongsToMany

View file

@ -56,44 +56,47 @@ module Moderator
def handle_user_status(role, note)
case role
when "Admin"
assign_elevated_role_to_user(user, :admin)
TagModerators::AddTrustedRole.call(user)
when "Comment Suspend"
comment_suspended
when "Suspend" || "Spammer"
user.add_role(:suspended)
remove_privileges
when "Warn"
warned
when "Comment Suspend"
comment_suspended
when "Moderator"
assign_elevated_role_to_user(user, :moderator)
TagModerators::AddTrustedRole.call(user)
when "Regular Member"
regular_member
when "Trusted"
remove_negative_roles
TagModerators::AddTrustedRole.call(user)
when "Admin"
check_super_admin
remove_negative_roles
user.add_role(:admin)
TagModerators::AddTrustedRole.call(user)
when "Super Admin"
check_super_admin
remove_negative_roles
user.add_role(:super_admin)
TagModerators::AddTrustedRole.call(user)
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
user.add_role(:single_resource_admin, role.split("Resource Admin: ").last.safe_constantize)
when "Super Admin"
assign_elevated_role_to_user(user, :super_admin)
TagModerators::AddTrustedRole.call(user)
when "Tech Admin"
assign_elevated_role_to_user(user, :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 "Trusted"
remove_negative_roles
TagModerators::AddTrustedRole.call(user)
when "Warn"
warned
end
create_note(role, note)
end
def assign_elevated_role_to_user(user, role)
check_super_admin
remove_negative_roles
user.add_role(role)
end
def check_super_admin
raise I18n.t("services.moderator.manage_activity_and_roles.need_super") unless @admin.super_admin?
end

View file

@ -0,0 +1,5 @@
{
"username": "moderator_user",
"email": "moderator-user@forem.local",
"password": "password"
}

View file

@ -21,57 +21,96 @@ describe('Moderation Tools for Posts', () => {
});
});
it('should not alter tags from a post if a reason is not specified', () => {
cy.fixture('users/adminUser.json').as('adminUser');
cy.get('@adminUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/tag-test-article').then(() => {
cy.findByRole('button', { name: 'Moderation' }).click();
context('as admin user', () => {
beforeEach(() => {
cy.fixture('users/adminUser.json').as('adminUser');
});
// Helper function for pipe command
const click = ($el) => $el.click();
it('should not alter tags from a post if a reason is not specified', () => {
cy.get('@adminUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/tag-test-article').then(() => {
cy.findByRole('button', { name: 'Moderation' }).click();
cy.getIframeBody('[title="Moderation panel actions"]').within(() => {
// We use `pipe` here to retry the click, as the animation of the mod tools opening can sometimes cause the button to not be ready yet
cy.findByRole('button', { name: 'Open adjust tags section' })
.as('adjustTagsButton')
.pipe(click)
.should('have.attr', 'aria-expanded', 'true');
// Helper function for pipe command
const click = ($el) => $el.click();
cy.findByRole('button', { name: '#tag1 Remove tag' }).click();
cy.findByRole('button', { name: 'Submit' }).click();
cy.getIframeBody('[title="Moderation panel actions"]').within(() => {
// We use `pipe` here to retry the click, as the animation of the mod tools opening can sometimes cause the button to not be ready yet
cy.findByRole('button', { name: 'Open adjust tags section' })
.as('adjustTagsButton')
.pipe(click)
.should('have.attr', 'aria-expanded', 'true');
cy.findByRole('button', { name: '#tag1 Remove tag' }).click();
cy.findByRole('button', { name: 'Submit' }).click();
});
cy.findByTestId('snackbar').should('not.exist');
});
});
});
cy.findByTestId('snackbar').should('not.exist');
it('should show Feature Post button on an unfeatured post for an admin user', () => {
cy.get('@adminUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/unfeatured-article-slug').then(
() => {
cy.findByRole('button', { name: 'Moderation' }).click();
cy.getIframeBody('[title="Moderation panel actions"]').within(
() => {
cy.findByRole('button', { name: 'Feature Post' }).should(
'exist',
);
},
);
},
);
});
});
it('should show Unfeature Post button on a featured post for an admin user', () => {
cy.get('@adminUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/test-article-slug').then(() => {
cy.findByRole('button', { name: 'Moderation' }).click();
cy.getIframeBody('[title="Moderation panel actions"]').within(() => {
cy.findByRole('button', { name: 'Unfeature Post' }).should('exist');
});
});
});
});
});
it('should show Feature Post button on an unfeatured post for an admin user', () => {
cy.fixture('users/adminUser.json').as('adminUser');
cy.get('@adminUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/unfeatured-article-slug').then(
() => {
cy.findByRole('button', { name: 'Moderation' }).click();
cy.getIframeBody('[title="Moderation panel actions"]').within(() => {
cy.findByRole('button', { name: 'Feature Post' }).should('exist');
});
},
);
context('as moderator user', () => {
beforeEach(() => {
cy.fixture('users/moderatorUser.json').as('moderatorUser');
});
});
it('should show Unfeature Post button on a featured post for an admin user', () => {
cy.fixture('users/adminUser.json').as('adminUser');
cy.get('@adminUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/test-article-slug').then(() => {
cy.findByRole('button', { name: 'Moderation' }).click();
cy.getIframeBody('[title="Moderation panel actions"]').within(() => {
cy.findByRole('button', { name: 'Unfeature Post' }).should('exist');
it('should load moderation tools on a post for a moderator user', () => {
cy.get('@moderatorUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/test-article-slug').then(() => {
cy.findByRole('button', { name: 'Moderation' }).should('exist');
});
});
});
it('should not show Feature Post button on a post for a moderator user', () => {
cy.get('@moderatorUser').then((user) => {
cy.loginAndVisit(user, '/admin_mcadmin/unfeatured-article-slug').then(
() => {
cy.findByRole('button', { name: 'Moderation' }).click();
cy.getIframeBody('[title="Moderation panel actions"]').within(
() => {
cy.findByRole('button', { name: 'Feature Post' }).should(
'not.exist',
);
},
);
},
);
});
});
});
context('as trusted user', () => {

View file

@ -10,9 +10,9 @@ RSpec.describe Role, type: :model do
expected_roles = %w[
admin codeland_admin comment_suspended mod_relations_admin podcast_admin
restricted_liquid_tag single_resource_admin super_admin support_admin suspended tag_moderator tech_admin
trusted warned workshop_pass creator
trusted warned workshop_pass creator moderator
]
expect(described_class::ROLES).to eq(expected_roles)
expect(described_class::ROLES).to match_array(expected_roles)
end
end
end

View file

@ -119,5 +119,15 @@ RSpec.describe Moderator::ManageActivityAndRoles, type: :service do
)
end.to raise_error(StandardError)
end
it "updates user to moderator" do
expect do
described_class.handle_user_roles(
admin: admin,
user: user,
user_params: { note_for_current_role: "Upgrading to moderator", user_status: "Moderator" },
)
end.to raise_error(StandardError)
end
end
end

View file

@ -34,6 +34,7 @@ work_attr = ProfileField.find_by(label: "Work").attribute_name
education_attr = ProfileField.find_by(label: "Education").attribute_name
##############################################################################
# admin-user needs to be the first user, to maintain specs validity
seeder.create_if_doesnt_exist(User, "email", "admin@forem.local") do
user = User.create!(
name: "Admin McAdmin",
@ -71,6 +72,7 @@ admin_user = User.find_by(email: "admin@forem.local")
##############################################################################
# trusted-user-1 needs to be the second user, to maintain specs validity
seeder.create_if_doesnt_exist(User, "email", "trusted-user-1@forem.local") do
user = User.create!(
name: "Trusted User 1 \\:/",
@ -99,6 +101,7 @@ trusted_user = User.find_by(email: "trusted-user-1@forem.local")
##############################################################################
# punctuated-name-user needs to remain the 3rd user created, for tests' sake
seeder.create_if_doesnt_exist(User, "email", "punctuated-name-user@forem.local") do
user = User.create!(
name: "User \"The test breaker\" A'postrophe \\:/",
@ -175,6 +178,33 @@ end
##############################################################################
seeder.create_if_doesnt_exist(User, "email", "moderator-user@forem.local") do
user = User.create!(
name: "Moderator User",
email: "moderator-user@forem.local",
username: "moderator_user",
profile_image: File.open(Rails.root.join("app/assets/images/#{rand(1..40)}.png")),
confirmed_at: Time.current,
registered_at: Time.current,
password: "password",
password_confirmation: "password",
saw_onboarding: true,
checked_code_of_conduct: true,
checked_terms_and_conditions: true,
)
user.notification_setting.update(
email_comment_notifications: false,
email_follower_notifications: false,
)
user.profile.update(website_url: Faker::Internet.url)
user.add_role(:moderator)
user.add_role(:trusted)
end
##############################################################################
seeder.create_if_doesnt_exist(Organization, "slug", "bachmanity") do
organization = Organization.create!(
name: "Bachmanity",