Created
June 22, 2018 14:22
-
-
Save RStankov/ed5cc5e80ba13aed8823a3f765469ea0 to your computer and use it in GitHub Desktop.
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
module ApplicationPolicy | |
READ = :read | |
MANAGE = :manage | |
MANAGE_FIELD = { parent_role: MANAGE } # NOTE(rstankov): Used for GraphQL fields | |
UPDATE = :update | |
MODERATE = :moderate | |
extend Ship::Policy | |
extend Posts::Policy | |
# ... extend with policies | |
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
class Graph::Mutations::CommentUpdate < API::V2::Resolvers::Mutation | |
input :body, types.String | |
node :comment, type: Comment | |
authorize ApplicationPolicy::UPDATE | |
returns Graph::Types::CommentType | |
def perform | |
form = ::Comments::Update.new(comment: node, user: current_user, request_info: request_info) | |
form.update inputs | |
form | |
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
module KittyPolicy | |
def can?(user, ability, subject = :empty) | |
if subject == :empty | |
public_send Utils.rule_name(ability), user | |
else | |
public_send Utils.rule_name(ability, subject), user, subject | |
end | |
end | |
def authorize!(*args) | |
raise AccessDenied.new(*args) unless can?(*args) | |
end | |
private | |
def can(abilities, subject = nil, allow_guest: false, &block) | |
Array(abilities).each do |ability| | |
define_method Utils.rule_name(ability, subject) do |*args| | |
(args[0] || allow_guest) && !!block.call(*args) | |
end | |
end | |
end | |
class AccessDenied < StandardError | |
attr_reader :user, :ability, :subject | |
def initialize(user = nil, ability = nil, subject = nil) | |
@user = user | |
@ability = ability | |
@subject = subject | |
super 'Not authorized' | |
end | |
end | |
module Utils | |
extend self | |
def rule_name(ability, subject = nil) | |
name = "can_#{ ability }" | |
name << "_#{ subject_to_string(subject).underscore.tr('/', '_') }" if subject | |
name << '?' | |
end | |
private | |
def subject_to_string(subject) | |
case subject | |
when Class, Symbol then subject.to_s | |
when String then subject.gsub(/[^\w]/, '') | |
else subject.class.to_s | |
end | |
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
module Ship::Policy | |
extend KittyPolicy | |
can :manage, Ship::Account do |user, account| | |
account.user_id == user.id || account.memers.where(user_id: user.id).exists? | |
end | |
can :manage, Ship::Contact do |user, contact| | |
can? user, :manage, contact.account | |
end | |
can :read, Ship::Survey, allow_guest: true do |user, survey| | |
survey.published? || can?(user, :manage, survey.account) | |
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
require 'spec_helper' | |
describe Ships::Policy do | |
include SpecSupport::AuthorizationHelper | |
let(:account) { build :ship_account } | |
let(:owner) { account.user } | |
let(:member) { build(:ship_member, account: account).user } | |
let(:user) { build :user } | |
let(:guest) { nil } | |
describe "can? :manage, Ship::Survey" do | |
let(:survey) { build :ship_survey, account: account } | |
it 'returns true for account owner' do | |
expect(owner).to be_able_to ability, survey | |
end | |
it 'returns true for account members' do | |
expect(member).to be_able_to ability, survey | |
end | |
it 'returns false for other users' do | |
expect(user).not_to be_able_to ability, survey | |
end | |
it 'returns false for guest users' do | |
expect(guest).not_to be_able_to ability, survey | |
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
Graph::Types::ShipSurvey = GraphQL::ObjectType.define do | |
name 'ShipSurvey' | |
authorize ApplicationPolicy::READ | |
field :id, !types.ID | |
field :title, !types.String | |
field :can_manage, function: Graph::Resolvers::CanResolver.new(ApplicationPolicy::MANAGE_FIELD) | |
field :answers, authorize: ApplicationPolicy::MANAGE_FIELD, fallback: [], function: Graph::Resolvers::Ship::Surveys::Answers | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment