- Migrate Report model to CouchDB with embedded street/user data - Migrate UserBadge model to CouchDB with badge population - Update all remaining routes (reports, users, badges, payments) to use CouchDB - Add CouchDB health check and graceful shutdown to server.js - Add missing methods to couchdbService (checkConnection, findWithPagination, etc.) - Update Kubernetes deployment manifests for CouchDB support - Add comprehensive CouchDB setup documentation All core functionality now uses CouchDB as primary database while maintaining MongoDB for backward compatibility during transition period. 🤖 Generated with [AI Assistant] Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
117 lines
3.0 KiB
JavaScript
117 lines
3.0 KiB
JavaScript
const express = require("express");
|
|
const User = require("../models/User");
|
|
const Street = require("../models/Street");
|
|
const auth = require("../middleware/auth");
|
|
const { asyncHandler } = require("../middleware/errorHandler");
|
|
const { userIdValidation } = require("../middleware/validators/userValidator");
|
|
const { upload, handleUploadError } = require("../middleware/upload");
|
|
const { uploadImage, deleteImage } = require("../config/cloudinary");
|
|
|
|
const router = express.Router();
|
|
|
|
// Get user by ID
|
|
router.get(
|
|
"/:id",
|
|
auth,
|
|
userIdValidation,
|
|
asyncHandler(async (req, res) => {
|
|
const user = await User.findById(req.params.id);
|
|
if (!user) {
|
|
return res.status(404).json({ msg: "User not found" });
|
|
}
|
|
|
|
// Get adopted streets data
|
|
let adoptedStreets = [];
|
|
if (user.adoptedStreets && user.adoptedStreets.length > 0) {
|
|
adoptedStreets = await Promise.all(
|
|
user.adoptedStreets.map(async (streetId) => {
|
|
const street = await Street.findById(streetId);
|
|
return street ? {
|
|
_id: street._id,
|
|
name: street.name,
|
|
location: street.location,
|
|
status: street.status,
|
|
} : null;
|
|
})
|
|
);
|
|
adoptedStreets = adoptedStreets.filter(Boolean);
|
|
}
|
|
|
|
const userWithStreets = {
|
|
...user,
|
|
adoptedStreets,
|
|
};
|
|
|
|
res.json(userWithStreets);
|
|
}),
|
|
);
|
|
|
|
// Upload profile picture
|
|
router.post(
|
|
"/profile-picture",
|
|
auth,
|
|
upload.single("image"),
|
|
handleUploadError,
|
|
asyncHandler(async (req, res) => {
|
|
if (!req.file) {
|
|
return res.status(400).json({ msg: "No image file provided" });
|
|
}
|
|
|
|
const user = await User.findById(req.user.id);
|
|
if (!user) {
|
|
return res.status(404).json({ msg: "User not found" });
|
|
}
|
|
|
|
// Delete old profile picture if exists
|
|
if (user.cloudinaryPublicId) {
|
|
await deleteImage(user.cloudinaryPublicId);
|
|
}
|
|
|
|
// Upload new image to Cloudinary
|
|
const result = await uploadImage(
|
|
req.file.buffer,
|
|
"adopt-a-street/profiles",
|
|
);
|
|
|
|
// Update user with new profile picture
|
|
const updatedUser = await User.update(req.user.id, {
|
|
profilePicture: result.url,
|
|
cloudinaryPublicId: result.publicId,
|
|
});
|
|
|
|
res.json({
|
|
msg: "Profile picture updated successfully",
|
|
profilePicture: updatedUser.profilePicture,
|
|
});
|
|
}),
|
|
);
|
|
|
|
// Delete profile picture
|
|
router.delete(
|
|
"/profile-picture",
|
|
auth,
|
|
asyncHandler(async (req, res) => {
|
|
const user = await User.findById(req.user.id);
|
|
if (!user) {
|
|
return res.status(404).json({ msg: "User not found" });
|
|
}
|
|
|
|
if (!user.cloudinaryPublicId) {
|
|
return res.status(400).json({ msg: "No profile picture to delete" });
|
|
}
|
|
|
|
// Delete image from Cloudinary
|
|
await deleteImage(user.cloudinaryPublicId);
|
|
|
|
// Remove from user
|
|
await User.update(req.user.id, {
|
|
profilePicture: undefined,
|
|
cloudinaryPublicId: undefined,
|
|
});
|
|
|
|
res.json({ msg: "Profile picture deleted successfully" });
|
|
}),
|
|
);
|
|
|
|
module.exports = router;
|