Skip to content

Conversation

@safiya2610
Copy link

@safiya2610 safiya2610 commented Jan 13, 2026

Description
Developed a FastAPI-based image gallery system supporting multi-user authentication and role-based authorization. Users can upload images with metadata and narratives, while admins can monitor all users through a centralized dashboard, view individual galleries, and perform moderation actions such as editing narratives and deleting images. The system uses SQLite as a shared database and Jinja2 for dynamic UI rendering.

Features

User Features
Google OAuth Login
Upload images
Add / edit narrative
Delete own images
View image metadata
Private / Public visibility support

Admin Features
Admin-only dashboard
View all users
Open any user’s gallery
Edit any user’s narrative
Delete any user’s images
View metadata of all images

safiya2610 and others added 23 commits January 4, 2026 02:42
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Add admin router with user management endpoints
- Create admin service for role-based access control
- Add admin dashboard and user gallery templates
- Implement admin authentication checks
- Add unauthorized access template
- Fix JWT configuration and improve token validation
- Update gallery to show metadata JSON properly
- Add admin navigation and styling
- Update tests for new admin functionality
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @safiya2610, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a comprehensive, full-stack image gallery application built with FastAPI. It establishes a secure environment for users to manage their image collections, complete with Google OAuth for authentication and a sophisticated admin panel for content oversight. The system also introduces an innovative image analysis component that detects and associates 'fuzzy emotions' with uploaded pictures, enriching the user's interaction with their visual content. The changes span across new routing, service layers, middleware, database schema, and front-end templates, creating a robust and feature-rich platform.

Highlights

  • Multi-User Image Gallery System: Introduced a complete FastAPI-based image gallery system supporting multi-user authentication and role-based authorization. Users can upload images with metadata and narratives, while admins can moderate content.
  • Admin Moderation Features: Implemented an admin dashboard allowing administrators to view all users, browse individual user galleries, edit image narratives, and delete images, providing robust content moderation capabilities.
  • Google OAuth Integration: Integrated Google OAuth for user authentication, simplifying the login process and leveraging external identity providers.
  • Image Metadata and Emotion Detection: Added functionality to extract metadata from uploaded images, including a unique 'fuzzy emotion' detection feature based on image colors, enhancing image categorization and user experience.
  • Enhanced Security and Middleware: Incorporated several security measures, including JWT-based authentication, an in-memory rate limiter, and a security headers middleware to protect against common web vulnerabilities. Global exception handlers were also added for consistent error responses.
  • Database Management and UI: Utilized SQLite for data storage with a defined schema for users, images, and admins, and Jinja2 for dynamic UI rendering across various pages like home, gallery, login, and admin dashboards.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist 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

This pull request introduces a significant amount of new functionality for a multi-user image gallery with admin moderation. The overall structure is well-organized, leveraging FastAPI's features like routers and dependencies. However, the review has identified several issues that need attention. These include a critical bug in the admin panel that leads to incorrect redirects, security vulnerabilities related to input sanitization and hardcoded credentials, and multiple areas where code can be refactored to improve maintainability, reduce duplication, and adhere to best practices. Addressing these points will significantly improve the quality and robustness of the application.

)
db.commit()

return RedirectResponse(f"/admin/user/{user_email}", status_code=303)
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

There is a critical bug in the redirect URL. You are redirecting to /admin/user/{user_email}, but the corresponding route /admin/user/{user_id} expects an integer user_id, not an email string. This will result in a 'Not Found' error.

To fix this, you need to query the database to get the user's ID from their email before creating the redirect response, similar to the pattern used in the admin_update_narrative endpoint.

Suggested change
return RedirectResponse(f"/admin/user/{user_email}", status_code=303)
cur.execute("SELECT id FROM users WHERE email = ?", (user_email,))
user_row = cur.fetchone()
if not user_row:
return RedirectResponse("/admin", status_code=303)
user_id = user_row[0]
return RedirectResponse(f"/admin/user/{user_id}", status_code=303)



def save_image(db, user, image, visibility):
ext = Path(image.filename).suffix or ".jpg"
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The filename from the user upload (image.filename) is used to determine the file extension without proper sanitization. A malicious filename could potentially contain path traversal characters (../) or other exploits. It is a security best practice to sanitize all user-provided input, including filenames. Consider using a library function like werkzeug.utils.secure_filename or implementing a custom sanitization function that whitelists allowed characters.


cur.execute("SELECT id FROM users WHERE email = ?", (user_email,))
user_row = cur.fetchone()
user_id = user_row[0] if user_row else 1
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Defaulting to user_id = 1 when a user is not found is dangerous. It could lead to incorrect redirects or actions being performed on the wrong user account. It's much safer to handle the 'not found' case explicitly, for example, by redirecting to the admin dashboard.

Suggested change
user_id = user_row[0] if user_row else 1
user_id = user_row[0] if user_row else None
if not user_id:
return RedirectResponse("/admin", status_code=303)

from fastapi import APIRouter, Request, Depends
from fastapi.responses import RedirectResponse
from db import get_db
from app.services.auth_service import *
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using wildcard imports (from ... import *) is discouraged by PEP 8 as it can pollute the namespace and make it unclear which names are being imported. It's better to explicitly import the functions you need.

Suggested change
from app.services.auth_service import *
from app.services.auth_service import google_login_redirect, google_callback_handler

Comment on lines +13 to +17
try:
with open("cleaned_data.json", "r", encoding="utf-8") as f:
CLEANED = json.load(f)
except Exception as e:
CLEANED = {"colors": []}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This broad except Exception can hide various issues (e.g., file not found, permission error, invalid JSON). It's better to catch specific exceptions (like FileNotFoundError, json.JSONDecodeError) and use the logging module to report errors instead of silently failing. This will make debugging much easier.

Comment on lines +119 to +121
except ValueError as e:

print(f"KMeans clustering failed: {e}")
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using print() for logging errors is not ideal in a library or application module, as the output can be easily lost or missed in a production environment. It's better to use Python's logging module to log the error, which allows for configurable and more robust error handling.

Comment on lines +85 to +91
@app.exception_handler(Exception)
async def unhandled_exception_handler(request: Request, exc: Exception):
# Do not leak internals; optionally log exc to server logs here
return JSONResponse(
status_code=500,
content={"detail": "Internal server error"},
)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The unhandled exception handler correctly avoids leaking internal details to the client. However, it's crucial for debugging to log the actual exception on the server side. The traceback module is imported but not used. I suggest using a proper logger to capture the stack trace of unhandled exceptions, which will be invaluable for debugging production issues.

Comment on lines +14 to +20
<img src="/static/images/home3.jpg" alt="" class="img">
</img>
</div>

<div class="card">
<img src="/static/images/home4.jpg" alt="" class="img">
</img>
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The </img> closing tag is invalid HTML. The <img> tag is a void element and does not need a closing tag. Please remove the </img> tags on lines 15 and 20.

Comment on lines +98 to +133
<img
src="https://talatyusuf.com/my-content/uploads/2025/02/99-Quotes-about-Change-in-People-Behaviour-Suddenly-4.jpg"
>
</img>

</div>
</section>


<section class="scene" data-speed="0.30">
<div class="scene-bg"
style="background-image:url('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRakOvNWFhYFkIwddm2a1O1BMJCZmR3QtHhyA&s')">
</div>

<div class="scene-content">

<img
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEgDJyE6Yw3Vd0jXOawqQSsTtkDg7GHK6i6w&s"
>
</img>
</div>

</section>


<section class="scene" data-speed="0.40">
<div class="scene-bg"
style="background-image:url('https://images.template.net/358779/Memphis-Cute-Background-edit-online-3.jpg')">
</div>

<div class="scene-content">

<img
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRbheh_eC-zLDcj8W76ksaBHyyEwjrtwZwM-A&s"
>
</img>
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The </img> closing tag is invalid HTML. The <img> tag is a void element and does not need a closing tag. Please remove the </img> tags on lines 101, 117, and 133.

@pradeeban pradeeban added the on hold Not merging this PR now. label Jan 14, 2026
@mdxabu mdxabu changed the base branch from main to dev January 17, 2026 04:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

on hold Not merging this PR now.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants