feature/IO-3255-simplified-parts-management - Deprovisoning route
This commit is contained in:
@@ -0,0 +1,187 @@
|
|||||||
|
const admin = require("firebase-admin");
|
||||||
|
const client = require("../../../graphql-client/graphql-client").client;
|
||||||
|
|
||||||
|
const { DELETE_SHOP } = require("../partsManagement.queries");
|
||||||
|
|
||||||
|
// Define corrected DELETE_VENDORS_BY_SHOP locally
|
||||||
|
const DELETE_VENDORS_BY_SHOP = `
|
||||||
|
mutation DELETE_VENDORS_BY_SHOP($shopId: uuid!) {
|
||||||
|
delete_vendors(where: {bodyshopid: {_eq: $shopId}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
// New queries for deprovisioning
|
||||||
|
const GET_BODYSHOP = `
|
||||||
|
query GetBodyshop($id: uuid!) {
|
||||||
|
bodyshops_by_pk(id: $id) {
|
||||||
|
external_shop_id
|
||||||
|
shopname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GET_ASSOCIATED_USERS = `
|
||||||
|
query GetAssociatedUsers($shopId: uuid!) {
|
||||||
|
associations(where: {shopid: {_eq: $shopId}}) {
|
||||||
|
user {
|
||||||
|
authid
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DELETE_ASSOCIATIONS_BY_SHOP = `
|
||||||
|
mutation DeleteAssociationsByShop($shopId: uuid!) {
|
||||||
|
delete_associations(where: {shopid: {_eq: $shopId}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GET_USER_ASSOCIATIONS_COUNT = `
|
||||||
|
query GetUserAssociationsCount($userEmail: String!) {
|
||||||
|
associations_aggregate(where: {useremail: {_eq: $userEmail}}) {
|
||||||
|
aggregate {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DELETE_USER = `
|
||||||
|
mutation DeleteUser($email: String!) {
|
||||||
|
delete_users(where: {email: {_eq: $email}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GET_VENDORS = `
|
||||||
|
query GetVendors($shopId: uuid!) {
|
||||||
|
vendors(where: {bodyshopid: {_eq: $shopId}}) {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a Firebase user by UID.
|
||||||
|
* @param uid
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const deleteFirebaseUser = async (uid) => {
|
||||||
|
return admin.auth().deleteUser(uid);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all vendors associated with a shop.
|
||||||
|
* @param shopId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const deleteVendorsByShop = async (shopId) => {
|
||||||
|
await client.request(DELETE_VENDORS_BY_SHOP, { shopId });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a bodyshop from the database.
|
||||||
|
* @param shopId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const deleteBodyshop = async (shopId) => {
|
||||||
|
await client.request(DELETE_SHOP, { id: shopId });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles deprovisioning a shop for parts management.
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
const partsManagementDeprovisioning = async (req, res) => {
|
||||||
|
const { logger } = req;
|
||||||
|
const p = req.body;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === "production") {
|
||||||
|
return res.status(403).json({ error: "Deprovisioning not allowed in production environment." });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!p.shopId) {
|
||||||
|
throw { status: 400, message: "shopId is required." };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch bodyshop and check external_shop_id
|
||||||
|
const shopResp = await client.request(GET_BODYSHOP, { id: p.shopId });
|
||||||
|
const shop = shopResp.bodyshops_by_pk;
|
||||||
|
if (!shop) {
|
||||||
|
throw { status: 404, message: `Bodyshop with id ${p.shopId} not found.` };
|
||||||
|
}
|
||||||
|
if (!shop.external_shop_id) {
|
||||||
|
throw { status: 400, message: "Cannot delete bodyshop without external_shop_id." };
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log("admin-delete-shop", "debug", null, null, {
|
||||||
|
shopId: p.shopId,
|
||||||
|
shopname: shop.shopname,
|
||||||
|
ioadmin: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get vendors
|
||||||
|
const vendorsResp = await client.request(GET_VENDORS, { shopId: p.shopId });
|
||||||
|
const deletedVendors = vendorsResp.vendors.map((v) => v.name);
|
||||||
|
|
||||||
|
// Get associated users
|
||||||
|
const assocResp = await client.request(GET_ASSOCIATED_USERS, { shopId: p.shopId });
|
||||||
|
const associatedUsers = assocResp.associations.map((assoc) => ({
|
||||||
|
authId: assoc.user.authid,
|
||||||
|
email: assoc.user.email
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Delete associations for the shop
|
||||||
|
const assocDeleteResp = await client.request(DELETE_ASSOCIATIONS_BY_SHOP, { shopId: p.shopId });
|
||||||
|
const associationsDeleted = assocDeleteResp.delete_associations.affected_rows;
|
||||||
|
|
||||||
|
// For each user, check if they have remaining associations; if not, delete user and Firebase account
|
||||||
|
const deletedUsers = [];
|
||||||
|
for (const user of associatedUsers) {
|
||||||
|
const countResp = await client.request(GET_USER_ASSOCIATIONS_COUNT, { userEmail: user.email });
|
||||||
|
const assocCount = countResp.associations_aggregate.aggregate.count;
|
||||||
|
if (assocCount === 0) {
|
||||||
|
await client.request(DELETE_USER, { email: user.email });
|
||||||
|
await deleteFirebaseUser(user.authId);
|
||||||
|
deletedUsers.push(user.email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete vendors
|
||||||
|
await deleteVendorsByShop(p.shopId);
|
||||||
|
|
||||||
|
// Delete shop
|
||||||
|
await deleteBodyshop(p.shopId);
|
||||||
|
|
||||||
|
// Summary log
|
||||||
|
console.log(
|
||||||
|
`Deleted bodyshop ${p.shopId} (${shop.shopname}), ${associationsDeleted} associations, ${deletedUsers.length} users (${deletedUsers.join(", ") || "none"}), ${deletedVendors.length} vendors (${deletedVendors.join(", ") || "none"}).`
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
message: `Bodyshop ${p.shopId} and associated resources deleted successfully.`,
|
||||||
|
deletedShop: { id: p.shopId, name: shop.shopname },
|
||||||
|
deletedAssociationsCount: associationsDeleted,
|
||||||
|
deletedUsers: deletedUsers,
|
||||||
|
deletedVendors: deletedVendors
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.log("admin-delete-shop-error", "error", null, null, {
|
||||||
|
message: err.message,
|
||||||
|
detail: err.detail || err
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(err.status || 500).json({ error: err.message || "Internal server error" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = partsManagementDeprovisioning;
|
||||||
@@ -19,6 +19,7 @@ if (typeof PARTS_MANAGEMENT_INTEGRATION_SECRET === "string" && PARTS_MANAGEMENT_
|
|||||||
const XML_BODY_LIMIT = "10mb"; // Set a limit for XML body size
|
const XML_BODY_LIMIT = "10mb"; // Set a limit for XML body size
|
||||||
|
|
||||||
const partsManagementProvisioning = require("../integrations/partsManagement/endpoints/partsManagementProvisioning");
|
const partsManagementProvisioning = require("../integrations/partsManagement/endpoints/partsManagementProvisioning");
|
||||||
|
const partsManagementDeprovisioning = require("../integrations/partsManagement/endpoints/partsManagementDeprovisioning");
|
||||||
const partsManagementIntegrationMiddleware = require("../middleware/partsManagementIntegrationMiddleware");
|
const partsManagementIntegrationMiddleware = require("../middleware/partsManagementIntegrationMiddleware");
|
||||||
const partsManagementVehicleDamageEstimateAddRq = require("../integrations/partsManagement/endpoints/vehicleDamageEstimateAddRq");
|
const partsManagementVehicleDamageEstimateAddRq = require("../integrations/partsManagement/endpoints/vehicleDamageEstimateAddRq");
|
||||||
const partsManagementVehicleDamageEstimateChqRq = require("../integrations/partsManagement/endpoints/vehicleDamageEstimateChgRq");
|
const partsManagementVehicleDamageEstimateChqRq = require("../integrations/partsManagement/endpoints/vehicleDamageEstimateChgRq");
|
||||||
@@ -43,6 +44,9 @@ if (typeof PARTS_MANAGEMENT_INTEGRATION_SECRET === "string" && PARTS_MANAGEMENT_
|
|||||||
partsManagementVehicleDamageEstimateChqRq
|
partsManagementVehicleDamageEstimateChqRq
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Deprovisioning route
|
||||||
|
router.post("/parts-management/deprovision", partsManagementIntegrationMiddleware, partsManagementDeprovisioning);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route to handle Parts Management Provisioning
|
* Route to handle Parts Management Provisioning
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user