access_context 1.0.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 +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +19 -0
- data/lib/access_context/permission.rb +13 -5
- data/lib/access_context/version.rb +1 -1
- data/lib/access_context.rb +35 -5
- metadata +17 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cf8fd9c40fd8ead10a5b0339819ebbe28df810da205a62ad2cfe89941719b378
|
|
4
|
+
data.tar.gz: 3c470c7062ef14ef0bf3b4f84de9300debfa56d6c7660a507f87ba8aacad3ec5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 10bc8fbdb23048b79ed04cff2331798b146697e077646795b3b84a5cd43b541a4fcbcfc7619c73c391379b4944fdc2ca2a2a2cae6710f76f6b0bef9c3b6e88d7
|
|
7
|
+
data.tar.gz: 2c21b244b465bf0f4e9a0b39af640dd27e57f849b3861a49022c944b77e1806a2359218e8747ed094a88f1d1f0d833f770b600d4098876f3addf7ab4ebbf9da0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
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
|
+
|
|
20
|
+
## [1.1.0] - 2025-03-24
|
|
21
|
+
|
|
22
|
+
- Able to setup context without actions
|
|
23
|
+
|
|
3
24
|
## [1.0.0] - 2025-03-23
|
|
4
25
|
|
|
5
26
|
- Initial release
|
data/README.md
CHANGED
|
@@ -29,6 +29,7 @@ AccessContext.config do
|
|
|
29
29
|
job :welcome, :perform
|
|
30
30
|
end
|
|
31
31
|
grant 'admin_default' do
|
|
32
|
+
controller "admin/products"
|
|
32
33
|
controller 'admin/dashboard', [:show]
|
|
33
34
|
context :controller, "admin/orders", :show
|
|
34
35
|
end
|
|
@@ -62,6 +63,24 @@ AccessContext.service(:visit, :call).permit?(support) #=> true
|
|
|
62
63
|
AccessContext.view("admin/orders", :order_edit_button).permit?(support) #=> false
|
|
63
64
|
```
|
|
64
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
|
+
|
|
65
84
|
3. Integrate it with Rails
|
|
66
85
|
|
|
67
86
|
```ruby
|
|
@@ -6,8 +6,12 @@ class AccessContext
|
|
|
6
6
|
permissions[name.to_sym] = new(name, &block)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def [](
|
|
10
|
-
|
|
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
|
|
@@ -28,13 +32,17 @@ class AccessContext
|
|
|
28
32
|
|
|
29
33
|
def permit?(context)
|
|
30
34
|
contexts.any? do |c|
|
|
31
|
-
c
|
|
35
|
+
c.contains?(context)
|
|
32
36
|
end
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
def context(type, name, targets=[])
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
if targets.present?
|
|
41
|
+
([targets] || []).flatten.each do |target|
|
|
42
|
+
contexts << AccessContext.new(type, name, target)
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
contexts << AccessContext.new(type, name)
|
|
38
46
|
end
|
|
39
47
|
end
|
|
40
48
|
|
data/lib/access_context.rb
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "access_context/version"
|
|
4
|
+
require 'active_support'
|
|
5
|
+
require 'active_support/dependencies/autoload'
|
|
6
|
+
require 'active_support/core_ext'
|
|
4
7
|
|
|
5
8
|
class AccessContext
|
|
6
9
|
|
|
@@ -36,14 +39,14 @@ class AccessContext
|
|
|
36
39
|
|
|
37
40
|
attr_reader :type, :name, :target
|
|
38
41
|
|
|
39
|
-
def initialize(type, name, target)
|
|
42
|
+
def initialize(type, name, target=nil)
|
|
40
43
|
@type = type.to_sym
|
|
41
44
|
@name = name.to_sym
|
|
42
|
-
@target = target
|
|
45
|
+
@target = target&.to_sym
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
def permit?(user)
|
|
46
|
-
|
|
49
|
+
user_roles(user).any? { |role| permit_role?(role) } || permit_permissions?(user)
|
|
47
50
|
end
|
|
48
51
|
|
|
49
52
|
def permit_role?(role)
|
|
@@ -52,10 +55,37 @@ class AccessContext
|
|
|
52
55
|
end
|
|
53
56
|
end
|
|
54
57
|
|
|
55
|
-
def
|
|
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
|
+
|
|
65
|
+
def contains?(context)
|
|
56
66
|
type == context.type &&
|
|
57
67
|
name == context.name &&
|
|
58
|
-
|
|
68
|
+
(
|
|
69
|
+
target == context.target ||
|
|
70
|
+
target.blank?
|
|
71
|
+
)
|
|
72
|
+
end
|
|
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
|
|
59
89
|
end
|
|
60
90
|
|
|
61
91
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: access_context
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
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:
|
|
12
|
-
dependencies:
|
|
11
|
+
date: 2026-10-09 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: activesupport
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
13
27
|
description: Setup role with lightweight context-based permission
|
|
14
28
|
email:
|
|
15
29
|
- hopper.gee@hey.com
|