Skip to content

Commit 476e78f

Browse files
jason-price-mongodbjason-price-mongodb
andauthored
DOCSP-28090 user-roles-in-aggregations (#3235)
* DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations * DOCSP-28090-user-roles-in-aggregations --------- Co-authored-by: jason-price-mongodb <[email protected]>
1 parent c180d50 commit 476e78f

16 files changed

+461
-7
lines changed

source/core/views/create-view.txt

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ Some operations are not available with views:
7676

7777
For more information, see :ref:`views-supported-operations`.
7878

79-
Example
80-
-------
79+
Examples
80+
--------
8181

82-
This example populates a collection with student data and creates a view
83-
to query the data.
82+
The first example populates a collection with student data and creates a
83+
view to query the data.
8484

8585
Populate the Collection
8686
~~~~~~~~~~~~~~~~~~~~~~~
@@ -202,6 +202,129 @@ lowercase letters.
202202
{ sID: 17301, name: 'harley', year: 6, score: 3.1 }
203203
]
204204

205+
.. _create-view-user-roles-system-variable-example:
206+
207+
Retrieve Documents for Roles Granted to the Current User
208+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
209+
210+
.. include:: /includes/user-roles-system-variable-introduction.rst
211+
212+
Perform the following steps to create a view and retrieve the documents
213+
accessible to ``John``:
214+
215+
.. procedure::
216+
:style: normal
217+
218+
.. step:: Create the view
219+
220+
.. include:: /includes/user-roles-system-variable-example-description-start.rst
221+
222+
Run:
223+
224+
.. code-block:: javascript
225+
:emphasize-lines: 7
226+
227+
db.createView(
228+
"budgetView", "budget",
229+
[ {
230+
$match: {
231+
$expr: {
232+
$not: {
233+
$eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
234+
}
235+
}
236+
}
237+
} ]
238+
)
239+
240+
If you cannot create the view, ensure you log in as a user with
241+
the privilege to create a view.
242+
243+
.. include:: /includes/user-roles-system-variable-example-description.rst
244+
245+
.. step:: Log in as John
246+
247+
.. include:: /includes/user-roles-system-variable-example-login-john.rst
248+
249+
.. step:: Retrieve the documents
250+
251+
Run:
252+
253+
.. code-block:: javascript
254+
255+
db.budgetView.find()
256+
257+
.. step:: Examine the documents
258+
259+
.. include:: /includes/user-roles-system-variable-example-output-john.rst
260+
261+
Perform the following steps to retrieve the documents accessible to
262+
Jane:
263+
264+
.. procedure::
265+
:style: normal
266+
267+
.. step:: Log in as ``Jane``
268+
269+
.. include:: /includes/user-roles-system-variable-example-login-jane.rst
270+
271+
.. step:: Retrieve the documents
272+
273+
Run:
274+
275+
.. code-block:: javascript
276+
277+
db.budgetView.find()
278+
279+
.. step:: Examine the documents
280+
281+
.. include:: /includes/user-roles-system-variable-example-output-jane.rst
282+
283+
Roles with the Same Name in Multiple Databases
284+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
285+
286+
Multiple databases can have roles with the same name. If you create a
287+
view and reference a specific role in the view, you should either
288+
specify both the ``db`` database name field and the ``role`` field, or
289+
specify the ``_id`` field that contains the database name and the role.
290+
291+
The following example returns the roles assigned to ``Jane``, who has
292+
roles with different names. The example returns the ``_id``, ``role``,
293+
and ``db`` database name:
294+
295+
.. procedure::
296+
:style: normal
297+
298+
.. step:: Log in as ``Jane``
299+
300+
.. include:: /includes/user-roles-system-variable-example-login-jane.rst
301+
302+
.. step:: Retrieve the documents
303+
304+
Run:
305+
306+
.. code-block:: javascript
307+
308+
db.budget.findOne( {}, { myRoles: "$$USER_ROLES" } )
309+
310+
.. step:: Examine the documents
311+
312+
Example output, which shows the ``_id``, ``role``, and ``db``
313+
database name in the ``myRoles`` array:
314+
315+
.. code-block:: javascript
316+
:copyable: false
317+
:emphasize-lines: 3-6
318+
319+
{
320+
_id: 0,
321+
myRoles: [
322+
{ _id: 'test.Operations', role: 'Operations', db: 'test' },
323+
{ _id: 'test.Sales', role: 'Sales', db: 'test' },
324+
{ _id: 'test.read', role: 'read', db: 'test' }
325+
]
326+
}
327+
205328
Behavior
206329
--------
207330

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
To use a system variable, add ``$$`` to the start of the variable name.
2+
The ``USER_ROLES`` system variable is specified as ``$$USER_ROLES`` as
3+
shown in the following example.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
The previous example returns the documents from the ``budget``
2+
collection that match at least one of the roles that the user who runs
3+
the example has. To do that, the example uses
4+
:expression:`$setIntersection` to return documents where the
5+
intersection between the ``budget`` document ``allowedRoles`` field and
6+
the set of user roles from ``$$USER_ROLES`` is not empty.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Run:
2+
3+
.. code-block:: javascript
4+
:emphasize-lines: 4
5+
6+
db.budget.find( {
7+
$expr: {
8+
$not: {
9+
$eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
10+
}
11+
}
12+
} )
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Run:
2+
3+
.. code-block:: javascript
4+
5+
db.auth( "Jane", "je009" )
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Run:
2+
3+
.. code-block:: javascript
4+
5+
db.auth( "John", "jn008" )
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
``Jane`` has the ``Sales`` and ``Operations`` roles, and sees these
2+
documents:
3+
4+
.. code-block:: javascript
5+
:copyable: false
6+
7+
[
8+
{
9+
_id: 1,
10+
allowedRoles: [ 'Sales' ],
11+
comment: 'For sales team',
12+
yearlyBudget: 17000,
13+
salesEventsBudget: 1000
14+
},
15+
{
16+
_id: 2,
17+
allowedRoles: [ 'Operations' ],
18+
comment: 'For operations team',
19+
yearlyBudget: 19000,
20+
cloudBudget: 12000
21+
}
22+
]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
``John`` has the ``Marketing``, ``Operations``, and ``Development``
2+
roles, and sees these documents:
3+
4+
.. code-block:: javascript
5+
:copyable: false
6+
7+
[
8+
{
9+
_id: 0,
10+
allowedRoles: [ 'Marketing' ],
11+
comment: 'For marketing team',
12+
yearlyBudget: 15000
13+
},
14+
{
15+
_id: 2,
16+
allowedRoles: [ 'Operations' ],
17+
comment: 'For operations team',
18+
yearlyBudget: 19000,
19+
cloudBudget: 12000
20+
},
21+
{
22+
_id: 3,
23+
allowedRoles: [ 'Development' ],
24+
comment: 'For development team',
25+
yearlyBudget: 27000
26+
}
27+
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Run:
2+
3+
.. code-block:: javascript
4+
:emphasize-lines: 5
5+
6+
db.budget.aggregate( [ {
7+
$match: {
8+
$expr: {
9+
$not: {
10+
$eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
11+
}
12+
}
13+
}
14+
} ] )
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
For examples that include ``USER_ROLES``, see the :ref:`find example
2+
<find-user-roles-system-variable-example>`, :ref:`aggregation example
3+
<setIntersection-user-roles-system-variable-example>`, and the
4+
:ref:`view example <create-view-user-roles-system-variable-example>`.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
Starting in MongoDB 7.0, you can use the new :variable:`USER_ROLES`
2+
system variable to return user :ref:`roles <roles>`.
3+
4+
The scenario in this section shows users with various roles who have
5+
limited access to documents in a collection containing budget
6+
information.
7+
8+
The scenario shows one possible use of ``USER_ROLES``. The ``budget``
9+
collection contains documents with a field named ``allowedRoles``. As
10+
you'll see in the following scenario, you can write queries that compare
11+
the user roles found in the ``allowedRoles`` field with the roles
12+
returned by the ``USER_ROLES`` system variable.
13+
14+
.. note::
15+
16+
Another possible ``USER_ROLES`` example scenario: you could store
17+
medical diagnosis and insurance data in a collection. You could then
18+
use ``USER_ROLES`` in an aggregation pipeline to transform the data
19+
so that the diagnosis data can only be viewed by a user with a
20+
provider role and the insurance data can only be viewed by a user
21+
with a billing role. You don't have to include those user roles in
22+
document fields to use ``USER_ROLES``.
23+
24+
For the budget scenario in this section, perform the following steps to
25+
create the required roles, users, and ``budget`` collection:
26+
27+
.. procedure::
28+
:style: normal
29+
30+
.. step:: Create the roles
31+
32+
Run:
33+
34+
.. code-block:: javascript
35+
36+
db.createRole( { role: "Marketing", roles: [], privileges: [] } )
37+
db.createRole( { role: "Sales", roles: [], privileges: [] } )
38+
db.createRole( { role: "Development", roles: [], privileges: [] } )
39+
db.createRole( { role: "Operations", roles: [], privileges: [] } )
40+
41+
.. step:: Create the users
42+
43+
Create users named ``John`` and ``Jane`` with the required roles.
44+
Replace the ``test`` database with your database name.
45+
46+
.. code-block:: javascript
47+
48+
db.createUser( {
49+
user: "John",
50+
pwd: "jn008",
51+
roles: [
52+
{ role: "Marketing", db: "test" },
53+
{ role: "Development", db: "test" },
54+
{ role: "Operations", db: "test" },
55+
{ role: "read", db: "test" }
56+
]
57+
} )
58+
59+
db.createUser( {
60+
user: "Jane",
61+
pwd: "je009",
62+
roles: [
63+
{ role: "Sales", db: "test" },
64+
{ role: "Operations", db: "test" },
65+
{ role: "read", db: "test" }
66+
]
67+
} )
68+
69+
.. step:: Create the collection
70+
71+
Run:
72+
73+
.. code-block:: javascript
74+
75+
db.budget.insertMany( [
76+
{
77+
_id: 0,
78+
allowedRoles: [ "Marketing" ],
79+
comment: "For marketing team",
80+
yearlyBudget: 15000
81+
},
82+
{
83+
_id: 1,
84+
allowedRoles: [ "Sales" ],
85+
comment: "For sales team",
86+
yearlyBudget: 17000,
87+
salesEventsBudget: 1000
88+
},
89+
{
90+
_id: 2,
91+
allowedRoles: [ "Operations" ],
92+
comment: "For operations team",
93+
yearlyBudget: 19000,
94+
cloudBudget: 12000
95+
},
96+
{
97+
_id: 3,
98+
allowedRoles: [ "Development" ],
99+
comment: "For development team",
100+
yearlyBudget: 27000
101+
}
102+
] )

source/meta/aggregation-quick-reference.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ prefix the variable name with ``$$``. For example:
107107

108108
* - Variable
109109

110-
- Access via ``$$``
110+
- Access using ``$$``
111111

112112
- Brief Description
113113

@@ -165,6 +165,16 @@ prefix the variable name with ``$$``. For example:
165165

166166
- One of the allowed results of a :pipeline:`$redact` expression.
167167

168+
* - :variable:`USER_ROLES`
169+
170+
- ``$$USER_ROLES``
171+
172+
- Returns the :ref:`roles <roles>` assigned to the current user.
173+
174+
.. include:: /includes/user-roles-system-variable-examples-list.rst
175+
176+
.. versionadded:: 7.0
177+
168178
For a more detailed description of these variables, see :ref:`system
169179
variables <agg-system-variables>`.
170180

source/reference/aggregation-variables.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ MongoDB offers the following system variables:
120120
</reference/atlas-search/facet/#search_meta-aggregation-variable>`
121121
and :atlas:`count </reference/atlas-search/counting/#search_meta-aggregation-variable>`.
122122

123+
* - .. variable:: USER_ROLES
124+
125+
- Returns the :ref:`roles <roles>` assigned to the current user.
126+
127+
.. include:: /includes/user-roles-system-variable-examples-list.rst
128+
129+
.. versionadded:: 7.0
130+
123131
.. seealso::
124132

125133
- :expression:`$let`

0 commit comments

Comments
 (0)