Module

@adminjs/nestjs

This is an official plugin which allows you to render AdminJS in NestJS framework

Installation

  1. 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

  1. 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.

  1. 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

Classes

AdminModule

Nest Module

Type Definitions

object

# AdminModuleOptions

Options passed to nestjs module
Properties:
Name Type Attributes Description
adminJsOptions AdminJSOptions

Standard AdminJS options

auth object <optional>

Authentication options. When NOT provided, it will initialize AdminJS without login page and authorization function.

authenticate function

verifies if given credentials are valid, therefore if user has access to Admin Panel

cookiePassword string
cookieName string
formidableOptions ExpressFormidableOptions <optional>

Options passed to express formidable (used only by AdminJS express module)

sessionOptions SessionOptions <optional>

Options passed to express session (used only by AdminJS express module), Here you might want to change the store from the default memory store to, something more reliable (i.e. database).

shouldBeInitialized boolean <optional>

Flag indicating if adminjs should be initialized. Helpful in cases like turning off admin for tests., Default is true.

View Source adminjs-nestjs/src/interfaces/admin-module-options.interface.ts, line 7