mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-04-27 03:59:43 -05:00
Merge branch 'master' into feat/check-routes
This commit is contained in:
@@ -12,6 +12,7 @@ BlueWave uptime monitoring application
|
||||
4. [Endpoints](#endpoints)
|
||||
- <code>POST</code> [/api/v1/auth/register](#post-register)
|
||||
- <code>POST</code> [/api/v1/auth/login](#post-login)
|
||||
- <code>POST</code> [/api/v1/auth/user/{userId}](#post-auth-user-edit-id)
|
||||
- <code>GET</code> [/api/v1/monitors](#get-monitors)
|
||||
- <code>GET</code> [/api/v1/monitor/{id}](#get-monitor-id)
|
||||
- <code>GET</code> [/api/v1/monitors/user/{userId}](#get-monitors-user-userid)
|
||||
@@ -251,6 +252,67 @@ curl --request POST \
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary id='post-auth-user-edit-id'><code>POST</code><b>/api/v1/auth/user/{userId}</b></summary>
|
||||
|
||||
###### Method/Headers
|
||||
|
||||
> | Method/Headers | Value |
|
||||
> | -------------- | ----- |
|
||||
> | Method | POST |
|
||||
|
||||
##### Body
|
||||
|
||||
> | Name | Type | Notes |
|
||||
> | ------------- | -------- | ----------- |
|
||||
> | firstname | `string` | |
|
||||
> | lastname | `string` | |
|
||||
> | profilePicUrl | `string` | |
|
||||
> | password | `string` | Min 8 chars |
|
||||
|
||||
###### Response Payload
|
||||
|
||||
> | Type | Notes |
|
||||
> | ------ | ------------------------ |
|
||||
> | `User` | Returns the updated user |
|
||||
|
||||
##### Sample CURL request
|
||||
|
||||
```
|
||||
curl --request POST \
|
||||
--url http://localhost:5000/api/v1/auth/user/6654d156634754f789e1f10e \
|
||||
--header 'Authorization: <bearer_token>' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"firstname": "First Name",
|
||||
"lastname: "Last Name"
|
||||
}'
|
||||
```
|
||||
|
||||
###### Sample Response
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"msg": "User updated",
|
||||
"data": {
|
||||
"_id": "6654d156634754f789e1f10e",
|
||||
"firstname": "First Name",
|
||||
"lastname": "Last Name",
|
||||
"email": "me@gmail.com",
|
||||
"isActive": true,
|
||||
"isVerified": false,
|
||||
"createdAt": "2024-05-27T18:30:46.358Z",
|
||||
"updatedAt": "2024-05-27T19:21:51.747Z",
|
||||
"__v": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary id='get-monitors'><code>GET</code> <b>/api/v1/monitors</b></summary>
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
const express = require("express");
|
||||
const { registerValidation, loginValidation } = require("../validation/joi");
|
||||
const {
|
||||
registerValidation,
|
||||
loginValidation,
|
||||
editUserParamValidation,
|
||||
editUserBodyValidation,
|
||||
} = require("../validation/joi");
|
||||
const logger = require("../utils/logger");
|
||||
require("dotenv").config();
|
||||
var jwt = require("jsonwebtoken");
|
||||
@@ -107,4 +112,36 @@ const loginController = async (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { registerController, loginController };
|
||||
const userEditController = async (req, res, next) => {
|
||||
try {
|
||||
await editUserParamValidation.validateAsync(req.params);
|
||||
await editUserBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
error.status = 422;
|
||||
error.service = SERVICE_NAME;
|
||||
error.message = error.details[0].message;
|
||||
next(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.userId !== req.user._id.toString()) {
|
||||
const error = new Error("Unauthorized access");
|
||||
error.status = 401;
|
||||
error.service = SERVICE_NAME;
|
||||
next(error);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const updatedUser = await req.db.updateUser(req, res);
|
||||
res
|
||||
.status(200)
|
||||
.json({ success: true, msg: "User updated", data: updatedUser });
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
next(error);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { registerController, loginController, userEditController };
|
||||
|
||||
@@ -63,6 +63,31 @@ const getUserByEmail = async (req, res) => {
|
||||
// Monitors
|
||||
//****************************************
|
||||
|
||||
/**
|
||||
* Update a user by ID
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @returns {Promise<UserModel>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
|
||||
const updateUser = async (req, res) => {
|
||||
const candidateUserId = req.params.userId;
|
||||
const candidateUser = req.body;
|
||||
|
||||
try {
|
||||
const updatedUser = await UserModel.findByIdAndUpdate(
|
||||
candidateUserId,
|
||||
candidateUser,
|
||||
{ new: true } // Returns updated user instead of pre-update user
|
||||
).select("-password");
|
||||
return updatedUser;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all monitors
|
||||
* @async
|
||||
@@ -244,6 +269,7 @@ module.exports = {
|
||||
connect,
|
||||
insertUser,
|
||||
getUserByEmail,
|
||||
updateUser,
|
||||
getAllMonitors,
|
||||
getMonitorById,
|
||||
getMonitorsByUserId,
|
||||
|
||||
+6
-6
@@ -65,12 +65,6 @@ app.use("/api/v1/auth", authRouter);
|
||||
app.use("/api/v1/monitors", verifyJWT, monitorRouter);
|
||||
app.use("/api/v1/checks", verifyJWT, checkRouter);
|
||||
|
||||
/**
|
||||
* Error handler middleware
|
||||
* MUST be called after all routes
|
||||
*/
|
||||
app.use(handleErrors);
|
||||
|
||||
// Testing email service
|
||||
// app.use('/sendEmail', async (req, res) => {
|
||||
// const response = sendEmail(['veysel.boybay@bluewavelabs.ca'], 'Testing email service', '<h1>Testing Bluewavelabs</h1>');
|
||||
@@ -88,4 +82,10 @@ app.use("/api/v1/healthy", (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Error handler middleware
|
||||
* Should be called last
|
||||
*/
|
||||
app.use(handleErrors);
|
||||
|
||||
connectDbAndRunServer(app, db);
|
||||
|
||||
@@ -3,7 +3,7 @@ const logger = require("../utils/logger");
|
||||
const handleErrors = (error, req, res, next) => {
|
||||
const status = error.status || 500;
|
||||
const message = error.message || "Something went wrong";
|
||||
const service = error.errorService || "Unknown service";
|
||||
const service = error.service || "Unknown service";
|
||||
|
||||
logger.error(error.message, { service: service });
|
||||
res.status(status).json({ success: false, msg: message });
|
||||
|
||||
@@ -19,6 +19,7 @@ const verifyOwnership = (Model, paramName) => {
|
||||
|
||||
// If the userID does not match the document's userID, return a 403 error
|
||||
if (userId.toString() !== doc.userId.toString()) {
|
||||
console.log("boom");
|
||||
const error = new Error("Unauthorized access");
|
||||
error.status = 403;
|
||||
throw error;
|
||||
|
||||
+34
-37
@@ -1,44 +1,41 @@
|
||||
const mongoose = require("mongoose");
|
||||
const bcrypt = require("bcrypt");
|
||||
|
||||
const UserSchema = mongoose.Schema({
|
||||
firstname: {
|
||||
type: String,
|
||||
required: true,
|
||||
const UserSchema = mongoose.Schema(
|
||||
{
|
||||
firstname: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
lastname: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
profilePicUrl: {
|
||||
type: String,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isVerified: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
lastname: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
profilePicUrl: {
|
||||
type: String,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isVerified: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
updated_at: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
created_at: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
});
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
UserSchema.pre("save", async function (next) {
|
||||
if (!this.isModified("password")) {
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
const router = require("express").Router();
|
||||
const { verifyJWT } = require("../middleware/verifyJWT");
|
||||
|
||||
const {
|
||||
registerController,
|
||||
loginController,
|
||||
userEditController,
|
||||
} = require("../controllers/authController");
|
||||
|
||||
router.post("/register", registerController);
|
||||
router.post("/login", loginController);
|
||||
router.post("/user/:userId", verifyJWT, userEditController);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const joi = require("joi");
|
||||
const user = require("../models/user");
|
||||
|
||||
const loginValidation = joi.object({
|
||||
email: joi.string().email().required(),
|
||||
@@ -30,10 +29,22 @@ const monitorValidation = joi.object({
|
||||
interval: joi.number(),
|
||||
});
|
||||
|
||||
const editUserParamValidation = joi.object({
|
||||
userId: joi.string().required(),
|
||||
});
|
||||
|
||||
const editUserBodyValidation = joi.object({
|
||||
firstname: joi.string(),
|
||||
lastname: joi.string(),
|
||||
profilePicUrl: joi.string(),
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
loginValidation,
|
||||
registerValidation,
|
||||
getMonitorByIdValidation,
|
||||
getMonitorsByUserIdValidation,
|
||||
monitorValidation,
|
||||
editUserParamValidation,
|
||||
editUserBodyValidation,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user