You're absolutely right! Let me update the Swagger documentation and create a database seeding script. I'll also provide guidance on the JWT environment variables.
I've now properly updated the Swagger documentation and created comprehensive database seeding scripts. Here's what's included:
The Swagger docs now include:
The seeding script creates:
Super Admin Account:
superadmin@bluehouse.comSuperAdmin123!super_adminRegular Admin Account:
admin@bluehouse.comAdmin123!adminSample Coupons:
WELCOME20 - 20% off, 100 uses, expires in 30 daysSAVE10 - 10% off, 50 uses, expires in 15 daysEARLYBIRD - 25% off, 25 uses, expires in 7 daysEXPIRED - 15% off, expired (for testing)For your JWT configuration, here are the recommended values:
Use the script I created to generate secure secrets:
npm run generate:jwtThis will output something like:
JWT_SECRET=a1b2c3d4e5f6...64-character-hex-string
JWT_REFRESH_SECRET=f6e5d4c3b2a1...64-character-hex-string
JWT_EXPIRES_IN=7d
JWT_REFRESH_EXPIRES_IN=30dJWT_SECRET & JWT_REFRESH_SECRET:
JWT_EXPIRES_IN:
15m - Very secure, frequent re-authentication1h - Good balance for most apps7d - Convenient for development/testing1d - Good for productionJWT_REFRESH_EXPIRES_IN:
7d - Short-lived, high security30d - Good balance90d - Longer conveniencenpm run generate:jwtnpm run seednpm run seed:clearhttp://localhost:3000/api-docs for Swagger documentationcurl -X POST http://localhost:3000/api/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"superadmin@bluehouse.com","password":"SuperAdmin123!"}'curl -X GET http://localhost:3000/api/admin/coupons \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"curl -X GET http://localhost:3000/api/coupon/validate/WELCOME20The Swagger documentation is now complete and includes all admin endpoints with proper authentication requirements!
When I attempted validating the coupons I seeded I got this error:
Coupon validation error: CastError: Cast to Number failed for value "$maxUses" (type string) at path "currentUses" for model "Coupon"
at SchemaNumber.cast (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\schema\number.js:381:11)
at SchemaNumber.handleSingle (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\schema\number.js:390:15)
at SchemaNumber.castForQuery (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\schema\number.js:431:20)
at cast (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\cast.js:367:39)
at model.Query.Query.cast (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:5055:12)
at model.Query.Query._castConditions (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:2351:10)
at model.Query._findOne (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:2674:8)
at model.Query.exec (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:4604:80)
at processTicksAndRejections (node:internal/process/task_queues:95:5) {
stringValue: '"$maxUses"',
messageFormat: undefined,
kind: 'Number',
value: '$maxUses',
path: 'currentUses',
reason: AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert.ok(!isNaN(val))
at castNumber (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\cast\number.js:27:10)
at SchemaNumber.cast (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\schema\number.js:379:12)
at SchemaNumber.handleSingle (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\schema\number.js:390:15)
at SchemaNumber.castForQuery (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\schema\number.js:431:20)
at cast (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\cast.js:367:39)
at model.Query.Query.cast (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:5055:12)
at model.Query.Query._castConditions (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:2351:10)
at model.Query._findOne (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:2674:8)
at model.Query.exec (C:\Users\USER\Desktop\Career\Work\BlueHouse\registration-payment-backend\node_modules\mongoose\lib\query.js:4604:80)
at processTicksAndRejections (node:internal/process/task_queues:95:5) {
generatedMessage: true,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
},
valueType: 'string'
}
And I got this typescript error for the jwtService file:
No overload matches this call.
Overload 1 of 5, '(payload: string | object | Buffer<ArrayBufferLike>, secretOrPrivateKey: null, options?: (SignOptions & { algorithm: "none"; }) | undefined): string', gave the following error.
Argument of type 'string' is not assignable to parameter of type 'null'.
Overload 2 of 5, '(payload: string | object | Buffer<ArrayBufferLike>, secretOrPrivateKey: Buffer<ArrayBufferLike> | Secret | PrivateKeyInput | JsonWebKeyInput, options?: SignOptions | undefined): string', gave the following error.
Type 'string' is not assignable to type 'number | StringValue | undefined'.
Overload 3 of 5, '(payload: string | object | Buffer<ArrayBufferLike>, secretOrPrivateKey: Buffer<ArrayBufferLike> | Secret | PrivateKeyInput | JsonWebKeyInput, callback: SignCallback): void', gave the following error.
Object literal may only specify known properties, and 'expiresIn' does not exist in type 'SignCallback'.ts(2769)
function sign(payload: string | object | Buffer<ArrayBufferLike>, secretOrPrivateKey: jwt.Secret | jwt.PrivateKey, options?: jwt.SignOptions): string (+4 overloads)
Synchronously sign the given payload into a JSON Web Token string payload - Payload to sign, could be an literal, buffer or string secretOrPrivateKey - Either the secret for HMAC algorithms, or the PEM encoded private key for RSA and ECDSA. [options] - Options for the signature returns - The JSON Web Token string
Let me fix both issues - the MongoDB query error and the JWT TypeScript error.
I've resolved both the MongoDB query error and the JWT TypeScript error:
Problem: The query was using $lt: "$maxUses" which MongoDB was interpreting as a string literal instead of a field reference.
Solution: I changed the coupon validation logic to:
currentUses >= maxUses in JavaScript code instead of in the MongoDB queryThis approach is more reliable and avoids the MongoDB field comparison issue.
Problem: The JWT library expects the options (including expiresIn) to be passed as an object in the third parameter.
Solution: I restructured the JWT function calls to use the correct signature:
jwt.sign(payload, secret, { expiresIn: "7d" })I've also added a comprehensive testing script that you can run to verify coupon functionality:
npm run test:couponsThis script will:
npm run seednpm run test:couponscurl http://localhost:3000/api/coupon/validate/WELCOME20http://localhost:3000/api-docs and try the coupon validation endpointWhen you run the coupon test, you should see:
The fixes ensure that:
Try running the test script now - it should work without any errors!
I want to work on the registration endpoints... Apparently what I actually need is to verify the payment by using the trasaction reference.
I'm not the one meant to initialize payment... But verify it by checking the trasaction reference and then send back an appropriate response based on the outcome of the verification.
So let's update the registration endpoint.
The frontend is going to send the trasaction reference alongside the rest of the other payload. And we're gonna use that to verify the payment and return an appropriate response.
You can send messages while the preview loads