verikloak-pundit 0.1.0 → 0.2.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 +26 -0
- data/README.md +53 -2
- data/lib/generators/verikloak/pundit/install/install_generator.rb +0 -1
- data/lib/verikloak/pundit/configuration.rb +166 -3
- data/lib/verikloak/pundit/controller.rb +4 -1
- data/lib/verikloak/pundit/user_context.rb +30 -12
- data/lib/verikloak/pundit/version.rb +1 -1
- data/lib/verikloak/pundit.rb +20 -4
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6936cd5efb5ccaecf789b427db2f7cd09f358604ba334f592f3e5079ac6501c4
|
|
4
|
+
data.tar.gz: 37db6dc08acd9918bebb15bd8dbb32320e00661ffc81b1b40c85850ec1c0822c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 120391c41f3f769ce49d7bddd83bed04b010ea367d8b63ddedb5de4610f9f8a6600f29f56f84c929b2209e4c26d6825a3d774ae1f32c20f16dd6d53378d5f9bf
|
|
7
|
+
data.tar.gz: a6d8babf7f27a842105fcc9ba44a42f9c73a21c45eeb486339c9afddca8aa1a6df97720c944407945ebd02a7918455bbb235b3e74de39025594d50d8babf0014
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2025-09-21
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Allow `permission_role_scope = :all_resources` to respect the new
|
|
14
|
+
`permission_resource_clients` whitelist so only approved clients contribute
|
|
15
|
+
to permission checks.
|
|
16
|
+
- Document verikloak-bff and verikloak-audience integration patterns,
|
|
17
|
+
including `env_claims_key` examples and role naming guidance.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- `UserContext` now snapshots the configuration at initialization to keep
|
|
21
|
+
behavior consistent even if `Verikloak::Pundit.configure` runs mid-request.
|
|
22
|
+
- Bump the minimum `verikloak` runtime dependency to `>= 0.1.5` to pick up
|
|
23
|
+
client whitelist support.
|
|
24
|
+
|
|
25
|
+
## [0.1.1] - 2025-09-20
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- Optional exposure flag for the Rails helper (`expose_helper_method`) so claims can stay hidden from views when not needed.
|
|
29
|
+
- Continuous integration job that installs the latest `verikloak` and `verikloak-rails` releases and executes `integration/check.rb` to verify compatibility.
|
|
30
|
+
- Detailed operational guidance in README/ERRORS explaining the risks of `permission_role_scope = :all_resources` and helper exposure.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- Configuration publishing now duplicates nested structures and freezes them, reducing race conditions when reconfiguring at runtime.
|
|
34
|
+
- `integration/check.rb` now exercises realm/resource roles, permission scopes, and helper exposure to catch regressions early.
|
|
35
|
+
|
|
10
36
|
## [0.1.0] - 2025-09-20
|
|
11
37
|
|
|
12
38
|
### Added
|
data/README.md
CHANGED
|
@@ -11,8 +11,6 @@ Pundit integration for the **Verikloak** family. This gem maps **Keycloak roles*
|
|
|
11
11
|
- Provides a `pundit_user` hook so policies can use `user.has_role?(:admin)` etc.
|
|
12
12
|
- Keeps role mapping **configurable** (project-specific mappings differ).
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
14
|
## Features
|
|
17
15
|
|
|
18
16
|
- **UserContext**: lightweight wrapper around JWT claims
|
|
@@ -88,10 +86,38 @@ Verikloak::Pundit.configure do |c|
|
|
|
88
86
|
# Permission mapping scope for `user.has_permission?`:
|
|
89
87
|
# :default_resource => realm roles + default client roles (recommended)
|
|
90
88
|
# :all_resources => realm roles + roles from all clients in resource_access
|
|
89
|
+
# (enabling this broadens permissions to every resource client;
|
|
90
|
+
# review the upstream role assignments before turning it on)
|
|
91
91
|
c.permission_role_scope = :default_resource
|
|
92
|
+
# Optional whitelist of resource clients when `permission_role_scope = :all_resources`.
|
|
93
|
+
# Leaving this as nil keeps the legacy "all clients" behavior, while providing
|
|
94
|
+
# an explicit list (e.g., %w[rails-api verikloak-bff]) limits which clients can
|
|
95
|
+
# contribute roles to permission checks.
|
|
96
|
+
c.permission_resource_clients = nil
|
|
97
|
+
|
|
98
|
+
# Expose `verikloak_claims` to views via helper_method (Rails only)
|
|
99
|
+
c.expose_helper_method = true
|
|
92
100
|
end
|
|
93
101
|
```
|
|
94
102
|
|
|
103
|
+
### Working with other Verikloak gems
|
|
104
|
+
|
|
105
|
+
- **verikloak-bff**: When your Rails application sits behind the BFF, the access
|
|
106
|
+
token presented to verikloak-pundit typically originates from the BFF
|
|
107
|
+
(e.g. via the `x-verikloak-user` header). Make sure your Rack stack stores the
|
|
108
|
+
decoded claims under the same `env_claims_key` configured above (the default
|
|
109
|
+
`"verikloak.user"` works out of the box with `verikloak-bff >= 0.3`). If the
|
|
110
|
+
BFF issues tokens for multiple downstream services, set
|
|
111
|
+
`permission_resource_clients` to the limited list of clients whose roles should
|
|
112
|
+
affect Rails-side authorization to avoid accidentally inheriting permissions
|
|
113
|
+
meant for other services.
|
|
114
|
+
- **verikloak-audience**: Audience services often mint resource roles with a
|
|
115
|
+
service-specific prefix (for example, `audience-service:editor`). Align your
|
|
116
|
+
`role_map` keys with that naming convention so `user.has_permission?` resolves
|
|
117
|
+
correctly. If Audience adds its own client entry inside `resource_access`, add
|
|
118
|
+
that client id to `permission_resource_clients` when you need to consume those
|
|
119
|
+
roles from Rails.
|
|
120
|
+
|
|
95
121
|
## Non-Rails / custom usage
|
|
96
122
|
|
|
97
123
|
```ruby
|
|
@@ -114,12 +140,37 @@ docker compose run --rm dev rspec
|
|
|
114
140
|
docker compose run --rm dev rubocop -a
|
|
115
141
|
```
|
|
116
142
|
|
|
143
|
+
An additional integration check exercises the gem together with the latest `verikloak` and `verikloak-rails` releases. This runs in CI automatically, and you can execute it locally with:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
docker compose run --rm -e BUNDLE_FROZEN=0 dev bash -lc '
|
|
147
|
+
cd integration && \
|
|
148
|
+
apk add --no-cache --virtual .integration-build-deps \
|
|
149
|
+
build-base \
|
|
150
|
+
linux-headers \
|
|
151
|
+
openssl-dev \
|
|
152
|
+
yaml-dev && \
|
|
153
|
+
bundle config set --local path vendor/bundle && \
|
|
154
|
+
bundle install --jobs 4 --retry 3 && \
|
|
155
|
+
bundle exec ruby check.rb && \
|
|
156
|
+
apk del .integration-build-deps
|
|
157
|
+
'
|
|
158
|
+
```
|
|
159
|
+
|
|
117
160
|
## Contributing
|
|
118
161
|
Bug reports and pull requests are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
119
162
|
|
|
120
163
|
## Security
|
|
121
164
|
If you find a security vulnerability, please follow the instructions in [SECURITY.md](SECURITY.md).
|
|
122
165
|
|
|
166
|
+
### Operational guidance
|
|
167
|
+
- Enabling `permission_role_scope = :all_resources` pulls roles from every Keycloak client in `resource_access`. Review the granted roles carefully to ensure you are not expanding permissions beyond what the application expects.
|
|
168
|
+
- Combine `permission_role_scope = :all_resources` with `permission_resource_clients`
|
|
169
|
+
to explicitly opt-in the clients that may contribute permissions. Leaving the
|
|
170
|
+
whitelist blank (the default) reverts to the legacy behavior of trusting
|
|
171
|
+
every client in the token.
|
|
172
|
+
- Leaving `expose_helper_method = true` exposes `verikloak_claims` to the Rails view layer. If the claims include personal or sensitive data, consider switching it to `false` and pass only the minimum required information through controller-provided helpers.
|
|
173
|
+
|
|
123
174
|
## License
|
|
124
175
|
This project is licensed under the [MIT License](LICENSE).
|
|
125
176
|
|
|
@@ -11,7 +11,6 @@ module Verikloak
|
|
|
11
11
|
desc 'Creates Verikloak Pundit initializer and a base ApplicationPolicy (optional).'
|
|
12
12
|
|
|
13
13
|
# Skip creating application_policy.rb
|
|
14
|
-
# @return [Boolean]
|
|
15
14
|
class_option :skip_policy, type: :boolean, default: false, desc: 'Do not create application_policy.rb'
|
|
16
15
|
|
|
17
16
|
# Create the initializer file under config/initializers.
|
|
@@ -16,13 +16,67 @@ module Verikloak
|
|
|
16
16
|
# @return [Array<String,Proc>] path inside JWT claims to reach resource roles
|
|
17
17
|
# @!attribute permission_role_scope
|
|
18
18
|
# @return [Symbol] :default_resource or :all_resources for permission mapping scope
|
|
19
|
+
# @!attribute permission_resource_clients
|
|
20
|
+
# @return [Array<String>, nil] list of resource clients allowed when
|
|
21
|
+
# {#permission_role_scope} is `:all_resources`. `nil` permits every client.
|
|
22
|
+
# @!attribute expose_helper_method
|
|
23
|
+
# @return [Boolean] whether to register `verikloak_claims` as a Rails helper method
|
|
19
24
|
class Configuration
|
|
20
25
|
attr_accessor :resource_client, :role_map, :env_claims_key,
|
|
21
26
|
:realm_roles_path, :resource_roles_path,
|
|
22
|
-
:permission_role_scope
|
|
27
|
+
:permission_role_scope, :permission_resource_clients,
|
|
28
|
+
:expose_helper_method
|
|
23
29
|
|
|
24
|
-
#
|
|
25
|
-
|
|
30
|
+
# Build a new configuration, optionally copying values from another
|
|
31
|
+
# configuration so callers can mutate a safe duplicate.
|
|
32
|
+
#
|
|
33
|
+
# @param copy_from [Configuration, nil]
|
|
34
|
+
def initialize(copy_from = nil)
|
|
35
|
+
if copy_from
|
|
36
|
+
initialize_from(copy_from)
|
|
37
|
+
else
|
|
38
|
+
initialize_defaults
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Create a deep-ish copy that can be safely mutated without affecting the
|
|
43
|
+
# source configuration. `dup` is overridden so the object returned from
|
|
44
|
+
# `Verikloak::Pundit.config.dup` behaves as expected.
|
|
45
|
+
#
|
|
46
|
+
# @return [Configuration]
|
|
47
|
+
def dup
|
|
48
|
+
self.class.new(self)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Duplicate the configuration via Ruby's `dup`, ensuring the new instance
|
|
52
|
+
# receives freshly-copied nested state.
|
|
53
|
+
#
|
|
54
|
+
# @param other [Configuration]
|
|
55
|
+
def initialize_copy(other)
|
|
56
|
+
super
|
|
57
|
+
initialize_from(other)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Freeze the configuration and its nested structures to prevent runtime
|
|
61
|
+
# mutations once it is published to the global state. Returns `self` to
|
|
62
|
+
# allow chaining inside callers.
|
|
63
|
+
#
|
|
64
|
+
# @return [Configuration]
|
|
65
|
+
def finalize!
|
|
66
|
+
@resource_client = freeze_string(@resource_client)
|
|
67
|
+
@env_claims_key = freeze_string(@env_claims_key)
|
|
68
|
+
@role_map = dup_hash(@role_map).freeze
|
|
69
|
+
@realm_roles_path = dup_array(@realm_roles_path).freeze
|
|
70
|
+
@resource_roles_path = dup_array(@resource_roles_path).freeze
|
|
71
|
+
@permission_resource_clients = freeze_permission_clients(@permission_resource_clients)
|
|
72
|
+
@expose_helper_method = !@expose_helper_method.nil? && @expose_helper_method
|
|
73
|
+
freeze
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
# Populate default values that mirror the gem's out-of-the-box behavior.
|
|
79
|
+
def initialize_defaults
|
|
26
80
|
@resource_client = 'rails-api'
|
|
27
81
|
@role_map = {} # e.g., { admin: :manage_all }
|
|
28
82
|
@env_claims_key = 'verikloak.user'
|
|
@@ -32,6 +86,115 @@ module Verikloak
|
|
|
32
86
|
# rubocop:enable Style/SymbolProc
|
|
33
87
|
# :default_resource (realm + default client), :all_resources (realm + all clients)
|
|
34
88
|
@permission_role_scope = :default_resource
|
|
89
|
+
@permission_resource_clients = nil
|
|
90
|
+
@expose_helper_method = true
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Copy configuration fields from another instance, duplicating mutable
|
|
94
|
+
# structures so future writes do not leak across instances.
|
|
95
|
+
#
|
|
96
|
+
# @param other [Configuration]
|
|
97
|
+
def initialize_from(other)
|
|
98
|
+
@resource_client = dup_string(other.resource_client)
|
|
99
|
+
@role_map = dup_hash(other.role_map)
|
|
100
|
+
@env_claims_key = dup_string(other.env_claims_key)
|
|
101
|
+
@realm_roles_path = dup_array(other.realm_roles_path)
|
|
102
|
+
@resource_roles_path = dup_array(other.resource_roles_path)
|
|
103
|
+
@permission_role_scope = other.permission_role_scope
|
|
104
|
+
@permission_resource_clients = dup_array(other.permission_resource_clients)
|
|
105
|
+
@expose_helper_method = other.expose_helper_method
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Duplicate and freeze a string value, returning `nil` when appropriate.
|
|
109
|
+
#
|
|
110
|
+
# @param value [String, nil]
|
|
111
|
+
# @return [String, nil]
|
|
112
|
+
def freeze_string(value)
|
|
113
|
+
return nil if value.nil?
|
|
114
|
+
|
|
115
|
+
dup_string(value).freeze
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Recursively duplicate a hash, cloning nested structures so the copy can
|
|
119
|
+
# be mutated safely.
|
|
120
|
+
#
|
|
121
|
+
# @param value [Hash, nil]
|
|
122
|
+
# @return [Hash, nil]
|
|
123
|
+
def dup_hash(value)
|
|
124
|
+
return nil if value.nil?
|
|
125
|
+
|
|
126
|
+
copy = value.dup
|
|
127
|
+
copy.each do |key, element|
|
|
128
|
+
copy[key] =
|
|
129
|
+
case element
|
|
130
|
+
when Hash
|
|
131
|
+
dup_hash(element)
|
|
132
|
+
when Array
|
|
133
|
+
dup_array(element)
|
|
134
|
+
when String
|
|
135
|
+
dup_string(element)
|
|
136
|
+
else
|
|
137
|
+
duplicable?(element) ? element.dup : element
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
copy
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Duplicate a string guardingly, returning `nil` when no value is present.
|
|
144
|
+
#
|
|
145
|
+
# @param value [String, nil]
|
|
146
|
+
# @return [String, nil]
|
|
147
|
+
def dup_string(value)
|
|
148
|
+
return nil if value.nil?
|
|
149
|
+
|
|
150
|
+
value.dup
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Recursively duplicate an array while copying nested structures.
|
|
154
|
+
#
|
|
155
|
+
# @param value [Array, nil]
|
|
156
|
+
# @return [Array, nil]
|
|
157
|
+
def dup_array(value)
|
|
158
|
+
return nil if value.nil?
|
|
159
|
+
|
|
160
|
+
copy = value.dup
|
|
161
|
+
return copy unless copy.respond_to?(:map)
|
|
162
|
+
|
|
163
|
+
copy.map do |element|
|
|
164
|
+
case element
|
|
165
|
+
when Hash
|
|
166
|
+
dup_hash(element)
|
|
167
|
+
when Array
|
|
168
|
+
dup_array(element)
|
|
169
|
+
when String
|
|
170
|
+
dup_string(element)
|
|
171
|
+
else
|
|
172
|
+
duplicable?(element) ? element.dup : element
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Check whether a value can be safely duplicated using `dup`.
|
|
178
|
+
#
|
|
179
|
+
# @param value [Object]
|
|
180
|
+
# @return [Boolean]
|
|
181
|
+
def duplicable?(value)
|
|
182
|
+
return false if value.nil?
|
|
183
|
+
return false if [true, false].include?(value)
|
|
184
|
+
return false if value.is_a?(Symbol) || value.is_a?(Numeric) || value.is_a?(Proc)
|
|
185
|
+
|
|
186
|
+
value.respond_to?(:dup)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Normalize and freeze the configured permission clients list.
|
|
190
|
+
#
|
|
191
|
+
# @param value [Array<String, Symbol>, nil]
|
|
192
|
+
# @return [Array<String>, nil]
|
|
193
|
+
def freeze_permission_clients(value)
|
|
194
|
+
array = dup_array(value)
|
|
195
|
+
return nil if array.nil?
|
|
196
|
+
|
|
197
|
+
array.compact.map(&:to_s).uniq.freeze
|
|
35
198
|
end
|
|
36
199
|
end
|
|
37
200
|
end
|
|
@@ -7,7 +7,10 @@ module Verikloak
|
|
|
7
7
|
# Hook used by Rails to include helper methods in views when available.
|
|
8
8
|
# @param base [Class]
|
|
9
9
|
def self.included(base)
|
|
10
|
-
|
|
10
|
+
return unless base.respond_to?(:helper_method)
|
|
11
|
+
|
|
12
|
+
config = Verikloak::Pundit.config
|
|
13
|
+
base.helper_method :verikloak_claims if config.expose_helper_method
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
# Pundit hook returning the UserContext built from Rack env claims.
|
|
@@ -4,15 +4,17 @@ module Verikloak
|
|
|
4
4
|
module Pundit
|
|
5
5
|
# Lightweight wrapper around Keycloak claims for Pundit policies.
|
|
6
6
|
class UserContext
|
|
7
|
-
attr_reader :claims, :resource_client
|
|
7
|
+
attr_reader :claims, :resource_client, :config
|
|
8
8
|
|
|
9
9
|
# Create a new user context from JWT claims.
|
|
10
10
|
#
|
|
11
11
|
# @param claims [Hash] JWT claims issued by Keycloak
|
|
12
12
|
# @param resource_client [String] default resource client name for resource roles
|
|
13
|
-
|
|
13
|
+
# @param config [Verikloak::Pundit::Configuration] configuration snapshot to use
|
|
14
|
+
def initialize(claims, resource_client: nil, config: nil)
|
|
15
|
+
@config = config || Verikloak::Pundit.config
|
|
14
16
|
@claims = claims || {}
|
|
15
|
-
@resource_client = resource_client.to_s
|
|
17
|
+
@resource_client = (resource_client || @config.resource_client).to_s
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
# Subject identifier from claims.
|
|
@@ -30,7 +32,7 @@ module Verikloak
|
|
|
30
32
|
# Realm-level roles from claims based on configuration path.
|
|
31
33
|
# @return [Array<String>]
|
|
32
34
|
def realm_roles
|
|
33
|
-
path = resolve_path(
|
|
35
|
+
path = resolve_path(config.realm_roles_path)
|
|
34
36
|
Array(claims.dig(*path))
|
|
35
37
|
end
|
|
36
38
|
|
|
@@ -40,7 +42,7 @@ module Verikloak
|
|
|
40
42
|
# @return [Array<String>]
|
|
41
43
|
def resource_roles(client = resource_client)
|
|
42
44
|
client = client.to_s
|
|
43
|
-
path = resolve_path(
|
|
45
|
+
path = resolve_path(config.resource_roles_path, client: client)
|
|
44
46
|
Array(claims.dig(*path))
|
|
45
47
|
end
|
|
46
48
|
|
|
@@ -82,7 +84,7 @@ module Verikloak
|
|
|
82
84
|
def has_permission?(perm) # rubocop:disable Naming/PredicatePrefix
|
|
83
85
|
pr = perm.to_sym
|
|
84
86
|
roles = realm_roles + resource_roles_scope
|
|
85
|
-
mapped = roles.map { |r| RoleMapper.map(r,
|
|
87
|
+
mapped = roles.map { |r| RoleMapper.map(r, config) }
|
|
86
88
|
mapped.map(&:to_sym).include?(pr)
|
|
87
89
|
end
|
|
88
90
|
|
|
@@ -91,8 +93,9 @@ module Verikloak
|
|
|
91
93
|
# @param env [Hash] Rack environment
|
|
92
94
|
# @return [UserContext]
|
|
93
95
|
def self.from_env(env)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
config = Verikloak::Pundit.config
|
|
97
|
+
claims = env[config.env_claims_key]
|
|
98
|
+
new(claims, config: config)
|
|
96
99
|
end
|
|
97
100
|
|
|
98
101
|
private
|
|
@@ -108,9 +111,9 @@ module Verikloak
|
|
|
108
111
|
when Proc
|
|
109
112
|
# Support lambdas that accept (config) or (config, client)
|
|
110
113
|
if seg.arity >= 2
|
|
111
|
-
seg.call(
|
|
114
|
+
seg.call(config, client).to_s
|
|
112
115
|
else
|
|
113
|
-
seg.call(
|
|
116
|
+
seg.call(config).to_s
|
|
114
117
|
end
|
|
115
118
|
else
|
|
116
119
|
seg.to_s
|
|
@@ -121,7 +124,7 @@ module Verikloak
|
|
|
121
124
|
# Resolve resource roles based on configured permission scope.
|
|
122
125
|
# @return [Array<String>]
|
|
123
126
|
def resource_roles_scope
|
|
124
|
-
case
|
|
127
|
+
case config.permission_role_scope&.to_sym
|
|
125
128
|
when :all_resources
|
|
126
129
|
resource_roles_all_clients
|
|
127
130
|
else
|
|
@@ -137,7 +140,22 @@ module Verikloak
|
|
|
137
140
|
|
|
138
141
|
# Bypass configured path lambda (which targets the default client)
|
|
139
142
|
# and gather roles from all clients explicitly.
|
|
140
|
-
access.
|
|
143
|
+
access.each_with_object([]) do |(client_id, entry), roles|
|
|
144
|
+
next unless permission_client_allowed?(client_id)
|
|
145
|
+
|
|
146
|
+
roles.concat(Array(entry['roles']))
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Check whether the given client is allowed for permission scope.
|
|
151
|
+
#
|
|
152
|
+
# @param client_id [String]
|
|
153
|
+
# @return [Boolean]
|
|
154
|
+
def permission_client_allowed?(client_id)
|
|
155
|
+
whitelist = config.permission_resource_clients
|
|
156
|
+
return true if whitelist.nil?
|
|
157
|
+
|
|
158
|
+
whitelist.include?(client_id.to_s)
|
|
141
159
|
end
|
|
142
160
|
end
|
|
143
161
|
end
|
data/lib/verikloak/pundit.rb
CHANGED
|
@@ -19,16 +19,32 @@ module Verikloak
|
|
|
19
19
|
# @yield [Configuration] Yields the configuration instance for mutation.
|
|
20
20
|
# @return [Configuration] the current configuration after applying changes
|
|
21
21
|
def configure
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
new_config = nil
|
|
23
|
+
config_mutex.synchronize do
|
|
24
|
+
current = @config&.dup || Configuration.new
|
|
25
|
+
yield current if block_given?
|
|
26
|
+
new_config = current.finalize!
|
|
27
|
+
@config = new_config
|
|
28
|
+
end
|
|
29
|
+
new_config
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
# Access the current configuration without mutating it.
|
|
28
33
|
#
|
|
29
34
|
# @return [Configuration]
|
|
30
35
|
def config
|
|
31
|
-
|
|
36
|
+
config_mutex.synchronize do
|
|
37
|
+
@config ||= Configuration.new.finalize!
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# Mutex protecting configuration reads/writes to maintain thread safety.
|
|
44
|
+
#
|
|
45
|
+
# @return [Mutex]
|
|
46
|
+
def config_mutex
|
|
47
|
+
@config_mutex ||= Mutex.new
|
|
32
48
|
end
|
|
33
49
|
end
|
|
34
50
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: verikloak-pundit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- taiyaky
|
|
@@ -49,20 +49,20 @@ dependencies:
|
|
|
49
49
|
requirements:
|
|
50
50
|
- - ">="
|
|
51
51
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: 0.1.
|
|
52
|
+
version: 0.1.5
|
|
53
53
|
- - "<"
|
|
54
54
|
- !ruby/object:Gem::Version
|
|
55
|
-
version:
|
|
55
|
+
version: 1.0.0
|
|
56
56
|
type: :runtime
|
|
57
57
|
prerelease: false
|
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
|
59
59
|
requirements:
|
|
60
60
|
- - ">="
|
|
61
61
|
- !ruby/object:Gem::Version
|
|
62
|
-
version: 0.1.
|
|
62
|
+
version: 0.1.5
|
|
63
63
|
- - "<"
|
|
64
64
|
- !ruby/object:Gem::Version
|
|
65
|
-
version:
|
|
65
|
+
version: 1.0.0
|
|
66
66
|
description: Maps Keycloak JWT roles to a Pundit-friendly UserContext with helpers
|
|
67
67
|
and a Rails generator.
|
|
68
68
|
executables: []
|
|
@@ -92,7 +92,7 @@ metadata:
|
|
|
92
92
|
source_code_uri: https://github.com/taiyaky/verikloak-pundit
|
|
93
93
|
changelog_uri: https://github.com/taiyaky/verikloak-pundit/blob/main/CHANGELOG.md
|
|
94
94
|
bug_tracker_uri: https://github.com/taiyaky/verikloak-pundit/issues
|
|
95
|
-
documentation_uri: https://rubydoc.info/gems/verikloak-pundit/0.
|
|
95
|
+
documentation_uri: https://rubydoc.info/gems/verikloak-pundit/0.2.0
|
|
96
96
|
rubygems_mfa_required: 'true'
|
|
97
97
|
rdoc_options: []
|
|
98
98
|
require_paths:
|