diff --git a/Dockerfile b/Dockerfile index ff03956..de47844 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,21 @@ FROM node:latest -WORKDIR /usr/src/app +ARG UID=987 +ARG GID=987 +RUN groupadd -g ${GID} chat && useradd -d /usr/src/app -g ${GID} -u ${UID} chat + +RUN mkdir -p /usr/src/app +RUN chmod 750 -R /usr/src/app COPY package*.json ./ -#RUN apk update && apk upgrade # && apk add --update alpine-sdk && apk add --update python +WORKDIR /usr/src/app +RUN chown -R chat:chat /usr/src/app RUN npm install -# If you are building your code for production -# RUN npm ci --omit=dev - COPY . . EXPOSE 8080 + +USER chat + + CMD [ "node", "src/index.js" ] diff --git a/config.json b/config.json new file mode 100644 index 0000000..0a994db --- /dev/null +++ b/config.json @@ -0,0 +1,9 @@ +{ + "sessionSecret": "PLEASE!!CHANGE!!TO!!A!!STRONG!!ONE!!", + "dbUser": "smk", + "dbName": "chat", + "dbPort": 5432, + "dbPassword": "CHANGEME", + "dbHost": "db", + "listenPort": 8080 +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 1d6f367..0d6f0e1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,9 +22,9 @@ services: volumes: - ./postgres:/var/lib/postgresql/data environment: - POSTGRES_USER: smk # The PostgreSQL user (useful to connect to the database) - POSTGRES_PASSWORD: CHANGEME # The PostgreSQL password (useful to connect to the database) - POSTGRES_DB: chat # The PostgreSQL default database (automatically created at first launch) + POSTGRES_USER: smk # do not forget to change these in config.json! + POSTGRES_PASSWORD: CHANGEME + POSTGRES_DB: chat networks: ne_nuzhen: diff --git a/docs.md b/docs.md index 8478720..61b2ad7 100644 --- a/docs.md +++ b/docs.md @@ -118,3 +118,23 @@ Otherwise, compares passwords If passwords match, creating session and redirects to __/__ Requires client to be not logged in. + + +## Deployment +### Traditional +To deploy an application in traditional way, follow these steps: + +1. edit ``config.json`` to your needs. + +2. Install dependencies: ``npm i`` + +3. Run __src/index.js__. Use ``npm run prod`` if you want to run it as a production and ``npm run dev`` if you want to run it with nodemon. + +### Docker +To deploy an application with Docker, you need to: + +1. edit ``config.json`` to your needs ( do not forget that backend must be able to connect to db container.) + +2. edit ``docker-compose.yml`` as with the data you've wrote to ``config.json`` + +3. Build and launch: ``docker-compose up --build`` \ No newline at end of file diff --git a/package.json b/package.json index ef80a81..46a20f4 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "test.js", "scripts": { "test": "nodemon test.js", - "dev": "nodemon src/index.js" + "dev": "nodemon src/index.js", + "prod": "node src/index.js" }, "repository": { "type": "git", diff --git a/src/index.js b/src/index.js index f5d5b84..e15ae67 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,9 @@ const cors = require("cors"); const WebSocket = require('ws'); const http = require('http'); const session = require('express-session'); +const fs = require('fs') + +const config = JSON.parse(fs.readFileSync('config.json')); sessions = {}; // logged in clients, there are stored objects like {"token": "some_token_here", "socket": here-is-websocket-object} @@ -12,7 +15,7 @@ const utils = require("./utils") const app = express(); -const PORT = 8080; +const PORT = config.listenPort; utils.initDb(); @@ -135,7 +138,7 @@ console.log("[LOG] Socket has been started"); const sessionParser = session({ name: 'smk_chat', - secret: 'PLEASE!!GENERATE!!A!!STRONG!!ONE!!', + secret: config.sessionSecret, resave: false, saveUninitialized: false }); @@ -282,7 +285,7 @@ app.get('/api/getChatInfo/:chatId', middleware.requireToBeLoggedIn, async (req, membersRequest.rows.forEach((member, index, membersRequest) => { members.push(member.id) }); - + if (!members.includes(sessions[req.session.token].userId)) { return res.send("-2").status(403).end(); } @@ -300,10 +303,7 @@ app.get('/api/getChatInfo/:chatId', middleware.requireToBeLoggedIn, async (req, } }); -//IN: UserId, array of UserIDs that are to be invited. -//OUT: "Ok" if successful, "User with id ${MEMBERID} does not exist." -//Return -1 if amout of users to invite is 0. -//Requires to be logged in + app.post('/api/createChat', middleware.requireToBeLoggedIn, async (req, res) => { try { const userId = sessions[req.session.token].userId @@ -343,10 +343,6 @@ app.post('/api/createChat', middleware.requireToBeLoggedIn, async (req, res) => } }); -//IN: none. -//OUT: redirect to /login. -//Removes client's session, thus unlogging a user. -//Requires to be logged in. app.get('/api/logout', middleware.requireToBeLoggedIn, (req, res) => { try { sessions[req.session.token] = undefined; @@ -359,11 +355,7 @@ app.get('/api/logout', middleware.requireToBeLoggedIn, (req, res) => { }); -//IN: lastname, firstname, middlename, password. -//OUT: redirect to /. -//Checks if user exist. If so, returns 400 with response "Such user exists.". -//Otherwise, registers a user with given data. -//Requires to be not logged in. + app.post('/api/register', middleware.requireToBeNotLoggedIn, async (req, res) => { try { const { lastname, firstname, middlename, password } = req.body; @@ -391,11 +383,7 @@ app.post('/api/register', middleware.requireToBeNotLoggedIn, async (req, res) => } }); -//IN: lastname, firstname, middlename, password. -//OUT: redirect to /. -//Checks if user exists. If not, returns 400 with response "No such user.". -//Otherwise, compares passwords using bcrypt -//If passwords match, creating session and redirects to / + app.post('/api/login', middleware.requireToBeNotLoggedIn, async (req, res) => { try { const { lastname, firstname, middlename, password } = req.body; diff --git a/src/utils.js b/src/utils.js index 24a3658..bf3793b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,15 +1,16 @@ const pg = require('pg'); const fs = require('fs'); +const config = JSON.parse(fs.readFileSync('config.json')) + const { Client } = pg; client = new Client({ - user: "smk", - password: "CHANGEME", // do not forget to change it in docker-compose.yml in db section. - // host: "10.5.0.6", //defined in docker-compose.yml. - host: 'localhost', - port: 5432, - database: "chat" + user: config.dbUser, + password: config.dbPassword, + host: config.dbHost, + port: config.dbPort, + database: config.dbName }); module.exports = {