Admin API

What is the Admin API?

The Admin API is a REST API generated automatically by the Forest Liana when you launch your application. This API covers all the common requirements of a fully functional Admin Interface (CRUD operations, search & filters, sort, pagination and more). The API is hosted on your side, so you have virtually no limitation to extend it.

However, to ease the customization of your back office, we’ve introduced the concept of Smart features which helps you to fully extend the API.

All your Smart features will be implemented by you and hosted on your server. The default folder to organize your customization is /forest, however you can change it using: configDir: 'my/path' in your Forest Admin initialization middleware.

Before you start to deep dive into this documentation, it’s a good idea to see how the Admin API is designed.

Retrieving the back office user details

Every time you interact with your application data from the Forest UI, it triggers an API call to your back office server. This API call is authenticated using the Data Token. This token is a JWT token signed with your FOREST_AUTH_SECRET (see the Security section for more information) and it is passed to the HTTP request through the Authorization header.

GET /forest/...
Host: ...
Origin: ...
Content-Type: ...
Accept: application/json
Authorization: Bearer <DATA_TOKEN>

The JWT Data Token contains all the details of the admin user. From a route, you can retrieve them with the variable req.user. On our Live Demo example, we’ve developed a Whoami global Smart Action available that returns the full name of the admin user.

Lumber
Rails
Express/Sequelize
Express/Mongoose
/forest/companies.js
const Liana = require('forest-express-sequelize');
Liana.collection('companies', {
actions: [{
name: 'Whoami',
type: 'global',
endpoint: '/forest/whoami',
httpMethod: 'GET'
}]
});
req.user content
{
id: '2',
type: 'users',
data: {
email: 'sandro@munda.me',
first_name: 'Sandro',
last_name: 'Munda',
teams: ['Operations']
},
relationships: {
renderings: {
data: [{
type: 'renderings',
id: '22631'
}]
}
},
iat: 1521711363,
exp: 1522920963
}
/routes/whoami.js
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
router.get('/actions/whoami', Liana.ensureAuthenticated, (req, res) => {
res.send({ success: `You are ${req.user.data.first_name} ${req.user.data.last_name}.` });
});
module.exports = router;
/lib/forest_liana/collections/company.rb
class Forest::Company
include ForestLiana::Collection
collection :Company
action 'Whoami', type: 'global', endpoint: '/forest/whoami', http_method: 'GET'
end
/config/routes.rb
Rails.application.routes.draw do
# MUST be declared before the mount ForestLiana::Engine.
namespace :forest do
get '/whoami' => 'admins#whoami'
end
mount ForestLiana::Engine => '/forest'
end
/app/controllers/forest/admins_controller.rb
class Forest::AdminsController < ForestLiana::ApplicationController
def whoami
first_name = forest_user['data']['data']['first_name']
last_name = forest_user['data']['data']['last_name']
render json: { success: "You are #{first_name} #{last_name}." }
end
end
/forest/companies.js
const Liana = require('forest-express-sequelize');
Liana.collection('companies', {
actions: [{
name: 'Whoami',
type: 'global',
endpoint: '/forest/whoami',
httpMethod: 'GET'
}]
});
req.user content
{
id: '2',
type: 'users',
data: {
email: 'sandro@munda.me',
first_name: 'Sandro',
last_name: 'Munda',
teams: ['Operations']
},
relationships: {
renderings: {
data: [{
type: 'renderings',
id: '22631'
}]
}
},
iat: 1521711363,
exp: 1522920963
}
/routes/whoami.js
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
router.get('/actions/whoami', Liana.ensureAuthenticated, (req, res) => {
res.send({ success: `You are ${req.user.data.first_name} ${req.user.data.last_name}.` });
});
module.exports = router;
/forest/companies.js
const Liana = require('forest-express-mongoose');
Liana.collection('companies', {
actions: [{
name: 'Whoami',
type: 'global',
endpoint: '/forest/whoami',
httpMethod: 'GET'
}]
});
req.user content
{
id: '2',
type: 'users',
data: {
email: 'sandro@munda.me',
first_name: 'Sandro',
last_name: 'Munda',
teams: ['Operations']
},
relationships: {
renderings: {
data: [{
type: 'renderings',
id: '22631'
}]
}
},
iat: 1521711363,
exp: 1522920963
}
/routes/whoami.js
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-mongoose');
router.get('/actions/whoami', Liana.ensureAuthenticated, (req, res) => {
res.send({ success: `You are ${req.user.data.first_name} ${req.user.data.last_name}.` });
});
module.exports = router;

Configuring the CORS headers

If you encounter CORS issues, check out this How-to to help you solve them.