access_context 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c8b79da1f521761e1922742ede30f2cd14c69df038d3cfc739de86f44147b3b
4
- data.tar.gz: aa777a59f8da4674768401f67c4a46762bf2573fd3d86744bf6a626002235e82
3
+ metadata.gz: cf8fd9c40fd8ead10a5b0339819ebbe28df810da205a62ad2cfe89941719b378
4
+ data.tar.gz: 3c470c7062ef14ef0bf3b4f84de9300debfa56d6c7660a507f87ba8aacad3ec5
5
5
  SHA512:
6
- metadata.gz: 1c996e61280f3cba03af73a2eb7b344c0b5cbf2edf0b97349cc869f7fdb8b9f3098a1983ac75b50684e3ce4df8289902c3da01d9bcdb29df46fe15ffe8804e7d
7
- data.tar.gz: 78f97d10ce1e040fa72fcf34263523cbfdc5655ba336095948a9c8ad52ce6e612a4e5904d908d2c8eaa357a4dd119a9bafebcbeb1988ef2a8380295c1f83f0fb
6
+ metadata.gz: 10bc8fbdb23048b79ed04cff2331798b146697e077646795b3b84a5cd43b541a4fcbcfc7619c73c391379b4944fdc2ca2a2a2cae6710f76f6b0bef9c3b6e88d7
7
+ data.tar.gz: 2c21b244b465bf0f4e9a0b39af640dd27e57f849b3861a49022c944b77e1806a2359218e8747ed094a88f1d1f0d833f770b600d4098876f3addf7ab4ebbf9da0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.0.0] - 2026-10-10
4
+
5
+ - Add `AccessContext#granted_by_permission?` to check a context against a single permission
6
+ - `AccessContext#permit?` also checks `user.permissions` when the user responds to it
7
+ - `AccessContext#permit?` also checks `user.roles` when the user responds to it
8
+ - `AccessContext#permit?` no longer requires `user.role`; a missing or `nil` role counts as no role
9
+ - Fix loading with activesupport 7.1+
10
+
11
+ ### Upgrading from 1.x
12
+
13
+ `permit?(user)` used to check only `user.role`. It now also checks `user.roles` and `user.permissions` whenever the user responds to them. Before upgrading, check whether your `User` already has `roles` or `permissions` methods for other reasons (e.g. a `has_many :roles` association from rolify):
14
+
15
+ - `roles` must return role names (or `AccessContext::Role` objects) defined in `AccessContext.config`. Unknown names, or records that are not names, will raise.
16
+ - `permissions` must return permission names (or `AccessContext::Permission` objects) defined in `AccessContext.config`. Any matching name now grants access, and an unknown name raises `AccessContext::Error`.
17
+
18
+ If those methods mean something else in your app, rename them or pass `permit?` an object that only exposes what AccessContext should see, for example `permit?(OpenStruct.new(role: user.role))`.
19
+
3
20
  ## [1.1.0] - 2025-03-24
4
21
 
5
22
  - Able to setup context without actions
data/README.md CHANGED
@@ -63,6 +63,24 @@ AccessContext.service(:visit, :call).permit?(support) #=> true
63
63
  AccessContext.view("admin/orders", :order_edit_button).permit?(support) #=> false
64
64
  ```
65
65
 
66
+ `permit?` also supports users with several roles via `roles`, and users with their own `permissions`. Each of `role`, `roles` and `permissions` is only checked when `User` responds to it, and access is granted when any of them grants the context.
67
+
68
+ ```ruby
69
+ user = User.new(roles: [:support, :admin])
70
+ AccessContext.controller('admin/dashboard', :show).permit?(user) #=> true
71
+
72
+ support = User.new(role: :support, permissions: ['admin_default'])
73
+ AccessContext.controller('admin/dashboard', :show).permit?(support) #=> true
74
+ ```
75
+
76
+ Or check whether a specific permission grants the context, regardless of role. An unknown permission name raises `AccessContext::Error`.
77
+
78
+ ```ruby
79
+ AccessContext.controller(:home, :show).granted_by_permission?(:default) #=> true
80
+ AccessContext.controller("admin/products", :new).granted_by_permission?(:admin_default) #=> true
81
+ AccessContext.view("admin/orders", :order_edit_button).granted_by_permission?(:default) #=> false
82
+ ```
83
+
66
84
  3. Integrate it with Rails
67
85
 
68
86
  ```ruby
@@ -6,8 +6,12 @@ class AccessContext
6
6
  permissions[name.to_sym] = new(name, &block)
7
7
  end
8
8
 
9
- def [](name)
10
- permissions[name.to_sym]
9
+ def [](permission)
10
+ if permission.is_a?(Permission)
11
+ permission
12
+ else
13
+ permissions[permission.to_sym]
14
+ end
11
15
  end
12
16
 
13
17
  def all
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class AccessContext
4
- VERSION = "1.1.0"
4
+ VERSION = "2.0.0"
5
5
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "access_context/version"
4
+ require 'active_support'
4
5
  require 'active_support/dependencies/autoload'
5
6
  require 'active_support/core_ext'
6
7
 
@@ -45,7 +46,7 @@ class AccessContext
45
46
  end
46
47
 
47
48
  def permit?(user)
48
- permit_role?(user.role)
49
+ user_roles(user).any? { |role| permit_role?(role) } || permit_permissions?(user)
49
50
  end
50
51
 
51
52
  def permit_role?(role)
@@ -54,6 +55,13 @@ class AccessContext
54
55
  end
55
56
  end
56
57
 
58
+ def granted_by_permission?(permission)
59
+ granted_permission = AccessContext::Permission[permission]
60
+ raise Error, "Unknown permission: #{permission.inspect}" unless granted_permission
61
+
62
+ granted_permission.permit?(self)
63
+ end
64
+
57
65
  def contains?(context)
58
66
  type == context.type &&
59
67
  name == context.name &&
@@ -63,4 +71,21 @@ class AccessContext
63
71
  )
64
72
  end
65
73
 
74
+ private
75
+
76
+ def user_roles(user)
77
+ roles = []
78
+ roles.concat(Array(user.role)) if user.respond_to?(:role)
79
+ roles.concat(Array(user.roles)) if user.respond_to?(:roles)
80
+ roles
81
+ end
82
+
83
+ def permit_permissions?(user)
84
+ return false unless user.respond_to?(:permissions)
85
+
86
+ Array(user.permissions).any? do |permission|
87
+ granted_by_permission?(permission)
88
+ end
89
+ end
90
+
66
91
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: access_context
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hopper Gee
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-03-23 00:00:00.000000000 Z
11
+ date: 2026-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport