Client Profile API
Manage authenticated client profile actions.
Authentication & Authorization
- Auth method: HTTP-only session cookie named
token(JWT). - Required role:
client - Middleware:
authorize(["client"]) - Requests without a valid
tokenor without the required role receive 401 Unauthorized.
Upload/Replace Passport
Upload a passport image/PDF to the client’s profile. If a passport already exists, the previous file is deleted and replaced with the new upload.
- Endpoint:
POST /api/client/profile/passport - Auth:
clientrole - Content-Type:
multipart/form-data - Form field:
passport(file) - Max file size: 10 MB (enforced by
multerconfig) - Accepted types: Any file accepted by your server configuration (commonly images/PDFs). The server stores the raw file and does not transform the format.
Request
Headers
Cookie: token=<JWT>
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
Body (multipart/form-data)
passport— required, the file to upload.
Behavior
- Validates the presence of
passportfile; returns 400 if missing. - Looks up the authenticated client by
req.user.id. - If a previous passport exists, it is deleted from storage:
- Local file system via
deleteFile(existingPath).
- Local file system via
- Stores the new file via
saveFile(req.file)and obtains a storage path. - Updates the client row:
passport = <new file path>updatedAt = new Date()
- Responds with 200 OK and the stored
path.
Responses
200 OK
{
"message": "Passport uploaded successfully",
"path": "/uploads/passports/abc123.png"
}
400 Bad Request
{ "message": "No file uploaded" }
401 Unauthorized
{ "message": "Unauthorized" }
500 Internal Server Error
{ "message": "Error uploading passport" }
cURL Example
curl -X POST https://<api-host>/api/client/profile/passport \
-H "Cookie: token=<JWT>" \
-F "passport=@/path/to/passport.png"
JavaScript (Axios) Example
import axios from "axios";
import FormData from "form-data";
import fs from "fs";
async function uploadPassport(filePath: string, baseURL = "https://<api-host>") {
const form = new FormData();
form.append("passport", fs.createReadStream(filePath));
const res = await axios.post(
baseURL + "/api/client/profile/passport",
form,
{
headers: {
...form.getHeaders(),
Cookie: `token=<JWT>`
},
withCredentials: true
}
);
console.log(res.data);
}
Notes & Considerations
- Replacement semantics: Each successful call replaces the previously stored passport and removes the old file from storage.
- Storage path: The response
pathis the server-side location returned bysaveFile. Treat it as opaque. - File validation: The server currently validates presence and size. If you need strict MIME-type validation (e.g., only images/PDF), add it at the
multerlayer or validatereq.file.mimetype. - Audit fields:
updatedAtis refreshed on success. - Rate limiting / quotas: Not enforced here (implement at reverse proxy/middleware if needed).
- Security: Because the JWT is stored in an HTTP-only cookie, do not attempt to read it from client-side JS; rely on the browser to attach it automatically when
withCredentials: true.