Skip to content

Comments

eat: add Docker support and implement API-driven collaboration request handling#301

Open
shivansh023023 wants to merge 5 commits intoAOSSIE-Org:mainfrom
shivansh023023:feature/add-docker-support
Open

eat: add Docker support and implement API-driven collaboration request handling#301
shivansh023023 wants to merge 5 commits intoAOSSIE-Org:mainfrom
shivansh023023:feature/add-docker-support

Conversation

@shivansh023023
Copy link

@shivansh023023 shivansh023023 commented Feb 17, 2026

This PR provides a comprehensive upgrade to the repository by introducing Full-Stack Collaboration Logic and Containerization Support. It transitions the project from a manual setup to an automated environment while completing the core "Accept/Deny" functionality in the Collaboration Hub.

Changes

  1. Infrastructure (Docker)
    Onboarding Automation: Created a Dockerfile using python:3.10-slim to ensure a consistent development environment across Linux, macOS, and Windows.

Modular Targeting: Configured the build process to correctly handle the project's structure by targeting the /Backend directory and installing all necessary system-level dependencies (build-essential).

  1. Backend (FastAPI)
    New API Route: Developed Backend/app/routes/collaboration.py to handle asynchronous status updates for collaboration requests.

Database Integration: Implemented logic to update the collaborations table, ensuring the "status" column accurately reflects 'accepted' or 'denied' states.

App Lifecycle: Registered the new router in main.py to ensure the backend recognizes the new collaboration endpoints.

  1. Frontend (React/TypeScript)
    Bridge Implementation: Replaced mock TODO placeholders in CollabRequests.tsx with real asynchronous fetch calls to the backend API.

State Management: Optimized the UI to automatically filter out requests once they have been successfully accepted or denied by the user.

Why?
As a student developer using Pop!_OS, I identified that manual environment setup was prone to system-specific errors. Furthermore, bridging the UI to the existing database structure was a critical step in making the platform functional for the GSoC 2026 cycle. These changes improve both the developer experience and the end-user functionality.

Checklist
[x] My PR addresses infrastructure and core functional gaps.

[x] My code follows the project's modular FastAPI/React architecture.

[x] All automated CodeRabbit and CI checks have passed.

[x] I have verified the changes locally using the new Docker environment.

Summary by CodeRabbit

  • New Features

    • Collaboration requests can be accepted or denied; status updates persist to the server with clearer success/error feedback.
    • UI improvements: per-request loading state disables buttons during network calls and prevents duplicate actions.
  • Chores

    • Added Docker containerization for simplified deployment and environment management.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

Adds a Dockerfile for containerization, registers a new collaboration APIRouter in the FastAPI app, implements a PUT endpoint to update collaboration status with validation and async DB update, and updates frontend handlers to call that endpoint with loading state and detailed error handling.

Changes

Cohort / File(s) Summary
Docker Configuration
Dockerfile
New Dockerfile based on python:3.10-slim; installs build tools, copies Backend/requirements.txt, installs Python deps, copies project, sets PYTHONUNBUFFERED, and sets working dir to /app/Backend.
Backend - entry & collaboration route
Backend/app/main.py, Backend/app/routes/collaboration.py
main.py now includes the collaboration APIRouter. New PUT /collaboration/update-status/{collab_id} endpoint validates status (accepted/denied), performs an async SQLAlchemy UPDATE on Collaboration, commits, checks affected rows, and returns 200 or raises 400/404 as appropriate.
Frontend - collaboration UI handlers & state
Frontend/src/components/collaboration-hub/CollabRequests.tsx
Moved BASE_URL to module scope, changed mock IDs to strings, added loadingId state to disable buttons for in-flight requests, implemented handleAccept/handleDeny as async PUT calls to /collaboration/update-status/{id}?status=..., parse and surface server error details, and remove request from UI on success.

Sequence Diagram(s)

sequenceDiagram
    participant Frontend as Frontend
    participant Backend as Backend
    participant Database as Database

    Frontend->>Backend: PUT /collaboration/update-status/{id}?status=accepted
    activate Backend
    Backend->>Database: UPDATE Collaboration SET status='accepted' WHERE id={id}
    activate Database
    Database-->>Backend: rows affected / ACK
    deactivate Database
    Backend-->>Frontend: 200 { message }
    deactivate Backend
    Frontend->>Frontend: remove request from UI list
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through files to change the gate,
PUTs dispatched and statuses update.
Buttons pause while the network sings,
DB nods yes, and the frontend springs. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add Docker support and implement API-driven collaboration request handling' clearly and specifically summarizes the two main changes: Docker containerization and the new collaboration API endpoints with frontend integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
Dockerfile (1)

16-17: COPY . . pulls in the entire repo — consider a .dockerignore or narrower COPY.

This copies .git/, IDE config, other top-level directories, and potentially secrets or large artifacts into the image. At minimum, add a .dockerignore file (e.g., excluding .git, __pycache__, *.pyc, .env, node_modules, etc.). Alternatively, since the WORKDIR is switched to /app/Backend, consider copying only what's needed:

-COPY . .
+COPY Backend/ ./Backend/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 16 - 17, The Dockerfile currently uses COPY . .
which pulls the entire repo (including .git, IDE files, secrets and large
artifacts); add a .dockerignore that excludes .git, node_modules, __pycache__,
*.pyc, .env, etc., or replace COPY . . with a targeted copy that only copies the
Backend app sources (e.g., COPY ./Backend/ . after the WORKDIR change) so only
required files are included; update the Dockerfile's COPY invocation or add the
.dockerignore accordingly and verify build context to ensure sensitive/large
files are excluded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfile`:
- Around line 1-23: The Dockerfile currently misses a default runtime command;
add an ENTRYPOINT or CMD in the Dockerfile to start the backend service (e.g.,
invoke Python on your app entrypoint or start Uvicorn for an ASGI app). Update
the Dockerfile to include a final line that runs the correct entrypoint
(reference the project's actual startup target such as main.py or the ASGI app
module) and ensure the referenced script/module (e.g., main.py or app:app) is
present in Backend and executable; adjust the entrypoint string to match that
symbol.
- Around line 8-10: The apt-get install invocation in the Dockerfile (the RUN
line that performs "apt-get update && apt-get install -y build-essential && rm
-rf /var/lib/apt/lists/*") should include --no-install-recommends to avoid
installing unnecessary recommended packages; update that RUN command to use
"apt-get install -y --no-install-recommends build-essential" (keeping the
existing apt-get update and the rm -rf /var/lib/apt/lists/* cleanup) so the
image size is reduced and Trivy DS-0029 is addressed.
- Around line 1-2: The container currently runs as root; add a non-root user and
switch to it at the end of the Dockerfile: create a user and group (e.g.,
appuser/appgroup) with non-root UID/GID, ensure application files/directories
are owned by that user (chown relevant paths), set appropriate permissions, and
add a USER appuser (or UID:GID) instruction as the final step so the process
runs unprivileged; reference the Dockerfile and the USER directive when making
the changes.

---

Nitpick comments:
In `@Dockerfile`:
- Around line 16-17: The Dockerfile currently uses COPY . . which pulls the
entire repo (including .git, IDE files, secrets and large artifacts); add a
.dockerignore that excludes .git, node_modules, __pycache__, *.pyc, .env, etc.,
or replace COPY . . with a targeted copy that only copies the Backend app
sources (e.g., COPY ./Backend/ . after the WORKDIR change) so only required
files are included; update the Dockerfile's COPY invocation or add the
.dockerignore accordingly and verify build context to ensure sensitive/large
files are excluded.

Comment on lines +1 to +23
# Use a stable Python base image
FROM python:3.10-slim

# Set the working directory
WORKDIR /app

# Install system-level dependencies for building Python packages
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*

# Copy requirements from the Backend folder and install
COPY Backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy the entire project into the container
COPY . .

# Set environment variables (standard for AI platforms)
ENV PYTHONUNBUFFERED=1

# Change to the Backend directory to run the application
WORKDIR /app/Backend No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

No CMD or ENTRYPOINT — the container has no default run command.

The Dockerfile sets up the environment but never declares what to run. Without a CMD or ENTRYPOINT, docker run on this image will drop into a shell (inherited from the base image) rather than starting the backend service. This makes the image unusable out of the box.

Add an appropriate entrypoint, e.g.:

Proposed fix
 # Change to the Backend directory to run the application
 WORKDIR /app/Backend
+
+# Run the application
+CMD ["python", "main.py"]

Adjust main.py to whatever the actual entry point script is.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Use a stable Python base image
FROM python:3.10-slim
# Set the working directory
WORKDIR /app
# Install system-level dependencies for building Python packages
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements from the Backend folder and install
COPY Backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the entire project into the container
COPY . .
# Set environment variables (standard for AI platforms)
ENV PYTHONUNBUFFERED=1
# Change to the Backend directory to run the application
WORKDIR /app/Backend
# Use a stable Python base image
FROM python:3.10-slim
# Set the working directory
WORKDIR /app
# Install system-level dependencies for building Python packages
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements from the Backend folder and install
COPY Backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the entire project into the container
COPY . .
# Set environment variables (standard for AI platforms)
ENV PYTHONUNBUFFERED=1
# Change to the Backend directory to run the application
WORKDIR /app/Backend
# Run the application
CMD ["python", "main.py"]
🧰 Tools
🪛 Trivy (0.69.1)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)


[error] 8-10: 'apt-get' missing '--no-install-recommends'

'--no-install-recommends' flag is missed: 'apt-get update && apt-get install -y build-essential && rm -rf /var/lib/apt/lists/*'

Rule: DS-0029

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 1 - 23, The Dockerfile currently misses a default
runtime command; add an ENTRYPOINT or CMD in the Dockerfile to start the backend
service (e.g., invoke Python on your app entrypoint or start Uvicorn for an ASGI
app). Update the Dockerfile to include a final line that runs the correct
entrypoint (reference the project's actual startup target such as main.py or the
ASGI app module) and ensure the referenced script/module (e.g., main.py or
app:app) is present in Backend and executable; adjust the entrypoint string to
match that symbol.

Comment on lines +1 to +2
# Use a stable Python base image
FROM python:3.10-slim
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Container runs as root — add a non-root USER.

Running the application as root inside the container is a security risk. If the process is compromised, the attacker has full root privileges within the container. This was also flagged by Trivy (DS-0002).

Proposed fix — add a non-root user at the end
+# Create a non-root user
+RUN useradd --create-home appuser
+USER appuser
+
 # Change to the Backend directory to run the application
 WORKDIR /app/Backend
🧰 Tools
🪛 Trivy (0.69.1)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 1 - 2, The container currently runs as root; add a
non-root user and switch to it at the end of the Dockerfile: create a user and
group (e.g., appuser/appgroup) with non-root UID/GID, ensure application
files/directories are owned by that user (chown relevant paths), set appropriate
permissions, and add a USER appuser (or UID:GID) instruction as the final step
so the process runs unprivileged; reference the Dockerfile and the USER
directive when making the changes.

Comment on lines +8 to +10
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add --no-install-recommends to reduce image bloat.

Without this flag, apt-get install pulls in recommended (but unnecessary) packages, increasing image size. Also flagged by Trivy (DS-0029).

Proposed fix
-RUN apt-get update && apt-get install -y \
+RUN apt-get update && apt-get install -y --no-install-recommends \
     build-essential \
     && rm -rf /var/lib/apt/lists/*
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
&& rm -rf /var/lib/apt/lists/*
🧰 Tools
🪛 Trivy (0.69.1)

[error] 8-10: 'apt-get' missing '--no-install-recommends'

'--no-install-recommends' flag is missed: 'apt-get update && apt-get install -y build-essential && rm -rf /var/lib/apt/lists/*'

Rule: DS-0029

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 8 - 10, The apt-get install invocation in the
Dockerfile (the RUN line that performs "apt-get update && apt-get install -y
build-essential && rm -rf /var/lib/apt/lists/*") should include
--no-install-recommends to avoid installing unnecessary recommended packages;
update that RUN command to use "apt-get install -y --no-install-recommends
build-essential" (keeping the existing apt-get update and the rm -rf
/var/lib/apt/lists/* cleanup) so the image size is reduced and Trivy DS-0029 is
addressed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (1)
Backend/app/routes/collaboration.py (1)

10-10: Suppress the Ruff B008 false positive — or migrate to the modern Annotated style

Depends(get_db) as a default argument is idiomatic FastAPI and B008 is a known false positive in this context. Ruff's own docs show extend-immutable-calls = ["fastapi.Depends", "fastapi.Query"] as the canonical way to suppress it project-wide. Alternatively, the modern FastAPI-recommended style avoids the issue entirely:

♻️ Modern `Annotated` style (also silences FAST002)
+from typing import Annotated
 ...
-async def update_collab_status(collab_id: str, status: str, db: AsyncSession = Depends(get_db)):
+async def update_collab_status(collab_id: str, status: str, db: Annotated[AsyncSession, Depends(get_db)]):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Backend/app/routes/collaboration.py` at line 10, Ruff flags the use of
Depends(get_db) as a B008 false positive in update_collab_status; fix by either
adding "fastapi.Depends" to your Ruff config's extend-immutable-calls (to
suppress B008 project-wide) or convert the parameter to the modern Annotated
style (e.g., use Annotated[AsyncSession, Depends(get_db)]) so the linter and
FastAPI both accept it—update the function signature for update_collab_status
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Backend/app/routes/collaboration.py`:
- Line 10: Add authentication and authorization to update_collab_status: require
the current user via a dependency (e.g., add Depends(get_current_user)
parameter) and after loading the collaboration record inside
update_collab_status verify that current_user.id matches either
collaboration.creator_1_id or collaboration.creator_2_id; if no match, raise an
HTTPException(403). Ensure you import/get_current_user and use the existing
get_db AsyncSession dependency, and return/continue only when the authorization
check passes.
- Line 5: Remove the inline developer note from the import statement so the
production code reads only the import (i.e., keep "from ..models.models import
Collaboration" and delete the trailing comment "# Verify this name in
models/models.py"); before committing, verify that the Collaboration symbol
exists and is correctly named in models/models.py but do not leave that
verification note in the source file.
- Around line 15-18: The handler currently calls
db.execute(update(Collaboration)... ) and always returns success; change it to
capture the execution result (e.g., result = await db.execute(query)), check
result.rowcount, and if rowcount == 0 raise an HTTPException(status_code=404,
detail=f"Collaboration {collab_id} not found"); only call await db.commit() and
return the success message when rowcount > 0. Make sure to import HTTPException
from fastapi if not already present.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx`:
- Around line 100-124: Change the id parameter types of the handlers to accept
string IDs (update handleAccept(id: string) and handleDeny(id: string)) and
adjust any related usages (e.g., setRequests callback) so they treat req.id as a
string; also update mockRequests so its id fields are UUID strings (or change
the mock type to mark id as string) to keep types consistent with backend
Collaboration.id and prevent mismatched requests to update-status endpoints.
- Around line 105-107: The current approve flow checks response.ok and only
updates state on success, leaving non-OK responses silently ignored; update the
handler (e.g., handleApprove and mirror in handleDeny) to handle the else branch
when response.ok is false by reporting the error to the user (show a
toast/notification or at least console.warn) and avoid silently doing
nothing—read response.text() or response.json() for details to include in the
message, and ensure any non-OK path doesn't falsely assume removal via
setRequests(prev => prev.filter(req => req.id !== id)).
- Line 102: Hardcoded backend origin in CollabRequests.tsx (used in handleAccept
and handleDeny) breaks non-local deployments; define a BASE_URL from a Vite env
var (e.g. import.meta.env.VITE_API_BASE_URL) at module scope and replace the
literal "http://localhost:8000" in the fetch calls inside handleAccept and
handleDeny with `${BASE_URL}/collaboration/update-status/${id}?status=...`,
ensuring both handlers use the shared BASE_URL constant so staging/production
pick up the correct host.
- Around line 100-111: The function declaration for handleAccept inside the
CollabRequests component is mis-indented (starts at column 0); update its
indentation to match the component body (2 spaces) like the other handlers
(e.g., handleDeny) so the function signature and its block are aligned with
other declarations in CollabRequests; ensure the entire async function (from
"const handleAccept = async (id: number) => {" through its closing brace) is
shifted by two spaces.

---

Nitpick comments:
In `@Backend/app/routes/collaboration.py`:
- Line 10: Ruff flags the use of Depends(get_db) as a B008 false positive in
update_collab_status; fix by either adding "fastapi.Depends" to your Ruff
config's extend-immutable-calls (to suppress B008 project-wide) or convert the
parameter to the modern Annotated style (e.g., use Annotated[AsyncSession,
Depends(get_db)]) so the linter and FastAPI both accept it—update the function
signature for update_collab_status accordingly.

router = APIRouter(prefix="/collaboration", tags=["Collaboration"])

@router.put("/update-status/{collab_id}")
async def update_collab_status(collab_id: str, status: str, db: AsyncSession = Depends(get_db)):
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Missing authentication/authorization — any caller can update any collaboration record

The endpoint has no auth dependency (e.g., get_current_user). An unauthenticated request to PUT /collaboration/update-status/{collab_id} can flip the status of any collaboration row without proving the caller is a party to it. This should also verify the requesting user is creator_1_id or creator_2_id of the target record.

🧰 Tools
🪛 Ruff (0.15.1)

[warning] 10-10: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Backend/app/routes/collaboration.py` at line 10, Add authentication and
authorization to update_collab_status: require the current user via a dependency
(e.g., add Depends(get_current_user) parameter) and after loading the
collaboration record inside update_collab_status verify that current_user.id
matches either collaboration.creator_1_id or collaboration.creator_2_id; if no
match, raise an HTTPException(403). Ensure you import/get_current_user and use
the existing get_db AsyncSession dependency, and return/continue only when the
authorization check passes.

Comment on lines 15 to 18
query = update(Collaboration).where(Collaboration.id == collab_id).values(status=status)
await db.execute(query)
await db.commit()
return {"message": f"Collaboration {status} successfully"} No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Silent no-op when collab_id doesn't exist — returns 200 instead of 404

db.execute(update(...)) succeeds even when zero rows match. The response always reports success. Check result.rowcount and raise a 404 if nothing was updated.

🐛 Proposed fix
     query = update(Collaboration).where(Collaboration.id == collab_id).values(status=status)
-    await db.execute(query)
+    result = await db.execute(query)
     await db.commit()
+    if result.rowcount == 0:
+        raise HTTPException(status_code=404, detail="Collaboration not found")
     return {"message": f"Collaboration {status} successfully"}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
query = update(Collaboration).where(Collaboration.id == collab_id).values(status=status)
await db.execute(query)
await db.commit()
return {"message": f"Collaboration {status} successfully"}
query = update(Collaboration).where(Collaboration.id == collab_id).values(status=status)
result = await db.execute(query)
await db.commit()
if result.rowcount == 0:
raise HTTPException(status_code=404, detail="Collaboration not found")
return {"message": f"Collaboration {status} successfully"}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Backend/app/routes/collaboration.py` around lines 15 - 18, The handler
currently calls db.execute(update(Collaboration)... ) and always returns
success; change it to capture the execution result (e.g., result = await
db.execute(query)), check result.rowcount, and if rowcount == 0 raise an
HTTPException(status_code=404, detail=f"Collaboration {collab_id} not found");
only call await db.commit() and return the success message when rowcount > 0.
Make sure to import HTTPException from fastapi if not already present.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
Frontend/src/components/collaboration-hub/CollabRequests.tsx (3)

100-101: Move BASE_URL to module scope — it's a compile-time constant

import.meta.env.VITE_API_BASE_URL is resolved at build time and never changes, so evaluating it inside the component body on every render is unnecessary. Define it once at the top of the module alongside the imports.

♻️ Proposed refactor
+const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000";
+
 const CollabRequests: React.FC = () => {
   const [requests, setRequests] = useState(mockRequests);
 
-  // Use environment variable for the API base URL
-  const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000";
-
   const handleAccept = async (id: string) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx` around lines
100 - 101, Move the BASE_URL constant out of the CollabRequests component and
into module scope near the imports so it's evaluated once at build time instead
of on every render; locate the BASE_URL definition in CollabRequests.tsx (the
line using import.meta.env.VITE_API_BASE_URL) and cut/paste it to the top of the
file (above the CollabRequests component/function) so the component references
the module-scoped BASE_URL constant.

136-139: id parameter in handleMessage is declared but never used

The function ignores its argument entirely. Prefix with _ or remove it until the chat feature is implemented.

♻️ Proposed fix
- const handleMessage = (id: string) => {
+ const handleMessage = (_id: string) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx` around lines
136 - 139, handleMessage currently declares an unused parameter id; either
remove the parameter or mark it as intentionally unused by renaming it to _id so
linters won't warn. Update the handleMessage function signature in
CollabRequests.tsx (function name: handleMessage) to either () => { ... } if you
don't need the id yet, or ( _id: string ) => { ... } if you want to keep the
parameter for future use, and keep the existing TODO and alert body unchanged.

113-113: Add a toast library and replace blocking alert() calls with non-blocking user feedback

alert() freezes the entire browser tab until dismissed. The project doesn't currently have a toast/notification library installed. Consider adding one (e.g., sonner is popular with Radix UI-based stacks), then replace these calls with toast notifications for better UX and consistent error presentation.

Applies to lines 113, 129, and 138 in CollabRequests.tsx.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx` at line 113,
Install a lightweight toast library (e.g., sonner) and replace blocking alert()
calls in the CollabRequests React component with non-blocking toast
notifications: add the toast provider (Toaster) at your app root, import the
toast function into
Frontend/src/components/collaboration-hub/CollabRequests.tsx, and swap each
alert(`Failed to accept: ${err.detail || "Server error"}`) / similar alerts at
the accept/decline/remove handlers with toast.error or toast.success calls that
include the same message (use err.detail || "Server error" as the message
fallback); ensure imports and provider wiring (Toaster) are added so toasts
render.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx`:
- Around line 103-134: Add a local in-flight tracker (e.g.,
useState<Set<string>> or useRef Set) and guard handleAccept and handleDeny so
they early-return if the id is already in-flight, add the id to the tracker
before calling fetch and remove it in finally, and update the buttons that call
handleAccept/handleDeny to be disabled when the id is present in that tracker;
update references in handleAccept/handleDeny, the fetch calls to
`${BASE_URL}/collaboration/update-status/${id}?status=...`, and the JSX
Accept/Deny buttons so rapid clicks are ignored until the request settles.
- Around line 127-130: The non-OK branch in handleDeny currently shows a
hardcoded alert and never reads the response body, unlike handleAccept; update
handleDeny to await response.json(), extract the error detail the same way
handleAccept does (e.g., const body = await response.json(); const message =
body?.err?.detail ?? "Failed to deny request. Please try again."); and use that
message in the alert so server-side validation errors (like "already denied" or
"not found") are displayed to the user.
- Around line 105-107: The backend endpoint /collaboration/update-status/{id}
must require authentication and enforce authorization: update the route handler
that serves this endpoint to include an authentication dependency (e.g., add
Depends(get_current_user) to the handler signature) and, inside the handler (the
function implementing update-status), verify that the authenticated user is the
owner or has permission to modify the collaboration record with the given id
before applying the status change; if the check fails return an appropriate
401/403 response. Ensure the same changes are applied to the other update-status
variant referenced (lines 122-124) so all status updates are protected.

---

Nitpick comments:
In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx`:
- Around line 100-101: Move the BASE_URL constant out of the CollabRequests
component and into module scope near the imports so it's evaluated once at build
time instead of on every render; locate the BASE_URL definition in
CollabRequests.tsx (the line using import.meta.env.VITE_API_BASE_URL) and
cut/paste it to the top of the file (above the CollabRequests
component/function) so the component references the module-scoped BASE_URL
constant.
- Around line 136-139: handleMessage currently declares an unused parameter id;
either remove the parameter or mark it as intentionally unused by renaming it to
_id so linters won't warn. Update the handleMessage function signature in
CollabRequests.tsx (function name: handleMessage) to either () => { ... } if you
don't need the id yet, or ( _id: string ) => { ... } if you want to keep the
parameter for future use, and keep the existing TODO and alert body unchanged.
- Line 113: Install a lightweight toast library (e.g., sonner) and replace
blocking alert() calls in the CollabRequests React component with non-blocking
toast notifications: add the toast provider (Toaster) at your app root, import
the toast function into
Frontend/src/components/collaboration-hub/CollabRequests.tsx, and swap each
alert(`Failed to accept: ${err.detail || "Server error"}`) / similar alerts at
the accept/decline/remove handlers with toast.error or toast.success calls that
include the same message (use err.detail || "Server error" as the message
fallback); ensure imports and provider wiring (Toaster) are added so toasts
render.

Comment on lines 105 to 107
const response = await fetch(`${BASE_URL}/collaboration/update-status/${id}?status=accepted`, {
method: 'PUT',
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "*.py" | head -20

Repository: AOSSIE-Org/InPactAI

Length of output: 682


🏁 Script executed:

# Look for the backend endpoint implementation
rg -n "update-status|update_status" -t py -B 5 -A 10

Repository: AOSSIE-Org/InPactAI

Length of output: 1150


🏁 Script executed:

# Search for authentication patterns in the codebase
rg -n "Depends\(.*get_current_user\)|HTTPBearer|oauth2_scheme|@.*auth" -t py -B 2 -A 2

Repository: AOSSIE-Org/InPactAI

Length of output: 316


🏁 Script executed:

cat -n Backend/app/routes/collaboration.py | head -50

Repository: AOSSIE-Org/InPactAI

Length of output: 1385


🏁 Script executed:

# Check other routes to see authentication patterns
rg -n "get_current_user|HTTPBearer|oauth2_scheme" Backend/app/routes/ -B 2 -A 2

Repository: AOSSIE-Org/InPactAI

Length of output: 45


🏁 Script executed:

# Check main.py for middleware or global auth setup
cat -n Backend/app/main.py

Repository: AOSSIE-Org/InPactAI

Length of output: 2425


🏁 Script executed:

# Check full auth.py to understand authentication mechanisms
cat -n Backend/app/routes/auth.py

Repository: AOSSIE-Org/InPactAI

Length of output: 251


🏁 Script executed:

# Check other routes that modify data (POST, PUT, DELETE) for auth patterns
rg -n "@router\.(post|put|delete)" Backend/app/routes/ -A 5

Repository: AOSSIE-Org/InPactAI

Length of output: 4408


Backend endpoint currently lacks authentication — critical security vulnerability

The /collaboration/update-status/{id} endpoint does not require authentication. While the frontend omits auth headers, the real issue is that the backend allows unauthenticated requests to modify collaboration records. Any user can update any collaboration status without verification.

The endpoint must implement authentication (e.g., Depends(get_current_user)) and authorization checks (verify the requester owns or has permission for the collaboration).

Also applies to: 122-124

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx` around lines
105 - 107, The backend endpoint /collaboration/update-status/{id} must require
authentication and enforce authorization: update the route handler that serves
this endpoint to include an authentication dependency (e.g., add
Depends(get_current_user) to the handler signature) and, inside the handler (the
function implementing update-status), verify that the authenticated user is the
owner or has permission to modify the collaboration record with the given id
before applying the status change; if the check fails return an appropriate
401/403 response. Ensure the same changes are applied to the other update-status
variant referenced (lines 122-124) so all status updates are protected.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Frontend/src/components/collaboration-hub/CollabRequests.tsx (1)

241-243: ⚠️ Potential issue | 🟡 Minor

Email button has no onClick handler — it renders but does nothing when clicked.

Unlike the Message button which has handleMessage, the Email button is inert. Either wire it up with a placeholder (like handleMessage) or disable it to set correct user expectations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx` around lines
241 - 243, In CollabRequests.tsx the Email Button (the <Button> rendering the
<Mail /> icon) lacks an onClick, so add an onClick to either call the existing
handleMessage handler or implement a new handler (e.g., handleEmail) in the
CollabRequests component and wire it to the Button; alternatively, if email
functionality isn't available yet, set the Button's disabled prop and update
aria-label to indicate it's disabled. Ensure the handler name (handleEmail or
reuse handleMessage) is defined in the same component and referenced on the
Button's onClick to provide expected behavior.
🧹 Nitpick comments (2)
Frontend/src/components/collaboration-hub/CollabRequests.tsx (2)

105-144: handleAccept and handleDeny are near-identical — extract a shared helper to reduce duplication

The two handlers differ only in the status query param and the log/alert verb. Consider a single handleStatusUpdate(id, status) function to keep this DRY.

Sketch
+  const handleStatusUpdate = async (id: string, status: "accepted" | "denied") => {
+    if (loadingId) return;
+    setLoadingId(id);
+    try {
+      const response = await fetch(`${BASE_URL}/collaboration/update-status/${id}?status=${status}`, {
+        method: 'PUT',
+      });
+      if (response.ok) {
+        setRequests(prev => prev.filter(req => req.id !== id));
+      } else {
+        const err = await response.json().catch(() => ({}));
+        alert(`Failed to ${status === "accepted" ? "accept" : "deny"}: ${err.detail || "Server error"}`);
+      }
+    } catch (error) {
+      console.error(`Failed to ${status} request:`, error);
+    } finally {
+      setLoadingId(null);
+    }
+  };
+
+  const handleAccept = (id: string) => handleStatusUpdate(id, "accepted");
+  const handleDeny = (id: string) => handleStatusUpdate(id, "denied");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx` around lines
105 - 144, Extract the duplicate logic in handleAccept and handleDeny into a
single helper like handleStatusUpdate(id: string, status: 'accepted' | 'denied',
verb: string) that uses setLoadingId,
fetch(`${BASE_URL}/collaboration/update-status/${id}?status=${status}`, {
method: 'PUT' }), handles response.ok by removing the request via
setRequests(prev => prev.filter(req => req.id !== id)), parses server error JSON
on non-ok to show alert(`Failed to ${verb}: ${err.detail || "Server error"}`),
logs exceptions with console.error("Failed to {verb} request:", error), and
finally clears setLoadingId(null); then reimplement handleAccept and handleDeny
to call handleStatusUpdate(id, 'accepted', 'accept') and handleStatusUpdate(id,
'denied', 'deny') respectively.

105-144: disabled prop and handler guard are inconsistent — buttons on other requests appear clickable but silently no-op

The guard if (loadingId) return blocks all requests while one is in-flight, but disabled={loadingId === req.id} only visually disables the active request's buttons. Clicking Accept/Deny on a different request silently does nothing — no feedback, no visual cue.

Either disable all action buttons while any request is in-flight, or switch to a Set<string> to allow parallel operations:

Option A: disable all buttons globally
-                  disabled={loadingId === req.id}
+                  disabled={loadingId !== null}
Option B: allow parallel requests with a Set
- const [loadingId, setLoadingId] = useState<string | null>(null);
+ const [loadingIds, setLoadingIds] = useState<Set<string>>(new Set());

  const handleAccept = async (id: string) => {
-   if (loadingId) return;
-   setLoadingId(id);
+   if (loadingIds.has(id)) return;
+   setLoadingIds(prev => new Set(prev).add(id));
    ...
    } finally {
-     setLoadingId(null);
+     setLoadingIds(prev => { const next = new Set(prev); next.delete(id); return next; });
    }
  };
-                  disabled={loadingId === req.id}
+                  disabled={loadingIds.has(req.id)}

Also applies to: 220-235

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx` around lines
105 - 144, The current single-string loadingId causes inconsistent UX; switch to
a Set to track concurrent requests: replace loadingId/setLoadingId state with
loadingIds (a Set<string>) and update handlers handleAccept and handleDeny to
(1) return early only if loadingIds.has(id), (2) add id to loadingIds before the
fetch and remove it in finally (use functional updater to clone/update the Set),
and (3) update the button disabled prop to disabled={loadingIds.has(req.id)} so
only the in-flight request's buttons are disabled while others remain clickable.
Ensure error handling and request-success logic (setRequests filter) remain
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx`:
- Around line 105-123: Both handleAccept and handleDeny swallow network
exceptions (their catch blocks only console.error) so users get no feedback when
the server is unreachable; update the catch blocks in handleAccept and
handleDeny to show a user-visible notification (e.g., alert or your app's toast)
that includes a brief message plus the error message (use error?.message or a
fallback string) so failures due to network/backend outages are communicated to
the user while still preserving the existing finally behavior that calls
setLoadingId(null).

---

Outside diff comments:
In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx`:
- Around line 241-243: In CollabRequests.tsx the Email Button (the <Button>
rendering the <Mail /> icon) lacks an onClick, so add an onClick to either call
the existing handleMessage handler or implement a new handler (e.g.,
handleEmail) in the CollabRequests component and wire it to the Button;
alternatively, if email functionality isn't available yet, set the Button's
disabled prop and update aria-label to indicate it's disabled. Ensure the
handler name (handleEmail or reuse handleMessage) is defined in the same
component and referenced on the Button's onClick to provide expected behavior.

---

Nitpick comments:
In `@Frontend/src/components/collaboration-hub/CollabRequests.tsx`:
- Around line 105-144: Extract the duplicate logic in handleAccept and
handleDeny into a single helper like handleStatusUpdate(id: string, status:
'accepted' | 'denied', verb: string) that uses setLoadingId,
fetch(`${BASE_URL}/collaboration/update-status/${id}?status=${status}`, {
method: 'PUT' }), handles response.ok by removing the request via
setRequests(prev => prev.filter(req => req.id !== id)), parses server error JSON
on non-ok to show alert(`Failed to ${verb}: ${err.detail || "Server error"}`),
logs exceptions with console.error("Failed to {verb} request:", error), and
finally clears setLoadingId(null); then reimplement handleAccept and handleDeny
to call handleStatusUpdate(id, 'accepted', 'accept') and handleStatusUpdate(id,
'denied', 'deny') respectively.
- Around line 105-144: The current single-string loadingId causes inconsistent
UX; switch to a Set to track concurrent requests: replace loadingId/setLoadingId
state with loadingIds (a Set<string>) and update handlers handleAccept and
handleDeny to (1) return early only if loadingIds.has(id), (2) add id to
loadingIds before the fetch and remove it in finally (use functional updater to
clone/update the Set), and (3) update the button disabled prop to
disabled={loadingIds.has(req.id)} so only the in-flight request's buttons are
disabled while others remain clickable. Ensure error handling and
request-success logic (setRequests filter) remain unchanged.

@shivansh023023 shivansh023023 changed the title feat: add Dockerfile for backend environment eat: add Docker support and implement API-driven collaboration request handling Feb 18, 2026
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.

1 participant