Class: PapersPlease::Policy

Inherits:
Object
  • Object
show all
Defined in:
lib/papers_please/policy.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user) ⇒ Policy

Returns a new instance of Policy.



9
10
11
12
13
14
15
16
# File 'lib/papers_please/policy.rb', line 9

def initialize(user)
  @user          = user
  @default_scope = nil
  @roles         = {}
  @cache         = {}

  configure
end

Instance Attribute Details

#fallthroughObject (readonly)

Returns the value of attribute fallthrough.



7
8
9
# File 'lib/papers_please/policy.rb', line 7

def fallthrough
  @fallthrough
end

#rolesObject

Returns the value of attribute roles.



5
6
7
# File 'lib/papers_please/policy.rb', line 5

def roles
  @roles
end

#userObject (readonly)

Returns the value of attribute user.



7
8
9
# File 'lib/papers_please/policy.rb', line 7

def user
  @user
end

Instance Method Details

#add_permissions(keys) ⇒ Object Also known as: permit

Add permissions to the Role



43
44
45
46
47
48
49
50
51
# File 'lib/papers_please/policy.rb', line 43

def add_permissions(keys)
  return unless block_given?

  Array(keys).each do |key|
    raise MissingRole unless roles.key?(key)

    yield roles[key]
  end
end

#add_role(name, predicate = nil) ⇒ Object Also known as: role

Add a role to the Policy

Raises:



31
32
33
34
35
36
37
38
39
# File 'lib/papers_please/policy.rb', line 31

def add_role(name, predicate = nil)
  name = name.to_sym
  raise DuplicateRole if roles.key?(name)

  role = Role.new(name, predicate: predicate)
  roles[name] = role

  role
end

#allow_fallthroughObject



18
19
20
# File 'lib/papers_please/policy.rb', line 18

def allow_fallthrough
  @fallthrough = true
end

#applicable_rolesObject

Fetch roles that apply to the current user



114
115
116
117
118
# File 'lib/papers_please/policy.rb', line 114

def applicable_roles
  @applicable_roles ||= roles.select do |_, role|
    role.applies_to?(user)
  end
end

#authorize!(action, subject) ⇒ Object

Raises:



78
79
80
81
82
# File 'lib/papers_please/policy.rb', line 78

def authorize!(action, subject)
  raise AccessDenied, "Access denied for #{action} on #{subject}" if cannot?(action, subject)

  subject
end

#can?(action, subject = nil, roles: nil) ⇒ Boolean

Look up a stored permission block and call with the current user and subject

Returns:

  • (Boolean)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/papers_please/policy.rb', line 56

def can?(action, subject = nil, roles: nil)
  roles_to_check(roles: roles).each do |_, role|
    permission = role&.find_permission(action, subject)
    next if permission.nil?

    # Proxy permission check if granted by other
    subject, permission = get_proxied_permission(permission, action, subject, role) if permission.granted_by_other?

    # Check permission
    granted = permission_granted?(permission, action, subject)
    next if granted.nil? || (granted == false && fallthrough)

    return granted
  end

  false
end

#cannot?(*args) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/papers_please/policy.rb', line 74

def cannot?(*args)
  !can?(*args)
end

#configureObject

Raises:

  • (NotImplementedError)


26
27
28
# File 'lib/papers_please/policy.rb', line 26

def configure
  raise NotImplementedError, 'The #configure method of the access policy was not implemented'
end

#default_scope(scope) ⇒ Object



22
23
24
# File 'lib/papers_please/policy.rb', line 22

def default_scope(scope)
  @default_scope = scope
end

#get_applicable_roles_by_keys(keys) ⇒ Object



84
85
86
# File 'lib/papers_please/policy.rb', line 84

def get_applicable_roles_by_keys(keys)
  applicable_roles.slice(*Array(keys))
end

#roles_that_can(action, subject) ⇒ Object



88
89
90
91
92
93
# File 'lib/papers_please/policy.rb', line 88

def roles_that_can(action, subject)
  applicable_roles.filter do |_, role|
    permission = role.find_permission(action, subject)
    permission&.granted?(user, subject, action) || false
  end.keys
end

#scope_for(action, klass, roles: nil) ⇒ Object Also known as: query

Look up a stored scope block and call with the current user and class



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/papers_please/policy.rb', line 97

def scope_for(action, klass, roles: nil)
  roles_to_check(roles: roles).each do |_, role|
    next if role.nil?

    permission = role.find_permission(action, klass)
    scope = permission&.fetch(user, klass, action)

    next if permission.nil? || (scope.nil? && fallthrough)

    return scope
  end

  @default_scope || nil
end