mirror of
https://github.com/astuto/astuto.git
synced 2025-12-16 11:47:56 +01:00
Add role 'owner' to users (#185)
This commit is contained in:
committed by
GitHub
parent
e86748edca
commit
0e96ff7ad4
@@ -4,7 +4,7 @@ class SiteSettingsController < ApplicationController
|
|||||||
before_action :authenticate_admin,
|
before_action :authenticate_admin,
|
||||||
only: [:general, :boards, :post_statuses, :roadmap, :authentication]
|
only: [:general, :boards, :post_statuses, :roadmap, :authentication]
|
||||||
|
|
||||||
before_action :authenticate_power_user,
|
before_action :authenticate_moderator,
|
||||||
only: [:users]
|
only: [:users]
|
||||||
|
|
||||||
def general
|
def general
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ class UsersController < ApplicationController
|
|||||||
|
|
||||||
@user.assign_attributes user_update_params
|
@user.assign_attributes user_update_params
|
||||||
|
|
||||||
|
# Handle special case: trying to set user role to 'owner'
|
||||||
|
raise Pundit::NotAuthorizedError if @user.owner?
|
||||||
|
|
||||||
if @user.save
|
if @user.save
|
||||||
render json: @user
|
render json: @user
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ module ApplicationHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticate_power_user
|
def authenticate_moderator
|
||||||
return if check_user_signed_in == false
|
return if check_user_signed_in == false
|
||||||
|
|
||||||
unless current_user.admin? or current_user.moderator?
|
unless current_user.moderator?
|
||||||
flash[:alert] = t('errors.not_enough_privileges')
|
flash[:alert] = t('errors.not_enough_privileges')
|
||||||
redirect_to root_path
|
redirect_to root_path
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as React from "react";
|
|||||||
import Gravatar from 'react-gravatar';
|
import Gravatar from 'react-gravatar';
|
||||||
import I18n from 'i18n-js';
|
import I18n from 'i18n-js';
|
||||||
|
|
||||||
import IUser, { UserRoles, USER_ROLE_ADMIN, USER_ROLE_USER, USER_STATUS_ACTIVE, USER_STATUS_BLOCKED, USER_STATUS_DELETED } from "../../../interfaces/IUser";
|
import IUser, { UserRoles, USER_ROLE_ADMIN, USER_ROLE_MODERATOR, USER_ROLE_OWNER, USER_ROLE_USER, USER_STATUS_ACTIVE, USER_STATUS_BLOCKED, USER_STATUS_DELETED } from "../../../interfaces/IUser";
|
||||||
import Separator from "../../common/Separator";
|
import Separator from "../../common/Separator";
|
||||||
import UserForm from "./UserForm";
|
import UserForm from "./UserForm";
|
||||||
import { MutedText } from "../../common/CustomTexts";
|
import { MutedText } from "../../common/CustomTexts";
|
||||||
@@ -79,15 +79,14 @@ class UserEditable extends React.Component<Props, State> {
|
|||||||
const { user, currentUserRole, currentUserEmail } = this.props;
|
const { user, currentUserRole, currentUserEmail } = this.props;
|
||||||
const { editMode } = this.state;
|
const { editMode } = this.state;
|
||||||
|
|
||||||
const editEnabled =
|
const hasPrivilege = user.role !== USER_ROLE_OWNER &&
|
||||||
user.status === USER_STATUS_ACTIVE &&
|
(currentUserRole === USER_ROLE_OWNER ||
|
||||||
currentUserRole === USER_ROLE_ADMIN &&
|
(currentUserRole === USER_ROLE_ADMIN && (user.role === USER_ROLE_MODERATOR || user.role === USER_ROLE_USER)) ||
|
||||||
|
(currentUserRole === USER_ROLE_MODERATOR && user.role === USER_ROLE_USER)) &&
|
||||||
currentUserEmail !== user.email;
|
currentUserEmail !== user.email;
|
||||||
|
|
||||||
const blockEnabled =
|
const editEnabled = hasPrivilege && user.status === USER_STATUS_ACTIVE;
|
||||||
user.status !== USER_STATUS_DELETED &&
|
const blockEnabled = hasPrivilege && user.status !== USER_STATUS_DELETED;
|
||||||
(currentUserRole === USER_ROLE_ADMIN || user.role === USER_ROLE_USER) &&
|
|
||||||
currentUserEmail !== user.email;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="userEditable">
|
<li className="userEditable">
|
||||||
|
|||||||
@@ -23,11 +23,14 @@ class UserForm extends React.Component<Props, State> {
|
|||||||
this._handleUpdateUserRole = this._handleUpdateUserRole.bind(this);
|
this._handleUpdateUserRole = this._handleUpdateUserRole.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleUpdateUserRole(selectedRole: UserRoles) {
|
_handleUpdateUserRole(selectedRole: UserRoles, currentRole: UserRoles) {
|
||||||
const { user, updateUserRole } = this.props;
|
const { user, updateUserRole } = this.props;
|
||||||
let confirmation = true;
|
let confirmation = true;
|
||||||
|
|
||||||
if (selectedRole === 'admin') {
|
if (selectedRole !== currentRole) {
|
||||||
|
if (selectedRole === 'moderator')
|
||||||
|
confirmation = confirm(I18n.t('site_settings.users.role_to_moderator_confirmation', { name: user.fullName }));
|
||||||
|
else if (selectedRole === 'admin')
|
||||||
confirmation = confirm(I18n.t('site_settings.users.role_to_admin_confirmation', { name: user.fullName }));
|
confirmation = confirm(I18n.t('site_settings.users.role_to_admin_confirmation', { name: user.fullName }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +71,7 @@ class UserForm extends React.Component<Props, State> {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button onClick={() => this._handleUpdateUserRole(selectedRole)} className="updateUserButton">
|
<Button onClick={() => this._handleUpdateUserRole(selectedRole, user.role)} className="updateUserButton">
|
||||||
{ I18n.t('common.buttons.update') }
|
{ I18n.t('common.buttons.update') }
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
export const USER_ROLE_USER = 'user';
|
export const USER_ROLE_USER = 'user';
|
||||||
export const USER_ROLE_MODERATOR = 'moderator';
|
export const USER_ROLE_MODERATOR = 'moderator';
|
||||||
export const USER_ROLE_ADMIN = 'admin';
|
export const USER_ROLE_ADMIN = 'admin';
|
||||||
|
export const USER_ROLE_OWNER = 'owner';
|
||||||
|
|
||||||
export type UserRoles =
|
export type UserRoles =
|
||||||
typeof USER_ROLE_USER |
|
typeof USER_ROLE_USER |
|
||||||
typeof USER_ROLE_MODERATOR |
|
typeof USER_ROLE_MODERATOR |
|
||||||
typeof USER_ROLE_ADMIN;
|
typeof USER_ROLE_ADMIN |
|
||||||
|
typeof USER_ROLE_OWNER;
|
||||||
|
|
||||||
// Statuses
|
// Statuses
|
||||||
export const USER_STATUS_ACTIVE = 'active';
|
export const USER_STATUS_ACTIVE = 'active';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class User < ApplicationRecord
|
|||||||
has_many :likes, dependent: :destroy
|
has_many :likes, dependent: :destroy
|
||||||
has_many :comments, dependent: :destroy
|
has_many :comments, dependent: :destroy
|
||||||
|
|
||||||
enum role: [:user, :moderator, :admin]
|
enum role: [:user, :moderator, :admin, :owner]
|
||||||
enum status: [:active, :blocked, :deleted]
|
enum status: [:active, :blocked, :deleted]
|
||||||
|
|
||||||
after_initialize :set_default_role, if: :new_record?
|
after_initialize :set_default_role, if: :new_record?
|
||||||
@@ -63,20 +63,16 @@ class User < ApplicationRecord
|
|||||||
"https://secure.gravatar.com/avatar/#{gravatar_id}"
|
"https://secure.gravatar.com/avatar/#{gravatar_id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def power_user?
|
def owner?
|
||||||
role == 'admin' || role == 'moderator'
|
role == 'owner'
|
||||||
end
|
end
|
||||||
|
|
||||||
def admin?
|
def admin?
|
||||||
role == 'admin'
|
owner? || role == 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
def moderator?
|
def moderator?
|
||||||
role == 'moderator'
|
admin? || role == 'moderator'
|
||||||
end
|
|
||||||
|
|
||||||
def user?
|
|
||||||
role == 'user'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def active?
|
def active?
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class CommentPolicy < ApplicationPolicy
|
class CommentPolicy < ApplicationPolicy
|
||||||
def permitted_attributes_for_create
|
def permitted_attributes_for_create
|
||||||
if user.power_user?
|
if user.moderator?
|
||||||
[:body, :parent_id, :is_post_update]
|
[:body, :parent_id, :is_post_update]
|
||||||
else
|
else
|
||||||
[:body, :parent_id]
|
[:body, :parent_id]
|
||||||
@@ -8,7 +8,7 @@ class CommentPolicy < ApplicationPolicy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def permitted_attributes_for_update
|
def permitted_attributes_for_update
|
||||||
if user.power_user?
|
if user.moderator?
|
||||||
[:body, :is_post_update]
|
[:body, :is_post_update]
|
||||||
else
|
else
|
||||||
[:body]
|
[:body]
|
||||||
@@ -16,10 +16,10 @@ class CommentPolicy < ApplicationPolicy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
user == record.user or user.power_user?
|
user == record.user or user.moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
user == record.user or user.power_user?
|
user == record.user or user.moderator?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -28,10 +28,10 @@ class OAuthPolicy < ApplicationPolicy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
user.admin? and user.tenant_id == record.tenant_id
|
user.admin?
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
user.admin? and user.tenant_id == record.tenant_id
|
user.admin?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -4,7 +4,7 @@ class PostPolicy < ApplicationPolicy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def permitted_attributes_for_update
|
def permitted_attributes_for_update
|
||||||
if user.power_user?
|
if user.moderator?
|
||||||
[:title, :description, :board_id, :post_status_id]
|
[:title, :description, :board_id, :post_status_id]
|
||||||
else
|
else
|
||||||
[:title, :description]
|
[:title, :description]
|
||||||
@@ -12,10 +12,10 @@ class PostPolicy < ApplicationPolicy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
user == record.user or user.power_user?
|
user == record.user or user.moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
user == record.user or user.power_user?
|
user == record.user or user.moderator?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -10,14 +10,16 @@ class UserPolicy < ApplicationPolicy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def index?
|
def index?
|
||||||
user.power_user?
|
user.moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
if user.admin?
|
if user.owner?
|
||||||
record.id != user.id
|
true
|
||||||
|
elsif user.admin?
|
||||||
|
record.role == 'moderator' || record.role == 'user'
|
||||||
elsif user.moderator?
|
elsif user.moderator?
|
||||||
record.user?
|
record.role == 'user'
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
<span class="fullname"><%= current_user.full_name %></span>
|
<span class="fullname"><%= current_user.full_name %></span>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
<% if current_user.power_user? %>
|
<% if current_user.moderator? %>
|
||||||
<%=
|
<%=
|
||||||
link_to t('header.menu.site_settings'),
|
link_to t('header.menu.site_settings'),
|
||||||
current_user.admin? ? site_settings_general_path : site_settings_users_path,
|
current_user.admin? ? site_settings_general_path : site_settings_users_path,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
boards: @boards,
|
boards: @boards,
|
||||||
postStatuses: @post_statuses,
|
postStatuses: @post_statuses,
|
||||||
isLoggedIn: user_signed_in?,
|
isLoggedIn: user_signed_in?,
|
||||||
isPowerUser: user_signed_in? ? current_user.power_user? : false,
|
isPowerUser: user_signed_in? ? current_user.moderator? : false,
|
||||||
currentUserFullName: user_signed_in? ? current_user.full_name : nil,
|
currentUserFullName: user_signed_in? ? current_user.full_name : nil,
|
||||||
currentUserEmail: user_signed_in? ? current_user.email : nil,
|
currentUserEmail: user_signed_in? ? current_user.email : nil,
|
||||||
authenticityToken: form_authenticity_token,
|
authenticityToken: form_authenticity_token,
|
||||||
|
|||||||
@@ -177,10 +177,12 @@ en:
|
|||||||
unblock: 'Unblock'
|
unblock: 'Unblock'
|
||||||
block_confirmation: "%{name} won't be able to log in until it is unblocked. Are you sure?"
|
block_confirmation: "%{name} won't be able to log in until it is unblocked. Are you sure?"
|
||||||
unblock_confirmation: "%{name} will be able to log in and submit feedback. Are you sure?"
|
unblock_confirmation: "%{name} will be able to log in and submit feedback. Are you sure?"
|
||||||
role_to_admin_confirmation: "%{name} will have the same privileges as you, so they could even demote or block you. Proceed only if you really trust %{name}. Are you sure?"
|
role_to_moderator_confirmation: "%{name} will be able to manage posts and users. Proceed only if you trust this person. Are you sure?"
|
||||||
|
role_to_admin_confirmation: "%{name} will be able to manage boards, posts, statuses, users and more. Proceed only if you trust this person. Are you sure?"
|
||||||
role_user: 'User'
|
role_user: 'User'
|
||||||
role_moderator: 'Moderator'
|
role_moderator: 'Moderator'
|
||||||
role_admin: 'Administrator'
|
role_admin: 'Administrator'
|
||||||
|
role_owner: 'Owner'
|
||||||
status_active: 'Active'
|
status_active: 'Active'
|
||||||
status_blocked: 'Blocked'
|
status_blocked: 'Blocked'
|
||||||
status_deleted: 'Deleted'
|
status_deleted: 'Deleted'
|
||||||
|
|||||||
16
db/seeds.rb
16
db/seeds.rb
@@ -7,11 +7,11 @@ tenant = Tenant.create(
|
|||||||
Current.tenant = tenant
|
Current.tenant = tenant
|
||||||
|
|
||||||
# Create an admin user and confirm its email automatically
|
# Create an admin user and confirm its email automatically
|
||||||
admin = User.create(
|
owner = User.create(
|
||||||
full_name: 'Admin',
|
full_name: 'Admin',
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
password: 'password',
|
password: 'password',
|
||||||
role: 'admin',
|
role: 'owner',
|
||||||
confirmed_at: Time.zone.now
|
confirmed_at: Time.zone.now
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,12 +58,12 @@ post1 = Post.create(
|
|||||||
title: 'Users can submit feedback by publishing posts!',
|
title: 'Users can submit feedback by publishing posts!',
|
||||||
description: 'You can assign a **status** to each post: this one, for example, is marked as "Planned". Remember that you can customise post statuses from Site settings > Statuses',
|
description: 'You can assign a **status** to each post: this one, for example, is marked as "Planned". Remember that you can customise post statuses from Site settings > Statuses',
|
||||||
board_id: feature_board.id,
|
board_id: feature_board.id,
|
||||||
user_id: admin.id,
|
user_id: owner.id,
|
||||||
post_status_id: planned_post_status.id
|
post_status_id: planned_post_status.id
|
||||||
)
|
)
|
||||||
PostStatusChange.create(
|
PostStatusChange.create(
|
||||||
post_id: post1.id,
|
post_id: post1.id,
|
||||||
user_id: admin.id,
|
user_id: owner.id,
|
||||||
post_status_id: planned_post_status.id
|
post_status_id: planned_post_status.id
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -71,17 +71,17 @@ post2 = Post.create(
|
|||||||
title: 'There are multiple boards',
|
title: 'There are multiple boards',
|
||||||
description: 'For now you have Feature Requests and Bug Reports, but you can add or remove as many as you want! Just go to Site settings > Boards!',
|
description: 'For now you have Feature Requests and Bug Reports, but you can add or remove as many as you want! Just go to Site settings > Boards!',
|
||||||
board_id: bug_board.id,
|
board_id: bug_board.id,
|
||||||
user_id: admin.id
|
user_id: owner.id
|
||||||
)
|
)
|
||||||
|
|
||||||
# # Create some comments
|
# # Create some comments
|
||||||
post1.comments.create(
|
post1.comments.create(
|
||||||
body: 'Users can comment to express their opinions! As with posts and board descriptions, comments can be *Markdown* **formatted**',
|
body: 'Users can comment to express their opinions! As with posts and board descriptions, comments can be *Markdown* **formatted**',
|
||||||
user_id: admin.id
|
user_id: owner.id
|
||||||
)
|
)
|
||||||
|
|
||||||
# Let the user know how to log in with admin account
|
# Let the user know how to log in with admin account
|
||||||
puts "A default tenant has been created with name #{tenant.site_name}"
|
puts "A default tenant has been created with name #{tenant.site_name}"
|
||||||
puts 'A default admin account has been created. Credentials:'
|
puts 'A default admin account has been created. Credentials:'
|
||||||
puts "-> email: #{admin.email}"
|
puts "-> email: #{owner.email}"
|
||||||
puts "-> password: #{admin.password}"
|
puts "-> password: #{owner.password}"
|
||||||
@@ -23,6 +23,14 @@ FactoryBot.define do
|
|||||||
role { 'admin' }
|
role { 'admin' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :owner, class: User do
|
||||||
|
sequence(:email) { |n| "owner#{n}@example.com" }
|
||||||
|
|
||||||
|
full_name { 'First Last' }
|
||||||
|
password { 'password' }
|
||||||
|
role { 'owner' }
|
||||||
|
end
|
||||||
|
|
||||||
factory :blocked, class: User do
|
factory :blocked, class: User do
|
||||||
sequence(:email) { |n| "admin#{n}@example.com" }
|
sequence(:email) { |n| "admin#{n}@example.com" }
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ RSpec.describe User, type: :model do
|
|||||||
let(:user) { FactoryBot.build(:user) }
|
let(:user) { FactoryBot.build(:user) }
|
||||||
let(:moderator) { FactoryBot.build(:moderator) }
|
let(:moderator) { FactoryBot.build(:moderator) }
|
||||||
let(:admin) { FactoryBot.build(:admin) }
|
let(:admin) { FactoryBot.build(:admin) }
|
||||||
|
let(:owner) { FactoryBot.build(:owner) }
|
||||||
|
|
||||||
it 'should be valid' do
|
it 'should be valid' do
|
||||||
expect(user).to be_valid
|
expect(user).to be_valid
|
||||||
@@ -13,14 +14,16 @@ RSpec.describe User, type: :model do
|
|||||||
expect(User.new.role).to eq('user')
|
expect(User.new.role).to eq('user')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'can have the following roles: "user", "moderator" and "admin"' do
|
it 'can have the following roles: "user", "moderator", "admin" and "owner"' do
|
||||||
expect(user.role).to eq('user')
|
expect(user.role).to eq('user')
|
||||||
expect(moderator.role).to eq('moderator')
|
expect(moderator.role).to eq('moderator')
|
||||||
expect(admin.role).to eq('admin')
|
expect(admin.role).to eq('admin')
|
||||||
|
expect(owner.role).to eq('owner')
|
||||||
|
|
||||||
expect(user).to be_valid
|
expect(user).to be_valid
|
||||||
expect(moderator).to be_valid
|
expect(moderator).to be_valid
|
||||||
expect(admin).to be_valid
|
expect(admin).to be_valid
|
||||||
|
expect(owner).to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has status "active" by default' do
|
it 'has status "active" by default' do
|
||||||
@@ -67,10 +70,25 @@ RSpec.describe User, type: :model do
|
|||||||
expect(invalid_email_user).to be_invalid
|
expect(invalid_email_user).to be_invalid
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'knows if it is a power user' do
|
it 'knows if it has moderator privileges' do
|
||||||
expect(user).not_to be_a_power_user
|
expect(user).not_to be_a_moderator
|
||||||
expect(moderator).to be_a_power_user
|
expect(moderator).to be_a_moderator
|
||||||
expect(admin).to be_a_power_user
|
expect(admin).to be_a_moderator
|
||||||
|
expect(owner).to be_a_moderator
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'knows if it has admin privileges' do
|
||||||
|
expect(user).not_to be_a_admin
|
||||||
|
expect(moderator).not_to be_a_admin
|
||||||
|
expect(admin).to be_a_admin
|
||||||
|
expect(owner).to be_a_admin
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'knows if it has owner privileges' do
|
||||||
|
expect(user).not_to be_a_owner
|
||||||
|
expect(moderator).not_to be_a_owner
|
||||||
|
expect(admin).not_to be_a_owner
|
||||||
|
expect(owner).to be_a_owner
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'knows if it is active or blocked' do
|
it 'knows if it is active or blocked' do
|
||||||
|
|||||||
43
spec/policies/board_policy_spec.rb
Normal file
43
spec/policies/board_policy_spec.rb
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe BoardPolicy do
|
||||||
|
subject { BoardPolicy.new(user, record) }
|
||||||
|
|
||||||
|
let(:record) { FactoryBot.build_stubbed(:board) }
|
||||||
|
|
||||||
|
context 'being a user' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:user) }
|
||||||
|
|
||||||
|
it { should_not permit(:create) }
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
it { should_not permit(:update_order) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a moderator' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:moderator) }
|
||||||
|
|
||||||
|
it { should_not permit(:create) }
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
it { should_not permit(:update_order) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a admin' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:admin) }
|
||||||
|
|
||||||
|
it { should permit(:create) }
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
it { should permit(:update_order) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a owner' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:owner) }
|
||||||
|
|
||||||
|
it { should permit(:create) }
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
it { should permit(:update_order) }
|
||||||
|
end
|
||||||
|
end
|
||||||
60
spec/policies/comment_policy_spec.rb
Normal file
60
spec/policies/comment_policy_spec.rb
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe CommentPolicy do
|
||||||
|
subject { CommentPolicy.new(user, record) }
|
||||||
|
|
||||||
|
let(:record) { FactoryBot.create(:comment) }
|
||||||
|
|
||||||
|
context 'being a user' do
|
||||||
|
context 'not being the comment author' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:user) }
|
||||||
|
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being the post author' do
|
||||||
|
let(:user) { FactoryBot.build(:user, id: record.user_id) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
|
||||||
|
it 'permits "body" and "parent_id" attributes for create' do
|
||||||
|
expect(subject.permitted_attributes_for_create).to eq([:body, :parent_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'permits "body" attribute for update' do
|
||||||
|
expect(subject.permitted_attributes_for_update).to eq([:body])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a moderator' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:moderator) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
|
||||||
|
it 'permits "body", "parent_id" and "is_post_update" attributes for create' do
|
||||||
|
expect(subject.permitted_attributes_for_create).to eq([:body, :parent_id, :is_post_update])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'permits "body" and "is_post_update" attribute for update' do
|
||||||
|
expect(subject.permitted_attributes_for_update).to eq([:body, :is_post_update])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a admin' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:admin) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a owner' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:owner) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
end
|
||||||
|
end
|
||||||
43
spec/policies/o_auth_policy_spec.rb
Normal file
43
spec/policies/o_auth_policy_spec.rb
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe OAuthPolicy do
|
||||||
|
subject { OAuthPolicy.new(user, record) }
|
||||||
|
|
||||||
|
let(:record) { FactoryBot.build_stubbed(:o_auth) }
|
||||||
|
|
||||||
|
context 'being a user' do
|
||||||
|
let(:user) { FactoryBot.build(:user) }
|
||||||
|
|
||||||
|
it { should_not permit(:index) }
|
||||||
|
it { should_not permit(:create) }
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a moderator' do
|
||||||
|
let(:user) { FactoryBot.build(:moderator) }
|
||||||
|
|
||||||
|
it { should_not permit(:index) }
|
||||||
|
it { should_not permit(:create) }
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a admin' do
|
||||||
|
let(:user) { FactoryBot.build(:admin) }
|
||||||
|
|
||||||
|
it { should permit(:index) }
|
||||||
|
it { should permit(:create) }
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a owner' do
|
||||||
|
let(:user) { FactoryBot.build(:owner) }
|
||||||
|
|
||||||
|
it { should permit(:index) }
|
||||||
|
it { should permit(:create) }
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
end
|
||||||
|
end
|
||||||
53
spec/policies/post_policy_spec.rb
Normal file
53
spec/policies/post_policy_spec.rb
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe PostPolicy do
|
||||||
|
subject { PostPolicy.new(user, record) }
|
||||||
|
|
||||||
|
let(:record) { FactoryBot.create(:post) }
|
||||||
|
|
||||||
|
context 'being a user' do
|
||||||
|
context 'not being the post author' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:user) }
|
||||||
|
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being the post author' do
|
||||||
|
let(:user) { FactoryBot.build(:user, id: record.user_id) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
|
||||||
|
it 'permits "title" and "description" attributes' do
|
||||||
|
expect(subject.permitted_attributes_for_update).to eq([:title, :description])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a moderator' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:moderator) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
|
||||||
|
it 'permits "title", "description", "board_id" and "post_status_id" attributes' do
|
||||||
|
permitted_attributes = [:title, :description, :board_id, :post_status_id]
|
||||||
|
expect(subject.permitted_attributes_for_update).to eq(permitted_attributes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a admin' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:admin) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a owner' do
|
||||||
|
let(:user) { FactoryBot.build_stubbed(:owner) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
end
|
||||||
|
end
|
||||||
43
spec/policies/post_status_policy_spec.rb
Normal file
43
spec/policies/post_status_policy_spec.rb
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe PostStatusPolicy do
|
||||||
|
subject { PostStatusPolicy.new(user, record) }
|
||||||
|
|
||||||
|
let(:record) { FactoryBot.build_stubbed(:post_status) }
|
||||||
|
|
||||||
|
context 'being a user' do
|
||||||
|
let(:user) { FactoryBot.build(:user) }
|
||||||
|
|
||||||
|
it { should_not permit(:create) }
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
it { should_not permit(:update_order) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a moderator' do
|
||||||
|
let(:user) { FactoryBot.build(:moderator) }
|
||||||
|
|
||||||
|
it { should_not permit(:create) }
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
it { should_not permit(:destroy) }
|
||||||
|
it { should_not permit(:update_order) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a admin' do
|
||||||
|
let(:user) { FactoryBot.build(:admin) }
|
||||||
|
|
||||||
|
it { should permit(:create) }
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
it { should permit(:update_order) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a owner' do
|
||||||
|
let(:user) { FactoryBot.build(:owner) }
|
||||||
|
|
||||||
|
it { should permit(:create) }
|
||||||
|
it { should permit(:update) }
|
||||||
|
it { should permit(:destroy) }
|
||||||
|
it { should permit(:update_order) }
|
||||||
|
end
|
||||||
|
end
|
||||||
34
spec/policies/tenant_policy_spec.rb
Normal file
34
spec/policies/tenant_policy_spec.rb
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe TenantPolicy do
|
||||||
|
subject { TenantPolicy.new(user, record) }
|
||||||
|
|
||||||
|
let(:record) { FactoryBot.build_stubbed(:tenant) }
|
||||||
|
let(:user) { nil }
|
||||||
|
|
||||||
|
it { should permit(:create) }
|
||||||
|
|
||||||
|
context 'being a user' do
|
||||||
|
let(:user) { FactoryBot.build(:user, tenant_id: record.id) }
|
||||||
|
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a moderator' do
|
||||||
|
let(:user) { FactoryBot.build(:moderator, tenant_id: record.id) }
|
||||||
|
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a admin' do
|
||||||
|
let(:user) { FactoryBot.build(:admin, tenant_id: record.id) }
|
||||||
|
|
||||||
|
it { should permit(:update) }
|
||||||
|
|
||||||
|
context 'having a tenant_id different from the tenant being updated' do
|
||||||
|
let(:user) { FactoryBot.build(:admin, tenant_id: record.id + 1) }
|
||||||
|
|
||||||
|
it { should_not permit(:update) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
106
spec/policies/user_policy_spec.rb
Normal file
106
spec/policies/user_policy_spec.rb
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe UserPolicy do
|
||||||
|
subject { UserPolicy.new(user, record) }
|
||||||
|
|
||||||
|
context 'being a user' do
|
||||||
|
let(:user) { FactoryBot.build(:user) }
|
||||||
|
let(:record) { FactoryBot.build(:user) }
|
||||||
|
|
||||||
|
it { should_not permit(:index) }
|
||||||
|
it { should_not permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a moderator' do
|
||||||
|
let(:user) { FactoryBot.build(:moderator) }
|
||||||
|
let(:record) { User }
|
||||||
|
|
||||||
|
it { should permit(:index) }
|
||||||
|
|
||||||
|
context 'acting on a user of role "user"' do
|
||||||
|
let(:record) { FactoryBot.build(:user) }
|
||||||
|
|
||||||
|
it { should permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "moderator"' do
|
||||||
|
let(:record) { FactoryBot.build(:moderator) }
|
||||||
|
|
||||||
|
it { should_not permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "admin"' do
|
||||||
|
let(:record) { FactoryBot.build(:admin) }
|
||||||
|
|
||||||
|
it { should_not permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "owner"' do
|
||||||
|
let(:record) { FactoryBot.build(:owner) }
|
||||||
|
|
||||||
|
it { should_not permit(:edit) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being an admin' do
|
||||||
|
let(:user) { FactoryBot.build(:admin) }
|
||||||
|
let(:record) { User }
|
||||||
|
|
||||||
|
it { should permit(:index) }
|
||||||
|
|
||||||
|
context 'acting on a user of role "user"' do
|
||||||
|
let(:record) { FactoryBot.build(:user) }
|
||||||
|
|
||||||
|
it { should permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "moderator"' do
|
||||||
|
let(:record) { FactoryBot.build(:moderator) }
|
||||||
|
|
||||||
|
it { should permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "admin"' do
|
||||||
|
let(:record) { FactoryBot.build(:admin) }
|
||||||
|
|
||||||
|
it { should_not permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "owner"' do
|
||||||
|
let(:record) { FactoryBot.build(:owner) }
|
||||||
|
|
||||||
|
it { should_not permit(:edit) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'being a owner' do
|
||||||
|
let(:user) { FactoryBot.build(:owner) }
|
||||||
|
let(:record) { User }
|
||||||
|
|
||||||
|
it { should permit(:index) }
|
||||||
|
|
||||||
|
context 'acting on a user of role "user"' do
|
||||||
|
let(:record) { FactoryBot.build(:user) }
|
||||||
|
|
||||||
|
it { should permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "moderator"' do
|
||||||
|
let(:record) { FactoryBot.build(:moderator) }
|
||||||
|
|
||||||
|
it { should permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "admin"' do
|
||||||
|
let(:record) { FactoryBot.build(:admin) }
|
||||||
|
|
||||||
|
it { should permit(:edit) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'acting on a user of role "owner"' do
|
||||||
|
let(:record) { FactoryBot.build(:owner) }
|
||||||
|
|
||||||
|
it { should permit(:edit) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
13
spec/support/pundit_matcher.rb
Normal file
13
spec/support/pundit_matcher.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
RSpec::Matchers.define :permit do |action|
|
||||||
|
match do |policy|
|
||||||
|
policy.public_send("#{action}?")
|
||||||
|
end
|
||||||
|
|
||||||
|
failure_message do |policy|
|
||||||
|
"#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
|
||||||
|
end
|
||||||
|
|
||||||
|
failure_message_when_negated do |policy|
|
||||||
|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user