Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Add endpoints to retrieve site and device details by ID #4407

Closed
wants to merge 1 commit into from
Closed
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
21 changes: 21 additions & 0 deletions src/device-registry/controllers/device.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@ function handleResponse({
}

const device = {
getDeviceDetailsById: async (req, res, next) => {
try {
const { id } = req.params;
const defaultTenant = constants.DEFAULT_TENANT || "airqo";
req.query.tenant = isEmpty(req.query.tenant)
? defaultTenant
: req.query.tenant;

const result = await createDeviceUtil.getDeviceById(req, next); // Call the utility function
handleResponse({ result, res });
} catch (error) {
logger.error(`🐛🐛 Internal Server Error ${error.message}`);
next(
new HttpError(
"Internal Server Error",
httpStatus.INTERNAL_SERVER_ERROR,
{ message: error.message }
)
);
}
},
bulkCreate: async (req, res, next) => {
try {
return res.status(httpStatus.NOT_IMPLEMENTED).json({
Expand Down
23 changes: 23 additions & 0 deletions src/device-registry/controllers/site.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@ function handleResponse({
}

const manageSite = {
getSiteDetailsById: async (req, res, next) => {
try {
const { id } = req.params;
const defaultTenant = constants.DEFAULT_TENANT || "airqo";
req.query.tenant = isEmpty(req.query.tenant)
? defaultTenant
: req.query.tenant;

const result = await createSiteUtil.getSiteById(req, next);

handleResponse({ result, res });
} catch (error) {
logger.error(`🐛🐛 Internal Server Error ${error.message}`);
next(
new HttpError(
"Internal Server Error",
httpStatus.INTERNAL_SERVER_ERROR,
{ message: error.message }
)
);
}
},
bulkCreate: async (req, res, next) => {
try {
return res.status(httpStatus.NOT_IMPLEMENTED).json({
Expand Down Expand Up @@ -597,6 +619,7 @@ const manageSite = {
return;
}
},

findNearestSite: async (req, res, next) => {
try {
logText("list all sites by coordinates...");
Expand Down
11 changes: 11 additions & 0 deletions src/device-registry/routes/v2/devices.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ const {
validateListDevices,
validateArrayBody,
validateBulkUpdateDevices,
validateDeviceIdParam,
} = require("@validators/device.validators");

const { validate } = require("@validators/common");

router.use(headers);

// Decrypt key route
Expand Down Expand Up @@ -146,4 +149,12 @@ router.put(
validateBulkUpdateDevices,
deviceController.updateManyDevicesOnPlatform
);

router.get(
"/:id",
validateTenant,
validateDeviceIdParam,
validate,
deviceController.getDeviceDetailsById
);
module.exports = router;
9 changes: 9 additions & 0 deletions src/device-registry/routes/v2/sites.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const {
validateSiteQueryParams,
validateMandatorySiteIdentifier,
validateCreateSite,
validateSiteIdParam,
validateSiteMetadata,
validateUpdateSite,
validateRefreshSite,
Expand All @@ -16,6 +17,7 @@ const {
validateNearestSite,
validateBulkUpdateSites,
} = require("@validators/site.validators");
const { validate } = require("@validators/common");
const { headers, pagination } = require("@validators/common");

router.use(headers);
Expand Down Expand Up @@ -99,4 +101,11 @@ router.get(
siteController.findNearestSite
);
router.put("/bulk", validateBulkUpdateSites, siteController.updateManySites);
router.get(
"/:id",
validateTenant,
validateSiteIdParam,
validate,
siteController.getSiteDetailsById
);
module.exports = router;
32 changes: 32 additions & 0 deletions src/device-registry/utils/device.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,38 @@ const kafka = new Kafka({
});

const createDevice = {
getDeviceById: async (req, next) => {
try {
const { id } = req.params;
const { tenant } = req.query;

const device = await DeviceModel(tenant.toLowerCase()).findById(id);

if (!device) {
throw new HttpError("Device not found", httpStatus.NOT_FOUND);
}

return {
success: true,
message: "Device details fetched successfully",
data: device,
status: httpStatus.OK,
};
} catch (error) {
if (error instanceof HttpError) {
next(error);
return;
}
logger.error(`🐛🐛 Internal Server Error ${error.message}`);
next(
new HttpError(
"Internal Server Error",
httpStatus.INTERNAL_SERVER_ERROR,
{ message: error.message }
)
);
}
},
doesDeviceSearchExist: async (request, next) => {
try {
const { filter, tenant } = request;
Expand Down
33 changes: 32 additions & 1 deletion src/device-registry/utils/site.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,38 @@ const kafka = new Kafka({
});

const createSite = {
getSiteById: async (req, next) => {
try {
const { id } = req.params;
const { tenant } = req.query;

const site = await SiteModel(tenant.toLowerCase()).findById(id);

if (!site) {
throw new HttpError("site not found", httpStatus.NOT_FOUND);
}

return {
success: true,
message: "site details fetched successfully",
data: site,
status: httpStatus.OK,
};
} catch (error) {
if (error instanceof HttpError) {
next(error);
return;
}
logger.error(`🐛🐛 Internal Server Error ${error.message}`);
next(
new HttpError(
"Internal Server Error",
httpStatus.INTERNAL_SERVER_ERROR,
{ message: error.message }
)
);
}
},
fetchSiteDetails: async (tenant, req, next) => {
const filter = generateFilter.sites(req, next);
logObject("the filter being used to filter", filter);
Expand Down Expand Up @@ -79,7 +111,6 @@ const createSite = {

return request;
},

fetchAdditionalSiteDetails: async (tenant, id, next) => {
const baseQuery = { query: { tenant, id } };
const additionalDetails = {};
Expand Down
15 changes: 14 additions & 1 deletion src/device-registry/validators/device.validators.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { query, body, oneOf } = require("express-validator");
const { query, body, oneOf, param } = require("express-validator");
const constants = require("@config/constants");
const mongoose = require("mongoose");
const ObjectId = mongoose.Types.ObjectId;
Expand Down Expand Up @@ -76,6 +76,18 @@ const validateDeviceIdentifier = oneOf([
.withMessage("the device names do not have spaces in them"),
]);

const validateDeviceIdParam = [
param("id")
.exists()
.withMessage("The device ID is missing in the request path.")
.bail()
.trim()
.isMongoId()
.withMessage("Invalid device ID. Must be a valid MongoDB ObjectId.")
.bail()
.customSanitizer((value) => ObjectId(value)),
];

const validateCreateDevice = [
oneOf([
body("name")
Expand Down Expand Up @@ -813,6 +825,7 @@ module.exports = {
validateArrayBody,
validateCreateDevice,
validateUpdateDevice,
validateDeviceIdParam,
validateEncryptKeys,
validateListDevices,
validateDecryptKeys,
Expand Down
49 changes: 38 additions & 11 deletions src/device-registry/validators/site.validators.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { query, body, oneOf } = require("express-validator");
const { query, body, oneOf, param } = require("express-validator");
const constants = require("@config/constants");
const mongoose = require("mongoose");
const ObjectId = mongoose.Types.ObjectId;
Expand Down Expand Up @@ -60,19 +60,38 @@ const createMongoIdValidation = (field, options = {}) => {
isOptional = false,
existsMessage = `the ${field} identifier is missing in request`,
isQuery = true,
isParam = false,
isBody = false, // Add isBody option
} = options;

const validationChain = isQuery
? isOptional
? query(field).optional()
: query(field)
let validationChain;

if (isParam) {
validationChain = isOptional
? param(field).optional()
: param(field)
.exists()
.withMessage(existsMessage)
: isOptional
? body(field).optional()
: body(field)
.exists()
.withMessage(existsMessage);
.withMessage(existsMessage);
} else if (isBody) {
validationChain = isOptional
? body(field).optional()
: body(field)
.exists()
.withMessage(existsMessage);
} else {
// Default to query parameter validation
validationChain = isQuery
? isOptional
? query(field).optional()
: query(field)
.exists()
.withMessage(existsMessage)
: isOptional
? body(field).optional()
: body(field)
.exists()
.withMessage(existsMessage);
}

return validationChain
.notEmpty()
Expand Down Expand Up @@ -169,6 +188,13 @@ const siteIdentifierChains = [
.trim(),
];

const validateSiteIdParam = oneOf([
createMongoIdValidation("id", {
isParam: true,
existsMessage: "The site ID is missing in the request path.",
}),
]);

// Composed Validation Middleware
const validateSiteIdentifier = siteIdentifierChains;

Expand Down Expand Up @@ -464,5 +490,6 @@ module.exports = {
validateGetApproximateCoordinates,
validateNearestSite,
validateBulkUpdateSites,
validateSiteIdParam,
validateCategoryField,
};
Loading