-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement customizable permissions for roles
- Loading branch information
1 parent
9aecee0
commit 23a0505
Showing
21 changed files
with
230 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# frozen_string_literal: true | ||
|
||
class TeamMemberRole < ApplicationRecord | ||
belongs_to :role, class_name: 'TeamRole', inverse_of: :member_roles | ||
belongs_to :member, class_name: 'TeamMember', inverse_of: :member_roles | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# frozen_string_literal: true | ||
|
||
class TeamRoleAbility < ApplicationRecord | ||
ABILITIES = { | ||
create_team_role: 1, | ||
read_team_role: 2, | ||
}.with_indifferent_access | ||
|
||
enum :ability, ABILITIES, prefix: :can | ||
|
||
belongs_to :team_role, inverse_of: :abilities | ||
|
||
validates :ability, presence: true, | ||
inclusion: { | ||
in: ABILITIES.keys.map(&:to_s), | ||
}, | ||
uniqueness: { scope: :team_role_id } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# frozen_string_literal: true | ||
|
||
module CustomizablePermission | ||
extend ActiveSupport::Concern | ||
|
||
class_methods do | ||
attr_reader :team_resolver_block | ||
|
||
def team_resolver(&block) | ||
@team_resolver_block = block | ||
end | ||
|
||
def customizable_permission(ability) | ||
condition(ability) { user_has_ability?(ability, @user, @subject) } | ||
|
||
rule { send ability }.enable ability | ||
end | ||
end | ||
|
||
included do | ||
def team(subject) | ||
@team ||= self.class.team_resolver_block.call(subject) | ||
end | ||
|
||
def team_member(user, subject) | ||
@team_member ||= team(subject).team_members.find_by(user: user) | ||
end | ||
|
||
def user_has_ability?(ability, user, subject) | ||
return false if team_member(user, subject).nil? | ||
|
||
team_member(user, subject).roles.joins(:abilities).exists?(team_role_abilities: { ability: ability }) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,17 @@ | ||
# frozen_string_literal: true | ||
|
||
class TeamPolicy < BasePolicy | ||
include CustomizablePermission | ||
|
||
condition(:is_member) { @subject.member?(@user) } | ||
|
||
rule { is_member }.policy do | ||
enable :read_team | ||
enable :read_team_member | ||
enable :create_team_role | ||
enable :read_team_role | ||
end | ||
|
||
team_resolver { |team| team } | ||
|
||
customizable_permission :read_team_role | ||
customizable_permission :create_team_role | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
class CreateTeamRoleAbilities < Sagittarius::Database::Migration[1.0] | ||
def change | ||
create_table :team_role_abilities do |t| | ||
t.references :team_role, null: false, foreign_key: true | ||
t.integer :ability, null: false | ||
|
||
t.index %i[team_role_id ability], unique: true | ||
|
||
t.timestamps_with_timezone | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# frozen_string_literal: true | ||
|
||
class CreateTeamMemberRoles < Sagittarius::Database::Migration[1.0] | ||
def change | ||
create_table :team_member_roles do |t| | ||
t.references :role, null: false, foreign_key: { to_table: :team_roles } | ||
t.references :member, null: false, foreign_key: { to_table: :team_members } | ||
|
||
t.timestamps_with_timezone | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
e00734fdb95a7b119f0d019b4bb0b6c00ca031e6455aba7692b44925010c410e |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
703a10ef28c2895862250b9b15d71c59f72a53e5a560c90fd9b4ba18e21de661 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :team_member_role do | ||
role factory: :team_role | ||
member factory: :team_member | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :team_role_ability do | ||
team_role | ||
ability { nil } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe TeamMemberRole do | ||
subject { create(:team_member_role) } | ||
|
||
describe 'associations' do | ||
it { is_expected.to belong_to(:role).required.inverse_of(:member_roles) } | ||
it { is_expected.to belong_to(:member).required.inverse_of(:member_roles) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe TeamRoleAbility do | ||
subject { create(:team_role_ability, ability: :create_team_role) } | ||
|
||
describe 'associations' do | ||
it { is_expected.to belong_to(:team_role).required } | ||
end | ||
|
||
describe 'validations' do | ||
it { is_expected.to validate_uniqueness_of(:ability).ignoring_case_sensitivity.scoped_to(:team_role_id) } | ||
it { is_expected.to allow_values(*described_class::ABILITIES.keys).for(:ability) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# frozen_string_literal: true | ||
|
||
module StubAbility | ||
def stub_allowed_ability(policy_class, ability, user: nil, subject: nil) | ||
# rubocop:disable RSpec/AnyInstance -- policy instances are per user and subject | ||
allow_any_instance_of(policy_class) | ||
.to receive(:user_has_ability?) | ||
.with(ability, user, subject) | ||
.and_return(true) | ||
# rubocop:enable RSpec/AnyInstance | ||
end | ||
end | ||
|
||
RSpec.configure do |config| | ||
config.include StubAbility | ||
end |