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 KeyDefaultDetails
AUTH_USER_API_KEY_LOCATIONHEADERThe location of where the API Key is passed in the requests, options are: HEADER QUERY BODY
AUTH_USER_API_KEY_NAMEx-api-keyThe key of the key:value pair passed, e.g. x-api-key:YOURKEY
AUTH_USER_TABLE_NAMEUserThe main identity table containing your user identity
AUTH_USER_IDENTITY_COLUMNundefinedThe column containing your users identity key in your users identity table, defaults to the primary key of the identity table
AUTH_USER_API_KEY_FIELDUserApiKey.apiKeyThe 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 KeyDefaultDetails
AUTH_USER_TABLE_NAMEUserThe main identity table containing your user identity
AUTH_USER_IDENTITY_COLUMNundefinedThe column containing your users identity key, defaults to the primary key of the identity table
AUTH_USER_TABLE_USERNAME_FIELDemailThe column of your username field in the user identity table
AUTH_USER_TABLE_PASSWORD_FIELDpasswordThe column of your password field in the user identity table
AUTH_USER_TABLE_PASSWORD_ENCRYPTIONBCRYPTThe encoding type for your password field, options are: BCRYPT SHA1, SHA256, SHA512, MD5, ARGON2
AUTH_USER_TABLE_PASSWORD_SALT10Optional 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.

FieldTypeDetails
authenumWhich auth type this applies to, either APIKEY or JWT
typeenumIf to INCLUDE or EXCLUDE the endpoint, excluding means authentication will not be required
tablestringThe table this rule applies to
public_recordsenumThe 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 KeyDefaultDetails
ROLE_LOCATION_USER_TABLE_NAME$AUTH_USER_TABLE_NAMEThe table containing your roles, defaults to your auth users table
ROLE_LOCATION_USER_TABLE_ROLE_FIELDroleThe column containing your users role type
ROLE_LOCATION_USER_TABLE_IDENTITY_COLUMNundefinedThe column containing your users identity key, defaults to the primary key of the identity table

You can manage roles via the _llana_role table.

FieldTypeDetails
custombooleanIf this is a custom role (applies to specific endpoints)
tablestringIf not default, which table does this restriction apply to
identity_columnstringIf not default and the primary key of the table is not the user identifier, which column should be used to identify the user
rolestringThe name of the role, which should match the value from your users role field
recordsenumThe permission level for this role across all records in the table, either NONE READ WRITE DELETE
own_recordsenumThe 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:

CustomTableIdentityRoleRecordsOwn Records
falseADMINDELETE
falseEDITORWRITE
falseVIEWERREAD
true$AUTH_USER_TABLE_NAMEADMINDELETEDELETE
true$AUTH_USER_TABLE_NAMEEDITORNONEWRITE
true$AUTH_USER_TABLE_NAMEVIEWERNONEWRITE
true$AUTH_USER_API_KEY_TABLE_NAME$AUTH_USER_API_KEY_TABLE_IDENTITY_COLUMNADMINDELETEDELETE
true$AUTH_USER_API_KEY_TABLE_NAME$AUTH_USER_API_KEY_TABLE_IDENTITY_COLUMNEDITORNONEWRITE
true$AUTH_USER_API_KEY_TABLE_NAME$AUTH_USER_API_KEY_TABLE_IDENTITY_COLUMNVIEWERNONEWRITE

Role permissions work progressively, which means:

  • DELETE - Has full permission to DELETE WRITE and READ
  • WRITE - Can also READ records
  • READ - Can only READ records and has no WRITE permissions
  • NONE - 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.

FieldTypeDetails
tablestringThe name of the data source for the relation
columnstringThe field name containing the lookup value
org_tablestringThe name of the original data source
org_columnstringThe 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 ValueDefault
DOCS_TITLEAPI 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 a 403 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