Skip to content

[Data-integrity] PUT /api/user/profile replaces whole subdocuments — a partial edit wipes GitHub avatar & connected handles #342

Description

@vedant7007

Editing one profile field silently erases every other field in that subdocument, because the update replaces the whole nested object instead of merging.

Root cause

server/modules/user/service.js:14-35 (updateProfile) copies whole nested objects:

if (updateData.profile !== undefined)     allowedFields.profile = updateData.profile;
if (updateData.handles !== undefined)     allowedFields.handles = updateData.handles;
if (updateData.preferences !== undefined) allowedFields.preferences = updateData.preferences;

server/modules/user/repository.js:16-22 passes them straight to Mongoose:

return await User.findByIdAndUpdate(id, updateData, { new: true, runValidators: true });

A top-level nested object becomes $set: { profile: {…} }, which replaces the entire profile subdocument. Correct partial update needs dot-notation ($set: { "profile.bio": … }).

Failure scenario

A user signs up via GitHub → profile.avatar = GitHub avatar, handles.github = login, handles.codeforces = e.g. tourist. They later edit only their bio → frontend sends { profile: { bio: "hi" } }profile becomes { bio: "hi" }; avatar, college, location, skills are gone. Likewise { handles: { leetcode: "x" } } erases handles.github/handles.codeforces. The wiped handles.github also degrades GitHubService.#getToken (its user.handles.github fallback, github/service.js:50).

Fix

Flatten the incoming nested fields to dot-notation before $set (merge), so only the provided keys are updated.

Dedup

No issue references profile-update data loss; no PR touches user/service.js or user/repository.js. Distinct from #301/#302/#303/#304. Unreported.

Contributing as part of Elite Coders Summer of Code (ECSoC 2026).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions