Skip to content

Commit

Permalink
Add section about how events work with permissions (#790)
Browse files Browse the repository at this point in the history
Co-authored-by: David Bottiau <[email protected]>
  • Loading branch information
Xkonti and Odonno authored Aug 27, 2024
1 parent f307006 commit c837776
Showing 1 changed file with 73 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,27 @@ Below is an example showing how to create an event which upon updating a user's
```surql
-- Create a new event whenever a user changes their email address
-- One-statement event
DEFINE EVENT email ON TABLE user WHEN $before.email != $after.email THEN (
CREATE event SET user = $value.id, time = time::now(), value = $after.email, action = 'email_changed'
);
DEFINE EVENT email ON TABLE user
WHEN $before.email != $after.email
THEN (
CREATE event SET user = $value.id, time = time::now(), value = $after.email, action = 'email_changed'
);
-- Create a relation between a customer and a product whenever a purchase is made
-- Notice the subtle difference when we use multiple statements inside an event:
-- we have to use {curly brackets} instead of (parenthesis)
DEFINE EVENT purchase ON TABLE purchase WHEN $before == NONE THEN {
LET $from = (SELECT * FROM customer WHERE id == $after.customer);
LET $to = (SELECT * FROM product WHERE id == $after.product);
RELATE $from->purchases->$to CONTENT {
quantity: $after.quantity,
total: $after.total,
status: 'Pending',
DEFINE EVENT purchase ON TABLE purchase
WHEN $before == NONE
THEN {
LET $from = (SELECT * FROM customer WHERE id == $after.customer);
LET $to = (SELECT * FROM product WHERE id == $after.product);
RELATE $from->purchases->$to CONTENT {
quantity: $after.quantity,
total: $after.total,
status: 'Pending',
};
};
};
```
## Specific events

Expand All @@ -55,30 +59,38 @@ You can trigger events based on specific events. You can use the variable $event
-- CREATE event is triggered when a new record is inserted into the table.
-- Here we are updating the status of the post to PUBLISHED
-- when a new record is inserted into the publish_post table.
DEFINE EVENT publish_post ON TABLE publish_post WHEN $event = "CREATE" THEN (
UPDATE post SET status = "PUBLISHED" WHERE id = $after.post_id
);
DEFINE EVENT publish_post ON TABLE publish_post
WHEN $event = "CREATE"
THEN (
UPDATE post SET status = "PUBLISHED" WHERE id = $after.post_id
);
-- UPDATE event
-- Here we are creating a notification when a user is updated.
DEFINE EVENT user_updated ON TABLE user WHEN $event = "UPDATE" THEN (
CREATE notification SET message = "User updated", user_id = $after.id, created_at = time::now()
);
DEFINE EVENT user_updated ON TABLE user
WHEN $event = "UPDATE"
THEN (
CREATE notification SET message = "User updated", user_id = $after.id, created_at = time::now()
);
-- DELETE event is triggered when a record is deleted from the table.
-- Here we are creating a notification when a user is deleted.
DEFINE EVENT user_deleted ON TABLE user WHEN $event = "DELETE" THEN (
CREATE notification SET message = "User deleted", user_id = $before.id, created_at = time::now()
);
DEFINE EVENT user_deleted ON TABLE user
WHEN $event = "DELETE"
THEN (
CREATE notification SET message = "User deleted", user_id = $before.id, created_at = time::now()
);
-- You can combine multiple events based on your use cases.
-- Here we are creating a log when a user is created, updated or deleted.
DEFINE EVENT user_event ON TABLE user WHEN $event = "CREATE" OR $event = "UPDATE" OR $event = "DELETE" THEN (
CREATE log SET
table = "user",
event = $event,
happened_at = time::now()
);
DEFINE EVENT user_event ON TABLE user
WHEN $event = "CREATE" OR $event = "UPDATE" OR $event = "DELETE"
THEN (
CREATE log SET
table = "user",
event = $event,
happened_at = time::now()
);
```

## Using `IF NOT EXISTS` clause
Expand Down Expand Up @@ -106,3 +118,37 @@ The `OVERWRITE` clause can be used to define an event and overwrite an existing
-- Create an EVENT and overwrite if it already exists
DEFINE EVENT OVERWRITE example ON example THEN {};
```

## Events and permissions

Queries inside the event always execute without any permission checks, even when triggered by changes made by the currently authenticated user. This can be very useful to perform additional checks and changes that involve tables/records that are inaccessible for the user.

Consider a CREATE query sent by a record user that has CREATE access to the `comment` table only:

```surql
CREATE comment SET
post = post:tomatosoup,
content = "So delicious!",
author = $auth.id
;
```

By having the following event defined, SurrealDB will perform the additional checks and changes:

```surql
DEFINE EVENT on_comment_created ON TABLE comment
WHEN $event = "CREATE"
THEN {
-- Check if the post allows for adding comments.
-- User record doesn't have access to the `post` table.
IF $after.post.disable_comments {
THROW "Can't create a comment - Comments are disabled for this post";
};
-- Set the `approved` field on the new comment - automatically approve
-- comments made by the author of the post.
-- For security reasons, record users don't have any permissions for the `approved` field.
UPDATE $after.id SET
approved = $after.post.author == $after.author;
};
```

0 comments on commit c837776

Please sign in to comment.