diff --git a/config/api.yaml b/config/api.yaml deleted file mode 100644 index 842380b..0000000 --- a/config/api.yaml +++ /dev/null @@ -1,422 +0,0 @@ -openapi: 3.0.0 -info: - title: Milan API - description: - Feel free to raise an issue or PR - [here](https://github.com/MilanCommunity/Milan-Backend/issues/new/choose). - version: 1.0 - -servers: - - url: http://localhost:5000/ - description: Local server - - url: https://api.milanhub.org/ - description: Production server - -components: - securitySchemes: - ApiTokenss: - type: http - scheme: bearer - - ApiKey: - type: apiKey - in: header - name: apikey - -paths: - /display/users: - get: - tags: - - Get Data API - security: - - ApiTokenss: [] - - ApiKey: [] - summary: Returns all the users. - responses: - 200: - description: successful operation - content: - application/json: - example: - - _id: "630c75df01038c415989c00f" - firstName: John - lastName: Doe - email: johndoe@gmail.com" - password: akldjh^%&^%sdhjh12^%&^%kh534&^%&^%&^jh - address: 123 Main Street - pincode: 12345 - __v: 0 - - /display/clubs: - get: - tags: - - Get Data API - security: - - ApiTokenss: [] - - ApiKey: [] - summary: Returns all the clubs/NGOs. - responses: - "200": - description: OK - - /display/events: - get: - tags: - - Get Data API - security: - - ApiTokenss: [] - - ApiKey: [] - summary: Returns all the events. - responses: - "200": - description: OK - - /user/register: - post: - tags: - - User Authentication API - summary: Creates a new user in the database. - description: - Request (required)

- firstname
- - lastname
- email
- password


Request (optional)

- address -
- pincode
- - post: - requestBody: - content: - application/json: - schema: - type: object - properties: - firstname: - type: string - example: "Tamal" - lastname: - type: string - example: "Das" - email: - type: string - example: "tamalcodes@gmail.com" - password: - type: string - format: password - example: "HelloWorld@123$11" - address: - type: string - example: "Salt Lake city, Kolkata" - pincode: - type: string - example: "700001" - - responses: - "201": - description: User has been signed up. - "409": - description: User already exists, must login. - "404": - description: Not found. - default: - description: Internal Server Error. - - /user/login: - post: - tags: - - User Authentication API - summary: Logs in an user. - description: - Request (required)

- email
- - password
- - post: - requestBody: - content: - application/json: - schema: - type: object - properties: - email: - type: string - example: "tamalcodes@gmail.com" - password: - type: string - format: password - example: "HelloWorld@123$11" - - responses: - "201": - description: User has logged in. - "401": - description: Invalid Credentials. - "404": - description: USer was not found. - default: - description: Internal Server Error. - - /auth/logout: - get: - tags: - - User Authentication API - security: - - ApiTokenss: [] - - ApiKey: [] - summary: Log out the user. - responses: - "200": - description: OK - - /user/report: - post: - tags: - - User Contact API - summary: Report a problem. - description: - Request (required)

- firstname
- - lastname
- email
- reportmessage -
- - post: - requestBody: - content: - application/json: - schema: - type: object - properties: - firstname: - type: string - example: "John" - lastname: - type: string - example: "Doe" - email: - type: string - example: "john.doe@example.com" - reportmessage: - type: string - example: "I encountered an issue with the website." - - responses: - "200": - description: Report has been submitted sucessfully. - "429": - description: Too many requests in 2 hours. - default: - description: Internal Server Error. - - /user/contact: - post: - tags: - - User Contact API - summary: Send a message through the contact form. - description: - Request (required)

- firstname
- - lastname
- email
- message
- requestBody: - content: - application/json: - schema: - type: object - properties: - firstName: - type: string - example: "John" - lastName: - type: string - example: "Doe" - email: - type: string - example: "john.doe@example.com" - message: - type: string - example: "Hello, I have a question." - - responses: - "201": - description: Message has been submitted sucessfully. - default: - description: Internal Server Error. - - /club/register: - post: - tags: - - Club Authentication API - summary: Register a new club account. - description: - Request (required)

- name
- - email
- password
- address
- - pincode
- description
- tagLine -
- requestBody: - content: - application/json: - schema: - type: object - properties: - name: - type: string - example: "Example Club" - email: - type: string - example: "club@example.com" - password: - type: string - example: "Password@123" - address: - type: string - example: "123 Main Street" - pincode: - type: string - example: "12345" - description: - type: string - example: "A description of the club" - tagLine: - type: string - example: "Our club, our pride" - responses: - "201": - description: Registration successful, please login. - "409": - description: Account already exists. - default: - description: Internal Server Error. - - /club/login: - post: - tags: - - Club Authentication API - summary: Log in to a club account. - description: - Request (required)

- email
- - password
- requestBody: - content: - application/json: - schema: - type: object - properties: - email: - type: string - example: "club@example.com" - password: - type: string - example: "Password@123" - responses: - "201": - description: Registration successful, please login. - "404": - description: Account doesnot exists. - "401": - description: Invalid credentials.' - default: - description: Internal Server Error. - - /event/create: - post: - tags: - - Create event API - summary: Create a new event - description: - Request (required)

- name
- - slug
- about
- hostClubSlug
- - hostClubName
- bannerImage
- - thumbnailImage
- mode
- address
- city
- state
- country
- iframe
- data
- time
- tags
- isApproved
- createdAt -
- updatedAt
- requestBody: - content: - application/json: - schema: - type: object - properties: - name: - type: string - example: "Clean plastics" - slug: - type: string - example: "cleanplastics" - about: - type: string - example: "Plastic waste management" - hostClubSlug: - type: string - example: "exampleclub" - hostClubName: - type: string - example: "Example club" - bannerImage: - type: string - example: "https://example.image.com" - thumbnailImage: - type: string - example: "https://thumbnail.image.com" - mode: - type: string - example: "physical mode" - address: - type: string - example: "123 Main street" - city: - type: string - example: "pune" - state: - type: string - example: "Maharashtra" - country: - type: string - example: "India" - iframe: - type: string - example: "Example iframe" - date: - type: date - example: "12.09.2023" - time: - type: string - example: "10:20 AM" - tags: - type: array - items: - type: string - example: - - "cleaning" - - "waste management" - createdAt: - type: date - example: "12.09.2023" - updatedAt: - type: date - eample: "13.09.2023" - responses: - "409": - description: Event slug already exists - "201": - description: Event created - default: - description: Internal Server Error - - /event: - get: - tags: - - Get Data API - security : - - ApiTokens: [] - - ApiKey: [] - summary: Returns event details or all events - parameters: - - in: query - name: slug - required: false - schema: - type: string - description : Optional. If provided, fetches a specific event by its slug. - responses: - '200': - description: Success response with event details or all events. - '404': - description: Event Not Found. - default: - description: Internal Server Error. \ No newline at end of file diff --git a/config/swagger.js b/config/swagger.js deleted file mode 100644 index b9a91be..0000000 --- a/config/swagger.js +++ /dev/null @@ -1,16 +0,0 @@ -const swaggerUI = require("swagger-ui-express"); -const YAML = require("js-yaml"); -const fs = require("fs"); - -const path = require("path"); -const apiYamlPath = path.join(__dirname, "api.yaml"); -const swaggerJSDocs = YAML.load(fs.readFileSync(apiYamlPath, "utf8")); - -const options = { - customCss: ".swagger-ui .topbar { display: none }", -}; - -module.exports = { - swaggerServe: swaggerUI.serve, - swaggerSetup: swaggerUI.setup(swaggerJSDocs, options), -}; diff --git a/index.js b/index.js index 87359d8..ed0578c 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,6 @@ const session = require("express-session"); const cookieParser = require("cookie-parser"); const passport = require("passport"); require("./config/passport-googleAuth-strategy"); -const { swaggerServe, swaggerSetup } = require("./config/swagger"); const path = require("path"); @@ -48,14 +47,6 @@ app.use( app.use(passport.initialize()); app.use(passport.session()); app.use(express.static(path.join(__dirname, "public"))); -app.use("/api-docs", swaggerServe, swaggerSetup); - -app.use( - "/docs", - express.static("node_modules/swagger-ui-dist/", { index: false }), - swaggerServe, - swaggerSetup, -); app.get("/", (req, res) => { res.send("HELLO FROM HOME"); @@ -67,6 +58,6 @@ app.use("/clubs", require("./routes/club/Club")); app.use("/display", require("./routes/display/Display")); app.use("/payment", require("./routes/payment/Payment")); app.use("/product", require("./routes/shop/Products")); -app.use("/event", require("./routes/events/Event")); +app.use("/events", require("./routes/events/Event")); app.listen(port, () => console.log("API IS RUNNING 🚀 at port:", port)); diff --git a/routes/events/Event.js b/routes/events/Event.js index c3616f8..39913a6 100644 --- a/routes/events/Event.js +++ b/routes/events/Event.js @@ -28,29 +28,65 @@ router.get("/", async (req, res) => { router.post("/create", async (req, res) => { try { - const { slug, ...data } = req.body; - const existingEvent = await Event.findOne({ slug }); + const { uid, ...data } = req.body; + // Validate required fields: + if ( + !data.name || + !uid || + !data.about || + !data.hostUsername || + !data.hostName || + !data.thumbnailImage || + !data.mode || + !data.date || + !data.startTime || + !data.endTime || + !data.timezone + ) { + console.log(data); + return res + .status(STATUSCODE.BAD_REQUEST) + .json({ message: "Missing Required Fields" }); + } + + // Ensure unique slug: + const existingEvent = await Event.findOne({ uid }); if (existingEvent) { return res .status(STATUSCODE.CONFLICT) - .json({ message: STATUSMESSAGE.EVENT_SLUG_ALREADY_EXISTS }); + .json({ message: "Already exists" }); } - const newEvent = await new Event({ + // Combine sanitized data with timestamp fields: + const newEvent = new Event({ ...data, - slug, + uid, createdAt: setTime(), updatedAt: setTime(), }); + // Validate data before saving: + const validationErrors = newEvent.validateSync(); + if (validationErrors) { + const errors = Object.values(validationErrors.errors).map( + (error) => error.message, + ); + return res + .status(STATUSCODE.BAD_REQUEST) + .json({ message: "Event Validation failed", errors }); + } + + // Save the event: const savedEvent = await newEvent.save(); - return res.status(STATUSCODE.CREATED).json(savedEvent); + + // Respond with the created event: + res.status(STATUSCODE.CREATED).json(savedEvent); } catch (error) { - console.log(error); - return res + console.error(error); + res .status(STATUSCODE.INTERNAL_SERVER_ERROR) - .json({ message: STATUSMESSAGE.CREATE_EVENT_FAILED }); + .json({ message: "Create Event Failed" }); } }); diff --git a/schema/events/EventSchema.js b/schema/events/EventSchema.js index 5183096..a610366 100644 --- a/schema/events/EventSchema.js +++ b/schema/events/EventSchema.js @@ -1,63 +1,85 @@ const mongoose = require("mongoose"); -const EventSchema = mongoose.Schema({ +const EventSchema = new mongoose.Schema({ name: { type: String, required: true, + trim: true, }, - slug: { + uid: { type: String, required: true, + unique: true, }, about: { type: String, required: true, + trim: true, }, - hostClubSlug: { + + hostUsername: { type: String, required: true, }, - hostClubName: { + hostName: { type: String, required: true, + trim: true, }, bannerImage: { type: String, + trim: true, }, thumbnailImage: { type: String, required: true, + trim: true, }, + mode: { type: String, required: true, + enum: ["online", "offline"], }, address: { type: String, + trim: true, }, city: { type: String, + trim: true, }, state: { type: String, + trim: true, }, country: { type: String, + trim: true, }, iframe: { type: String, + trim: true, }, date: { - type: String, + type: Date, + required: true, + }, + startTime: { + type: Date, required: true, }, - time: { + endTime: { + type: Date, + required: true, + }, + timezone: { type: String, required: true, }, tags: { type: [String], - required: true, + default: [], }, isApproved: { type: Boolean, @@ -65,12 +87,17 @@ const EventSchema = mongoose.Schema({ }, createdAt: { type: Date, - required: true, + default: Date.now, }, updatedAt: { type: Date, - required: true, + default: Date.now, }, }); +// Indexes for efficient querying: +EventSchema.index({ uid: 1 }, { unique: true }); // Ensure unique `uid` +EventSchema.index({ host: 1 }); // Optimize queries based on `host` +EventSchema.index({ isApproved: 1 }); // Optimize queries based on `isApproved` + module.exports = mongoose.model("Event", EventSchema);