Coder Social home page Coder Social logo

bluewave-uptime's Introduction

BlueWave Uptime

BlueWave Uptime is an open source server monitoring application. It is a tool used to track the operational status and performance of servers and websites. It regularly checks whether a server/website is accessible and performing optimally, providing real-time alerts and reports on the availability, downtime, and response time of the monitored services.

Contributing

You are welcome to provide contributions to the project. It uses React on the FE, and Nodejs and MongoDB on the BE, hence if you are comfortable with working with those technologies, you are encouraged to send your PRs. Please read Contributor's guideline

Note that We have a Figma file that includes:

  • All the dashboard elements and components
  • The design guideline for the app

You can see the designs here. Since it is read-only, we encourage you to copy to your own Figma page, then work on it.

Getting Started

  • Clone this repository to your local machine
  1. Installation (Client)
  2. Configuration(Client)
  3. Getting Started (Server)
  4. Endpoints
    Auth
    Monitors
    Checks
    Alerts
  5. Error Handling
  6. Contributors

Client

Installation

  1. Change directory to the Client directory
  2. Install all dependencies by running npm install

Configuration

Environmental Variables
ENV Variable Name Required/Optional Type Description Accepted Values
VITE_APP_API_BASE_URL Required string Base URL of server {host}/api/v1

Starting Development Server

  1. Run npm run dev to start the development server.

Getting Started (Server)

Docker Quickstart

The fastest way to start the server is to use our Dockerfiles and Docker Compose.

To get the server up and running you need to:

  1. In the Server/docker directory run the build script build_images.sh to build docker images for the server, Redis database, and MongoDB database.
  2. In the Server/docker directory, create a .env file with the requried environtmental variables. Sample file:
CLIENT_HOST="http://localhost:5173"
JWT_SECRET="my_secret"
DB_TYPE="MongoDB"
DB_CONNECTION_STRING="mongodb://mongodb:27017/uptime_db"
REDIS_HOST="redis"
REDIS_PORT=6379
SYSTEM_EMAIL_ADDRESS="<email>"
SENDGRID_API_KEY="<api_key>"
LOGIN_PAGE_URL="<login_page"
  1. In the Server/docker directory run docker compose up to run the docker-compose.yaml file and start all three images.

That's it, the server is ready to use.

Manual Install

Install Server
  1. Change directory to the Server directory
  2. Install all dependencies by running npm install

Environmental Variables

Configure the server with the following environmental variables:

ENV Variable Name Required/Optional Type Description Accepted Values
CLIENT_HOST Required string Frontend Host
JWT_SECRET Required string JWT secret
DB_TYPE Optional string Specify DB to use MongoDB | FakeDB
DB_CONNECTION_STRING Required string Specifies URL for MongoDB Database
PORT Optional integer Specifies Port for Server
SENDGRID_API_KEY Required string Specifies API KEY for SendGrid email service
SYSTEM_EMAIL_ADDRESS Required string Specifies System email to be used in emailing service, must be a verified email by sendgrid
LOGIN_PAGE_URL Required string Login url to be used in emailing service
REDIS_HOST Required string Host address for Redis database
REDIS_PORT Required integer Port for Redis database

Databases

This project requires a number of databases to run:

  1. Main database for the application. This project includes an implementation for a MongoDB database as well as a MongoDB Docker image.
  2. A Redis database is required for the Queue implementation in the PingService. This project includes a Redis docker image.

You may use the included Dockerfiles to spin up databases quickly if you wish.

(Optional) Dockerised Databases

Dockerfiles for the server and databases are located in the ./Server/docker directory

MongoDB Image Location: `./Server/docker/mongoDB.Dockerfile`

The ./Server/docker/mongo/data directory should be mounted to the MongoDB container in order to persist data.

From the Server/docker directory run

  1. Build the image: docker build -f mongoDB.Dockerfile -t uptime_database_mongo .
  2. Run the docker image: docker run -d -p 27017:27017 -v $(pwd)/mongo/data:/data/db --name uptime_database_mongo uptime_database_mongo
Redis Image Location `./Server/docker/redislDockerfile`

the ./Server/docker/redis/data directory should be mounted to the Redis container in order to persist data.

From the Server/docker directory run

  1. Build the image: docker build -f redis.Dockerfile -t uptime_redis .
  2. Run the image: docker run -d -p 6379:6379 -v $(pwd)/redis/data:/data --name uptime_redis uptime_redis

Starting the Development Server
  • run npm run dev to start the development server

OR

  • run node index.js to start server

Endpoints

All endpoints return a response in this format:

Name Type Notes
success boolean Success or failure of request
msg string Message describing response
data Object Arbitrary Payload

Example:

{success: true, msg: "Successful Request", data: {test: testData}}

Data Types
User
Name Type Notes
firstname string First name
lastname string Last name
email string User's email
profilePicUrl string URL to User's picture
isActive boolean Default to true
isVerified boolean Default to false
updated_at Date Last update time
created_at Date Time created at
Monitor
Name Type Notes
userId string Unique ID identifying monitor creator
name string Name of the monitor
description string Description of the monitor
url string Url the monitor will ping
isActive boolean Whether or not the monitor is active
interval integer Interval with which to ping monitor (ms)
updatedAt Date Last time the monitor was updated
CreatedAt Date When the monitor was updated
Check
Name Type Notes
monitorId string Unique ID for the monitor
status boolean Indicates the service is Up or Down
responseTime integer Indicates the response time of the service (ms)
statusCode integer Status Code returned from the service
message string Message returned from the service
updatedAt Date Last time the check was updated
CreatedAt Date When the check was created
Alert
Name Type Notes
checkId string Unique ID for the associated check
monitorId string Unique ID for the associated monitor
userId string Unique ID for the associated user
status boolean Indicates the service is Up or Down
message string Message for the user about the down service
notifiedStatus boolean Indicates whether the user is notified
acknowledgeStatus boolean Indicates whether the user acknowledged the alert
updatedAt Date Last time the alert was updated
CreatedAt Date When the alert was created

Auth
POST /api/v1/auth/register
Method/Headers
Method/Headers Value
Method POST
content-type application/json
Body
Name Type Notes
firstname string
lastname string
email string Valid email address
password string Min 8 chars
Response Payload
Type Notes
JWT JSON Web Token containing a User
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/auth/register \
  --header 'Content-Type: application/json' \
  --data '{
	"firstname" : "User First Name",
	"lastname": "User Last Name",
	"email" : "[email protected]",
	"password": "user_password"
}'
Sample Response
{
  "success": true,
  "msg": "User created",
  "data": "<encoded_user>"
}
POST /api/v1/auth/login
Method/Headers
Method/Headers Value
Method POST
content-type application/json
Body
Name Type Notes
email string Valid email address
password string Min 8 chars
Response Payload
Type Notes
JWT JSON Web Token Containing a User
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/auth/login \
  --header 'Content-Type: application/json' \
  --data '{
	"email" : "[email protected]",
	"password": "user_password"
}'
Sample response
{
  "success": true,
  "msg": "Found user",
  "data": "<encoded_user>"
}
POST/api/v1/auth/user/{userId}
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
{
  "success": true,
  "msg": "User updated",
  "data": {
    "_id": "6654d156634754f789e1f10e",
    "firstname": "First Name",
    "lastname": "Last Name",
    "email": "[email protected]",
    "isActive": true,
    "isVerified": false,
    "createdAt": "2024-05-27T18:30:46.358Z",
    "updatedAt": "2024-05-27T19:21:51.747Z",
    "__v": 0
  }
}
POST/api/v1/auth/recovery/request
Method/Headers
Method/Headers Value
Method POST
Body
Name Type Notes
email string User's email
Response Payload
Type Notes
RecoveryToken Returns a recovery token if email found
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/auth/recovery/request \
  --header 'Content-Type: application/json' \
  --data '{
	"email" : "[email protected]"
}'
Sample Response
{
  "success": true,
  "msg": "Created recovery token",
  "data": {
    "email": "[email protected]",
    "token": "f519da5e4a9be40cfc3c0fde97e60c0e6d17bdaa613f5ba537a45073f3865193",
    "_id": "6668878263587f30748e968e",
    "expiry": "2024-06-11T17:21:06.984Z",
    "createdAt": "2024-06-11T17:21:06.985Z",
    "updatedAt": "2024-06-11T17:21:06.985Z",
    "__v": 0
  }
}
POST/api/v1/auth/recovery/validate
Method/Headers
Method/Headers Value
Method POST
Body
Name Type Notes
recoveryToken string Token issued in /recovery/request
Response Payload
Type Notes
RecoveryToken Returns the recovery token
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/auth/recovery/validate \
  --header 'Content-Type: application/json' \
  --data '{
	"recoveryToken" : "f519da5e4a9be40cfc3c0fde97e60c0e6d17bdaa613f5ba537a45073f3865193"
}'
Sample Response
{
  "success": true,
  "msg": "Token is valid",
  "data": {
    "_id": "6668894263587f30748e969a",
    "email": "[email protected]",
    "token": "457d9926b24dedf613f120eeb524ef00ac45b3f0fc5c70bd25b1cc8aa83a64a0",
    "expiry": "2024-06-11T17:28:34.349Z",
    "createdAt": "2024-06-11T17:28:34.349Z",
    "updatedAt": "2024-06-11T17:28:34.349Z",
    "__v": 0
  }
}
POST/api/v1/auth/recovery/reset
Method/Headers
Method/Headers Value
Method POST
Body
Name Type Notes
recoveryToken string Token issued returned by /recovery/validate
password string User's new password`
Response Payload
Type Notes
User Returns the updated user
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/auth/recovery/reset \
  --header 'Content-Type: application/json' \
  --data '{
	"recoveryToken" : "f519da5e4a9be40cfc3c0fde97e60c0e6d17bdaa613f5ba537a45073f3865193",
	"password": "testtest"
}'
Sample Response
{
  "success": true,
  "msg": "Password reset",
  "data": {
    "_id": "66675891cb17336d84c25d9f",
    "firstname": "User First Name",
    "lastname": "User Last Name",
    "email": "[email protected]",
    "isActive": true,
    "isVerified": false,
    "createdAt": "2024-06-10T19:48:33.863Z",
    "updatedAt": "2024-06-11T17:21:22.289Z",
    "__v": 0
  }
}

Monitors
GET /api/v1/monitors
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Monitor> Array of all monitors
Sample cURL Request
curl --request GET \
  --url http://localhost:5000/api/v1/monitors \
  --header '<bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Monitors found",
  "data": [
    {
      "_id": "664d070786e62625ac612ca1",
      "userId": "6645079aae0b439371913972",
      "name": "Wha3",
      "description": "Description",
      "url": "https://monitor0.com",
      "isActive": true,
      "interval": 60000,
      "createdAt": "2024-05-21T20:41:43.051Z",
      "updatedAt": "2024-05-21T20:45:10.496Z",
      "__v": 0
    },
    {
      "_id": "664e5ccf189c864800debc16",
      "userId": "6645079aae0b439371913972",
      "name": "Inserting a new Monitor",
      "description": "Description",
      "url": "https://monitor0.com",
      "isActive": true,
      "interval": 60000,
      "createdAt": "2024-05-22T20:59:59.295Z",
      "updatedAt": "2024-05-22T20:59:59.295Z",
      "__v": 0
    }
  ]
}
GET /api/v1/monitor/{id}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Monitor Single monitor with the id in the request parameter
Sample cURL Request
curl --request GET \
  --url http://localhost:5000/api/v1/monitors/664d070786e62625ac612ca1 \
  --header '<bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Got monitor by Id successfully",
  "data": {
    "_id": "6671eb54f7040ece47892f53",
    "userId": "666c9146c9bfa20db790b1df",
    "name": "Google Monitor",
    "description": "Google",
    "type": "http",
    "url": "https://www.google.com/404",
    "isActive": true,
    "interval": 10000,
    "createdAt": "2024-06-18T20:17:24.112Z",
    "updatedAt": "2024-06-18T20:17:24.112Z",
    "__v": 0,
    "checks": [
      {
        "_id": "6671eb5af7040ece47892f61",
        "monitorId": "6671eb54f7040ece47892f53",
        "status": false,
        "responseTime": 145,
        "expiry": "2024-06-18T20:17:30.246Z",
        "statusCode": 404,
        "createdAt": "2024-06-18T20:17:30.246Z",
        "updatedAt": "2024-06-18T20:17:30.246Z",
        "__v": 0
      },
      {
        "_id": "6671eb64f7040ece47892f6b",
        "monitorId": "6671eb54f7040ece47892f53",
        "status": false,
        "responseTime": 170,
        "expiry": "2024-06-18T20:17:40.209Z",
        "statusCode": 404,
        "createdAt": "2024-06-18T20:17:40.210Z",
        "updatedAt": "2024-06-18T20:17:40.210Z",
        "__v": 0
      }
    ]
  }
}
GET /api/v1/monitors/user/{userId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Monitor> Array of monitors created by user with specified UserID
Sample cURL Request
curl --request GET \
  --url http://localhost:5000/api/v1/monitors/user/6645079aae0b439371913972 \
  --header '<bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Got monitor for 666c9146c9bfa20db790b1df successfully\"",
  "data": [
    {
      "_id": "6671eb54f7040ece47892f53",
      "userId": "666c9146c9bfa20db790b1df",
      "name": "Google Monitor",
      "description": "Google",
      "type": "http",
      "url": "https://www.google.com/404",
      "isActive": true,
      "interval": 10000,
      "createdAt": "2024-06-18T20:17:24.112Z",
      "updatedAt": "2024-06-18T20:17:24.112Z",
      "__v": 0,
      "checks": [
        {
          "_id": "6671eb5af7040ece47892f61",
          "monitorId": "6671eb54f7040ece47892f53",
          "status": false,
          "responseTime": 145,
          "expiry": "2024-06-18T20:17:30.246Z",
          "statusCode": 404,
          "createdAt": "2024-06-18T20:17:30.246Z",
          "updatedAt": "2024-06-18T20:17:30.246Z",
          "__v": 0
        }
      ]
    }
  ]
}
POST/api/v1/monitors
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Monitor Returns newly created Monitor
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/monitors \
  --header <bearer_token> \
  --header 'Content-Type: application/json' \
  --data '{"userId": "6645079aae0b439371913972",
			"name": "Inserting a new Monitor",
			"description": "Description",
			"url": "https://monitor0.com",
			"isActive": true,
			"interval": 60000}'
Sample Response
{
  "success": true,
  "msg": "Monitor created",
  "data": {
    "userId": "6645079aae0b439371913972",
    "name": "Inserting a new Monitor",
    "description": "Description",
    "url": "https://monitor0.com",
    "isActive": true,
    "interval": 60000,
    "_id": "664e5ccf189c864800debc16",
    "createdAt": "2024-05-22T20:59:59.295Z",
    "updatedAt": "2024-05-22T20:59:59.295Z",
    "__v": 0
  }
}
POST/api/v1/monitors/delete/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
None No payload returned
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/monitors/delete/664e632a7a3ee9d620761938 \
  --header '<bearer_token>' \
  --header 'Content-Type: application/json' \
Sample Response
{
  "success": true,
  "msg": "Monitor deleted"
}

POST/api/v1/monitors/edit/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Monitor Returns the updated monitor
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/monitors/edit/664e5ccf189c864800debc16 \
  --header '<bearer_token' \
  --header 'Content-Type: application/json' \
  --data '
		{
			"_id": "664e5ccf189c864800debc16",
			"userId": "6645079aae0b439371913972",
			"name": "Edited monitor",
			"description": "Description",
			"url": "https://monitor0.com",
			"isActive": true,
			"interval": 60000
		}'
Sample Response
{
  "success": true,
  "msg": "Monitor edited",
  "data": {
    "_id": "664e5ccf189c864800debc16",
    "userId": "6645079aae0b439371913972",
    "name": "Edited monitor",
    "description": "Description",
    "url": "https://monitor0.com",
    "isActive": true,
    "interval": 60000,
    "createdAt": "2024-05-22T20:59:59.295Z",
    "updatedAt": "2024-05-22T21:34:33.893Z",
    "__v": 0
  }
}

Checks
POST/api/v1/checks/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Check Returns newly created check
Body
Name Type Notes
monitorId string Monitor associated with Check
status boolean true for up and false for down
responseTime number How long it took the server to respond
statusCode number HTTP Status code of response
message string
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
  --header 'Authorization: <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
	"monitorId": "66562414035c4ce6a8a610ac",
	"status": true,
	"responseTime": 1,
	"statusCode": 200,
	"message": "good"
}'
Sample Response
{
  "success": true,
  "msg": "Check created",
  "data": {
    "monitorId": "66562414035c4ce6a8a610ac",
    "status": true,
    "responseTime": 1,
    "statusCode": 200,
    "message": "good",
    "_id": "66576decba9f70148ea1f354",
    "createdAt": "2024-05-29T18:03:24.445Z",
    "updatedAt": "2024-05-29T18:03:24.445Z",
    "__v": 0
  }
}
GET/api/v1/checks/{monitorId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Checks> Array of Check objects
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Checks retrieved",
  "data": [
    {
      "_id": "66576c0194e11c0d4409d3c1",
      "monitorId": "66562414035c4ce6a8a610ac",
      "status": true,
      "responseTime": 1,
      "statusCode": 200,
      "message": "good",
      "createdAt": "2024-05-29T17:55:13.581Z",
      "updatedAt": "2024-05-29T17:55:13.581Z",
      "__v": 0
    },
    {
      "_id": "66576c0994e11c0d4409d3c5",
      "monitorId": "66562414035c4ce6a8a610ac",
      "status": true,
      "responseTime": 2,
      "statusCode": 200,
      "message": "good",
      "createdAt": "2024-05-29T17:55:21.127Z",
      "updatedAt": "2024-05-29T17:55:21.127Z",
      "__v": 0
    }
  ]
}
POST/api/v1/checks/delete/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Object {deletedCount: n} Returns an object showing how many items deleted
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/checks/delete/66562414035c4ce6a8a610ac \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Checks deleted",
  "data": {
    "deletedCount": 3
  }
}

Alerts
POST/api/v1/alerts/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Alert Returns newly created Alert
Body
"checkId": "66577a3fd16dcf7c1ce35148",
"monitorId": "6657789ebf6766ee8e2d2edb",
"userId": "6654d1a2634754f789e1f115",
"status": false,
"message": "This is a test alert",
"notifiedStatus": "false",
"acknowledgeStatus": false
Name Type Notes
checkId string Id of Check associated with Alert
monitorId string Id of Monitor associated with Alert
userId string Id of User associated with Alert
status boolean Status of Alert
message string Alert message
notifiedStatus boolean
acknowledgeStatus boolean
Sample CURL request

Sample Response
GET/api/v1/alerts/user/{userId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Alert> Returns all Alert created by a User
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/alerts/user/6654d1a2634754f789e1f115 \
  --header 'Authorization: <bearer_token>'
Sample Response
{
  "success": true,
  "msg": "Got alerts",
  "data": [
    {
      "_id": "6657813d809adfded891a6b7",
      "checkId": "66577a3fd16dcf7c1ce35148",
      "monitorId": "6657789ebf6766ee8e2d2edb",
      "userId": "6654d1a2634754f789e1f115",
      "status": false,
      "message": "This is a test alert",
      "notifiedStatus": false,
      "acknowledgeStatus": false,
      "createdAt": "2024-05-29T19:25:49.317Z",
      "updatedAt": "2024-05-29T19:25:49.317Z",
      "__v": 0
    }
  ]
}
GET/api/v1/alerts/monitor/{monitorId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Alert> Returns an array of Alert belonging to a specified Monitor
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/alerts/monitor/6657789ebf6766ee8e2d2edb \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Got alerts by Monitor",
  "data": [
    {
      "_id": "6657813d809adfded891a6b7",
      "checkId": "66577a3fd16dcf7c1ce35148",
      "monitorId": "6657789ebf6766ee8e2d2edb",
      "userId": "6654d1a2634754f789e1f115",
      "status": false,
      "message": "This is a test alert",
      "notifiedStatus": false,
      "acknowledgeStatus": false,
      "createdAt": "2024-05-29T19:25:49.317Z",
      "updatedAt": "2024-05-29T19:25:49.317Z",
      "__v": 0
    }
  ]
}
GET/api/v1/alerts/{alertId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Alert Returns specified Alert
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/alerts/66577ddae5ff3c91437d0887 \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Got Alert By alertID",
  "data": {
    "_id": "66577ddae5ff3c91437d0887",
    "checkId": "66577a3fd16dcf7c1ce35148",
    "monitorId": "6657789ebf6766ee8e2d2edb",
    "userId": "6654d1a2634754f789e1f115",
    "status": false,
    "message": "This is a test alert",
    "notifiedStatus": false,
    "acknowledgeStatus": false,
    "createdAt": "2024-05-29T19:11:22.205Z",
    "updatedAt": "2024-05-29T19:11:22.205Z",
    "__v": 0
  }
}
POST/api/v1/alerts/edit/{alertId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Alert Returns edited Alert
Body
Name Type Notes
checkId string ID of Check associated with Alert
monitorId string ID of Monitor id associated with Alert
userId string ID of User associated with Alert
status boolean Alert status
message string Alert message
notifiedStatus boolean
acknowledgeStatus boolean
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/alerts/edit/66577ddae5ff3c91437d0887 \
  --header 'Authorization: <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
	"acknowledgeStatus": true
}'
Sample Response
{
  "success": true,
  "msg": "Edited alert",
  "data": {
    "_id": "66577ddae5ff3c91437d0887",
    "checkId": "66577a3fd16dcf7c1ce35148",
    "monitorId": "6657789ebf6766ee8e2d2edb",
    "userId": "6654d1a2634754f789e1f115",
    "status": false,
    "message": "This is a test alert",
    "notifiedStatus": false,
    "acknowledgeStatus": true,
    "createdAt": "2024-05-29T19:11:22.205Z",
    "updatedAt": "2024-05-29T19:12:23.951Z",
    "__v": 0
  }
}
POST/api/v1/alerts/delete/{alertId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Alert Returns the deleted Alert
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/alerts/delete/66577ddae5ff3c91437d0887 \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Deleted alert",
  "data": {
    "_id": "66577ddae5ff3c91437d0887",
    "checkId": "66577a3fd16dcf7c1ce35148",
    "monitorId": "6657789ebf6766ee8e2d2edb",
    "userId": "6654d1a2634754f789e1f115",
    "status": false,
    "message": "This is a test alert",
    "notifiedStatus": false,
    "acknowledgeStatus": true,
    "createdAt": "2024-05-29T19:11:22.205Z",
    "updatedAt": "2024-05-29T19:12:23.951Z",
    "__v": 0
  }
}

Checks
POST/api/v1/checks/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Check Returns newly created check
Body
Name Type Notes
monitorId string Monitor associated with Check
status boolean true for up and false for down
responseTime number How long it took the server to respond
statusCode number HTTP Status code of response
message string
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
  --header 'Authorization: <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
	"monitorId": "66562414035c4ce6a8a610ac",
	"status": true,
	"responseTime": 1,
	"statusCode": 200,
	"message": "good"
}'
Sample Response
{
  "success": true,
  "msg": "Check created",
  "data": {
    "monitorId": "66562414035c4ce6a8a610ac",
    "status": true,
    "responseTime": 1,
    "statusCode": 200,
    "message": "good",
    "_id": "66576decba9f70148ea1f354",
    "createdAt": "2024-05-29T18:03:24.445Z",
    "updatedAt": "2024-05-29T18:03:24.445Z",
    "__v": 0
  }
}
GET/api/v1/checks/{monitorId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Checks> Array of Check objects
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Checks retrieved",
  "data": [
    {
      "_id": "66576c0194e11c0d4409d3c1",
      "monitorId": "66562414035c4ce6a8a610ac",
      "status": true,
      "responseTime": 1,
      "statusCode": 200,
      "message": "good",
      "createdAt": "2024-05-29T17:55:13.581Z",
      "updatedAt": "2024-05-29T17:55:13.581Z",
      "__v": 0
    },
    {
      "_id": "66576c0994e11c0d4409d3c5",
      "monitorId": "66562414035c4ce6a8a610ac",
      "status": true,
      "responseTime": 2,
      "statusCode": 200,
      "message": "good",
      "createdAt": "2024-05-29T17:55:21.127Z",
      "updatedAt": "2024-05-29T17:55:21.127Z",
      "__v": 0
    }
  ]
}
POST/api/v1/checks/delete/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Object {deletedCount: n} Returns an object showing how many items deleted
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/checks/delete/66562414035c4ce6a8a610ac \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Checks deleted",
  "data": {
    "deletedCount": 3
  }
}

Alerts
POST/api/v1/alerts/{monitorId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Alert Returns newly created Alert
Body
"checkId": "66577a3fd16dcf7c1ce35148",
"monitorId": "6657789ebf6766ee8e2d2edb",
"userId": "6654d1a2634754f789e1f115",
"status": false,
"message": "This is a test alert",
"notifiedStatus": "false",
"acknowledgeStatus": false
Name Type Notes
checkId string Id of Check associated with Alert
monitorId string Id of Monitor associated with Alert
userId string Id of User associated with Alert
status boolean Status of Alert
message string Alert message
notifiedStatus boolean
acknowledgeStatus boolean
Sample CURL request

Sample Response
GET/api/v1/alerts/user/{userId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Alert> Returns all Alert created by a User
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/alerts/user/6654d1a2634754f789e1f115 \
  --header 'Authorization: <bearer_token>'
Sample Response
{
  "success": true,
  "msg": "Got alerts",
  "data": [
    {
      "_id": "6657813d809adfded891a6b7",
      "checkId": "66577a3fd16dcf7c1ce35148",
      "monitorId": "6657789ebf6766ee8e2d2edb",
      "userId": "6654d1a2634754f789e1f115",
      "status": false,
      "message": "This is a test alert",
      "notifiedStatus": false,
      "acknowledgeStatus": false,
      "createdAt": "2024-05-29T19:25:49.317Z",
      "updatedAt": "2024-05-29T19:25:49.317Z",
      "__v": 0
    }
  ]
}
GET/api/v1/alerts/monitor/{monitorId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Array<Alert> Returns an array of Alert belonging to a specified Monitor
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/alerts/monitor/6657789ebf6766ee8e2d2edb \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Got alerts by Monitor",
  "data": [
    {
      "_id": "6657813d809adfded891a6b7",
      "checkId": "66577a3fd16dcf7c1ce35148",
      "monitorId": "6657789ebf6766ee8e2d2edb",
      "userId": "6654d1a2634754f789e1f115",
      "status": false,
      "message": "This is a test alert",
      "notifiedStatus": false,
      "acknowledgeStatus": false,
      "createdAt": "2024-05-29T19:25:49.317Z",
      "updatedAt": "2024-05-29T19:25:49.317Z",
      "__v": 0
    }
  ]
}
GET/api/v1/alerts/{alertId}
Method/Headers
Method/Headers Value
Method GET
Response Payload
Type Notes
Alert Returns specified Alert
Sample CURL request
curl --request GET \
  --url http://localhost:5000/api/v1/alerts/66577ddae5ff3c91437d0887 \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Got Alert By alertID",
  "data": {
    "_id": "66577ddae5ff3c91437d0887",
    "checkId": "66577a3fd16dcf7c1ce35148",
    "monitorId": "6657789ebf6766ee8e2d2edb",
    "userId": "6654d1a2634754f789e1f115",
    "status": false,
    "message": "This is a test alert",
    "notifiedStatus": false,
    "acknowledgeStatus": false,
    "createdAt": "2024-05-29T19:11:22.205Z",
    "updatedAt": "2024-05-29T19:11:22.205Z",
    "__v": 0
  }
}
POST/api/v1/alerts/edit/{alertId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Alert Returns edited Alert
Body
Name Type Notes
checkId string ID of Check associated with Alert
monitorId string ID of Monitor id associated with Alert
userId string ID of User associated with Alert
status boolean Alert status
message string Alert message
notifiedStatus boolean
acknowledgeStatus boolean
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/alerts/edit/66577ddae5ff3c91437d0887 \
  --header 'Authorization: <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
	"acknowledgeStatus": true
}'
Sample Response
{
  "success": true,
  "msg": "Edited alert",
  "data": {
    "_id": "66577ddae5ff3c91437d0887",
    "checkId": "66577a3fd16dcf7c1ce35148",
    "monitorId": "6657789ebf6766ee8e2d2edb",
    "userId": "6654d1a2634754f789e1f115",
    "status": false,
    "message": "This is a test alert",
    "notifiedStatus": false,
    "acknowledgeStatus": true,
    "createdAt": "2024-05-29T19:11:22.205Z",
    "updatedAt": "2024-05-29T19:12:23.951Z",
    "__v": 0
  }
}
POST/api/v1/alerts/delete/{alertId}
Method/Headers
Method/Headers Value
Method POST
Response Payload
Type Notes
Alert Returns the deleted Alert
Sample CURL request
curl --request POST \
  --url http://localhost:5000/api/v1/alerts/delete/66577ddae5ff3c91437d0887 \
  --header 'Authorization: <bearer_token>' \
Sample Response
{
  "success": true,
  "msg": "Deleted alert",
  "data": {
    "_id": "66577ddae5ff3c91437d0887",
    "checkId": "66577a3fd16dcf7c1ce35148",
    "monitorId": "6657789ebf6766ee8e2d2edb",
    "userId": "6654d1a2634754f789e1f115",
    "status": false,
    "message": "This is a test alert",
    "notifiedStatus": false,
    "acknowledgeStatus": true,
    "createdAt": "2024-05-29T19:11:22.205Z",
    "updatedAt": "2024-05-29T19:12:23.951Z",
    "__v": 0
  }
}

Error handling

Errors are returned in a standard format:

{"success": false, "msg": "No token provided"}

Errors are handled by error handling middleware and should be thrown with the following parameters

Name Type Default Notes
status integer 500 Standard HTTP codes
message string "Something went wrong" An error message
service string "Unknown Service" Name of service that threw the error

Example:

const myRoute = async(req, res, next) => {
  try{
    const result = myRiskyOperationHere();
  }
  catch(error){
    error.status = 404
    error.message = "Resource not found"
    error.service = service name
    next(error)
    return;
  }
}

Errors should not be handled at the controller level and should be left to the middleware to handle.

Contributors

Made with contrib.rocks.

bluewave-uptime's People

Contributors

ajhollid avatar muhammadkhalilzadeh avatar veyselboybay avatar skorpios604 avatar danielcj2 avatar gorkem-bwl avatar alvarotorrestx avatar

Stargazers

 avatar Burak Sonmez avatar Can Erdoğan avatar  avatar  avatar  avatar  avatar Erdem avatar

Watchers

 avatar Erdem avatar  avatar

bluewave-uptime's Issues

Adding Subroutes to client side

Please add subroutes for Monitors, Incidents, Status, Integrations, and Settings pages and create their default page components.
What I mean is;

<Route exact path="/" element={<HomeLayout />} >
   <Route path="monitors" element={<Monitors />} />
   ...
 </Route>

Create routes for Checks and Alerts

We need API routes for creating Checks and Alerts.

Checks should have

  • Create
  • Read

Alerts should have

  • Create
  • Read
  • Update

Both should have deleteAll routes for deleting all Checks and Alerts associated with a Monitor. This will be useful for deleting or resetting a monitor

Frontend - Root Layout

It looks like the main layout is aligned using margins to offset content, it may be beneficial to refactor the layout into a grid or a flexbox.

Open for disucssion, I'm not sure if there is a particular reason it was set up that way.

Dockerise Server

Eventually it will be nice to have a docker image for the server as well as the DBs, that way we can spin up the whole backend from a script.

Error Handling Middleware

As the number of middleware grows, it might be nice to write an error handling middleware?

That way we can just have all the middleware throw errors instead of returing responses.

This will allow us to have a consistent error handling process rather than dealing with errors in each middleware.

Cascading Delete Operations

I believe Delete operation for Monitor should cascade to Checks and Alerts

In other words, if a user deletes a Monitor they created all Checks and Alerts associated with that monitor should be deleted.

Style Consistency

As the number of components grows it's probably worth thinking about how to maintain consistency across our library of components.

I suggest going over the frontend components before we get too far along and refactor out any common dimensions to the theme, or at least a root level CSS file.

I'm mostly thinking of values like:

  • margin and padding
  • font sizes
  • widths/heights

I'm sure there's going to be exceptions and one off's, but I imagine there are also a large number of values that are going to be shared between many components

The sooner we get to this the less painful it will be 😆

Frontend Authentication

Looks like we'll be using JWT for authentication, we should consider how we want to deal with the token on the frontend.

I think we've got two options for storing the token

  1. Cookies
  2. Local storage

Cookies are probably somewhat safer, local storage is more flexible and convenient in my experience.

We can get JWT set up on the backend and worry about frontend details when we come to it, but we can start thinking about the frontend.

Register Page UI

Please implement the Register Page UI and make sure the third party register option is disabled for now. One more thing as well, make the first two text fields as firstname and lastname instead of name and surname.

Database Schema and Routes

It might be nice to descrie all the routes that we will need to implement for the backend?

Example:

/api/v1/monitors
/api/v1/montiors/{monitorId}

If we have a (for the time being) complete list of routes we will know what endpoints to implement on the backend.

Similarly, it would be nice to have all the schema we'll need defined. We have some so far,

User
Montior
Check
Alert

There may be a few more, it looks like each user can have a number of status pages, so that will likely need it's own schema to be defined.

NPM Dependency Versions

How does everyone feel about locking in depenency versions for the libaries that we are using?

Right now I see that we're using the npm default which is to update all packages to minor version changes whenever dependencies are installed.

It's been my experience that NPM packages often have breaking changes even in minor versions, so if we have a working config it might be nice to lock it in.

We can update the package.json files to use exact versions just by removing the caret ^ before the dependency.

"dotenv": "^16.4.5" => "dotenv": "16.4.5"

We can also avoid the issue by telling NPM to use exact versions in the future:

npm install dotenv --save-exact

It's a minor thing, but I've been burned here before. As they are "minor" version changes too the build often still works too, which makes breaking changes even more difficult to find.

Loading spinners and Results field

We need some progress spinners and general error fields for components that will make backend requests

The progress spinner should:

  1. Show progress when requesting data from backaned
  2. Stop showing progress when operation is complete, in either error or success form

Results field should:

  1. Show success/error message returned from the bakend on operation complete

Maybe a toast is a nice fromat for the response message? This might be worth checking out

Connect login page to backend

Login page needs at a minimum

  1. Listeners set on all text fields
  2. Axios POST to backend
  3. Save JWT to local storage after login
  4. Redirect user to home page after login

and for better UX we need

  1. Error handling
  2. Input validation

Add Ping Service for Server

The server likely needs some sort of service for pinging all the URLs specified in the monitors.

We've discusse dusing BullMQ to set up a queue to handle this operation

Eventually we may want to have a number of options for notifying users of up status changes (SMS, Email, websocket, etc)

Back End - Forgot password

Need to implement forgot password flow. I believe it should look like this:

  1. User navigates to forgot password page, enters email address
  2. Backend checks if user exists, if so, generate one time token with expiration time, saves to db, send link with token to user's email
  3. User clicks link, taken to reset password page. Password reset page talks to backend to see if token is valid, if so, user can reset their password. If not, display error
  4. User is redirected to login page to use new credentials or auto logged in

This task will aslo require a few front end pages

Authentication and Tokens

I believe we are going to develop a stateless RESTful API, if that's the case we'll likely need some authentication strategies, at least two:

  1. Provide local login (username/password)
  2. 3d party OAuth (Google, Facebook, etc)

Are we going to use a library for this like Passport.js? Or roll our own?

I assume we'll issue a token once a user authenticates, will we use JWT for this? Looks like jsonwebtoken is still the go to for this.

We can then write some middleware to verify the JWT on protected routes, or just use Passport.js.

In summary it might be helpful to:

  • Decide on authentication strategies
  • Decide which libraries (if any) to use for Oauth and JWT (if we decide on that standard)

NavBar UI

Please implement the NavBar UI. You can delete the default styles from app.css and index.css.

Backend - Service Error Handling

I think the back end needs more robust and consistent error handling in the JobQueue and NetworkService classes.

The express server has consistent error handling via middleware, but errors in the services do not, and should not, propagate to that middleware.

Errors in the services should be non-fatal and allow the service to continue making status requests.

Errors thrown by NetworkService need to be classified into errors connecting to a service indicating that the service is down and other errors.

Add route for updating user details

Add a POST route for updating user details.

Should this go under the auth route?

/api/v1/auth/user

Or should a new route be set up?

/api/v1/user

Docker images for Redis and MongoDB

Might be nice to include these in the project so someone spinning up the project from scratch can just run a script to run start up docker images with the databases required without having to config anything.

Edit Monitor Route Security

Editing a monitor should only be possible for the user that created that monitor.

It's probably worth it to implement a middleware for this as there are going to be a number of operations that require a user to be the owner of the entity being changed.

Implement the Login/index.jsx

  • There's no logic for handling user input on the login page.
  • The listeners on the text fields are not exposed.
  • Need to get the user input from the text fields, serialize it into a JSON object, and send to the backend.

Implement the dashboard.

We want the bar chart for the team area, the status, host, and actions.

We also want to add the metric item at the top.

image

Login Page

Implement the Login Page UI and make the third party login option disabled for now.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.