Skip to content

Get All Users (Admin) ​

Get a paginated list of all users. Admin only.

Endpoint ​

http
GET /users

Authentication ​

Required: Yes (JWT access token with admin role)

http
Authorization: Bearer <admin_access_token>

Access Control ​

  • Role Required: admin
  • Guard: JwtAuthGuard + RolesGuard
  • Regular users will receive 403 Forbidden

Query Parameters ​

ParameterTypeRequiredDefaultDescription
limitnumberNo20Number of users per page (max 100)
offsetnumberNo0Number of users to skip

Example URLs ​

GET /users
GET /users?limit=50
GET /users?limit=20&offset=40

Response ​

Success (200 OK) ​

json
{
  "users": [
    {
      "id": "507f1f77bcf86cd799439011",
      "email": "user1@example.com",
      "name": "John Doe",
      "phoneNumber": "+1234567890",
      "role": "user",
      "preferences": {
        "platforms": ["codeforces", "leetcode"],
        "alertFrequency": "immediate",
        "contestTypes": [],
        "notificationChannels": {
          "whatsapp": true,
          "email": true,
          "push": false
        },
        "notifyBefore": 24
      },
      "isActive": true,
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    },
    {
      "id": "507f1f77bcf86cd799439012",
      "email": "admin@example.com",
      "name": "Admin User",
      "role": "admin",
      "preferences": {
        "platforms": ["codeforces", "leetcode", "codechef", "atcoder"],
        "alertFrequency": "immediate",
        "contestTypes": [],
        "notificationChannels": {
          "whatsapp": true,
          "email": true,
          "push": true
        },
        "notifyBefore": 24
      },
      "isActive": true,
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  ],
  "total": 100,
  "limit": 20,
  "offset": 0
}

Response Fields ​

FieldTypeDescription
usersarrayArray of user objects
users[].idstringUser's unique identifier
users[].emailstringUser's email address
users[].namestringUser's full name
users[].phoneNumberstringUser's phone number (optional)
users[].rolestringUser role ('user' or 'admin')
users[].preferencesobjectUser's notification preferences
users[].isActivebooleanAccount active status
users[].createdAtstringAccount creation timestamp
users[].updatedAtstringLast update timestamp
totalnumberTotal number of users in database
limitnumberNumber of users per page (from request)
offsetnumberNumber of users skipped (from request)

Error Responses ​

401 Unauthorized ​

Missing or invalid JWT token.

json
{
  "statusCode": 401,
  "message": "Unauthorized",
  "error": "Unauthorized"
}

403 Forbidden ​

User is not an admin.

json
{
  "statusCode": 403,
  "message": "Forbidden resource",
  "error": "Forbidden"
}

Examples ​

Get First Page ​

bash
curl -X GET http://localhost:3000/users \
  -H "Authorization: Bearer <admin_access_token>"

Get with Pagination ​

bash
curl -X GET "http://localhost:3000/users?limit=50&offset=0" \
  -H "Authorization: Bearer <admin_access_token>"

JavaScript (Fetch) ​

javascript
const getAllUsers = async (limit = 20, offset = 0) => {
  const response = await fetch(
    `http://localhost:3000/users?limit=${limit}&offset=${offset}`,
    {
      headers: {
        'Authorization': `Bearer ${adminAccessToken}`
      }
    }
  );

  if (!response.ok) {
    throw new Error('Failed to fetch users');
  }

  return await response.json();
};

// Usage
const { users, total, limit, offset } = await getAllUsers(20, 0);
console.log(`Showing ${users.length} of ${total} users`);

React Component with Pagination ​

typescript
import { useState, useEffect } from 'react';

const UsersList = () => {
  const [users, setUsers] = useState([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(0);
  const [loading, setLoading] = useState(true);
  const limit = 20;

  useEffect(() => {
    const fetchUsers = async () => {
      setLoading(true);
      try {
        const response = await fetch(
          `/users?limit=${limit}&offset=${page * limit}`,
          {
            headers: {
              'Authorization': `Bearer ${adminAccessToken}`
            }
          }
        );
        const data = await response.json();
        setUsers(data.users);
        setTotal(data.total);
      } catch (error) {
        console.error('Failed to load users:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, [page]);

  const totalPages = Math.ceil(total / limit);

  return (
    <div>
      <h1>Users ({total})</h1>
      
      {loading ? (
        <div>Loading...</div>
      ) : (
        <>
          <table>
            <thead>
              <tr>
                <th>Name</th>
                <th>Email</th>
                <th>Role</th>
                <th>Status</th>
                <th>Created</th>
              </tr>
            </thead>
            <tbody>
              {users.map(user => (
                <tr key={user.id}>
                  <td>{user.name}</td>
                  <td>{user.email}</td>
                  <td>{user.role}</td>
                  <td>{user.isActive ? 'Active' : 'Inactive'}</td>
                  <td>{new Date(user.createdAt).toLocaleDateString()}</td>
                </tr>
              ))}
            </tbody>
          </table>

          <div>
            <button
              onClick={() => setPage(p => Math.max(0, p - 1))}
              disabled={page === 0}
            >
              Previous
            </button>
            <span>Page {page + 1} of {totalPages}</span>
            <button
              onClick={() => setPage(p => p + 1)}
              disabled={page >= totalPages - 1}
            >
              Next
            </button>
          </div>
        </>
      )}
    </div>
  );
};

Python (Requests) ​

python
import requests

def get_all_users(admin_token, limit=20, offset=0):
    headers = {
        'Authorization': f'Bearer {admin_token}'
    }
    
    params = {
        'limit': limit,
        'offset': offset
    }
    
    response = requests.get(
        'http://localhost:3000/users',
        headers=headers,
        params=params
    )
    
    if response.status_code == 200:
        return response.json()
    elif response.status_code == 403:
        raise Exception('Admin access required')
    else:
        raise Exception(f'Error: {response.json()}')

# Usage
data = get_all_users(admin_token, limit=50, offset=0)
print(f"Total users: {data['total']}")
for user in data['users']:
    print(f"{user['name']} ({user['email']}) - {user['role']}")

Pagination ​

Calculate Pages ​

javascript
const limit = 20;
const totalPages = Math.ceil(total / limit);
const currentPage = Math.floor(offset / limit) + 1;
javascript
// First page
const firstPage = { limit: 20, offset: 0 };

// Next page
const nextPage = { limit: 20, offset: offset + limit };

// Previous page
const prevPage = { limit: 20, offset: Math.max(0, offset - limit) };

// Last page
const lastPage = { limit: 20, offset: Math.floor(total / limit) * limit };

// Specific page (1-indexed)
const goToPage = (pageNum) => ({
  limit: 20,
  offset: (pageNum - 1) * limit
});

Fetch All Users (Multiple Requests) ​

javascript
const fetchAllUsers = async () => {
  const allUsers = [];
  const limit = 100; // Max per request
  let offset = 0;
  let total = 0;

  do {
    const response = await fetch(
      `/users?limit=${limit}&offset=${offset}`,
      {
        headers: { 'Authorization': `Bearer ${adminToken}` }
      }
    );
    const data = await response.json();
    
    allUsers.push(...data.users);
    total = data.total;
    offset += limit;
  } while (offset < total);

  return allUsers;
};

Implementation Details ​

Controller Method ​

File: server/src/users/users.controller.ts

typescript
@Get()
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@HttpCode(HttpStatus.OK)
async getAllUsers(@Query() query: GetAllUsersDto): Promise<{
  users: Array<{
    id: string;
    email: string;
    name: string;
    phoneNumber?: string;
    role: string;
    preferences: UserPreferences;
    isActive: boolean;
    createdAt: Date;
    updatedAt: Date;
  }>;
  total: number;
  limit: number;
  offset: number;
}> {
  const { users, total } = await this.usersService.getAllUsersWithPagination(
    query.limit,
    query.offset,
  );

  return {
    users: users.map((user) => ({
      id: user.id,
      email: user.email,
      name: user.name,
      phoneNumber: user.phoneNumber,
      role: user.role,
      preferences: user.preferences,
      isActive: user.isActive,
      createdAt: user.createdAt,
      updatedAt: user.updatedAt,
    })),
    total,
    limit: query.limit,
    offset: query.offset,
  };
}

Service Method ​

File: server/src/users/users.service.ts

typescript
async getAllUsersWithPagination(
  limit: number,
  offset: number,
): Promise<{ users: UserDocument[]; total: number }> {
  const [users, total] = await Promise.all([
    this.userModel
      .find()
      .select('-password -refreshToken')
      .skip(offset)
      .limit(limit)
      .sort({ createdAt: -1 })
      .exec(),
    this.userModel.countDocuments().exec(),
  ]);

  return { users, total };
}

Validation Schema ​

File: server/src/common/dto/user.dto.ts

typescript
export const GetAllUsersSchema = z.object({
  limit: z
    .string()
    .optional()
    .transform((val) => (val ? parseInt(val, 10) : 20)),
  offset: z
    .string()
    .optional()
    .transform((val) => (val ? parseInt(val, 10) : 0)),
});

Sorting ​

Users are sorted by creation date (newest first).

typescript
.sort({ createdAt: -1 })

Security Considerations ​

Admin-Only Access ​

  • Requires admin role in JWT token
  • Regular users receive 403 Forbidden
  • Role is checked by RolesGuard

Data Exclusions ​

Sensitive fields are excluded:

  • password (hashed password)
  • refreshToken (hashed refresh token)

Rate Limiting ​

  • Limit: 1000 requests per 15 minutes (admin)
  • Scope: Per IP address
  • Higher limit for admin operations

Use Cases ​

Admin Dashboard ​

Display all users with pagination, filtering, and actions.

User Management ​

View, edit, and manage user accounts.

Analytics ​

Count users by role, active status, or registration date.

Export Users ​

Fetch all users for CSV export or backup.

Best Practices ​

✅ Do ​

  1. Use pagination (don't fetch all at once)
  2. Cache results for better performance
  3. Handle 403 errors (check admin role)
  4. Show loading states during fetch
  5. Display total count for user reference

❌ Don't ​

  1. Don't fetch without pagination (performance issue)
  2. Don't expose admin endpoint to regular users
  3. Don't ignore rate limits
  4. Don't display sensitive data (password, tokens)
  5. Don't make excessive requests

Notes ​

  • Returns all users (active and inactive)
  • Sorted by creation date (newest first)
  • Password and refresh token are excluded
  • Default limit is 20 users per page
  • Total count includes all users in database

Built with ❤️ for competitive programmers worldwide.