Skip to content

Comments

Typed API form fields#3036

Draft
gantoine wants to merge 3 commits intomasterfrom
api-form-fields
Draft

Typed API form fields#3036
gantoine wants to merge 3 commits intomasterfrom
api-form-fields

Conversation

@gantoine
Copy link
Member

@gantoine gantoine commented Feb 19, 2026

Description
Explain the changes or enhancements you are proposing with this pull request.

Checklist
Please check all that apply.

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

Screenshots (if applicable)

Screenshot 2026-02-18 at 2 21 14 PM

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gantoine, 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 introduces a significant architectural improvement by standardizing how form data and JSON payloads are handled in the backend API. By moving from manual request parsing to explicit FastAPI dependencies and Pydantic models, the API becomes more robust, type-safe, and self-documenting. The frontend has been comprehensively updated to consume these refined API definitions, ensuring seamless integration and leveraging the benefits of strong typing for API interactions.

Highlights

  • Backend API Refactoring: FastAPI endpoints were refactored to explicitly define form data using Form() and File() dependencies, and JSON request bodies using Pydantic BaseModels. This eliminates manual parsing of request.form() and request.json().
  • Enhanced Type Safety and OpenAPI Generation: The explicit typing of API parameters improves type safety across the application and enhances the accuracy of generated OpenAPI documentation.
  • Frontend API Integration Updates: Frontend API service calls were updated to align with the new backend type definitions, leveraging newly generated TypeScript types and a new buildFormInput utility for streamlined FormData construction.
  • New Utility for FormData Handling: A new utility function, buildFormInput, was introduced in the frontend to simplify the creation of FormData objects for API requests, promoting consistency and reducing boilerplate.
Changelog
  • backend/endpoints/collections.py
    • Modified add_collection, add_smart_collection, update_collection, and update_smart_collection to use File() and Form() for explicit parameter typing.
  • backend/endpoints/configs.py
    • Refactored add_platform_binding, add_platform_version, and add_exclusion to accept Pydantic BaseModel payloads instead of raw JSON.
  • backend/endpoints/rom.py
    • Updated update_rom to use a new RomUpdateForm Pydantic model and update_rom_user to use RomUserUpdatePayload, removing manual FormData parsing.
  • backend/endpoints/saves.py
    • Changed add_save and update_save to use explicit File() parameters for uploaded files.
  • backend/endpoints/screenshots.py
    • Modified add_screenshot to use an explicit File() parameter for the screenshot file.
  • backend/endpoints/states.py
    • Updated add_state and update_state to use explicit File() parameters for state and screenshot files.
  • backend/tests/endpoints/test_config.py
    • Added new test cases to verify the payload shapes for config-related endpoints.
  • backend/tests/endpoints/test_rom.py
    • Added new tests for the update_rom_user endpoint, covering data envelope and last played flags.
  • examples/config.example.yml
    • Updated comments for roms_folder and skip_hash_calculation in the example configuration.
  • frontend/src/generated/index.ts
    • Regenerated OpenAPI types, including new Body_add_*, Body_update_*, ExclusionPayload, PlatformBindingPayload, and RomUserUpdatePayload types.
  • frontend/src/generated/models/Body_add_collection_api_collections_post.ts
    • Modified generated type to include artwork, name, description, and url_cover.
  • frontend/src/generated/models/Body_add_save_api_saves_post.ts
    • Added new generated type for add_save API request body.
  • frontend/src/generated/models/Body_add_screenshot_api_screenshots_post.ts
    • Added new generated type for add_screenshot API request body.
  • frontend/src/generated/models/Body_add_smart_collection_api_collections_smart_post.ts
    • Added new generated type for add_smart_collection API request body.
  • frontend/src/generated/models/Body_add_state_api_states_post.ts
    • Added new generated type for add_state API request body.
  • frontend/src/generated/models/Body_update_collection_api_collections__id__put.ts
    • Modified generated type to include artwork, rom_ids, name, description, and url_cover.
  • frontend/src/generated/models/Body_update_rom_api_roms__id__put.ts
    • Modified generated type to include various metadata IDs, raw metadata fields, and file-related fields.
  • frontend/src/generated/models/Body_update_save_api_saves__id__put.ts
    • Added new generated type for update_save API request body.
  • frontend/src/generated/models/Body_update_smart_collection_api_collections_smart__id__put.ts
    • Added new generated type for update_smart_collection API request body.
  • frontend/src/generated/models/Body_update_state_api_states__id__put.ts
    • Added new generated type for update_state API request body.
  • frontend/src/generated/models/DetailedRomSchema.ts
    • Added ra_hash field to the schema.
  • frontend/src/generated/models/ExclusionPayload.ts
    • Added new generated type for ExclusionPayload.
  • frontend/src/generated/models/PlatformBindingPayload.ts
    • Added new generated type for PlatformBindingPayload.
  • frontend/src/generated/models/RomFileSchema.ts
    • Added ra_hash field to the schema.
  • frontend/src/generated/models/RomUserUpdatePayload.ts
    • Renamed Body_update_rom_user_api_roms__id__props_put.ts to RomUserUpdatePayload.ts and updated its structure.
  • frontend/src/generated/models/SimpleRomSchema.ts
    • Added ra_hash field to the schema.
  • frontend/src/components/common/Collection/Dialog/CreateCollection.vue
    • Adjusted API call to createCollection to remove { data } destructuring.
  • frontend/src/components/common/Collection/Dialog/CreateSmartCollection.vue
    • Adjusted API call to createSmartCollection to remove { data } destructuring.
  • frontend/src/components/common/Game/Dialog/EditRom.vue
    • Adjusted API call to uploadManuals to remove { data } destructuring.
  • frontend/src/components/common/Game/Dialog/UploadRom.vue
    • Adjusted API call to uploadRoms to remove { data } destructuring.
  • frontend/src/components/common/Platform/Dialog/UploadFirmware.vue
    • Adjusted API call to uploadFirmware to remove { data } destructuring.
  • frontend/src/composables/useFavoriteToggle.ts
    • Adjusted API call to createCollection and updated filtering logic for rom_ids.
  • frontend/src/console/views/Play.vue
    • Modified boot function to use buildFormInput for constructing FormData for state and screenshot uploads.
  • frontend/src/services/api/collection.ts
    • Refactored API calls to use buildFormInput for FormData and updated return types to match generated types.
  • frontend/src/services/api/config.ts
    • Updated API calls to use explicit PlatformBindingPayload and ExclusionPayload types for request bodies and adjusted return types.
  • frontend/src/services/api/firmware.ts
    • Updated API calls to use AddFirmwareInput and adjusted return types.
  • frontend/src/services/api/gamelist.ts
    • Adjusted exportGamelist return type.
  • frontend/src/services/api/identity.ts
    • Updated API calls for password reset and logout to use explicit payload types and adjusted return types.
  • frontend/src/services/api/platform.ts
    • Updated API calls for platform management to use explicit payload types and adjusted return types.
  • frontend/src/services/api/rom.ts
    • Extensively refactored API calls for ROM management to use buildFormInput and explicit payload/return types.
  • frontend/src/services/api/save.ts
    • Refactored API calls for save management to use buildFormInput and explicit payload/return types.
  • frontend/src/services/api/screenshot.ts
    • Refactored API calls for screenshot management to use buildFormInput and explicit payload/return types.
  • frontend/src/services/api/setup.ts
    • Updated SetupLibraryInfo to use PlatformSchema.
  • frontend/src/services/api/sgdb.ts
    • Adjusted searchCover return type.
  • frontend/src/services/api/state.ts
    • Refactored API calls for state management to use buildFormInput and explicit payload/return types.
  • frontend/src/services/api/task.ts
    • Adjusted API call return types for task management.
  • frontend/src/services/api/user.ts
    • Updated API calls for user management to use explicit payload types and adjusted return types.
  • frontend/src/utils/formData.ts
    • Added a new utility function buildFormInput to simplify FormData creation.
  • frontend/src/views/Patcher.vue
    • Adjusted API call to uploadPatchedRom to remove { data } destructuring.
Activity
  • The pull request introduces significant changes across both backend and frontend, indicating a coordinated effort to improve API consistency and type safety.
  • Backend endpoints were modified to leverage FastAPI's Form() and File() dependencies, and Pydantic models for request bodies.
  • Frontend code was updated to reflect these backend API changes, including the regeneration of OpenAPI types and the introduction of a new formData utility.
  • New tests were added for config and ROM endpoints to ensure the new payload structures are handled correctly.
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.

@github-actions
Copy link
Contributor

Test Results

806 tests  +5   805 ✅ +5   2m 6s ⏱️ -1s
  1 suites ±0     1 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit f4d9961. ± Comparison against base commit 445bd92.

@github-actions
Copy link
Contributor

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
13030 8575 66% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
backend/endpoints/collections.py 31% 🟢
backend/endpoints/configs.py 65% 🟢
backend/endpoints/rom.py 50% 🟢
backend/endpoints/saves.py 76% 🟢
backend/endpoints/screenshots.py 36% 🟢
backend/endpoints/states.py 32% 🟢
TOTAL 48% 🟢

updated for commit: f4d9961 by action🐍

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 significantly refactors the backend API by replacing manual parsing with typed fields using FastAPI's Form and Pydantic models, which enhances type safety, validation, and API documentation. The frontend has been updated accordingly, including a new buildFormInput utility. However, critical security vulnerabilities were identified: Path Traversal due to a lack of sanitization for user-provided filenames in upload endpoints, and Server-Side Request Forgery (SSRF) from insufficient validation of remote URLs used to fetch covers and manuals. These could allow arbitrary file writes or access to internal network resources. It is recommended to apply filename sanitization and URL validation across all affected endpoints. Additionally, an issue was found in the frontend's updateUser API call where multipart/form-data is likely being sent with an incorrect body format.

Comment on lines +51 to +53
url_cover: str = Form(
default="", description="Remote URL to fetch and use as cover artwork."
),
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The url_cover parameter is used to fetch remote content without validation in the add_collection endpoint. This can be exploited to perform Server-Side Request Forgery (SSRF). It is recommended to validate the URL scheme (e.g., allow only http/https) and ensure the host is not an internal IP address or a local hostname.

Comment on lines +128 to +129
url_cover: str | None = None
url_manual: str | None = None
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The url_cover and url_manual parameters are used to fetch remote content without proper validation, leading to potential SSRF. An attacker could provide URLs pointing to internal services or metadata endpoints. Ensure that provided URLs are validated against an allow-list of schemes and that internal network addresses are blocked.

Comment on lines +113 to +118
saveFile: UploadFile | None = File(
default=None, description="Save file to upload."
),
screenshotFile: UploadFile | None = File(
default=None, description="Screenshot file associated with this save."
),
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The saveFile and screenshotFile parameters are introduced as UploadFile objects. Their filename attribute is used directly to construct file paths on the server without sanitization (e.g., in line 189 and 260 of the full file). An attacker can provide a filename containing .. sequences to perform a path traversal attack and potentially write files to unauthorized locations. Use a sanitization function like sanitize_filename before using the filename in path construction.

Comment on lines +25 to +27
screenshotFile: UploadFile | None = File(
default=None, description="Screenshot file to upload."
),
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The screenshotFile parameter is used without filename sanitization, leading to a potential path traversal vulnerability when the file is written to disk. Always sanitize user-provided filenames to prevent directory traversal attacks.

Comment on lines +30 to +35
stateFile: UploadFile | None = File(
default=None, description="State file to upload."
),
screenshotFile: UploadFile | None = File(
default=None, description="Screenshot file associated with this state."
),
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The stateFile and screenshotFile parameters are used without filename sanitization, allowing for path traversal attacks during file upload. Ensure that all uploaded filenames are sanitized to remove directory traversal sequences like ...

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