Skip to content

Conversation

@ingale12345
Copy link

@ingale12345 ingale12345 commented Jul 1, 2025

✅ Completed : Admin Flow changes:

  • Added a Price column to the Subscription table.
  • User list (Name, Email, Plan Remaining, Used).
  • Edit subscription plan for a user (open a modal with only plan details editable)
  • When an admin clicks on a user, they can view all recordings for that specific user (API done)
  • Added admin api authorization wrapper for api security by validating role
  • added table column changes and its migration scripts
  • using the axios client for api calls from the UI
  • Added APIs to get transcriptions by user and sample transcriptions
  • EDIT and delete transcription APIs
  • Created all required Admin APIs and their Postman collection.With request body and responses(attached in PR

Summary by Bito

This pull request enhances the admin interface with new pages for managing users, recordings, and subscriptions, while adding corresponding API endpoints with improved validation. The changes include database schema updates to support pricing and role modifications, along with a standardized navigation system for admin features.

ingale12345 and others added 24 commits June 26, 2025 12:44
@ingale12345
Copy link
Author

Added @poojalandejosh

@ingale12345
Copy link
Author

Added All Required Admin APIS and Its postman collection. with reqest Body and responses.

Lingo.postman_collection.json

@poojalandejosh
Copy link
Contributor

Screenshot 2025-07-03 at 12 07 13 PM Screenshot 2025-07-03 at 12 07 25 PM Screenshot 2025-07-03 at 12 08 04 PM Screenshot 2025-07-03 at 12 08 09 PM Screenshot 2025-07-03 at 12 08 23 PM

@poojalandejosh poojalandejosh marked this pull request as ready for review July 3, 2025 06:45
@sourabh-josh
Copy link
Contributor

Let’s address the current build errors first.
The command used: npm run build

Also, please take a look at the following warnings related to missing dependencies in useEffect hooks. It would be good to refactor these as well:

./src/app/admin/components/EditSubscription.tsx
130:6  Warning: React Hook useEffect has a missing dependency: 'subscription.id'. Either include it or remove the dependency array.  react-hooks/exhaustive-deps

./src/app/admin/subscriptions/page.tsx
46:4  Warning: React Hook useEffect has a missing dependency: 'subs'. Either include it or remove the dependency array. You can also replace multiple useState variables with useReducer if 'setIsModalOpen' needs the current value of 'subs'.  react-hooks/exhaustive-deps

./src/components/Navigation.tsx
81:6  Warning: React Hook useEffect has missing dependencies: 'pathname', 'router', and 'updateUIState'. Either include them or remove the dependency array.  react-hooks/exhaustive-deps

info  - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/app/api-reference/config/eslint#disabling-rules
Failed to compile.

src/app/admin/page.tsx
Type error: File './src/app/admin/page.tsx' is not a module.

@sourabh-josh sourabh-josh self-requested a review July 7, 2025 12:05
@Selectus2
Copy link
Collaborator

/review

@bito-code-review
Copy link

Changelist by Bito

This pull request implements the following key changes.

Key Change Files Impacted
Feature Improvement - Database Schema and Migration Enhancements

0011_sour_maria_hill.sql - Adds migration steps to set default user roles, fix existing data issues, enforce NOT NULL constraints, and add a new price column to the subscriptions table.

0011_snapshot.json - Updates the database snapshot to reflect new column definitions and schema changes across tables, including adjustments for user role defaults and subscription pricing.

_journal.json - Records updated migration execution details with a new version tag and breakpoints for schema changes.

schema.ts - Updates the user table to enforce a non-null role with a default value and adds a new price column to the subscription schema.

New Feature - Admin UI Enhancements

EditSubscription.tsx - Introduces a client-side component for editing user subscription details with state management and API integration.

SubscriptionEdit.tsx - Adds a modal component to update subscription plan details using form inputs and API patch calls.

layout.tsx - Implements an admin layout with navigation links and role-based access control to secure admin operations.

page.tsx - Implements a client-side recordings listing page that fetches recordings via API and provides a UI for deletion.

page.tsx - Renders a subscriptions table with support for modal editing of subscription details and integrates with API endpoints.

RecordingsPage.tsx - Displays recordings specific to a user with delete functionality and formatted data presentation.

page.tsx - Wraps the user recordings component to pass the required user parameters seamlessly.

page.tsx - Lists users along with their subscription information and enables navigation to detailed recordings by handling click events.

useUser.ts - Updates navigation logic to redirect users based on their role, sending regular users to one route and admins to another.

axios.ts - Introduces a common axios client to standardize API calls throughout the admin UI.

Feature Improvement - Backend API Enhancements

route.ts - Provides GET and PATCH endpoints for subscription details with proper validation and error handling for updating subscriptions.

route.ts - Establishes endpoints for listing all subscriptions and creating new ones with input validation using zod.

route.ts - Offers endpoints to retrieve and delete specific transcriptions with necessary admin authorization.

route.ts - Introduces a paginated endpoint for fetching sample transcriptions based on default transcription flags.

route.ts - Retrieves and updates user information including subscription details and dynamically calculates transcription usage.

route.ts - Implements paginated user listing with search capabilities while joining subscription data for comprehensive admin management.

route.ts - Adds a GET endpoint for fetching user transcriptions with pagination and admin authorization checks.

route.ts - Implements a PATCH endpoint to update user roles with parameter validation and admin authorization.

route.ts - Implements a PATCH endpoint to update user subscription details after validating required parameters.

withAdmin.ts - Introduces an admin authorization wrapper to secure API endpoints by validating user roles before processing requests.

auth.ts - Enhances authentication by including user roles in the returned attributes and updating the DatabaseUserAttributes interface.

roles.ts - Defines and exports role constants to ensure consistent role management across the application.

Copy link

@bito-code-review bito-code-review bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #d83474

Actionable Suggestions - 4
  • app/src/app/api/admin/subscriptions/[id]/route.ts - 1
    • Unvalidated input allows unauthorized field modification · Line 35-49
  • app/src/app/admin/users/page.tsx - 1
  • app/src/app/admin/recordings/[id]/page.tsx - 1
    • Non-functional delete button implementation · Line 82-82
  • app/src/app/admin/subscriptions/page.tsx - 1
    • Infinite loop in useEffect dependency · Line 47-49
Additional Suggestions - 4
  • app/src/app/api/admin/users/route.ts - 1
    • Redundant authorization validation logic · Line 9-9
      Redundant authorization check detected. The `withAdmin` wrapper already validates admin access by calling `validateRequest()` and checking user role. Remove the duplicate validation (lines 9-13) to eliminate unnecessary database calls and improve performance.
      Code suggestion
       @@ -9,6 +9,1 @@
      -  const { user } = await validateRequest();
      -
      -  if (!user || user.role !== "ADMIN") {
      -    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
      -  }
      -  const { searchParams } = new URL(req.url);
      +  const { searchParams } = new URL(req.url);
  • app/src/app/admin/components/SubscriptionEdit.tsx - 1
    • Unused state variable and setter · Line 15-15
      The `editingField` state variable and its setter `setEditingField` are declared but never used in the component. Consider removing them to improve code cleanliness.
      Code suggestion
       @@ -14,6 +14,5 @@
        const SubscriptionEdit = ({ recording, onClose }: Props) => {
          const [editData, setEditData] = useState<SubscriptionData>(recording);
      -  const [editingField, setEditingField] = useState<string | null>(null);
          const [updating, setUpdating] = useState(false);
          console.log("recording", recording);
          useEffect(() => {
  • app/src/app/api/admin/users/transcriptions/[userId]/route.ts - 1
    • Unused import 'and' should be removed · Line 4-4
      The `and` import from drizzle-orm is defined but never used in this file. Please remove it to keep the code clean and avoid potential confusion.
      Code suggestion
       @@ -4,1 +4,1 @@
      -import { and, eq, sql } from "drizzle-orm";
      +import { eq, sql } from "drizzle-orm";
  • app/src/app/api/admin/users/[id]/route.ts - 1
    • Unused destructured variable in object pattern · Line 79-79
      The `password_hash` variable is destructured but never used. Consider using the rest operator directly without explicitly naming the unused variable.
      Code suggestion
       @@ -79,3 +79,3 @@
      -  const { password_hash, ...user } = updated; // removed password hash from response
      +  const { password_hash: _, ...user } = updated; // removed password hash from response
Review Details
  • Files reviewed - 27 · Commit Range: d75249a..d199bbc
    • app/migrations/0011_sour_maria_hill.sql
    • app/migrations/meta/0011_snapshot.json
    • app/migrations/meta/_journal.json
    • app/src/app/admin/components/EditSubscription.tsx
    • app/src/app/admin/components/SubscriptionEdit.tsx
    • app/src/app/admin/layout.tsx
    • app/src/app/admin/recordings/[id]/page.tsx
    • app/src/app/admin/subscriptions/page.tsx
    • app/src/app/admin/users/[id]/recordings/RecordingsPage.tsx
    • app/src/app/admin/users/[id]/recordings/page.tsx
    • app/src/app/admin/users/page.tsx
    • app/src/app/api/admin/subscriptions/[id]/route.ts
    • app/src/app/api/admin/subscriptions/route.ts
    • app/src/app/api/admin/transcriptions/[id]/route.ts
    • app/src/app/api/admin/transcriptions/sample/route.ts
    • app/src/app/api/admin/users/[id]/route.ts
    • app/src/app/api/admin/users/route.ts
    • app/src/app/api/admin/users/transcriptions/[userId]/route.ts
    • app/src/app/api/admin/users/update-role/route.ts
    • app/src/app/api/admin/users/update-subscription/route.ts
    • app/src/app/api/signin/route.ts
    • app/src/auth.ts
    • app/src/constants/roles.ts
    • app/src/db/schema.ts
    • app/src/hooks/useUser.ts
    • app/src/lib/axios.ts
    • app/src/lib/withAdmin.ts
  • Files skipped - 0
  • Tools
    • Eslint (Linter) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Default Agent You can customize the agent settings here or contact your Bito workspace admin at [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +35 to +49
const data = await req.json();
const { id } = params;

if (!id) {
return NextResponse.json(
{ error: "Subscription ID is required" },
{ status: 400 }
);
}

try {
const [updated] = await db
.update(subscriptionTable)
.set(data)
.where(eq(subscriptionTable.id, id))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unvalidated input allows unauthorized field modification

The PATCH endpoint accepts arbitrary data without validation and directly passes it to the database update. This creates a security vulnerability where malicious users could modify system fields like id or createdAt. Add input validation with a whitelist of allowed fields: ['name', 'recordingCount', 'fileSizeLimitMB', 'durationDays', 'price'].

Code suggestion
Check the AI-generated fix before applying
Suggested change
const data = await req.json();
const { id } = params;
if (!id) {
return NextResponse.json(
{ error: "Subscription ID is required" },
{ status: 400 }
);
}
try {
const [updated] = await db
.update(subscriptionTable)
.set(data)
.where(eq(subscriptionTable.id, id))
const requestData = await req.json();
const { id } = params;
if (!id) {
return NextResponse.json(
{ error: "Subscription ID is required" },
{ status: 400 }
);
}
// Whitelist allowed fields for update
const allowedFields = ['name', 'recordingCount', 'fileSizeLimitMB', 'durationDays', 'price'];
const sanitizedData = Object.fromEntries(
Object.entries(requestData).filter(([key]) => allowedFields.includes(key))
);
if (Object.keys(sanitizedData).length === 0) {
return NextResponse.json(
{ error: "No valid fields to update" },
{ status: 400 }
);
}
try {
const [updated] = await db
.update(subscriptionTable)
.set(sanitizedData)
.where(eq(subscriptionTable.id, id))

Code Review Run #d83474


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Comment on lines +37 to +42
useEffect(() => {
if (!isModalOpen) {
fetchUsers();
}
fetchUsers();
}, [isModalOpen]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant API calls in useEffect

Remove the redundant fetchUsers() call that causes duplicate API requests. The function is already called conditionally on line 39, making line 41 unnecessary and wasteful.

Code suggestion
Check the AI-generated fix before applying
Suggested change
useEffect(() => {
if (!isModalOpen) {
fetchUsers();
}
fetchUsers();
}, [isModalOpen]);
useEffect(() => {
if (!isModalOpen) {
fetchUsers();
}
}, [isModalOpen]);

Code Review Run #d83474


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

</TableCell>
<TableCell className="flex gap-2">
<div className="w-8 h-8 p-2 rounded-full flex items-center justify-center shadow-xl hover:bg-red-500 cursor-pointer hover:text-white">
<Trash2 onClick={() => {}} size={20} />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-functional delete button implementation

The Trash2 delete button has an empty onClick={() => {}} handler that does nothing when clicked. This creates a non-functional delete button that appears interactive but doesn't perform any action. Implement a proper delete function that calls the API to delete the recording and updates the local state.

Code suggestion
Check the AI-generated fix before applying
 -export default function RecordingsPage({ params }: PageProps) {
 -  const [recordings, setRecordings] = useState<Recording[]>([]);
 -  const searchParams = useSearchParams();
 -  const page = searchParams.get("page") || "1";
 -  const limit = searchParams.get("limit") || "20";
 +export default function RecordingsPage({ params }: PageProps) {
 +  const [recordings, setRecordings] = useState<Recording[]>([]);
 +  const searchParams = useSearchParams();
 +  const page = searchParams.get("page") || "1";
 +  const limit = searchParams.get("limit") || "20";
 +
 +  const handleDelete = async (recordingId: string) => {
 +    try {
 +      await API.delete(`/admin/users/transcriptions/${params.id}/${recordingId}`);
 +      setRecordings(recordings.filter((recording) => recording.id !== recordingId));
 +    } catch (error) {
 +      console.error("Failed to delete recording:", error);
 +    }
 +  };
 @@ -81,7 +81,7 @@
 -                    <Trash2 onClick={() => {}} size={20} />
 +                    <Trash2 onClick={() => handleDelete(audioFile.id)} size={20} />

Code Review Run #d83474


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Comment on lines +47 to +49
useEffect(() => {
fetchSubscriptions();
}, [isModalOpen]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Infinite loop in useEffect dependency

The useEffect with isModalOpen dependency creates an infinite loop. When modal opens/closes → triggers fetchSubscriptions() → updates subs → triggers first useEffect → updates isModalOpen → repeats endlessly. Fix: Remove isModalOpen from dependency array and use empty array for initial fetch.

Code suggestion
Check the AI-generated fix before applying
Suggested change
useEffect(() => {
fetchSubscriptions();
}, [isModalOpen]);
useEffect(() => {
fetchSubscriptions();
}, []); // Run only on mount
useEffect(() => {
if (isModalOpen === null) fetchSubscriptions();
}, [isModalOpen]);

Code Review Run #d83474


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants