Override a route
Last updated
Was this helpful?
Last updated
Was this helpful?
Please be sure of your agent type and version and pick the right documentation accordingly.
This is the documentation of the forest-express-sequelize
and forest-express-mongoose
Node.js agents that will soon reach end-of-support.
forest-express-sequelize
v9 and forest-express-mongoose
v9 are replaced by v1.
Please check your agent type and version and read on or switch to the right documentation.
This is still the latest Ruby on Rails documentation of the forest_liana
agent, you’re at the right place, please read on.
This is the documentation of the django-forestadmin
Django agent that will soon reach end-of-support.
If you’re using a Django agent, notice that django-forestadmin
v1 is replaced by v1.
If you’re using a Flask agent, go to the v1 documentation.
Please check your agent type and version and read on or switch to the right documentation.
This is the documentation of the forestadmin/laravel-forestadmin
Laravel agent that will soon reach end-of-support.
If you’re using a Laravel agent, notice that forestadmin/laravel-forestadmin
v1 is replaced by v3.
If you’re using a Symfony agent, go to the v1 documentation.
Please check your agent type and version and read on or switch to the right documentation.
Overriding a route allows you to change or completely replace a Forest Admin's route behavior.
To achieve this, use existing snippets of and modify them according to your needs.
Here are a few examples:
Use extended search by default
const express = require('express');
const {
PermissionMiddlewareCreator,
RecordsGetter,
RecordsCounter,
} = require('forest-express-sequelize');
const { companies } = require('../models');
const router = express.Router();
const permissionMiddlewareCreator = new PermissionMiddlewareCreator(
'companies'
);
//...
// Get a list of Companies - Check out our documentation for more details: https://docs.forestadmin.com/documentation/reference-guide/routes/default-routes#get-a-list-of-records
router.get(
'/companies',
permissionMiddlewareCreator.list(),
(request, response, next) => {
const { query, user } = request;
query.searchExtended = '1';
const recordsGetter = new RecordsGetter(companies, user, query);
recordsGetter
.getAll()
.then((records) => recordsGetter.serialize(records))
.then((recordsSerialized) => response.send(recordsSerialized))
.catch(next);
}
);
// Get a number of Companies - Check out our documentation for more details: https://docs.forestadmin.com/documentation/reference-guide/routes/default-routes#get-a-list-of-records
router.get(
'/companies/count',
permissionMiddlewareCreator.list(),
(request, response, next) => {
const { query, user } = request;
query.searchExtended = '1';
const recordsCounter = new RecordsCounter(companies, user, query);
recordsCounter
.count()
.then((count) => response.send({ count }))
.catch(next);
}
);
//...
const express = require('express');
const {
PermissionMiddlewareCreator,
RecordsGetter,
RecordsCounter,
} = require('forest-express-mongoose');
const { companies } = require('../models');
const router = express.Router();
const permissionMiddlewareCreator = new PermissionMiddlewareCreator(
'companies'
);
//...
// Get a list of Companies - Check out our documentation for more details: https://docs.forestadmin.com/documentation/reference-guide/routes/default-routes#get-a-list-of-records
router.get(
'/companies',
permissionMiddlewareCreator.list(),
(request, response, next) => {
const { query, user } = request;
query.searchExtended = '1';
const recordsGetter = new RecordsGetter(companies, user, query);
recordsGetter
.getAll()
.then((records) => recordsGetter.serialize(records))
.then((recordsSerialized) => response.send(recordsSerialized))
.catch(next);
}
);
// Get a number of Companies - Check out our documentation for more details: https://docs.forestadmin.com/documentation/reference-guide/routes/default-routes#get-a-list-of-records
router.get(
'/companies/count',
permissionMiddlewareCreator.list(),
(request, response, next) => {
const { query, user } = request;
query.searchExtended = '1';
const recordsCounter = new RecordsCounter(companies, user, query);
recordsCounter
.count()
.then((count) => response.send({ count }))
.catch(next);
}
);
//...
if ForestLiana::UserSpace.const_defined?('CompanyController')
ForestLiana::UserSpace::CompanyController.class_eval do
alias_method :default_index, :index
alias_method :default_count, :count
# Get a list of Companies
def index
params['searchExtended'] = '1'
default_index
end
# Get a number of Companies
def count
params['searchExtended'] = '1'
default_count
end
end
end
from django.http import JsonResponse
from django_forest.resources.utils.resource import ResourceView
from django_forest.resources.views import ListView
class CompaniesListView(ListView):
def get(self, request):
# default
queryset = self.Model.objects.all()
params = request.GET.dict()
# override for always setting search extended
params.update({'searchExtended': '1'})
try:
# enhance queryset
queryset = self.enhance_queryset(queryset, self.Model, params, request)
# handle smart fields
self.handle_smart_fields(queryset, self.Model._meta.db_table, many=True)
# json api serializer
data = self.serialize(queryset, self.Model, params)
# search decorator
data = self.decorators(data, self.Model, params)
except Exception as e:
return self.error_response(e)
else:
return JsonResponse(data, safe=False)
class CompaniesCountView(ResourceView):
def get(self, request):
queryset = self.Model.objects.all()
params = request.GET.dict()
params.update({'searchExtended': '1'})
return self.get_count(queryset, params, request)
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from . import views
app_name = 'app'
urlpatterns = [
path('/companies/count', views.CompaniesCountView.as_view(), name='companies-count'),
path('/companies', csrf_exempt(views.CompaniesListView.as_view()), name='companies-list'),
]
<?php
namespace App\Http\Controllers;
use ForestAdmin\LaravelForestAdmin\Http\Controllers\ResourcesController;
use Illuminate\Http\JsonResponse;
class CompaniesController extends ResourcesController
{
public function callAction($method, $parameters)
{
$parameters['collection'] = 'Company';
return parent::callAction($method, $parameters);
}
public function index()
{
request()->query->add(['searchExtended' => '1']);
return parent::index();
}
public function count(): JsonResponse
{
request()->query->add(['searchExtended' => '1']);
return parent::count();
}
}
<?php
use App\Http\Controllers\CompaniesController;
use Illuminate\Support\Facades\Route;
Route::get('forest/company', [CompaniesController::class, 'index']);
Route::get('forest/company/count', [CompaniesController::class, 'count']);
With this snippet, only the companies
collection would use extended search by default.
Using extended search is less performant than default search. Use this wisely.
Protect a specific record
router.delete(
'/companies/:recordId',
permissionMiddlewareCreator.delete(),
(request, response, next) => {
const { params, query, user } = request;
if (Number(params.recordId) === 82) {
response
.status(403)
.send('This record is protected, you cannot remove it.');
return;
}
const recordRemover = new RecordRemover(companies, user, query);
recordRemover
.remove(params.recordId)
.then(() => response.status(204).send())
.catch(next);
}
);
router.delete(
'/companies/:recordId',
permissionMiddlewareCreator.delete(),
(request, response, next) => {
const { params, query, user } = request;
if (Number(params.recordId) === 82) {
response
.status(403)
.send('This record is protected, you cannot remove it.');
return;
}
const recordRemover = new RecordRemover(companies, user, query);
recordRemover
.remove(params.recordId)
.then(() => response.status(204).send())
.catch(next);
}
);
if ForestLiana::UserSpace.const_defined?('CompanyController')
ForestLiana::UserSpace::CompanyController.class_eval do
alias_method :default_destroy, :destroy
def destroy
if params["id"] == "50"
render status: 403, plain: 'This record is protected, you cannot remove it.'
else
default_destroy
end
end
end
end
from django.http import HttpResponse
from django_forest.resources.views import DetailView
class CompaniesDetailView(DetailView):
def delete(self, request, pk):
if (pk == 82):
return HttpResponse(
'This record is protected, you cannot remove it.',
status=403);
return super(CompaniesDetailView, self).delete(request, pk)
<?php
namespace App\Http\Controllers;
use ForestAdmin\LaravelForestAdmin\Http\Controllers\ResourcesController;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
class CompaniesController extends ResourcesController
{
public function callAction($method, $parameters)
{
$parameters['collection'] = 'Company';
return parent::callAction($method, $parameters);
}
public function destroy(): JsonResponse
{
if (request()->route()->parameter('id') === "50") {
return response()->json(['error' => 'This record is protected, you cannot remove it.'], Response::HTTP_FORBIDDEN);
} else {
return parent::destroy();
}
}
}
To achieve this, simply remove the next()
statement of any route:
...
// Create a Company - Check out our documentation for more details: https://docs.forestadmin.com/documentation/reference-guide/routes/default-routes#create-a-record
router.post('/companies', permissionMiddlewareCreator.create(), (req, res, next) => {
// >> Add your own logic here <<
});
...
...
// Create a Company - Check out our documentation for more details: https://docs.forestadmin.com/documentation/reference-guide/routes/default-routes#create-a-record
router.post('/companies', permissionMiddlewareCreator.create(), (req, res, next) => {
// >> Add your own logic here <<
});
...
if ForestLiana::UserSpace.const_defined?('CompanyController')
ForestLiana::UserSpace::CompanyController.class_eval do
# Create a Company
def create
# >> Add your own logic here <<
end
end
end
from django.http import JsonResponse
from django_forest.resources.views import ListView
class CompaniesListView(ListView):
# Create a Company
def post(self, request):
body = self.get_body(request.body)
model = self.Model
# >> Add your own logic here <<
<?php
namespace App\Http\Controllers;
use ForestAdmin\LaravelForestAdmin\Http\Controllers\ResourcesController;
use Illuminate\Http\JsonResponse;
class UsersController extends ResourcesController
{
public function store(): JsonResponse
{
// >> Add your own logic here <<
}
}
For instance, if you have a Users
collection, you might want to create your users via your own api:
...
const axios = require('axios');
const { RecordSerializer } = require('forest-express-sequelize');
const { users } = require('../models');
...
router.post('/users', permissionMiddlewareCreator.create(), (request, response, next) => {
const recordSerializer = new RecordSerializer(users);
const axiosRequest = {
url: 'https://<your-api>/users',
method: 'post',
data: request.body.data.attributes,
};
axios(axiosRequest)
.then(result => recordSerializer.serialize(result.data))
.then(resultSerialized => response.send(resultSerialized))
.catch(error => {
console.log('error:', error);
next(error);
});
});
...
const axios = require('axios');
const { RecordSerializer } = require('forest-express-mongoose');
const { users } = require('../models');
...
router.post('/users', permissionMiddlewareCreator.create(), (request, response, next) => {
const recordSerializer = new RecordSerializer(users);
const axiosRequest = {
url: 'https://<your-api>/users',
method: 'post',
data: request.body.data.attributes,
};
axios(axiosRequest)
.then(result => recordSerializer.serialize(result.data))
.then(resultSerialized => response.send(resultSerialized))
.catch(error => {
console.log('error:', error);
next(error);
});
});
require 'net/http'
require 'uri'
if ForestLiana::UserSpace.const_defined?('UserController')
ForestLiana::UserSpace::UserController.class_eval do
# Create a User
def create
forest_authorize!('add', forest_user, @resource)
begin
response = Net::HTTP.post URI('https://<your-api>/users'), params.to_json, "Content-Type" => "application/json"
render serializer: nil, json: render_record_jsonapi(response.body)
rescue => errors
render serializer: nil, json: JSONAPI::Serializer.serialize_errors(errors), status: 400
end
end
end
end
import requests
import json
from django.http import JsonResponse
from django_forest.utils.schema.json_api_schema import JsonApiSchema
from django_forest.resources.views import ListView
class CompaniesListView(ListView):
# Create a Company
def post(self, request):
body = self.get_body(request.body)
r = requests.post('https://<your-api>/users', json.dumps(body), headers={'Content-Type': 'application/json'})
result = r.json()
instance = self.Model.objects.create(**result['data'])
# json api serializer
Schema = JsonApiSchema.get(self.Model._meta.db_table)
data = Schema().dump(instance)
return JsonResponse(data, safe=False)
<?php
namespace App\Http\Controllers;
use App\Models\User;
use ForestAdmin\LaravelForestAdmin\Facades\JsonApi;
use ForestAdmin\LaravelForestAdmin\Http\Controllers\ResourcesController;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Http;
class UsersController extends ResourcesController
{
public function callAction($method, $parameters)
{
$parameters['collection'] = 'User';
return parent::callAction($method, $parameters);
}
public function store(): JsonResponse
{
$this->authorize('create', $this->model);
$response = Http::post('https://<your-api>/users', request()->all())->json();
$user = User::findOrFail($response['id']);
return response()->json(JsonApi::render($user, $this->name), Response::HTTP_CREATED);
}
}
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
'forest/user',
];
}
<?php
use App\Http\Controllers\UsersController;
use Illuminate\Support\Facades\Route;
Route::post('forest/user', [UsersController::class, 'store']);
<?php
namespace App\Http\Controllers;
use App\Models\User;
use ForestAdmin\LaravelForestAdmin\Facades\JsonApi;
use ForestAdmin\LaravelForestAdmin\Http\Controllers\ResourcesController;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Http;
class UsersController extends ResourcesController
{
public function callAction($method, $parameters)
{
$parameters['collection'] = 'User';
return parent::callAction($method, $parameters);
}
public function store(): JsonResponse
{
$this->authorize('create', $this->model);
$response = Http::post('https://<your-api>/users', request()->all())->json();
$user = User::findOrFail($response['id']);
return response()->json(JsonApi::render($user, $this->name), Response::HTTP_CREATED);
}
}
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
'forest/user',
];
}
<?php
use App\Http\Controllers\UsersController;
use Illuminate\Support\Facades\Route;
Route::post('forest/user', [UsersController::class, 'store']);