Update a Model (PUT /api/models/:id)
Relevant source files
The following files were used as context for generating this wiki page:The PUT /api/models/:id endpoint is a core administrative function for modifying an existing model's data in the MongoDB database. This operation is restricted to users with an 'admin' role and is essential for maintaining the accuracy and details of model profiles. When a model is updated, the endpoint not only applies the changes but also records the update action in the model's history log, providing a basic audit trail.
The logic for this route is defined directly within server.js rather than a separate routing file. The update process involves fetching the document by its ID, applying the new data from the request body, and saving the changes back to the database. This triggers a Mongoose pre-save hook that also contributes to the history log.
Endpoint Definition
| Property | Value |
|---|---|
| Route | /api/models/:id |
| HTTP Method | PUT |
| Description | Updates the details of a specific model identified by its MongoDB _id. |
| Authentication | Admin-only. Requires a valid session with role: 'admin'. |
Sources: server.js:72-81
Request and Response Flow
The sequence diagram below illustrates the complete flow for a successful model update request, from the initial client call to the final database commit and response.
This diagram shows the interaction between the client, server, middleware, and database during an update operation.
Sources: server.js:40-43, server.js:72-81, APP/models/model.model.js:18-26
Error Flow
If a non-admin user attempts to access this endpoint, the isAdmin middleware will intercept the request and return a 403 Forbidden error.
Sources: server.js:40-43, server.js:72
Authentication and Authorization
Access to the update endpoint is controlled by the isAdmin middleware. This function checks if a user object exists in the current session and if that user's role is set to 'admin'.
// server.js:40-43
const isAdmin = (req, res, next) => {
if (req.session.user && req.session.user.role === 'admin') next();
else res.status(403).json({ message: 'Admin required' });
};
The user's role is determined during the login process (POST /api/login). If the provided email ends with @admin.com, the role is set to 'admin'; otherwise, it defaults to 'chatter'. This role is then stored in the session managed by express-session.
Sources: server.js:28-32, server.js:40-43, package.json:7
Data Handling and Persistence
The update operation interacts directly with the Model schema and collection in MongoDB.
Model Schema
The Model schema defines the structure for each model document. The data sent in the PUT request body should conform to this structure.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | String | Yes | - | A unique identifier for the model. |
name | String | Yes | - | The model's name. |
age | Number | No | - | The model's age. |
location | String | No | - | The model's location. |
profile | String | Yes | - | A detailed profile description. |
pricing | String | Yes | - | Pricing information for services. |
dosAndDonts | String | Yes | - | A list of allowed and disallowed activities. |
extraTabs | Array | No | [] | An array for additional information tabs. |
history | Array | No | [] | An audit log of changes made to the document. |
createdAt | Date | - | - | Timestamp added automatically by Mongoose. |
updatedAt | Date | - | - | Timestamp updated automatically by Mongoose. |
Sources: APP/models/model.model.js:2-16
The relationship between a model and its history is a one-to-many relationship embedded within the same document.
This diagram shows the fields defined in the Mongoose schema for a Model.
Sources: APP/models/model.model.js:2-16
Update Logic
The core update logic resides in the route handler. It first retrieves the model, modifies it in memory, and then saves it.
// server.js:72-81
app.put("/api/models/:id", isAdmin, async (req, res) => {
try {
const model = await Model.findById(req.params.id);
model.history.push({ timestamp: new Date(), action: 'update', user: req.session.user.email, changes: Object.keys(req.body) });
Object.assign(model, req.body);
await model.save();
res.json(model);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
The Object.assign(model, req.body) call merges the fields from the request body into the fetched Mongoose document. model.save() then persists these changes to the database.
Sources: server.js:72-81
History Tracking
A notable feature is the dual-entry history tracking. An update action is recorded in two different places:
-
In the Route Handler: Before saving, a history entry is manually pushed to the
historyarray. This entry captures the timestamp, the 'update' action, the email of the admin user who performed the update, and a list of keys included in the request body.
Sources: server.js:76 -
In the Mongoose
pre('save')Hook: Themodel.model.jsfile defines a hook that runs before any save operation on a modified (but not new) document. This hook also pushes a history entry, but it captures the specific paths that were modified, providing a more granular record of the changes. This entry does not include user information.
Sources: APP/models/model.model.js:18-26
This results in two separate history entries being added for a single PUT request.