Configuration
Llana's basic implementation can be configured quickly using .env
values which will connect to your data source and configure other basic options.
More advanced configuration is done via data tables (_llana_*
) which we add dynamically to your data source.
We do this to ensure the application is fully cloud based and there is no dependency on the file system.
Database
Replace the database connection string DATABASE_URI
in the .env
file.
See data sources for more information.
Hosts
You can lock down requests to specific origins by passing a comma separated list of IP addresses via the .env
HOSTS
property.
Warning: By default the system has no hosts and is open to all. If you are not operating a public application, we highly recommend you restrict your application to known services.
HOSTS="127.0.0.1,192.168.0.1"
Note: We are looking at the x-real-ip
header value, so any proxy service will likely result in a failed host check.
Authentication
As standard we ship with two types of authentication with some examples added, however if you are developing a public application you can skip authentication by adding SKIP_AUTH=true
to your .env
file.
This will remove the need for any user authentication and make all your endpoints public. Endpoints will be READ
only as standard, see Auth Inclusions and Exclusions to change this.
API KEY
Here are the configuration settings and their default settings:
Env Key | Default | Details |
---|---|---|
AUTH_USER_API_KEY_LOCATION | HEADER | The location of where the API Key is passed in the requests, options are: HEADER QUERY BODY |
AUTH_USER_API_KEY_NAME | x-api-key | The key of the key:value pair passed, e.g. x-api-key:YOURKEY |
AUTH_USER_TABLE_NAME | User | The main identity table containing your user identity |
AUTH_USER_IDENTITY_COLUMN | undefined | The column containing your users identity key in your users identity table, defaults to the primary key of the identity table |
AUTH_USER_API_KEY_FIELD | UserApiKey.apiKey | The column of the users API key accessed from the main identity table |
Note: if you specify a SOFT_DELETE_COLUMN
it will ensure this value is NULL
before authorizing.
JWT Token
We provide some special endpoints that allows you to exchange a username/password for a access_token
. You can then pass the access token in future requests.
Login
Example Request:
POST `/auth/login`
body: {
username: test@test.com,
password: test
}
Example Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidGVzdEB0ZXN0LmNvbSIsImlhdCI6MTcyNTM1NDI4OCwiZXhwIjoxNzI1NDQwNjg4fQ.Wb_Y6y1Mkb0xrhUX57s2XlKtqeZ5L68wNCVMWT8wFJw",
"id": 1
}
Profile
You can test your access token by using the /auth/profile
endpoint which also returns your users table data.
GET `/auth/profile`
Example Response:
{
"id": 1,
"email": "test@test.com",
"first_name": "Jon",
"last_name": "Doe"
}
JWT Configuration
You will need to add / update your .env
values to fit your database schema:
Env Key | Default | Details |
---|---|---|
AUTH_USER_TABLE_NAME | User | The main identity table containing your user identity |
AUTH_USER_IDENTITY_COLUMN | undefined | The column containing your users identity key, defaults to the primary key of the identity table |
AUTH_USER_TABLE_USERNAME_FIELD | email | The column of your username field in the user identity table |
AUTH_USER_TABLE_PASSWORD_FIELD | password | The column of your password field in the user identity table |
AUTH_USER_TABLE_PASSWORD_ENCRYPTION | BCRYPT | The encoding type for your password field, options are: BCRYPT SHA1 , SHA256 , SHA512 , MD5 , ARGON2 |
AUTH_USER_TABLE_PASSWORD_SALT | 10 | Optional salt used in conjunction with the encryption |
Auth Inclusions and Exclusions
By default authentications apply to all tables, however you can add specific inclusions or exclusions for more granular authentication support.
This allows you to open and close specific data sets to the public.
You can maintain routes in the table _llana_auth
.
Field | Type | Details |
---|---|---|
auth | enum | Which auth type this applies to, either APIKEY or JWT |
type | enum | If to INCLUDE or EXCLUDE the endpoint, excluding means authentication will not be required |
table | string | The table this rule applies to |
public_records | enum | The permission level if EXCLUDE and opened to the public, either NONE READ WRITE DELETE |
Any exclusions should also include a public_records
permission, otherwise we will default to READ
only
Password Encryption
To help ensure user passwords are always stored in an encrypted format, we perform checks on CREATE
and UPDATE
requests. If the request includes an update to your users identity table and includes the password field, we will encrypt the password using your configures (or default) encryption method.
This means you can delegate the user password encryption entirely to Llana.
#### Future Development
TODO: Add the ability to maintain routes via a web portal
Roles
User roles are an important part of granting the correct permissions to perform relevant actions on the API endpoints.
Firstly, you should configure where your roles are located:
Env Key | Default | Details |
---|---|---|
ROLE_LOCATION_USER_TABLE_NAME | $AUTH_USER_TABLE_NAME | The table containing your roles, defaults to your auth users table |
ROLE_LOCATION_USER_TABLE_ROLE_FIELD | role | The column containing your users role type |
ROLE_LOCATION_USER_TABLE_IDENTITY_COLUMN | undefined | The column containing your users identity key, defaults to the primary key of the identity table |
You can manage roles via the _llana_role
table.
Field | Type | Details |
---|---|---|
custom | boolean | If this is a custom role (applies to specific endpoints) |
table | string | If not default, which table does this restriction apply to |
identity_column | string | If not default and the primary key of the table is not the user identifier, which column should be used to identify the user |
role | string | The name of the role, which should match the value from your users role field |
records | enum | The permission level for this role across all records in the table, either NONE READ WRITE DELETE |
own_records | enum | The permission level for this role if it includes a reference back to the user identity (their own records) either NONE READ WRITE DELETE |
By default we will add the following roles to the table if non-exist on application startup:
Custom | Table | Identity | Role | Records | Own Records |
---|---|---|---|---|---|
false | ADMIN | DELETE | |||
false | EDITOR | WRITE | |||
false | VIEWER | READ | |||
true | $AUTH_USER_TABLE_NAME | ADMIN | DELETE | DELETE | |
true | $AUTH_USER_TABLE_NAME | EDITOR | NONE | WRITE | |
true | $AUTH_USER_TABLE_NAME | VIEWER | NONE | WRITE | |
true | $AUTH_USER_API_KEY_TABLE_NAME | $AUTH_USER_API_KEY_TABLE_IDENTITY_COLUMN | ADMIN | DELETE | DELETE |
true | $AUTH_USER_API_KEY_TABLE_NAME | $AUTH_USER_API_KEY_TABLE_IDENTITY_COLUMN | EDITOR | NONE | WRITE |
true | $AUTH_USER_API_KEY_TABLE_NAME | $AUTH_USER_API_KEY_TABLE_IDENTITY_COLUMN | VIEWER | NONE | WRITE |
Role permissions work progressively, which means:
DELETE
- Has full permission toDELETE
WRITE
andREAD
WRITE
- Can alsoREAD
recordsREAD
- Can onlyREAD
records and has noWRITE
permissionsNONE
- Has no access to the table
If the user has insufficient permissions they will get a 403 Forbidden
response.
#### Future Development
TODO: Add the ability to maintain routes via a web portal
Relations
In some situations you may have data sources which don't support relations but you still want a way of "relating" data together.
Imagine having two Google Sheets and you want to link them in some way. You can create "manual references" which will allow Llana to perform the relationship binding for you.
You can manage relations via the _llana_relation
table.
Field | Type | Details |
---|---|---|
table | string | The name of the data source for the relation |
column | string | The field name containing the lookup value |
org_table | string | The name of the original data source |
org_column | string | The name of the field, which should match the value from your data source relation field |
Example:
{
"table": "Customer",
"column": "id",
"org_table": "SalesOrder",
"org_column": "CustId"
}
This will create the relation on the SalesOrder table and link any customers by CustId > Customerid
#### Future Development
TODO: Add the ability to maintain routes via a web portal
System Cache
Out of the box we cache table schema and some user auth/identity data to help speed up requests and reduce load on the database.
The cache is reset each time the application boots up, this means if you make database schema changes, you can simply reboot the application and the cache will be cleared.
This allows us to set a longer-lived cache ttl, however, if you want to change these, you can set the, in the .env
file. Setting a ttl to 0
will result in no cache being used.
CACHE_TABLE_SCHEMA_TTL=3600000 #value in milliseconds
CACHE_IDENTITY_DATA_TTL=60000 #value in milliseconds
Documentation
As standard we generate OpenApi JSON and a Redoc page which can be viewed from the homepage of your instance. You can disable docs by adding the .env
value SKIP_DOCS=true
When the application boots up, it will build the OpenApi JSON schema based on your data source schema. If you make changes to your data source, simply reboot the application and the changes will be reflected in your documentation.
The OpenApi JSON is accessible via /openapi.json
, you can use this to power postman or any 3rd party API tooling.
We use this to display a Redoc page at the root /
of your instance. Here are the .env
values you can customize.
Env Value | Default |
---|---|
DOCS_TITLE | API Documentation |
Deleting
As standard the delete endpoint will physically remove the record from your database. You can provide the .env
value for SOFT_DELETE_COLUMN
e.g. deletedAt
or deleted_at
to perform a soft delete across your database.
Logging
You can update logging levels via a .env
value, for more details see: Developers > Debugging/Logging
Timezones
You can set a timezone globally using nodes default TZ
value in your .env
Llana's timezone should match your data source, for example if your data source is running on UTC then you can add TZ=UTC
to your .env
If they are not hosted in the same location you may need to set this manually.
Examples
Here are some common example configuration use cases:
Restricted By Host, No User Authentication
This use case could be an internal database, not accessed by clients but connected to other internal services.
- It is locked down by
HOSTS
which means only that host can access, everything else will get a403 Forbidden
response. SKIP_AUTH
has been added, so no user authentication is requires, all requests coming from the valid host will pass.
DOMAIN="llana.domain"
DATABASE_URI=********
HOSTS="123.123.123.123"
SKIP_AUTH=true
SKIP_DOCS=true