This is an official plugin which allows you to render AdminJS in NestJS
framework
Installation
- First of all, install the AdminJS along with the module:
yarn add adminjs @adminjs/nestjs
Express:
You have to additionally add adminjs express plugin along with packages it's using, express and express formidable:
yarn add express @adminjs/express express-formidable
If you are passing authenticate
object you have to also add express-session:
yarn add express-session
Fastify:
Work in progress - currently not available
- Once the installation process is complete, we can import the AdminModule
into the root AppModule.
import { Module } from '@nestjs/common';
import { AdminModule } from '@adminjs/nestjs';
@Module({
imports: [
AdminModule.createAdmin({
adminJsOptions: {
rootPath: '/admin',
resources: [],
}),
},
],
})
export class AppModule {}
Then enter /admin
path in your browser and you should see the AdminJS.
- Passing resources
Let say you use @nestjs/typeorm module, and you have users module.
- you have to install @adminjs/typeorm adapter
- you have to register it in AdminJS (as stated in the docs)
- and you have to pass it to your options
import AdminJS from 'adminjs';
import { Module } from '@nestjs/common';
import { AdminModule } from '@adminjs/nestjs';
import { Database, Resource } from '@adminjs/typeorm'
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersModule } from './users/users.module';
AdminJS.registerAdapter({ Database, Resource })
@Module({
imports: [
// you will have to change connection data of course :)
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: '',
database: 'database_test',
entities: [User],
synchronize: true,
}),
AdminModule.createAdmin({
adminJsOptions: {
rootPath: '/admin',
resources: [User],
}
}),
],
})
export class AppModule {}
Authentication
Apart from the adminJsOptions
you can define auth
settings.
This is an example which always logs users in, since authenticate method
always returns a Promise resolving to CurrentAdmin. You may
want to compare the password against what what you have encrypted
in the database.
AdminModule.createAdmin({
adminJsOptions: {
rootPath: '/admin',
resources: [User],
},
auth: {
authenticate: async (email, password) => Promise.resolve({ email: 'test' }),
cookieName: 'test',
cookiePassword: 'testPass',
},
}),
Advanced techniques
Sometimes some thing couldn't be provided synchronously, that's why there is also asynchronous way of providing options.
Let's say you use @nestjs/mongoose module, which could define models in modules that fit the best contextually.
This creates a problem that we don't have model instance available yet when we are creating AdminModule synchronously.
We can take advantage of nestjs dependency injection using AdminModule.createAdminAsync()
.
This method alows us to import modules that have necessary dependencies and then inject them to admin bro config.
For example:
- we have MongooseSchemasModule which defines Admin model and exports it:
@Module({
imports: [
MongooseModule.forFeature([{ name: 'Admin', schema: AdminSchema }]),
],
exports: [MongooseModule],
})
export class MongooseSchemasModule {}
- we want to use Admin model in adminjs panel, to be displayed as the resource
@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017/test'),
AdminModule.createAdminAsync({
imports: [
MongooseSchemasModule, // importing module that exported model we want to inject
],
inject: [
getModelToken('Admin'), // using mongoose function to inject dependency
],
useFactory: (adminModel: Model<Admin>) => ({ // injected dependecy will appear as an argument
adminJsOptions: {
rootPath: '/admin',
resources: [
{ resource: adminModel },
],
},
}),
}),
MongooseSchemasModule,
],
})
export class AppModule { }
Custom loader
In most cases default plugins for adminjs are enough for functionality we need, but in rare ocasions
we want to customize routing, or achieve different logic after login and this cases can be achieved only
by providing own plugin implementation. Because @adminjs/nestjs under the hood uses plugin for express (@adminjs/express)
it would require basically copying whole nestjs plugin and express plugin to own project to put any changes.
Instead there is optional parameter to put your custom loader if you don't want to use official one for any reason.
Your custom loader must extend AbstractLoader.
@Injectable()
export class CustomLoader extends AbstractLoader {
public register(
admin: AdminJS,
httpAdapter: AbstractHttpAdapter,
options: AdminModuleOptions,
) {}
}
And then in module:
AdminModule.createAdmin({
adminJsOptions: {
//...
},
auth: {
//...
},
customLoader: CustomLoader,
}),
or if you using more advanced techniques:
AdminModule.createAdmin({
useFactory: () => {}
customLoader: CustomLoader,
}),
Example
There is a working example here