Skip to main content

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 token or 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: client role
  • Content-Type: multipart/form-data
  • Form field: passport (file)
  • Max file size: 10 MB (enforced by multer config)
  • 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)

  • passportrequired, the file to upload.

Behavior

  1. Validates the presence of passport file; returns 400 if missing.
  2. Looks up the authenticated client by req.user.id.
  3. If a previous passport exists, it is deleted from storage:
    • Local file system via deleteFile(existingPath).
  4. Stores the new file via saveFile(req.file) and obtains a storage path.
  5. Updates the client row:
    • passport = <new file path>
    • updatedAt = new Date()
  6. 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 path is the server-side location returned by saveFile. 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 multer layer or validate req.file.mimetype.
  • Audit fields: updatedAt is 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.