Skip to content

Controller abstract

MartinDrost edited this page Nov 28, 2019 · 5 revisions

Extending your controllers with the CrudController will give you access to a set of basic Restful endpoints.

Method URL Response
Create model POST / Model
Get model by id GET /:id Model
Get many by id GET /many/:ids Model[]
Get all GET / Model[]
Overwrite model PUT /:id? Model
Merge model PATCH /:id? Model
Delete model DELETE /:id Model

Basic usage

Implementing the CrudController is pretty straightforward. The only prerequisite is that you have created a CrudService class which executes all of the actions the controller has to perform. Afterwards you can just extend your controller class as shown below.

@Controller('users')
export class UserController extends CrudController<IUserModel> {
  constructor(private readonly service: UserService) {
    super(service);
  }
}

Authorization

In almost every scenario you don't want all endpoints to be publicly available. This is why the package supports the use of NestJS guards on the generated endpoints.

const permissions = {
  admin: {
    guards: [RolesGuard],
    data: { roles: [Role.ADMIN] },
  },
  user: {
    guards: [RolesGuard],
    data: { roles: [] },
  },
};


@Controller('users')
export class UserController extends CrudController<IUserModel> {
  constructor(private readonly service: UserService) {
    super(service, {
      create: permissions.admin,
      read: permissions.user,
      update: permissions.admin,
      delete: permissions.admin,
    });
  }
}

Guards can be defined per CRUD action as a second parameter of the super() call and accept guards as defined in the NestJS documentation. The only difference is that provided data has to be retrieved from the context.metadata attribute instead of the reflector. You can support both methods as show below.

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(context: any) {
    const roles: Role[] =
      context.metadata?.roles ||
      this.reflector.get<string[]>('roles', context.getHandler());
    
    ...
  }
}

Query Parameters

In order to allow query parameter functionality in custom endpoints you will have to mold the received parameters into the correct format and forward it to the service. This can be easily achieved using the queryToOptions() method as shown below.

@Controller('users')
export class UserController extends CrudController<IUserModel> {
  constructor(private readonly service: UserService) {
    super(service);
  }

  @Get('inactive')
  getInactive(@Req() request: INuRequest, @Query() query: IHttpOptions) {
    const options: INuOptions = this.queryToOptions(query);
    options.request = request;

    this.service.getInactive(options);
  }
}
Clone this wiki locally