Skip to main content

How to add an action to a REST API controller

General

In this example, you will see how to add an action to a REST API controller.

The entity.controller.ts file is generated only once by Amplication, and you can freely customize it. Amplication will never override this file.

You can use this file to add new actions (endpoints) or override existing actions that are inherited from entity.controller.base

Example

The example will demonstrate how to get the parameters from the request and call a service to execute the operation.

It will also demonstrate how to check the user's permissions, how to add Swagger UI documentation, and how to log the request.

Adding a new endpoint to user.controller.ts

  1. Open the file user.controller.ts. The file is located in ./server/src/user/user.controller.ts.
info

When you add custom code to the root controller of an entity, even though this calls the super() class, all the decorators of this method must be copied from the base class.

Initially, the files should look like this

import * as common from "@nestjs/common";
import * as swagger from "@nestjs/swagger";
import * as nestAccessControl from "nest-access-control";
import { UserService } from "./user.service";
import { UserControllerBase } from "./base/user.controller.base";

@swagger.ApiTags("users")
@common.Controller("users")
export class UserController extends UserControllerBase {
constructor(
protected readonly service: UserService,
@nestAccessControl.InjectRolesBuilder()
protected readonly rolesBuilder: nestAccessControl.RolesBuilder
) {
super(service, rolesBuilder);
}
}
  1. Add the following imports at the beginning of the file
  import * as errors from "../errors";
import { User } from "./base/User";
import { UserWhereUniqueInput } from "./base/UserWhereUniqueInput";
import { AclValidateRequestInterceptor } from "src/interceptors/aclValidateRequest.interceptor";
  1. Add the following code at the bottom of the class.
  @common.UseInterceptors(AclValidateRequestInterceptor)
@common.Patch("/:id/password")
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "own",
})
@swagger.ApiOkResponse({ type: User })
@swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
async resetPassword(
@common.Param() params: UserWhereUniqueInput,
): Promise<User | null> {
const result = await this.service.resetPassword({
where: params,
});
if (result === null) {
throw new errors.NotFoundException(
`No resource was found for ${JSON.stringify(params)}`
);
}
return result;
}

The above code gets a user ID from the request, checks for the user permissions, and calls the user service to reset the password.

line-by-line instructions

Follow this line-by-line explanation to learn more about the code you used:

This decorator uses Nest interceptor that we created (AclValidateRequestInterceptor) to validate the request object by filtering it based on the user permissions.

@common.UseInterceptors(AclValidateRequestInterceptor)

This decorator sets the route for the endpoint.

  @common.Patch("/:id/password")

This decorator Uses nestJS Access Control to enforce access permissions based on the user's role permissions. This example validates that the current user can update user records.

  @nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "own",
})

These 3 decorators provide information for Swagger UI documentation

  @swagger.ApiOkResponse({ type: User })
@swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })

Create a function called resetPassword with parameter of type UserWhereUniqueInput and return type User | null.

async resetPassword(
@common.Param() params: UserWhereUniqueInput
): Promise<User | null> {

This line creates a parameter named userRoles and extract its value from the current context using nestAccessControl. UserWhereUniqueInput and return type User | null.

    @nestAccessControl.UserRoles() userRoles: string[]

Call the user service to execute the resetPassword, then check and filter the results before returning them to the client.

const result = await this.service.resetPassword({
where: params,
});
if (result === null) {
throw new errors.NotFoundException(
`No resource was found for ${JSON.stringify(params)}`
);
}
return results;

Check your changes

You are ready to check your changes. Just save all changes and restart your server. Navigate to http://localhost:3000/api/ to see and execute the new API endpoint.

tip

You can run your server in watch mode so it automatically restarts every time a file in the server code is changed. Instead of using npm start you should use this command

nest start --debug --watch