UNPKG

powr-sdk-api

Version:

Shared API core library for PowrStack projects. Zero dependencies - works with Express, Next.js API routes, and other frameworks. All features are optional and install only what you need.

256 lines (239 loc) 6.31 kB
"use strict"; const express = require("express"); const router = express.Router(); const { getDb } = require("../services/mongo"); const { ObjectId } = require("mongodb"); const { verifyToken } = require("../middleware/jwtToken"); const { getClientIp } = require("../utils/getClientIp"); const { coercePhoneForStorage } = require("../utils/phone"); // Create User router.post("/", verifyToken, async (req, res) => { const { phoneNumber, email, ...userData } = req.body; const projectId = req.projectId; // Use middleware-injected projectId try { // Check if user already exists const db = await getDb(); const storedPhone = phoneNumber && !String(phoneNumber).includes("@") ? coercePhoneForStorage(phoneNumber) : phoneNumber; if (phoneNumber && !String(phoneNumber).includes("@") && !storedPhone) { return res.status(400).json({ success: false, message: "Invalid phone number" }); } const existingUser = await db.collection("users").findOne({ $or: [{ phoneNumber: storedPhone }, { email }] }); if (existingUser) { return res.status(400).json({ success: false, message: "User with this phone number or email already exists" }); } const newUser = { ...userData, phoneNumber: storedPhone, email, createdAt: new Date(), updatedAt: new Date() }; const result = await db.collection("users").insertOne(newUser); // Create profile for this project const newProfile = { userId: result.insertedId, projectId: projectId, access: userData.access || 1, createdAt: new Date(), lastActiveAt: new Date(), lastActiveFrom: getClientIp(req) }; await db.collection("profiles").insertOne(newProfile); return res.status(201).json({ success: true, message: "User created successfully", userId: result.insertedId }); } catch (error) { console.error("Error creating user:", error); return res.status(500).json({ success: false, message: "Failed to create user." }); } }); // Get All Users router.get("/", verifyToken, async (req, res) => { const { _id, phoneNumber, email } = req.query; const projectId = req.projectId; // Use middleware-injected projectId try { let query = {}; // Add filters if provided if (_id) { query._id = new ObjectId(_id); } if (phoneNumber) { query.phoneNumber = phoneNumber; } if (email) { query.email = email; } const db = await getDb(); const users = await db.collection("users").find(query).toArray(); // Get profiles for this project const userIds = users.map(user => user._id); const profiles = await db.collection("profiles").find({ userId: { $in: userIds }, projectId: projectId }).toArray(); // Merge user data with profile data const usersWithProfiles = users.map(user => { const profile = profiles.find(p => p.userId.toString() === user._id.toString()); return { ...user, access: profile ? profile.access : 1, projectId: projectId }; }); return res.json({ success: true, data: usersWithProfiles }); } catch (error) { console.error("Error fetching users:", error); return res.status(500).json({ success: false, message: "Failed to fetch users." }); } }); // Update User router.put("/:id", verifyToken, async (req, res) => { const { id } = req.params; const { phoneNumber, email, ...userData } = req.body; const projectId = req.projectId; // Use middleware-injected projectId try { // Check if user exists const db = await getDb(); const existingUser = await db.collection("users").findOne({ _id: new ObjectId(id) }); if (!existingUser) { return res.status(404).json({ success: false, message: "User not found" }); } // Update user const normalizedPhone = phoneNumber && !String(phoneNumber).includes("@") ? coercePhoneForStorage(phoneNumber) : phoneNumber; if (phoneNumber && !String(phoneNumber).includes("@") && !normalizedPhone) { return res.status(400).json({ success: false, message: "Invalid phone number" }); } const updateData = { ...userData, phoneNumber: normalizedPhone, email, updatedAt: new Date() }; await db.collection("users").updateOne({ _id: new ObjectId(id) }, { $set: updateData }); // Update profile if access level is provided if (userData.access !== undefined) { await db.collection("profiles").updateOne({ userId: new ObjectId(id), projectId: projectId }, { $set: { access: userData.access, updatedAt: new Date() } }, { upsert: true }); } return res.json({ success: true, message: "User updated successfully" }); } catch (error) { console.error("Error updating user:", error); return res.status(500).json({ success: false, message: "Failed to update user." }); } }); // Delete User router.delete("/:id", verifyToken, async (req, res) => { const { id } = req.params; const projectId = req.projectId; // Use middleware-injected projectId try { // Check if user exists const db = await getDb(); const existingUser = await db.collection("users").findOne({ _id: new ObjectId(id) }); if (!existingUser) { return res.status(404).json({ success: false, message: "User not found" }); } // Delete user await db.collection("users").deleteOne({ _id: new ObjectId(id) }); // Delete profile for this project await db.collection("profiles").deleteOne({ userId: new ObjectId(id), projectId: projectId }); return res.json({ success: true, message: "User deleted successfully" }); } catch (error) { console.error("Error deleting user:", error); return res.status(500).json({ success: false, message: "Failed to delete user." }); } }); module.exports = router;