Showing AI reviews for tenant-service
Project AI Score ?
67%
Quality Avg ?
69%
Security Avg ?
64%
Reviews ?
143

Review Result ?

solutionbowl/tenant-service · f269636f
The commit adds a runner withdrawal API that voids bets and recalculates exposures accordingly, which has practical business value for managing race bets dynamically. The code integrates deeply with betting models and recalculates exposures carefully. However, the implementation lacks some code comments in critical parts, and error handling seems insufficient or commented out. The security risk is moderate because financial transactions like wallet refunds and ledger entries are handled, but the code review shows no explicit input validation or authorization checks to prevent misuse or injection attacks. Bug risk exists due to complexity and limited error logging or rollback mechanisms on partial failures. The fake work risk is low considering the complexity and meaningful domain logic shown.
Quality ?
75%
Security ?
50%
Business Value ?
70%
Maintainability ?
68%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Error Logging Is Commented Out
Where src/controllers/horseracing/test.controller.js:55
Issue / Evidence error logging is commented out
Suggested Fix uncomment or improve error logging to help debugging
Placeholder Console.log Statements Comment...
Where src/controllers/horseracing/test.controller.js:158
Issue / Evidence placeholder console.log statements commented out
Suggested Fix remove or replace with proper logging or debugging
Success Message Sent, But No Error Handlin...
Where src/controllers/horseracing/test.controller.js:236
Issue / Evidence success message sent, but no error handling in access workflow
Suggested Fix add try-catch blocks and error response handling
Fetching Market Data With Find Without Ver...
Where src/controllers/horseracing/test.controller.js:120
Issue / Evidence fetching market data with find without verifying existence
Suggested Fix add checks and handle missing market data gracefully
Missing Validation
Where src/controllers/horseracing/test.controller.js:137
Issue / Evidence wallet refund logic present but no validation of wallet balance or transaction safety
Suggested Fix add validations and atomic transactions if possible
Ledger Credit Entry Lacks Concurrency Cont...
Where src/controllers/horseracing/test.controller.js:143
Issue / Evidence ledger credit entry lacks concurrency control
Suggested Fix consider transaction or locking mechanisms
Missing Validation
Where src/controllers/horseracing/test.controller.js:190
Issue / Evidence object ids created but without validation or sanitization
Suggested Fix validate all external input before usage
Aggregation Pipelines Depend Heavily On Ob...
Where src/utils/exposureHelper.js:49
Issue / Evidence aggregation pipelines depend heavily on object ids and string conversions
Suggested Fix ensure inputs are validated before queries to avoid injections
Security Issue
Where src/routes/test.routes.js:7
Issue / Evidence no authentication or authorization middlewares shown
Suggested Fix add middleware to secure API endpoint
Insufficient Description
Where commit message
Issue / Evidence insufficient description
Suggested Fix expand commit message to describe key business logic and security considerations of runner withdrawal
Code Change Preview · src/controllers/horseracing/test.controller.js ?
Removed / Before Commit
- diff --git a/src/controllers/horseracing/test.controller.js b/src/controllers/horseracing/test.controller.js
- index 5381652..f05c28c 100644
- const mongoose = require("mongoose");
- const Exposure = require("../../models/Exposure");
- 
- exports.getTenantExposure = async (req, res) => {
- try {
- 
- return res.status(200).json({ success: true, data });
- } catch (error) {
-     console.error("Error fetching tenant exposure:", error);
- return res.status(500).json({ success: false, message: "Server error fetching tenant exposure" });
- }
- };
- exports.runnerWithdrawal = async (req, res) => {
- try {
- const { runner_id, race_id } = req.body;
-     const tenant = req.tenant;
Added / After Commit
+ diff --git a/src/controllers/horseracing/test.controller.js b/src/controllers/horseracing/test.controller.js
+ index 5381652..f05c28c 100644
+ const mongoose = require("mongoose");
+ const Exposure = require("../../models/Exposure");
+ const Bet = require("../../models/Bet");
+ const RacingBet = require("../../models/RacingBet");
+ const Wallet = require("../../models/Wallet");
+ const Ledger = require("../../models/Ledger");
+ const { recalculatePlacesExposure } = require("../../utils/exposureHelper");
+ const HorseRaceEvent = require("../../models/HorseRaceEvent");
+ const HorseRace = require("../../models/HorseRace");
+ const RaceMarket = require("../../models/RaceMarket");
+ 
+ exports.getTenantExposure = async (req, res) => {
+ try {
+ 
+ return res.status(200).json({ success: true, data });
+ } catch (error) {
Removed / Before Commit
- diff --git a/src/routes/test.routes.js b/src/routes/test.routes.js
- index e0984ec..9d50abc 100644
- 
- // Test Route for Exposure
- router.post("/exposure", testController.getTenantExposure);
- 
- module.exports = router;
Added / After Commit
+ diff --git a/src/routes/test.routes.js b/src/routes/test.routes.js
+ index e0984ec..9d50abc 100644
+ 
+ // Test Route for Exposure
+ router.post("/exposure", testController.getTenantExposure);
+ router.post("/runnerWithdrawal", testController.runnerWithdrawal);
+ 
+ module.exports = router;
Removed / Before Commit
- diff --git a/src/utils/exposureHelper.js b/src/utils/exposureHelper.js
- index 453d352..5ff3d62 100644
- const mongoose = require("mongoose");
- const Exposure = require("../models/Exposure");
- 
- const getTenantExposure = async ({ raceId, tenantId }) => {
- return await Exposure.aggregate([
- market.odds.forEach(runner => {
- const exp = exposureData.find(
- e => String(e._id.market_id) === String(market.marketId) &&
-                      String(e._id.runner_id) === String(runner.runnerId)
- );
- 
- runner.exposure = exp ? exp.exposure : 0;
- 
- return cloned;
- };
- // const mergeExposure = (marketData, exposureData) => {
Added / After Commit
+ diff --git a/src/utils/exposureHelper.js b/src/utils/exposureHelper.js
+ index 453d352..5ff3d62 100644
+ const mongoose = require("mongoose");
+ const Exposure = require("../models/Exposure");
+ const Bet = require("../models/Bet");
+ const RacingBet = require("../models/RacingBet");
+ 
+ const getTenantExposure = async ({ raceId, tenantId }) => {
+ return await Exposure.aggregate([
+ market.odds.forEach(runner => {
+ const exp = exposureData.find(
+ e => String(e._id.market_id) === String(market.marketId) &&
+                     String(e._id.runner_id) === String(runner.runnerId)
+ );
+ 
+ runner.exposure = exp ? exp.exposure : 0;
+ 
+ return cloned;
Removed / Before Commit
- diff --git a/src/utils/socketClient.js b/src/utils/socketClient.js
- index 2bcfeed..157d463 100644
- const { io } = require("socket.io-client");
- 
- let socket = null;
- 
- return socket;
- };
- 
- const emitRaceOdds = (raceId, oddsData) => {
- const s = getSocket();
-   s.emit("raceOdds", { raceId, oddsData });
- };
- 
- module.exports = { getSocket, emitRaceOdds };
Added / After Commit
+ diff --git a/src/utils/socketClient.js b/src/utils/socketClient.js
+ index 2bcfeed..157d463 100644
+ const { io } = require("socket.io-client");
+ const Exposure = require("../models/Exposure");
+ const mongoose = require("mongoose");
+ 
+ 
+ let socket = null;
+ 
+ return socket;
+ };
+ 
+ const emitRaceOdds = async (raceId, oddsData, tenantId = null) => {
+ const s = getSocket();
+ 
+   // 1️⃣ Emit raw odds to everyone (no exposure mixed in)
+   s.emit(`raceOdds`, { raceId, oddsData });
+