Conversation
wilke0818
commented
Mar 11, 2026
- Disabled the broken "Create your avatar" button and removed all its code
- Added "Upload your avatar" — drag-and-drop GLB upload with 3D preview, gender selection, per-user storage in src/server/uploads/
- Security: GLB external URI scan, 10-file per-user limit, UUID filenames, path traversal guard
- Persistence: Server is source of truth on page load; restores list after cache clear, prunes stale/missing/corrupted entries
- Corrupted avatar detection: Mismatched .glb/.json pairs flagged server-side, shown as warning-only cards client-side, never selectable
- Delete: Cleans up both files regardless of which one exists; requires auth; confirmed via Popconfirm
- Misc fixes: Vite proxy for /uploads/, email→dirname encoding fix, React index-key bug on delete, uniform card heights via flexbox
- readSelectedModelUrl() — reads and parses selectedAvatar from localStorage at component init (passed as a lazy initializer to useState so it only runs once)
- selectedModelUrl state — tracks the currently selected avatar's URL, kept in sync when selections are made or deleted
- Per card: if avatar.modelUrl === selectedModelUrl, the card gets:
- A green "Selected" tag with a checkmark in the title
- A green border + subtle green glow (boxShadow)
- Default avatar is Fabio though only shows/is selected when a session is generated
…y additions since file uploads inherently bring security concerns. Remove ready player me API calls. New avatars as defaults available.
- Highlight the currently selected avatar card with a green border, glow, and "Selected" tag so users know their active choice at a glance - Keep selectedModelUrl state in sync on select, delete, and server reconciliation (stale/corrupted upload detection) - Add links to Ready Player Me and Avaturn on the upload page as suggested tools for creating GLB avatars Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary of ChangesHello, 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 significantly overhauls the avatar management system by replacing the previous external avatar creation tool with a robust internal GLB avatar upload mechanism. It introduces new client-side components for uploading and previewing avatars, alongside comprehensive server-side APIs for secure storage, retrieval, and deletion of user-specific GLB files. The changes also enhance the user interface for avatar selection, providing better visual feedback and handling for both pre-configured and user-uploaded avatars. Highlights
🧠 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. Changelog
Activity
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Code Review
This pull request introduces a major update to avatar handling, replacing the old creator with a new file upload system. The changes are extensive, covering both frontend and backend. The new implementation includes features like GLB file validation, security checks for external URIs, per-user storage with file limits, and detection of corrupted avatar files. My review focuses on improving robustness in two areas: client-side data parsing from localStorage and server-side sanitization of user emails for directory naming. Overall, this is a well-executed feature addition with strong attention to security.
|
|
||
| // Persist in the user's uploaded avatars list | ||
| const existing = localStorage.getItem('uploadedAvatars'); | ||
| const uploads: { modelUrl: string; gender: string }[] = existing ? JSON.parse(existing) : []; |
There was a problem hiding this comment.
The JSON.parse call is not wrapped in a try-catch block. If localStorage contains invalid JSON for uploadedAvatars, this will throw an unhandled exception and could crash the component logic. It's safer to handle potential parsing errors, similar to how it's done elsewhere in the codebase (e.g., readSelectedModelUrl in AvatarCreatorPage.tsx).
Consider refactoring to safely parse the data:
const existing = localStorage.getItem('uploadedAvatars');
let uploads: { modelUrl: string; gender: string }[] = [];
if (existing) {
try {
const parsed = JSON.parse(existing);
if (Array.isArray(parsed)) {
uploads = parsed;
}
} catch (e) {
console.error('Failed to parse uploadedAvatars from localStorage', e);
}
}There was a problem hiding this comment.
@claude - update this PR with the above change, and also indicate to the user that an avatar could not be loaded.
There was a problem hiding this comment.
@claude - update this PR with the above change, and also indicate to the user that an avatar could not be loaded.
| def _email_to_dirname(email: str) -> str: | ||
| """Convert an email to a filesystem/URL-safe directory name.""" | ||
| return email.replace("@", "_at_") |
There was a problem hiding this comment.
The sanitization in _email_to_dirname is minimal. While it handles the @ symbol, it doesn't account for other special characters that are valid in email addresses but could be unsafe in directory names (e.g., +, /, ?, *). This could lead to unexpected behavior or security issues. A more robust approach would be to whitelist allowed characters.
Here is a more robust implementation that preserves the readability of _at_ while sanitizing other characters.
| def _email_to_dirname(email: str) -> str: | |
| """Convert an email to a filesystem/URL-safe directory name.""" | |
| return email.replace("@", "_at_") | |
| def _email_to_dirname(email: str) -> str: | |
| """Convert an email to a filesystem/URL-safe directory name.""" | |
| s = email.replace("@", "_at_") | |
| # Whitelist safe characters for directory names. | |
| return re.sub(r"[^\w.-]", "_", s) |