-
Notifications
You must be signed in to change notification settings - Fork 65
Added the api Routes for Subscription get/post. #127
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,11 +1,11 @@ | ||||||
| import mongoose from "mongoose"; | ||||||
| const mongoose = require("mongoose"); | ||||||
|
|
||||||
| const SubscriptionSchema = new mongoose.Schema( | ||||||
| { | ||||||
| userId: { | ||||||
| type: mongoose.Schema.Types.ObjectId, | ||||||
| ref: "User", | ||||||
| required: true, | ||||||
| // required: true, | ||||||
|
||||||
| // required: true, | |
| required: true, |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,10 @@ | ||||||||||||||||||||||||||||
| const express = require('express'); | ||||||||||||||||||||||||||||
| const router = express.Router(); | ||||||||||||||||||||||||||||
| const { addSubscription, getSubscriptions } = require('../controllers/Api'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| router.get('/subscriptions', getSubscriptions ) | ||||||||||||||||||||||||||||
| router.post('/subscriptions',addSubscription ) | ||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+7
|
||||||||||||||||||||||||||||
| router.get('/subscriptions', getSubscriptions ) | |
| router.post('/subscriptions',addSubscription ) | |
| // Simple authentication middleware to ensure req.user is populated | |
| function authenticate(req, res, next) { | |
| if (!req.user) { | |
| return res.status(401).json({ error: 'Unauthorized' }); | |
| } | |
| next(); | |
| } | |
| router.get('/subscriptions', authenticate, getSubscriptions ) | |
| router.post('/subscriptions', authenticate, addSubscription ) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,233 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const Subscription = require("../Models/SubscriptionSchema"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const toUtcDateOnly = (value) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const date = new Date(value); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Number.isNaN(date.getTime())) return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new Date( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const addUtcDays = (startUtc, days) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const date = new Date(startUtc); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| date.setUTCDate(date.getUTCDate() + days); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return date; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const addUtcMonths = (startUtc, months) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const date = new Date(startUtc); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| date.setUTCMonth(date.getUTCMonth() + months); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return date; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const addUtcYears = (startUtc, years) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const date = new Date(startUtc); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| date.setUTCFullYear(date.getUTCFullYear() + years); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return date; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const computeNextRenewalDate = (startUtc, billingInterval) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch (billingInterval) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "daily": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return addUtcDays(startUtc, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "weekly": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return addUtcDays(startUtc, 7); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "monthly": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return addUtcMonths(startUtc, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "yearly": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return addUtcYears(startUtc, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const computeIntervalCount = (startUtc, endUtc, billingInterval) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const msPerDay = 24 * 60 * 60 * 1000; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const diffMs = endUtc.getTime() - startUtc.getTime(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (diffMs <= 0) return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const diffDays = diffMs / msPerDay; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!Number.isInteger(diffDays)) return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch (billingInterval) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "daily": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return diffDays + 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "weekly": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return diffDays % 7 === 0 ? diffDays / 7 + 1 : null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "monthly": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (startUtc.getUTCDate() !== endUtc.getUTCDate()) return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const months = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (endUtc.getUTCFullYear() - startUtc.getUTCFullYear()) * 12 + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (endUtc.getUTCMonth() - startUtc.getUTCMonth()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return months > 0 ? months + 1 : null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "yearly": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| startUtc.getUTCMonth() !== endUtc.getUTCMonth() || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| startUtc.getUTCDate() !== endUtc.getUTCDate() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const years = endUtc.getUTCFullYear() - startUtc.getUTCFullYear(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return years > 0 ? years + 1 : null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+44
to
+73
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const getSubscriptions = (req, res) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const user = req.user; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!user || !user._id) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return res.status(401).json({ error: "Unauthorized" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Subscription.find({ userId: user._id }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((subscriptions) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| res.status(200).json({ subscriptions }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .catch((err) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .catch((err) => { | |
| .catch((err) => { | |
| console.error("Error fetching subscriptions for user:", user._id, err); |
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling error in the comment: "byt" should be "by". The comment contains a typo where "byt the user" should read "by the user".
| //in this function, I have made is so that the next renewal date and billing interval count are calculated based on the start and end date entered byt the user. | |
| //in this function, I have made is so that the next renewal date and billing interval count are calculated based on the start and end date entered by the user. |
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation for status and billingInterval only checks for truthiness, not whether the values are valid according to the schema enums. For example, status must be one of "trial", "active", "paused", "cancelled", or "expired", but any truthy value would pass this check. Consider validating against the allowed enum values before attempting to create the subscription.
| if (!name || typeof name !== "string" || !name.trim()) { | |
| return res.status(400).json({ error: "name is required" }); | |
| } | |
| if (!status) { | |
| return res.status(400).json({ error: "status is required" }); | |
| } | |
| if (!billingInterval) { | |
| return res.status(400).json({ error: "billingInterval is required" }); | |
| } | |
| // derive allowed enum values from the Subscription schema, if defined | |
| const statusPath = Subscription.schema && Subscription.schema.path | |
| ? Subscription.schema.path("status") | |
| : null; | |
| const billingIntervalPath = Subscription.schema && Subscription.schema.path | |
| ? Subscription.schema.path("billingInterval") | |
| : null; | |
| const allowedStatuses = | |
| statusPath && Array.isArray(statusPath.enumValues) | |
| ? statusPath.enumValues | |
| : null; | |
| const allowedBillingIntervals = | |
| billingIntervalPath && Array.isArray(billingIntervalPath.enumValues) | |
| ? billingIntervalPath.enumValues | |
| : null; | |
| if (!name || typeof name !== "string" || !name.trim()) { | |
| return res.status(400).json({ error: "name is required" }); | |
| } | |
| if (!status) { | |
| return res.status(400).json({ error: "status is required" }); | |
| } | |
| if ( | |
| allowedStatuses && | |
| (typeof status !== "string" || !allowedStatuses.includes(status)) | |
| ) { | |
| return res.status(400).json({ error: "status is invalid" }); | |
| } | |
| if (!billingInterval) { | |
| return res.status(400).json({ error: "billingInterval is required" }); | |
| } | |
| if ( | |
| allowedBillingIntervals && | |
| (typeof billingInterval !== "string" || | |
| !allowedBillingIntervals.includes(billingInterval)) | |
| ) { | |
| return res.status(400).json({ error: "billingInterval is invalid" }); | |
| } |
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message is inconsistent with how other field names are formatted in error messages. Throughout the code, field names in error messages are lowercase (e.g., "name is required", "status is required"), maintaining consistency would improve user experience.
| return res.status(400).json({ error: "billingInterval is required" }); | |
| } | |
| if (!startDate) { | |
| return res.status(400).json({ error: "startDate is required" }); | |
| } | |
| if (billingInterval !== "custom" && !endDate) { | |
| return res.status(400).json({ error: "endDate is required" }); | |
| } | |
| const parsedStartDate = toUtcDateOnly(startDate); | |
| if (!parsedStartDate) { | |
| return res.status(400).json({ error: "startDate must be a valid date" }); | |
| return res.status(400).json({ error: "billing interval is required" }); | |
| } | |
| if (!startDate) { | |
| return res.status(400).json({ error: "start date is required" }); | |
| } | |
| if (billingInterval !== "custom" && !endDate) { | |
| return res.status(400).json({ error: "end date is required" }); | |
| } | |
| const parsedStartDate = toUtcDateOnly(startDate); | |
| if (!parsedStartDate) { | |
| return res.status(400).json({ error: "start date must be a valid date" }); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -3,23 +3,20 @@ const path = require("path"); | |||||
| require("dotenv").config({ path: path.resolve(__dirname, "..", ".env") }); | ||||||
| const express = require("express"); | ||||||
| const mongoConnect = require("./utils/mongoConnect"); | ||||||
| const router = require("./Routes/routes"); | ||||||
|
|
||||||
| const app = express(); | ||||||
| app.use(cors()); | ||||||
| app.use(express.json()); | ||||||
|
|
||||||
| app.get("/", (req, res) => { | ||||||
| res.send("Server is running..."); | ||||||
| }); | ||||||
| app.use("/api",router); | ||||||
|
||||||
| app.use("/api",router); | |
| app.use("/api", router); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space after comma in the dev script. Should be "dev": "nodemon index.js" with a space after the colon for consistent JSON formatting.