rhino-rails 4.7.2 → 4.7.3
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/lib/rhino/context.rb +37 -7
- data/lib/rhino/query.rb +35 -7
- data/lib/rhino/templates/rhino.rb +8 -2
- data/lib/rhino/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c7f50b9ced877e5d2fc1b304798f7c2c6372e89754ea1c7c9efd296c8f478c33
|
|
4
|
+
data.tar.gz: cca1fbd5f280df7e94a1fa9a69c1ca338fdfff6b76d35158afdc16fd07ef4309
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 43e7ae4d3e346c984ab8452c8dbc2f3ceb7199f35f8e3eba3f971931aed8539e752f9744393f2429125cb94b6d092358c070d719b634fa95b0cd9e314ea362e1
|
|
7
|
+
data.tar.gz: d03e920444bfcdfc0c42ddfa0d494ac180aae4fc499acd852aafc1ca6486aeccaecdff54decf4e64f65e21e5c7cb0f078ea81b3426518d7495b7e8bc3a4bc7de
|
data/lib/rhino/context.rb
CHANGED
|
@@ -30,20 +30,24 @@ module Rhino
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
# The route group
|
|
34
|
-
#
|
|
35
|
-
#
|
|
33
|
+
# The active route group: the explicit override if one is in effect (set by
|
|
34
|
+
# Rhino.in_route_group), else the group stashed into RequestStore by Rhino's
|
|
35
|
+
# own controllers and by Rhino::RouteGroupContext in custom ones.
|
|
36
|
+
#
|
|
37
|
+
# Unlike user/organization, an override never *erases* the request's group —
|
|
38
|
+
# +with+ only installs a non-nil one — so Rhino.for_user(u).query(M) inside a
|
|
39
|
+
# non-tenant request keeps that request's group.
|
|
36
40
|
def route_group
|
|
37
|
-
|
|
41
|
+
value = store[:rhino_route_group]
|
|
42
|
+
value = RequestStore.store[:rhino_route_group] if value.nil? && defined?(RequestStore)
|
|
38
43
|
|
|
39
|
-
value
|
|
40
|
-
value.nil? || value.to_s.empty? ? nil : value
|
|
44
|
+
value.nil? || value.to_s.empty? ? nil : value.to_s
|
|
41
45
|
end
|
|
42
46
|
|
|
43
47
|
# Run +block+ with the given user/organization installed into RequestStore.
|
|
44
48
|
# Snapshots the prior RequestStore user+org, sets the new ones, yields, and
|
|
45
49
|
# restores the snapshot in an ensure. Returns the block's value.
|
|
46
|
-
def with(user:, organization:)
|
|
50
|
+
def with(user:, organization:, route_group: nil)
|
|
47
51
|
return yield unless defined?(RequestStore)
|
|
48
52
|
|
|
49
53
|
had_user = RequestStore.store.key?(:rhino_current_user)
|
|
@@ -51,6 +55,13 @@ module Rhino
|
|
|
51
55
|
prev_user = RequestStore.store[:rhino_current_user]
|
|
52
56
|
prev_org = RequestStore.store[:rhino_organization]
|
|
53
57
|
|
|
58
|
+
# A route group is only ever ADDED, never cleared: with no explicit group
|
|
59
|
+
# the request's own one (if any) stays in effect.
|
|
60
|
+
had_group = RequestStore.store.key?(:rhino_route_group)
|
|
61
|
+
prev_group = RequestStore.store[:rhino_route_group]
|
|
62
|
+
had_override_group = store.key?(:rhino_route_group)
|
|
63
|
+
prev_override_group = store[:rhino_route_group]
|
|
64
|
+
|
|
54
65
|
# Track the active override so Context.user/organization prefer it even when
|
|
55
66
|
# the passed value is nil (distinguishing "explicitly nil" from "absent").
|
|
56
67
|
had_override_user = store.key?(:rhino_current_user)
|
|
@@ -63,6 +74,11 @@ module Rhino
|
|
|
63
74
|
store[:rhino_current_user] = user
|
|
64
75
|
store[:rhino_organization] = organization
|
|
65
76
|
|
|
77
|
+
if route_group
|
|
78
|
+
RequestStore.store[:rhino_route_group] = route_group.to_s
|
|
79
|
+
store[:rhino_route_group] = route_group.to_s
|
|
80
|
+
end
|
|
81
|
+
|
|
66
82
|
begin
|
|
67
83
|
yield
|
|
68
84
|
ensure
|
|
@@ -87,6 +103,20 @@ module Rhino
|
|
|
87
103
|
else
|
|
88
104
|
store.delete(:rhino_organization)
|
|
89
105
|
end
|
|
106
|
+
|
|
107
|
+
if route_group
|
|
108
|
+
if had_group
|
|
109
|
+
RequestStore.store[:rhino_route_group] = prev_group
|
|
110
|
+
else
|
|
111
|
+
RequestStore.store.delete(:rhino_route_group)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
if had_override_group
|
|
115
|
+
store[:rhino_route_group] = prev_override_group
|
|
116
|
+
else
|
|
117
|
+
store.delete(:rhino_route_group)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
90
120
|
end
|
|
91
121
|
end
|
|
92
122
|
|
data/lib/rhino/query.rb
CHANGED
|
@@ -21,9 +21,10 @@ module Rhino
|
|
|
21
21
|
#
|
|
22
22
|
# Fail closed: an org-scopable model with no org context RAISES
|
|
23
23
|
# Rhino::MissingTenantContext rather than returning an unscoped relation —
|
|
24
|
-
# unless the
|
|
25
|
-
# (`tenant: false`),
|
|
26
|
-
#
|
|
24
|
+
# unless the query belongs to a route group declared non-tenant
|
|
25
|
+
# (`tenant: false`), either because the request is served by that group or
|
|
26
|
+
# because the caller said so with Rhino.in_route_group(...). An explicit
|
|
27
|
+
# organization is always honored, in every group.
|
|
27
28
|
def query(model_class)
|
|
28
29
|
org = Rhino::Context.organization
|
|
29
30
|
|
|
@@ -53,6 +54,20 @@ module Rhino
|
|
|
53
54
|
Rhino::PendingScopedContext.new(user: user)
|
|
54
55
|
end
|
|
55
56
|
|
|
57
|
+
# Begin an explicit context that acts as the named route group, for use
|
|
58
|
+
# where no request resolves one — an Active Job, a rake task, the console,
|
|
59
|
+
# a test.
|
|
60
|
+
#
|
|
61
|
+
# The group's own configuration still decides the boundary: naming a group
|
|
62
|
+
# declared +tenant: false+ lets the query span every organization, while
|
|
63
|
+
# naming any other group keeps failing closed.
|
|
64
|
+
#
|
|
65
|
+
# Rhino.in_route_group(:admin).query(Task)
|
|
66
|
+
# Rhino.for_user(user).in_route_group(:admin).run { ... }
|
|
67
|
+
def in_route_group(route_group)
|
|
68
|
+
Rhino::PendingScopedContext.new(user: nil, route_group: route_group)
|
|
69
|
+
end
|
|
70
|
+
|
|
56
71
|
# The ambient context resolver.
|
|
57
72
|
def context
|
|
58
73
|
Rhino::Context
|
|
@@ -89,9 +104,10 @@ module Rhino
|
|
|
89
104
|
# Fluent explicit-context builder. Holds a user (and, once chained, an org) and
|
|
90
105
|
# resolves queries with that context installed into RequestStore at build time.
|
|
91
106
|
class PendingScopedContext
|
|
92
|
-
def initialize(user:, organization: nil)
|
|
107
|
+
def initialize(user:, organization: nil, route_group: nil)
|
|
93
108
|
@user = user
|
|
94
109
|
@organization = organization
|
|
110
|
+
@route_group = route_group
|
|
95
111
|
end
|
|
96
112
|
|
|
97
113
|
def in_organization(organization)
|
|
@@ -99,6 +115,18 @@ module Rhino
|
|
|
99
115
|
self
|
|
100
116
|
end
|
|
101
117
|
|
|
118
|
+
# Act as the named route group for this context (see Rhino.in_route_group).
|
|
119
|
+
def in_route_group(route_group)
|
|
120
|
+
@route_group = route_group
|
|
121
|
+
self
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Set the explicit user for this context.
|
|
125
|
+
def for_user(user)
|
|
126
|
+
@user = user
|
|
127
|
+
self
|
|
128
|
+
end
|
|
129
|
+
|
|
102
130
|
# Build a fully-baked relation for +model_class+ under this explicit context.
|
|
103
131
|
#
|
|
104
132
|
# Because Rails default_scopes bake at BUILD time, we install the user+org into
|
|
@@ -106,14 +134,14 @@ module Rhino
|
|
|
106
134
|
# The org+user are baked into the returned relation — no stickiness, fully
|
|
107
135
|
# isolated: a later Rhino.query with no context still fails closed.
|
|
108
136
|
def query(model_class)
|
|
109
|
-
Rhino::Context.with(user: @user, organization: @organization) do
|
|
137
|
+
Rhino::Context.with(user: @user, organization: @organization, route_group: @route_group) do
|
|
110
138
|
Rhino.query(model_class)
|
|
111
139
|
end
|
|
112
140
|
end
|
|
113
141
|
|
|
114
142
|
# Build a fully-baked, named-scoped relation under this explicit context.
|
|
115
143
|
def scoped_query(model_class, scope_name = nil)
|
|
116
|
-
Rhino::Context.with(user: @user, organization: @organization) do
|
|
144
|
+
Rhino::Context.with(user: @user, organization: @organization, route_group: @route_group) do
|
|
117
145
|
Rhino.scoped_query(model_class, scope_name)
|
|
118
146
|
end
|
|
119
147
|
end
|
|
@@ -122,7 +150,7 @@ module Rhino
|
|
|
122
150
|
# inside the block see the context; RequestStore is restored afterward.
|
|
123
151
|
# Returns the block's value.
|
|
124
152
|
def run(&block)
|
|
125
|
-
Rhino::Context.with(user: @user, organization: @organization, &block)
|
|
153
|
+
Rhino::Context.with(user: @user, organization: @organization, route_group: @route_group, &block)
|
|
126
154
|
end
|
|
127
155
|
end
|
|
128
156
|
end
|
|
@@ -58,8 +58,14 @@ Rhino.configure do |config|
|
|
|
58
58
|
# Custom (non-Rhino) controllers publish their group by including
|
|
59
59
|
# Rhino::RouteGroupContext and declaring `rhino_route_group :admin`, or by
|
|
60
60
|
# tagging the route with `defaults: { route_group: 'admin' }`. Outside a
|
|
61
|
-
# request (jobs, rake tasks) no group resolves
|
|
62
|
-
#
|
|
61
|
+
# request (jobs, rake tasks, console) no group resolves, so the caller names
|
|
62
|
+
# the one it is acting as:
|
|
63
|
+
#
|
|
64
|
+
# Rhino.in_route_group(:admin).query(Task)
|
|
65
|
+
# Rhino.for_user(operator).in_route_group(:admin).run { ... }
|
|
66
|
+
#
|
|
67
|
+
# The group's own `tenant:` still decides: naming a tenant group there changes
|
|
68
|
+
# nothing, the query still fails closed.
|
|
63
69
|
|
|
64
70
|
# config.route_group :default, prefix: '', middleware: [], models: :all
|
|
65
71
|
|
data/lib/rhino/version.rb
CHANGED