Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions backend/src/controllers/authController.js
Original file line number Diff line number Diff line change
Expand Up @@ -567,12 +567,12 @@ const removeSubUser = async (req, res) => {
};

/**
* Update the role of a sub-user
* @route PUT /api/auth/sub-user/:subUserId/role
* Update the role of a sub-user for a specific pet
* @route PUT /api/auth/sub-user/:subUserId/pet/:petId/role
*/
const updateSubUserRole = async (req, res) => {
try {
const { subUserId } = req.params;
const { subUserId, petId } = req.params;
const { role } = req.body;
const requestingUserId = req.user.userId;

Expand Down Expand Up @@ -603,8 +603,8 @@ const updateSubUserRole = async (req, res) => {
});
}

// Update the sub-user role
const updatedSubUser = await User.updateSubUserRole(subUserId, role);
// Update the sub-user role for the specific pet
const updatedSubUser = await User.updateSubUserRole(subUserId, parseInt(petId), requestingUserId, role);

if (!updatedSubUser) {
return res.status(500).json({
Expand Down
9 changes: 8 additions & 1 deletion backend/src/middleware/validateSubUserRoleUpdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const validator = require('validator');
*/
const validateSubUserRoleUpdate = (req, res, next) => {
const { role } = req.body;
const { subUserId } = req.params;
const { subUserId, petId } = req.params;
const errors = [];

// Validate sub-user ID (must be UUID)
Expand All @@ -15,6 +15,13 @@ const validateSubUserRoleUpdate = (req, res, next) => {
errors.push('Invalid sub-user ID format');
}

// Validate pet ID (must be a positive integer)
if (!petId) {
errors.push('Pet ID is required');
} else if (!validator.isInt(petId, { min: 1 })) {
errors.push('Invalid pet ID format');
}

// Validate role (required)
if (!role) {
errors.push('Role is required');
Expand Down
12 changes: 7 additions & 5 deletions backend/src/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,21 +255,23 @@ class User {
}

/**
* Update the role of a sub-user
* Update the role of a sub-user for a specific pet
* @param {string} subUserId - Sub-user UUID
* @param {number} petId - Pet ID
* @param {string} ownerId - Owner UUID
* @param {string} newRole - New role value
* @returns {Promise<object>} Updated sub-user info
*/
static async updateSubUserRole(subUserId, newRole) {
static async updateSubUserRole(subUserId, petId, ownerId, newRole) {
const query = `
UPDATE pet_users
SET role = $1
WHERE user_id = $2
RETURNING owner_id as parent_user_id, user_id as sub_user_id, role
WHERE user_id = $2 AND pet_id = $3 AND owner_id = $4
RETURNING owner_id as parent_user_id, user_id as sub_user_id, pet_id, role
`;

try {
const result = await pool.query(query, [newRole, subUserId]);
const result = await pool.query(query, [newRole, subUserId, petId, ownerId]);
return result.rows[0] || null;
} catch (error) {
throw error;
Expand Down
6 changes: 3 additions & 3 deletions backend/src/routes/userRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ router.get('/sub-users', authenticateToken, getSubUsers);
router.delete('/sub-user/:subUserId', authenticateToken, removeSubUser);

/**
* @route PUT /api/auth/sub-user/:subUserId/role
* @desc Update the role of a sub-user
* @route PUT /api/auth/sub-user/:subUserId/pet/:petId/role
* @desc Update the role of a sub-user for a specific pet
* @access Private (parent account owner only)
*/
router.put('/sub-user/:subUserId/role', authenticateToken, validateSubUserRoleUpdate, updateSubUserRole);
router.put('/sub-user/:subUserId/pet/:petId/role', authenticateToken, validateSubUserRoleUpdate, updateSubUserRole);

module.exports = router;
Loading