Skip to content

Commit 1871512

Browse files
authored
Merge branch 'memgraph-3-1' into tzdata_warning
2 parents d92a62c + 0411e0e commit 1871512

File tree

15 files changed

+460
-43
lines changed

15 files changed

+460
-43
lines changed

next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
/// <reference types="next/image-types/global" />
33

44
// NOTE: This file should not be edited
5-
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
5+
// see https://nextjs.org/docs/basic-features/typescript for more information.

pages/client-libraries/python.mdx

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import CodeSnippet from '/components/code-snippet/CodeSnippet'
1111

1212
Learn how to create a Python application that connects to the Memgraph database and executes simple queries.
1313

14-
Both [Neo4j Python client](https://neo4j.com/docs/python-manual/current/) and [GQLAlchemy](https://github.com/memgraph/gqlalchemy) can be used to connect to Memgraph with Python.
15-
This guide will show how to use Neo4j Python client and for more information on GQLAlchemy, check out its [documentation](https://memgraph.github.io/gqlalchemy/).
14+
Both [Neo4j Python client](https://neo4j.com/docs/python-manual/current/) and [GQLAlchemy](https://github.com/memgraph/gqlalchemy) can be used to connect to Memgraph with Python.
15+
This guide will show how to use Neo4j Python client and for more information on GQLAlchemy, check out its [documentation](https://memgraph.github.io/gqlalchemy/).
1616

1717
Memgraph and Neo4j both support Bolt protocol and Cypher queries, which means that same client can be used to connect to both databases.
1818
This is very convenient if switching between the two databases is needed. This guide is based on the client version v5 and above. Some examples may
@@ -29,7 +29,7 @@ Necessary prerequisites that should be installed in your local environment are:
2929

3030
<Steps>
3131

32-
### Run Memgraph
32+
### Run Memgraph
3333

3434
If you're new to Memgraph or you're in a developing stage, we
3535
recommend using the Memgraph Platform. Besides the database, it also
@@ -60,7 +60,7 @@ communicate with the client using the exposed 7687 port. Memgraph Lab is a web
6060
application you can use to visualize the data. It's accessible at
6161
[http://localhost:3000](http://localhost:3000) if Memgraph Platform is running
6262
correctly. The 7444 port enables Memgraph Lab to access and preview the logs,
63-
which is why both of these ports need to be exposed.
63+
which is why both of these ports need to be exposed.
6464

6565
For more information visit the getting started guide on [how to run Memgraph
6666
with Docker](/getting-started/install-memgraph/docker).
@@ -178,6 +178,7 @@ Once the database is running and the client is installed or available in Python,
178178
- [Connect with authentication](#connect-with-authentication)
179179
- [Connect with self-signed certificate](#encrypted-database-connection-with-self-signed-certificate)
180180
- [Connect with Single sign-on (SSO)](#connect-with-single-sign-on-sso)
181+
- [Impersonate a user](#impersonate-a-user)
181182

182183
#### Connect without authentication (default)
183184

@@ -295,6 +296,22 @@ with neo4j.GraphDatabase.driver(
295296
) as driver:
296297
```
297298

299+
#### Impersonate a user
300+
301+
<Callout type="info">
302+
[User impersonation](/database-management/authentication-and-authorization/impersonate-user) is an Enterprise feature.
303+
</Callout>
304+
305+
Once logged in, a user with the correct permissions can impersonate a different
306+
users during a session. This means that any query executing during that session
307+
will be executed as if the impersonated user executed it. The target user can be
308+
defined during session creation as in the following snippet:
309+
310+
```python
311+
with driver.session(impersonated_user="user1") as session:
312+
# queries here will be executed as if user1 executed them
313+
```
314+
298315
### Query the database
299316

300317
After connecting your client to Memgraph, you can start running queries. The simplest way to run queries is by using the `execute_query()` method which has an automatic transaction management.
@@ -424,8 +441,8 @@ Path will contain [Nodes](#process-the-node-result) and [Relationships[#process-
424441

425442
Transaction is a unit of work that is executed on the database, it could be some basic read, write or complex set of steps in form of series of queries. There can be multiple ways to mange transaction, but usually, they are managed automatically by the client or manually by the explicit code steps. Transaction management defines how to handle the transaction, when to commit, rollback, or terminate it.
426443

427-
On the driver side, if a transaction fails because of a transient error, the transaction is retried automatically.
428-
The transient error will occur during write conflicts or network failures. The driver will retry the transaction function with an exponentially increasing delay.
444+
On the driver side, if a transaction fails because of a transient error, the transaction is retried automatically.
445+
The transient error will occur during write conflicts or network failures. The driver will retry the transaction function with an exponentially increasing delay.
429446

430447
#### Automatic transaction management
431448

@@ -671,9 +688,9 @@ The `Session.run()` method is most commonly used for `LOAD CSV` clause to preven
671688

672689
#### Concurrent transactions
673690

674-
It is possible to run concurrent transactions with Python's client by leveraging threads or processes.
675-
Using threads could cause your code to be partially locked because of [Global interpreter lock (GIL)](https://wiki.python.org/moin/GlobalInterpreterLock),
676-
resulting in slow execution. Hence, it is always better to run your workloads in separate processes,
691+
It is possible to run concurrent transactions with Python's client by leveraging threads or processes.
692+
Using threads could cause your code to be partially locked because of [Global interpreter lock (GIL)](https://wiki.python.org/moin/GlobalInterpreterLock),
693+
resulting in slow execution. Hence, it is always better to run your workloads in separate processes,
677694
where each process will have its own interpreter and memory space, avoiding GIL issues. To leverage multiple concurrent processes, you can use Python's `multiprocessing` module.
678695

679696
Here is an example of how to run concurrent transactions with `multiprocessing` module:
@@ -685,7 +702,7 @@ from neo4j import GraphDatabase
685702
HOST_PORT = "bolt://localhost:7687"
686703

687704
def process_chunk(query, create_list):
688-
try:
705+
try:
689706
driver = GraphDatabase.driver(HOST_PORT, auth=("", ""))
690707
with driver.session() as session:
691708
session.run(query, {"batch": create_list})
@@ -706,7 +723,7 @@ with multiprocessing.Pool(10) as pool:
706723
pool.starmap(process_chunk, [(query, chunk) for chunk in chunks])
707724
```
708725

709-
Each process will execute a query that contains a chunk of nodes.
726+
Each process will execute a query that contains a chunk of nodes.
710727
You can control the number of concurrent transactions and processes by
711728
specifying the number of processes in the `multiprocessing.Pool` constructor.
712729
Each transaction will be a separate connection to the database and will be
@@ -719,7 +736,7 @@ conflicting transactions. The typical scenario is when two transactions try to
719736
update the same node simultaneously, or add a relationship to the same node. It
720737
is a write-write conflict between transactions. In this case, the first
721738
transaction will pass, and one of the transactions will fail, and you will need
722-
to handle the error and retry the transaction.
739+
to handle the error and retry the transaction.
723740

724741
If you are running transactions in parallel, you should avoid [implicit
725742
transactions](#implicit-transactions) because you can't control the execution
@@ -728,7 +745,7 @@ process, and there are no retries.
728745
You can use the [managed transactions](#managed-transactions) or [explicit
729746
transactions](#explicit-transactions) to handle the conflicting transactions.
730747
Explicit API provides full control of the process, and it is recommended for
731-
production use and handling conflicts.
748+
production use and handling conflicts.
732749

733750
Here is an example of how to handle conflicting transactions in explicit API:
734751

@@ -742,7 +759,7 @@ def process_chunk(query, create_list, max_retries=100, initial_wait_time=0.200,
742759
tx.commit()
743760
break
744761
except TransientError as te:
745-
jitter = random.uniform(0, jitter) * initial_wait_time
762+
jitter = random.uniform(0, jitter) * initial_wait_time
746763
wait_time = initial_wait_time * (backoff_factor ** attempt) + jitter
747764
print(f"Commit failed on attempt {attempt+1}. Retrying in {wait_time} seconds...")
748765
time.sleep(wait_time)
@@ -756,9 +773,9 @@ In the example above, we are using the `begin_transaction()` method to start a
756773
transaction, and then we are running the query inside the transaction. If the
757774
transaction fails with a `TransientError,` the transaction will be retried using
758775
the retry strategy. Otherwise, another error occurred, and the transaction
759-
should be aborted.
776+
should be aborted.
760777

761-
The essential aspects of the retry strategy are the following arguments:
778+
The essential aspects of the retry strategy are the following arguments:
762779

763780
- `max_retries` - the maximum number of retries before the transaction will be
764781
aborted with a timeout error. This number should be set based on the expected
@@ -776,7 +793,7 @@ for 2 minutes + waiting time.
776793
retry. If there are a lot of transactions running in parallel, it is
777794
recommended to use `jitter` to avoid the thundering herd problem.
778795

779-
If you use managed transactions, you can configure the retry scenario to use the `session` configuration. Here is an example:
796+
If you use managed transactions, you can configure the retry scenario to use the `session` configuration. Here is an example:
780797

781798
```python
782799
import multiprocessing
@@ -807,18 +824,18 @@ In this case, the `TransientError` will be retried using the retry strategy that
807824
The essential configuration arguments are the following:
808825

809826
- `max_transaction_retry_time` - the maximum time the transaction will be
810-
retried; after that, it will be aborted with a timeout error.
827+
retried; after that, it will be aborted with a timeout error.
811828
- `initial_retry_delay` - the time that the transaction will wait before the
812-
first retry.
829+
first retry.
813830
- `retry_delay_multiplier` - the factor by which the retry delay will be
814831
multiplied after each retry.
815832
- `retry_delay_jitter_factor` - the factor by which the retry delay will be
816-
randomized after each retry.
833+
randomized after each retry.
817834

818835
<Callout type="info">
819836

820837
If you are still struggling with conflicts and serialization errors while using a Python client, we recommend
821838
referring to our [Serialization errors](/help-center/errors/serialization) page
822-
for detailed guidance on troubleshooting and best practices.
839+
for detailed guidance on troubleshooting and best practices.
823840

824841
</Callout>

pages/data-migration/csv.mdx

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,12 @@ There are also two variations of the files: files with a header and files withou
230230
- [`people_relationships_wh.csv`](https://public-assets.memgraph.com/import-data/load-csv-cypher/one-type-nodes/people_relationships_wh.csv)<br/>
231231
The file contains the following data:
232232
```plaintext
233-
id_from,id_to
234-
100,101
235-
100,102
236-
100,103
237-
101,103
238-
102,104
233+
id_from,id_to,type
234+
100,101,IS_FRIENDS_WITH
235+
100,102,IS_FRIENDS_WITH
236+
100,103,IS_FRIENDS_WITH
237+
101,103,IS_FRIENDS_WITH
238+
102,104,IS_FRIENDS_WITH
239239
```
240240
</Tabs.Tab>
241241
<Tabs.Tab>
@@ -285,13 +285,7 @@ There are also two variations of the files: files with a header and files withou
285285
```
286286

287287
If successful, you should receive an `Empty set (0.014 sec)` message.
288-
289-
You can also create, set, or remove labels using property values, here is an example:
290-
291-
```cypher
292-
LOAD CSV FROM "/path-to/people_nodes_wh.csv" WITH HEADER AS row
293-
CREATE (p:row.label {id: row.id, name: row.name});
294-
```
288+
Notice how **node labels can be dynamically created* from the CSV file.
295289

296290
</Tabs.Tab>
297291
<Tabs.Tab>
@@ -335,10 +329,11 @@ There are also two variations of the files: files with a header and files withou
335329
```cypher
336330
LOAD CSV FROM "/path-to/people_relationships_wh.csv" WITH HEADER AS row
337331
MATCH (p1:Person {id: row.id_from}), (p2:Person {id: row.id_to})
338-
CREATE (p1)-[:IS_FRIENDS_WITH]->(p2);
332+
CREATE (p1)-[:row.type]->(p2);
339333
```
340334

341335
If successful, you should receive an `Empty set (0.014 sec)` message.
336+
Notice how **relationship types can be dynamically created** from the CSV file.
342337

343338
</Tabs.Tab>
344339
<Tabs.Tab>

pages/data-modeling/graph-data-model/lpg-vs-rdf.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ format.
102102

103103
## Key differences between LPG and RDF
104104

105+
![rdf-vs-lpg](/pages/data-modeling/graph-modeling/rdf-vs-lpg.png)
106+
105107
| **Feature** | **LPG** | **RDF** |
106108
| --- | --- | --- |
107109
| **Data Structure** | Labeled nodes and edges with properties | Triples: subject-predicate-object |

pages/database-management/authentication-and-authorization.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@ Learn how to manage roles, set up their privileges and fine-grained access contr
2121

2222
Learn how to integrate with third-party auth systems and manage user
2323
authentication and access control using Memgraph's auth module.
24+
25+
## [Impersonate user](/database-management/authentication-and-authorization/impersonate-user) (Enterprise)
26+
27+
Learn how the impersonate user feature enables authorized users to execute
28+
queries with the full permissions and context of another user.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export default {
22
"users": "Users",
33
"role-based-access-control": "Role-based access control",
4-
"auth-system-integrations": "Auth system integrations"
4+
"auth-system-integrations": "Auth system integrations",
5+
"impersonate-user": "Impersonate user"
56
}
6-
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
title: Impersonate user
3+
description: Learn how the impersonate user feature enables authorized users to execute queries with the full permissions and context of another user.
4+
---
5+
6+
import { Callout } from 'nextra/components'
7+
import {CommunityLinks} from '/components/social-card/CommunityLinks'
8+
9+
10+
# Impersonate user (Enterprise)
11+
12+
13+
14+
The **impersonate user** feature lets authorized users run queries on behalf of
15+
another user. When using impersonation, the permitted user adopts the full
16+
permissions and context of the impersonated user. This means they can execute
17+
queries and perform actions exactly as the impersonated user, with all
18+
associated privileges.
19+
20+
This feature provides a powerful tool for managing user permissions, debugging,
21+
and performing administrative tasks. By leveraging the ability to impersonate
22+
other users, you can ensure more efficient management of users and roles while
23+
maintaining robust security and access control within your graph database.
24+
25+
<Callout type="info">
26+
27+
**Enterprise**: Impersonate user feature requires a Memgraph Enterprise license to
28+
function. For more information on Memgraph Enterprise and instructions
29+
on how to enable it, refer to the
30+
[enabling Memgraph Enterprise documentation](/database-management/enabling-memgraph-enterprise).
31+
32+
</Callout>
33+
34+
## Targeting impersonation
35+
36+
The impersonated user is defined at the session start, as shown in the example
37+
using the Neo4j Python driver:
38+
39+
```python
40+
with driver.session(impersonated_user="user1") as session:
41+
# queries here will be executed as if user1 executed them
42+
```
43+
44+
During this session, all queries will be executed with the privileges and
45+
context of the impersonated user (`user1` in this case), effectively "switching"
46+
the identity for the duration of the session.
47+
48+
## Permissions for impersonation
49+
50+
Only certain users or roles have the ability to impersonate other users. These permissions are managed with three key queries:
51+
- [`GRANT IMPERSONATE_USER`](#grant-impersonate-user)
52+
- [`DENY IMPERSONATE_USER`](#deny-impersonate-user)
53+
- [`REVOKE IMPERSONATE_USER`](#revoke-impersonate-user)
54+
55+
### Grant impersonate user
56+
57+
The `GRANT IMPERSONATE_USER` query allows a user or role to impersonate specific users or all users. The syntax and behavior are as follows:
58+
59+
```cypher
60+
GRANT IMPERSONATE_USER [*] [list of users] TO user/role;
61+
```
62+
63+
Here is the explanation of arguments:
64+
- `*`: Grants permission to impersonate all users.
65+
- `list of users`: Grants permission to impersonate specific users (comma-separated list).
66+
- `user/role`: The user or role receiving the impersonation permission.
67+
68+
Here is an example of granting the `admin` role permission to impersonate `user1` and `user2`:
69+
```cypher
70+
GRANT IMPERSONATE_USER user1,user2 TO admin;
71+
```
72+
73+
Here is an example of granting the `admin_user` user permission to impersonate all users:
74+
```cypher
75+
GRANT IMPERSONATE_USER * TO admin_user;
76+
```
77+
78+
### Deny impersonate user
79+
80+
The `DENY IMPERSONATE_USER` denies impersonation rights to specific users or roles, allowing you to restrict who can impersonate whom.
81+
The syntax and behavior are as follows:
82+
83+
```cypher
84+
DENY IMPERSONATE_USER list of users TO user/role;
85+
```
86+
87+
Here is the explanation of arguments:
88+
- `list of users`: Deny impersonation for specific users (comma-separated list).
89+
- `user/role`: The user or role being restricted from impersonating others.
90+
91+
Here is an example of denying the `admin` role the ability to impersonate `user1` and `user2`:
92+
```cypher
93+
DENY IMPERSONATE_USER user1,user2 TO admin;
94+
```
95+
96+
### Revoke impersonate user
97+
98+
The `REVOKE IMPERSONATE_USER` removes the impersonation rights for a given user or role. It revokes all impersonation permissions for the specified user/role.
99+
The syntax and behavior are as follows:
100+
101+
```cypher
102+
REVOKE IMPERSONATE_USER FROM user/role;
103+
```
104+
105+
Here is the explanation of arguments:
106+
- `user/role`: The user or role whose impersonation permissions are being revoked.
107+
108+
Here is an example of revoking all impersonation permissions for the `admin` role:
109+
```cypher
110+
REVOKE IMPERSONATE_USER FROM admin;
111+
```
112+
113+
<Callout type="info">
114+
**Important things to note**
115+
116+
When using the `GRANT` or `DENY` commands, you must provide exhaustive lists of users. This means that the existing configuration will be replaced by the new list provided.
117+
For example:
118+
- First command:
119+
```cypher
120+
GRANT IMPERSONATE_USER user1,user2 TO admin;
121+
```
122+
- Second command (this overrides the first one):
123+
```cypher
124+
GRANT IMPERSONATE_USER user3 TO admin;
125+
```
126+
After the second command, the `admin` role will only be able to impersonate `user3`, even though the first command allowed impersonation of `user1` and `user2`.
127+
128+
Permissions can be granted or denied to individual users or roles. For example, an `admin` role might have impersonation privileges that individual users do not have.
129+
The `REVOKE` command removes any impersonation permissions for the specified user or role, ensuring that they cannot impersonate any user unless granted explicitly again.
130+
</Callout>
131+
132+
<CommunityLinks/>

0 commit comments

Comments
 (0)