Skip to content

Instantly share code, notes, and snippets.

@koakh
Last active April 6, 2024 02:04
Show Gist options
  • Save koakh/fbbc37cde630bedcf57acfd4d6a6956b to your computer and use it in GitHub Desktop.
Save koakh/fbbc37cde630bedcf57acfd4d6a6956b to your computer and use it in GitHub Desktop.
SurrealDB : How to use signin and signup (server + client nodesjs)
**As a developer you have complete control over the signup and signin functionality...**
```shell
$ surreal sql --conn http://localhost:8000 --user root --pass root --ns test --db test
```
```sql
-- optional : this is the default see --ns test --db test start server flags
-- USE NS test DB test;
-- define TABLE user SCHEMAFULL PERMISSIONS FOR select, update WHERE id = $auth.id FOR create, delete NONE; // miss ,
-- Tobie: However, make it schemaless, as you haven't defined fields.
-- SCHEMAFULL if we defined fields else use SCHEMALESS
---opt1:SCHEMALESS
-- DEFINE TABLE user SCHEMALESS
-- PERMISSIONS
-- FOR select, update WHERE id = $auth.id,
-- FOR create, delete NONE;
-- warn with opt1 if we re signup again it will create another user with same email, and after it all signin's will fail,
-- to fix this issue always use next opt2 that have a UNIQUE INDEX, and prevents create a user with same email, and this is the expected behavior
---opt2:SCHEMAFULL
DEFINE TABLE user SCHEMAFULL
PERMISSIONS
FOR select, update WHERE id = $auth.id,
FOR create, delete NONE;
DEFINE FIELD user ON user TYPE string;
DEFINE FIELD pass ON user TYPE string;
DEFINE FIELD settings.* ON user TYPE object;
DEFINE FIELD settings.marketing ON user TYPE string;
DEFINE FIELD tags ON user TYPE array;
DEFINE INDEX idx_user ON user COLUMNS user UNIQUE;
-- define scope
DEFINE SCOPE allusers
-- the JWT session will be valid for 14 days
SESSION 14d
-- The optional SIGNUP clause will be run when calling the signup method for this scope
-- It is designed to create or add a new record to the database.
-- If set, it needs to return a record or a record id
-- The variables can be passed in to the signin method
SIGNUP ( CREATE user SET settings.marketing = $marketing, user = $user, pass = crypto::argon2::generate($pass), tags = $tags )
-- The optional SIGNIN clause will be run when calling the signin method for this scope
-- It is designed to check if a record exists in the database.
-- If set, it needs to return a record or a record id
-- The variables can be passed in to the signin method
SIGNIN ( SELECT * FROM user WHERE user = $user AND crypto::argon2::compare(pass, $pass) )
-- this optional clause will be run when calling the signup method for this scope
```
ctrl+c
check info db in shell
```shell
$ echo "INFO FOR DB;" | surreal sql --conn http://localhost:8000 --user root --pass root --ns test --db test | jq
```
check info db in REPL
```shell
$ surreal sql --conn http://localhost:8000 --user root --pass root --ns test --db test --pretty
```
```sql
INFO FOR DB;
```
```json
[
{
"time": "249.753µs",
"status": "OK",
"result": {
"dl": {},
"dt": {},
"sc": {
"allusers": "DEFINE SCOPE allusers SESSION 2w SIGNUP (CREATE user SET settings.marketing = $marketing, email = $email, pass = crypto::argon2::generate($pass), tags = $tags) SIGNIN (SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(pass, $pass))"
},
"tb": {
"user": "DEFINE TABLE user SCHEMALESS PERMISSIONS FOR select WHERE id = $auth.id, FOR create NONE, FOR update WHERE id = $auth.id, FOR delete NONE"
}
}
}
]
```
Then you could use the **following query from the client to signup (create) a new user**, or **signin (select) an existing user**...
```js
db.signup({
NS: 'my_ns',
DB: 'my_db',
SC: 'allusers', // We want to signup to the 'allusers' scope defined above
email: '[email protected]', // We can add any variable here to use in the SIGNUP clause
pass: 'some password', // We can add any variable here to use in the SIGNUP clause
marketing: true, // We can add any variable here to use in the SIGNUP clause
tags: ['rust', 'golang', 'javascript'], // We can add any variable here to use in the SIGNUP clause
});
// you should receive a jwt token
db.signin({
NS: 'my_ns',
DB: 'my_db',
SC: 'allusers', // We want to signup to the 'allusers' scope defined above
email: '[email protected]', // We can add any variable here to use in the SIGNUP clause
pass: 'some password', // We can add any variable here to use in the SIGNUP clause
});
// you should receive a jwt token
```
@bitdom8
Copy link

bitdom8 commented Jun 29, 2023

@koakh hi, can you help us with argon2 https://github.com/orgs/surrealdb/discussions/2196#discussioncomment-6314556

Thanks for the great guidance

@pkastoori
Copy link

pkastoori commented Jul 4, 2023

I am using the signup function and providing a username and password. After that I use the signin function with the same username but with the a different password, I was expecting an error but I still got a token also calling the authenticate function after that did not throw an error. How is this possible? What am I doing wrong?

await db.signup({
NS: "mydb",
DB: "mydb",
SC: "allusers",
user: "jane",
password: "jane",
email: "[email protected]",
});

const token = await db.signin({
NS: "mydb",
DB: "mydb",
SC: "allusers",
user: "jane",
password: "jane1",
});

await db.authenticate(token)

All of this still works even though I give an incorrect pass while signin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment