Skip to content

Commit

Permalink
refactor(api): update admin route handlers to use authenticateUser an…
Browse files Browse the repository at this point in the history
…d errorHandler 🔐

- Replaced custom headers with Authorization and �uthenticateUser for better security.
- Integrated errorHandler for consistent error responses with proper status codes.
- Streamlined the logic for handling admin data retrieval and error management.
  • Loading branch information
ad956 committed Sep 23, 2024
1 parent d5bb0b0 commit 1cb2480
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 88 deletions.
36 changes: 21 additions & 15 deletions app/api/admin/add-admin/route.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import dbConfig from "@utils/db";
import { authenticateUser } from "@lib/auth/authenticateUser";
import Admin from "@models/admin";
import { dbConfig, errorHandler, STATUS_CODES } from "@utils/index";
import hashPassword from "@utils/hashPassword";
import { NewAdminTemplate } from "@lib/emails/templates";
import { render } from "@react-email/render";
import sendEmail from "@lib/sendemail";
import { NextResponse } from "next/server";

export async function POST(request: Request) {
const authHeader = request.headers.get("Authorization");

try {
const id = request.headers.get("x-user-id");
const role = request.headers.get("x-user-role");
const { id, role } = await authenticateUser(authHeader);

if (!id || !role) {
return Response.json(
{ error: "Missing user ID or role" },
{ status: 400 }
return errorHandler(
"Missing user ID or role",
STATUS_CODES.VALIDATION_ERROR
);
}

Expand All @@ -22,13 +25,13 @@ export async function POST(request: Request) {
const formData = await request.json();
const { firstname, lastname, email, password } = formData;

// check if admin exists
// Check if admin exists
const existingAdmin = await Admin.findOne({ email });
if (existingAdmin) {
return Response.json({ error: "Admin already exists" }, { status: 409 });
return errorHandler("Admin already exists", STATUS_CODES.CONFLICT);
}

// generate a username
// Generate a username
let username = `${firstname.toLowerCase()}.${lastname.toLowerCase()}`;
let usernameSuffix = 0;
let usernameExists = true;
Expand All @@ -43,10 +46,10 @@ export async function POST(request: Request) {
}
}

// hashing password
// Hashing password
const hashedPassword = await hashPassword(password);

// new admin
// New admin
const newAdmin = new Admin({
firstname,
lastname,
Expand All @@ -70,7 +73,7 @@ export async function POST(request: Request) {
},
});

// save new admin
// Save new admin
await newAdmin.save();

const mailsent = await sendEmail({
Expand All @@ -95,15 +98,18 @@ export async function POST(request: Request) {
console.error("Failed to send welcome email to new admin");
}

return Response.json(
return NextResponse.json(
{
success: true,
message: "Admin added successfully",
},
{ status: 200 }
);
} catch (error) {
} catch (error: any) {
console.error("Error adding admin:", error);
return Response.json({ error: "Internal Server Error" }, { status: 500 });
return errorHandler(
error.message || "Internal Server Error",
STATUS_CODES.SERVER_ERROR
);
}
}
35 changes: 22 additions & 13 deletions app/api/admin/dashboard/recent-users/route.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import dbConfig from "@utils/db";
import { authenticateUser } from "@lib/auth/authenticateUser";
import mongoose from "mongoose";
import {
FormattedRecentUser,
RecentUserTile,
RecentUserPaginatedResponse,
} from "@pft-types/admin";
import { dbConfig, errorHandler, STATUS_CODES } from "@utils/index";
import { NextResponse } from "next/server";

export async function GET(request: Request): Promise<Response> {
const id = request.headers.get("x-user-id");
const role = request.headers.get("x-user-role");
const authHeader = request.headers.get("Authorization");

if (!id || !role) {
return Response.json({ error: "Missing user ID or role" }, { status: 400 });
}
try {
const { id, role } = await authenticateUser(authHeader);

const url = new URL(request.url);
const page = parseInt(url.searchParams.get("page") || "1");
const limit = parseInt(url.searchParams.get("limit") || "10");
if (!id || !role) {
return errorHandler(
"Missing user ID or role",
STATUS_CODES.VALIDATION_ERROR
);
}

const url = new URL(request.url);
const page = parseInt(url.searchParams.get("page") || "1");
const limit = parseInt(url.searchParams.get("limit") || "10");

try {
await dbConfig();

const oneMonthAgo = new Date();
Expand Down Expand Up @@ -76,10 +82,13 @@ export async function GET(request: Request): Promise<Response> {
totalItems,
};

return Response.json(response);
} catch (error) {
return NextResponse.json(response, { status: 200 });
} catch (error: any) {
console.error("Error fetching new users:", error);
return Response.json({ error: "Internal Server Error" }, { status: 500 });
return errorHandler(
error.message || "Internal Server Error",
STATUS_CODES.SERVER_ERROR
);
}
}

Expand Down
27 changes: 17 additions & 10 deletions app/api/admin/dashboard/tiles/route.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import dbConfig from "@utils/db";
import { Hospital, Patient, Doctor, Receptionist } from "@models/index";
import { authenticateUser } from "@lib/auth/authenticateUser";
import { NextResponse } from "next/server";
import { errorHandler, STATUS_CODES } from "@utils/index";

export async function GET(request: Request) {
const authHeader = request.headers.get("Authorization");

try {
const id = request.headers.get("x-user-id");
const role = request.headers.get("x-user-role");
const { id, role } = await authenticateUser(authHeader);

if (!id || !role) {
return Response.json(
{ error: "Missing user ID or role" },
{ status: 400 }
return errorHandler(
"Missing user ID or role",
STATUS_CODES.VALIDATION_ERROR
);
}

await dbConfig();

// start of the current month and the previous month
// Start of the current month and the previous month
const now = new Date();
const startOfCurrentMonth = new Date(now.getFullYear(), now.getMonth(), 1);
const startOfPreviousMonth = new Date(
Expand Down Expand Up @@ -82,9 +86,12 @@ export async function GET(request: Request) {
},
};

return Response.json(result);
} catch (error) {
console.error("Error fetching tiles data :", error);
return Response.json({ error: "Internal Server Error" }, { status: 500 });
return NextResponse.json(result, { status: 200 });
} catch (error: any) {
console.error("Error fetching tiles data:", error);
return errorHandler(
error.message || "Internal Server Error",
STATUS_CODES.SERVER_ERROR
);
}
}
26 changes: 17 additions & 9 deletions app/api/admin/hospitals/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@ import dbConfig from "@utils/db";
import Hospital from "@models/hospital";
import { HospitalDetails } from "@pft-types/admin";
import { Types } from "mongoose";
import { NextResponse } from "next/server";
import { errorHandler, STATUS_CODES } from "@utils/index";
import { authenticateUser } from "@lib/auth/authenticateUser";

export async function GET(request: Request) {
try {
const id = request.headers.get("x-user-id");
const role = request.headers.get("x-user-role");
const authHeader = request.headers.get("Authorization");
const { id, role } = await authenticateUser(authHeader);

if (!id || !role) {
return Response.json(
{ error: "Missing user ID or role" },
{ status: 400 }
return errorHandler(
"Missing user ID or role",
STATUS_CODES.VALIDATION_ERROR
);
}

const admin_id = new Types.ObjectId(id);

await dbConfig();

// parse query parameters for pagination
// Parse query parameters for pagination
const url = new URL(request.url);
const page = parseInt(url.searchParams.get("page") || "1");
const limit = parseInt(url.searchParams.get("limit") || "10");
Expand All @@ -28,6 +31,7 @@ export async function GET(request: Request) {
// Count total hospitals before applying skip and limit
const totalHospitals = await Hospital.countDocuments();
let hospitals = [];

if (skip < totalHospitals) {
const hospitalsPipeline = [
{
Expand Down Expand Up @@ -66,12 +70,16 @@ export async function GET(request: Request) {
totalPages: totalPages,
totalCount: totalHospitals,
};
return Response.json({

return NextResponse.json({
hospitals: hospitalDetails,
pagination: paginationMetadata,
});
} catch (error) {
} catch (error: any) {
console.error("Error fetching Hospital data:", error);
return Response.json({ error: "Internal Server Error" }, { status: 500 });
return errorHandler(
error.message || "Internal Server Error",
STATUS_CODES.SERVER_ERROR
);
}
}
40 changes: 23 additions & 17 deletions app/api/admin/hospitals/users/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ import dbConfig from "@utils/db";
import { Patient, Receptionist, Hospital, Doctor } from "@models/index";
import { HospitalUserDetails } from "@pft-types/admin";
import { Types } from "mongoose";
import { NextResponse } from "next/server";
import { errorHandler, STATUS_CODES } from "@utils/index";
import { authenticateUser } from "@lib/auth/authenticateUser";

export async function GET(request: Request) {
try {
const id = request.headers.get("x-user-id");
const role = request.headers.get("x-user-role");
const authHeader = request.headers.get("Authorization");
const { id, role } = await authenticateUser(authHeader);

if (!id || !role) {
return Response.json(
{ error: "Missing user ID or role" },
{ status: 400 }
return errorHandler(
"Missing user ID or role",
STATUS_CODES.VALIDATION_ERROR
);
}

await dbConfig();

// parse query parameters for pagination
// Parse query parameters for pagination
const url = new URL(request.url);
const page = parseInt(url.searchParams.get("page") || "1");
const limit = parseInt(url.searchParams.get("limit") || "10");
Expand All @@ -26,9 +29,9 @@ export async function GET(request: Request) {
const hospitalId = url.searchParams.get("hospitalId");

if (!hospitalId) {
return Response.json(
{ error: "hospitalId is required" },
{ status: 400 }
return errorHandler(
"hospitalId is required",
STATUS_CODES.VALIDATION_ERROR
);
}

Expand All @@ -47,7 +50,7 @@ export async function GET(request: Request) {
let userDetails: HospitalUserDetails[] = [];

if (skip < totalUsers) {
// base aggregation pipeline
// Base aggregation pipeline
const baseAggregationPipeline = [
{
$match: {
Expand All @@ -70,14 +73,14 @@ export async function GET(request: Request) {
{ $limit: limit },
];

// create role-specific pipeline
// Create role-specific pipeline
const createPipelineWithRole = (pipeline: any[], role: string) => [
...pipeline.slice(0, 1),
{ $addFields: { role: role } },
...pipeline.slice(1),
];

// create role-specific pipelines
// Create role-specific pipelines
const patientsPipeline = createPipelineWithRole(
baseAggregationPipeline,
"Patient"
Expand All @@ -91,14 +94,14 @@ export async function GET(request: Request) {
"Doctor"
);

// fetch users from each model
// Fetch users from each model
const [patients, receptionists, doctors] = await Promise.all([
Patient.aggregate(patientsPipeline),
Receptionist.aggregate(receptionistsPipeline),
Doctor.aggregate(doctorsPipeline),
]);

// combine and map results
// Combine and map results
const allUsers = [...patients, ...receptionists, ...doctors];
userDetails = allUsers.map((user) => ({
id: user._id.toString(),
Expand All @@ -122,12 +125,15 @@ export async function GET(request: Request) {
totalCount: totalUsers,
};

return Response.json({
return NextResponse.json({
users: userDetails,
pagination: paginationMetadata,
});
} catch (error) {
} catch (error: any) {
console.error("Error fetching Users data:", error);
return Response.json({ error: "Internal Server Error" }, { status: 500 });
return errorHandler(
error.message || "Internal Server Error",
STATUS_CODES.SERVER_ERROR
);
}
}
Loading

0 comments on commit 1cb2480

Please sign in to comment.