Admin Only Decorator

Introduction: Making Guard Usage Easier

Welcome back! In the last lessons, you learned how to use guards to protect user data and how to log API activity with interceptors. Now, let’s focus on a common challenge: protecting admin-only endpoints in your API.

As your API grows, you will likely have several endpoints that should only be accessed by admins. If you add guards and role checks to each of these endpoints one by one, your code can quickly become repetitive and harder to maintain. In this lesson, you will learn how to make this process easier and cleaner by creating a custom decorator called @AdminOnly().

By the end of this lesson, you will know how to use this decorator to protect admin-only routes in a simple and reusable way.

Quick Recap: Our API and Guards

Before we dive in, let’s briefly remind ourselves how our API is set up and how guards are used. In previous lessons, you saw how to use guards to check if a user is authenticated and if they have the right permissions.

Here’s a quick example of a controller method that uses guards and role checks:

@Post()
@UseGuards(AuthGuard('jwt'), RolesGuard)
@Roles('admin')
create(@Body() createBookDto: CreateBookDto) {
  // Only admins can create books
  const book = this.booksService.create(createBookDto);
  return { success: true, data: book };
}

In this example:

  • @UseGuards(AuthGuard('jwt'), RolesGuard) checks if the user is authenticated and if they have the right role.
  • @Roles('admin') makes sure only admins can access this endpoint.

While this works, repeating these decorators on every admin-only endpoint can make your code messy and harder to update.

Building the @AdminOnly() Decorator

To solve the problem of repeating guard and role logic, you can create a custom decorator called @AdminOnly(). This decorator will combine all the necessary checks into one simple line.

Here is the code for the AdminOnly decorator:

import { applyDecorators, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Roles } from './roles.decorator';
import { RolesGuard } from '../guards/roles.guard';

export const AdminOnly = () =>
  applyDecorators(
    UseGuards(AuthGuard('jwt'), RolesGuard),
    Roles('admin'),
  );

Let’s break down what’s happening here:

  • applyDecorators is a helper from NestJS that lets you combine multiple decorators into one.
  • UseGuards(AuthGuard('jwt'), RolesGuard) applies both the authentication guard and the roles guard.
  • Roles('admin') ensures that only users with the admin role can access the endpoint.

By wrapping these checks into a single decorator, you make your code much cleaner and easier to maintain.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal