This repository serves as the server for the Sheldon Chrome Extension and User Dashboard.
Sheldon is the ultimate chrome extension for boosting your productivity. With Sheldon, you can quickly and accurately answer any question, craft compelling and engaging social media posts in seconds, and even write emails and code snippets with ease. But that's not all – Sheldon can also help you with spreadsheets, presentations and much more making it the perfect tool for anyone looking to streamline their workflows and save time.
You can visit Sheldon at https://heysheldon.com.
Learn more about Sheldon at Sheldon's Github Page.
- The server is built using Node.js, Express.js, and MongoDB and is deployed on AWS EC2 and uses Nginx as a reverse proxy.
- The server uses JWT for authentication and authorization.
- The server uses OpenAI's GPT-3 API to generate responses.
- The server can rate-limit requests from the same IP address.
- The server blocks requests from origins other than the extension or the dashboard. This is done by using a custom header and a secret key. Redis is used to perform this task.
- The server can handle requests related to the user's account, such as login, signup and related to searching with a prompt.
To install the server, you will need to have Node.js, MongoDB, Redis, and PM2 installed on your machine.
AWS, MongoDB Atlas accounts not needed for local development.
Github Account only necessary for CI/CD (GitHub Actions)
Clone the repository and install the dependencies.
> git clone https://github.com/HeySheldonAI/extension-server.git
> cd extension-server
> npm installCreate a .env file in the root directory and add the environment variables as mentioned in the .env.example file or the table below.
| Variable Name | Description | Example |
|---|---|---|
MONGODB_URI |
The URI of the production MongoDB database. | mongodb+srv://<username>:<password>@example.mongodb.net/prod?retryWrites=true&w=majority |
STAGING_MONGODB_URI |
The URI of the staging MongoDB database. | mongodb+srv://<username>:<password>@example.mongodb.net/staging?retryWrites=true&w=majority |
JWT_SECRET |
The secret to encode and decode a JWT Token. | randomstringblabla |
ENCRYPTION_KEY |
The key to decode the x-custom-header. | randomstringblabla |
MAIN_OPENAI_ORG_ID |
The organization ID for Production OpenAI Account. | org-xxxxxxxxxxxxxxxxxxx |
MAIN_OPENAI_API_KEY |
The secret key for Production OpenAI Account. | sk-xxxxxxxxxxxxxxxxxxx |
TEST_OPENAI_ORG_ID |
The org ID for Dev/Staging OpenAI Account. | org-xxxxxxxxxxxxxxxxxxx |
TEST_OPENAI_API_KEY |
The secret key for Dev/Staging OpenAI Account. | sk-xxxxxxxxxxxxxxxxxxx |
For default/development keys and values, refer to the config.js file.
> npm run devIf you get any errors, make sure the following conditions are met:
- NodeJs, MongoDB, Redis, and PM2 are installed on your machine.
- The MongoDB and Redis servers are running.
- The environment variables are set correctly.
- Make sure you don't use any special characters like
$in theJWT_SECRETandENCRYPTION_KEYvariables. - Port 8080, 6379, and 27017 are not being used by any other process.
For most of the errors, you can see the logs in the logs folder under the src directory. The log file for in-app errors would go by the following naming convention: app_$ENVIRONMENT_$DD_MM_YYYY.logs.json.
For deployment, you will need to have an AWS account, MongoDB Atlas account, and a Github account.
- Create a new cluster on MongoDB Atlas.
- Create a new user for the cluster and give it the
readWriterole. - Create a new database and name it
prodorstagingdepending on the environment. - Allow access from anywhere if you want to test the server locally. If you want to deploy the server on a remote server, then allow access from the IP address of the remote server that we will be creating later.
- Create an AWS account and a Github account.
- Refer to the following article: How to Deploy a Node.js App to AWS EC2 Using GitHub Actions to setup the CI/CD pipeline.
- Instead of adding the userdata, ssh into the new EC2 instance and follow the steps mentioned in the following gist: How to setup a Node.js server on AWS EC2.
- Make sure to create a
.envfile in the root directory of the server and add the environment variables as mentioned in the.env.examplefile or the table above.
- Follow the following article to setup Nginx for SSL: How to Setup Nginx for SSL on Ubuntu Server.
- Make sure to edit the
nginx.conffile as per the following gist: Editing nginx.conf. This edit is necessary so that the express server can receive the IP address of the user instead of the IP address of the proxy server.
- For every function, there must be comments stating why the function is needed and what it does.
- Files must be arranged into folders based on their functionality.
- All file and folders must be named in
camelCase. - Try catching all errors and logging them in the
src/logsfolder. - Difference between helpers and util functions is that helper functions' response can directly be sent to frontend while utility functions' response cannot. Also, all the utility functions take direct arguments while helper functions take object(context) as argument.
All the logs are stored in the logs folder under the src directory.
There are 2 types of logs:
applogs: These logs are generated by the application in thetry/catchblock.networklogs: These logs are generated by themorganpackage.
The log file for in-app errors would go by the following naming convention: app_$ENVIRONMENT_$DD_MM_YYYY.logs.json. Here $ENVIRONMENT is the environment variable NODE_ENV and $DD_MM_YYYY is the current date. Example: app_development_01_01_2023.logs.json.
The log file for network errors would go by the following naming convention: network_$ENVIRONMENT_$DD_MM_YYYY.logs.json. Here $ENVIRONMENT is the environment variable NODE_ENV and $DD_MM_YYYY is the current date. Example: network_development_01_01_2023.logs.json.
These log files are created only when a request is made to the server. If no request is made, then no log file is created.
PS: The log files are created in the UTC timezone.
In the remote server, the log file is created at 5:30 AM IST and in the local server, the log file is created at 12:00 AM IST.
For every request, there should be a x-custom-header in the request header. The x-custom-header is encrypted using the ENCRYPTION_KEY and the encrypted string is sent in the x-custom-header header. The server decrypts the x-custom-header using the ENCRYPTION_KEY and verifies the origin of the request.
This is done to prevent any malicious requests from being made to the server.
The decrypted header is of the form: origin::timestamp::randomString. Here origin is the origin of the request, timestamp is the timestamp of the request, and randomString is a random string of length 10.
After decrypting the header, the random string is then stored in the redis cache, so that no other request can be made with the same random string.
If you have any questions, feel free to contact me at adityakrishnaoff@gmail.com or @adityakrishnag_ on Twitter.