Skip to content

Feat/color emotion analysis#109

Open
aggharsh2005 wants to merge 6 commits intoKathiraveluLab:mainfrom
aggharsh2005:feat/color-emotion-analysis
Open

Feat/color emotion analysis#109
aggharsh2005 wants to merge 6 commits intoKathiraveluLab:mainfrom
aggharsh2005:feat/color-emotion-analysis

Conversation

@aggharsh2005
Copy link
Copy Markdown

The emotion analysis module uses fuzzy logic to map dominant image colors to emotional associations — directly implementing the research component mentioned in the BHV project description.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 lays the essential groundwork for the BHV project by introducing a FastAPI-based backend. It delivers critical functionalities such as user authentication, image management, and administrative controls. Crucially, it integrates a novel color-emotion analysis module, fulfilling a key research requirement by applying fuzzy logic to image data. This comprehensive update establishes the core services necessary for the application's operation and future development.

Highlights

  • Color-Emotion Analysis Module: Implemented a new module that uses fuzzy logic to map dominant image colors to emotional associations, directly addressing a core research component of the BHV project.
  • Core API Infrastructure: Established the foundational FastAPI application structure, including database integration with SQLAlchemy and a SQLite backend.
  • User Authentication and Management: Introduced robust user authentication (registration, login) with password hashing, and administrative endpoints for managing user accounts (listing, updating, deleting users).
  • Image Upload and Storage: Developed API endpoints for secure image upload, retrieval, and deletion, including validation for file types and sizes, with images stored in a file system.
  • Project Setup and Documentation: Updated the README with comprehensive setup and installation instructions, along with a list of initial API endpoints.

🧠 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.

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
Copy Markdown
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 color-emotion analysis feature and sets up the basic structure for the FastAPI application. While the new feature is a good start, the initial implementation contains several critical security vulnerabilities. The authentication and authorization mechanisms are insecure, allowing for unauthorized access, privilege escalation, and arbitrary file deletion via path traversal. The authentication flow is also incomplete, as the login endpoint does not return an access token. I've provided detailed comments on these critical issues, along with suggestions for medium-severity improvements related to configuration, database management, and code quality.

Comment thread app/routes/admin.py
is_admin: bool = None

@router.get("/users")
def get_all_users(admin_id: int, db: Session = Depends(get_db)):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The authorization mechanism is critically insecure. Passing admin_id as a query parameter allows any user to impersonate an admin by simply providing a valid admin's user ID. Authorization must be based on a secure, server-verified identity, typically from an authentication token (e.g., JWT) passed in the request headers. This insecure pattern is repeated across all admin endpoints.

Comment thread app/routes/admin.py
raise HTTPException(status_code=403, detail="Admin access required")

total_users = db.query(User).count()
active_users No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This line contains an incomplete statement active_users, which will cause a SyntaxError when the application is run. The implementation of the get_stats endpoint appears to be unfinished and needs to be completed or removed.

Comment thread app/routes/auth.py
Comment on lines +56 to +72
def login(user: UserLogin, db: Session = Depends(get_db)):
"""Login with email and password."""
db_user = db.query(User).filter(User.email == user.email).first()
if not db_user or not verify_password(user.password, db_user.hashed_password):
raise HTTPException(
status_code=401,
detail="Invalid email or password"
)
return {
"message": "Login successful",
"user": {
"id": db_user.id,
"email": db_user.email,
"full_name": db_user.full_name,
"is_admin": db_user.is_admin
}
} No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The /login endpoint correctly verifies user credentials but fails to return an access token (e.g., a JWT). This is a critical flaw in the authentication design, as it leaves the client with no way to prove its identity in subsequent requests to protected endpoints. This has led to insecure workarounds like passing user IDs in URLs. The login process should conclude with the issuance of a bearer token.

Comment thread app/routes/images.py

@router.post("/upload", response_model=ImageResponse)
async def upload_image(
user_id: int,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This endpoint has a critical authorization vulnerability. It accepts a user_id as a parameter, allowing any authenticated or unauthenticated user to upload files on behalf of any other user by simply providing their ID. The user's identity must be determined from a secure authentication token, not a client-provided parameter.

Comment thread app/routes/images.py
if not user:
raise HTTPException(status_code=404, detail="User not found")

filepath = os.path.join(UPLOAD_DIR, str(user_id), filename)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This line constructs a file path using a user-provided filename without proper sanitization, creating a critical path traversal vulnerability. A malicious user could submit a filename like ../../../../etc/passwd to delete arbitrary files on the server. You must validate that the resolved file path is within the expected user directory before proceeding with deletion.

Suggested change
filepath = os.path.join(UPLOAD_DIR, str(user_id), filename)
filepath = os.path.join(UPLOAD_DIR, str(user_id), filename)
# Prevent path traversal attacks by ensuring the resolved path is within the user's upload directory.
user_dir = os.path.abspath(os.path.join(UPLOAD_DIR, str(user_id)))
if not os.path.abspath(filepath).startswith(user_dir):
raise HTTPException(status_code=400, detail="Invalid filename")

Comment thread app/main.py
from app.routes import auth, images, emotion ,admin

# Create database tables
Base.metadata.create_all(bind=engine)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Calling Base.metadata.create_all() on application startup is convenient for development but is not recommended for production. It does not handle schema migrations (e.g., adding/removing columns or changing types), which can lead to data loss or application downtime. A dedicated migration tool like Alembic should be used to manage the database schema in a safe and versioned manner.

Suggested change
Base.metadata.create_all(bind=engine)
# Base.metadata.create_all(bind=engine) # Consider using a migration tool like Alembic for production

Comment thread app/routes/admin.py
Comment on lines +94 to +97
if os.path.exists(user_dir):
for f in os.listdir(user_dir):
os.remove(os.path.join(user_dir, f))
os.rmdir(user_dir)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

os.rmdir() only works on empty directories and will fail if the user's directory contains subdirectories or if the file deletion loop fails. Using shutil.rmtree() is a more robust way to recursively delete a directory and all its contents. Remember to add import shutil at the top of the file.

    if os.path.exists(user_dir):
        shutil.rmtree(user_dir)

Comment thread app/routes/emotion.py
Comment on lines +25 to +50
def rgb_to_color_name(r, g, b):
"""Map RGB values to nearest color name using fuzzy logic."""
colors = {
"red": (255, 0, 0),
"blue": (0, 0, 255),
"green": (0, 128, 0),
"yellow": (255, 255, 0),
"purple": (128, 0, 128),
"orange": (255, 165, 0),
"black": (0, 0, 0),
"white": (255, 255, 255),
"brown": (139, 69, 19),
"gray": (128, 128, 128),
"pink": (255, 192, 203),
}

min_dist = float("inf")
nearest = "gray"

for name, (cr, cg, cb) in colors.items():
dist = ((r-cr)**2 + (g-cg)**2 + (b-cb)**2) ** 0.5
if dist < min_dist:
min_dist = dist
nearest = name

return nearest
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The colors dictionary is defined inside rgb_to_color_name, causing it to be re-created every time the function is called. Since this dictionary is a constant, it should be defined once at the module level to improve performance, especially since this function may be called many times during analysis.

_COLORS = {
    "red":    (255, 0, 0),
    "blue":   (0, 0, 255),
    "green":  (0, 128, 0),
    "yellow": (255, 255, 0),
    "purple": (128, 0, 128),
    "orange": (255, 165, 0),
    "black":  (0, 0, 0),
    "white":  (255, 255, 255),
    "brown":  (139, 69, 19),
    "gray":   (128, 128, 128),
    "pink":   (255, 192, 203),
}

def rgb_to_color_name(r, g, b):
    """Map RGB values to nearest color name using fuzzy logic."""
    min_dist = float("inf")
    nearest = "gray"
    
    for name, (cr, cg, cb) in _COLORS.items():
        dist = ((r-cr)**2 + (g-cg)**2 + (b-cb)**2) ** 0.5
        if dist < min_dist:
            min_dist = dist
            nearest = name
    
    return nearest

Comment thread app/routes/emotion.py
pixels = np.array(img).reshape(-1, 3)

# Simple clustering by rounding to nearest 50
rounded = (pixels // 50) * 50
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The method used for color clustering ((pixels // 50) * 50) is a very simple form of quantization. While fast, it may not accurately identify the dominant colors in images with more complex color palettes. For more robust and accurate results, consider using a standard clustering algorithm like K-Means, which is well-suited for this task. Libraries like scikit-learn provide efficient implementations.

Comment thread app/routes/emotion.py
Comment on lines +127 to +128
except Exception:
raise HTTPException(status_code=400, detail="Invalid image file")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Catching a generic Exception is too broad and can mask unexpected errors or bugs in the code, making debugging difficult. It's better to catch specific exceptions that you expect to be raised during image processing, such as Image.UnidentifiedImageError.

Suggested change
except Exception:
raise HTTPException(status_code=400, detail="Invalid image file")
except Image.UnidentifiedImageError:
raise HTTPException(status_code=400, detail="Invalid image file")

@pradeeban pradeeban added the on hold Not merging this PR now. label Mar 22, 2026
@aggharsh2005
Copy link
Copy Markdown
Author

@gemini-code-assist I have made the changes accordingly

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Thank you for letting me know! I cannot initiate a new review myself. If you would like me to perform a fresh code review of the current pull request, please use the /gemini review command in a new comment.

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