Skip to content

Commit dc12a52

Browse files
Merge pull request #365 from Real-Dev-Squad/doc/backendflow
Created Backend Flow doc of website-backend
2 parents b42e3b5 + 37ab9cc commit dc12a52

File tree

3 files changed

+304
-8351
lines changed

3 files changed

+304
-8351
lines changed

docs/backendFlow.md

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
# **Backend Flow 🕸️**
2+
3+
<br>
4+
5+
> ## Explaining the flow using `Users` created in the project ✌️
6+
7+
<br>
8+
9+
- [**Backend Flow 🕸️**](#backend-flow-️)
10+
- [server.js](#serverjs)
11+
- [Base or Global Route](#base-or-global-route)
12+
- [Different HTTP Routes](#different-http-routes)
13+
- [Middlewares](#middlewares)
14+
- [Controllers](#controllers)
15+
- [Models](#models)
16+
- [config.js](#configjs)
17+
- [test](#test)
18+
- [package.json file](#packagejson-file)
19+
- [Want to Contribute ??](#want-to-contribute-)
20+
21+
## server.js
22+
23+
<br>
24+
25+
> Entry point for the project
26+
27+
- `Config` and `logger` are added to the global object
28+
- Creating the server, and other server helper functions
29+
- Makes use of `http` module of node.js
30+
31+
💡 Know How: [Build http-server](https://nodejs.dev/learn/build-an-http-server "Create Http-server")
32+
33+
<br>
34+
35+
## Base or Global Route
36+
37+
- In project, base route `'/users'` means this is the base for every users route
38+
[ From: `routes> index.js` ]
39+
40+
👀 Example:
41+
42+
`routes/index.js`
43+
44+
```
45+
app.use('/users', require('./users.js'))
46+
```
47+
48+
Description:
49+
50+
- To access details of user with `userId`, the route will be `/users/userId` and so on.
51+
52+
👀 Example:
53+
54+
`router.get('/:username', users.getUser)`
55+
56+
<br>
57+
58+
## Different HTTP Routes
59+
60+
- Defines the path of the users request (can be, `GET` | `POST` | `PUT` | `PATCH` | `DELETE` etc.)
61+
- Each route can have one or more handler functions, which are executed when the route is matched
62+
63+
<br>
64+
65+
More on HTTP Methods: [MDN HTTP Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods "HTTP Methods") <br>
66+
Routing Basics: [Express Router](https://expressjs.com/en/guide/routing.html "Express way Routing")
67+
68+
<br>
69+
70+
👀 Example:
71+
72+
`GET /users Route`
73+
74+
```
75+
router.get('/', authenticate, usersController.getUsers)
76+
```
77+
78+
<br>
79+
80+
## Middlewares
81+
82+
- Middleware function has access to request object and response object
83+
- And it has the `next()` [ mandatory to add ] which calls to the next middleware, if any assigned
84+
85+
💡 Know How: [Express Middleware](https://expressjs.com/en/guide/writing-middleware.html "Middleware Docs")
86+
87+
<br>
88+
89+
👀 Example:
90+
91+
`authenticate middleware`
92+
93+
```JS
94+
module.exports = async (req, res, next) => {
95+
try {
96+
let token = req.cookies[config.get('userToken.cookieName')]
97+
98+
/**
99+
* Enable Bearer Token authentication for NON-PRODUCTION environments
100+
* This is enabled as Swagger UI does not support cookie authe
101+
*/
102+
if (process.env.NODE_ENV !== 'production' && !token) {
103+
token = req.headers.authorization.split(' ')[1]
104+
}
105+
106+
const { userId } = authService.verifyAuthToken(token)
107+
108+
// add user data to `req.userData` for further use
109+
const userData = await users.fetchUser({ userId })
110+
req.userData = userData.user
111+
112+
return next()
113+
} catch (err) {
114+
logger.error(err)
115+
116+
if (err.name === 'TokenExpiredError') {
117+
const refreshTtl = config.get('userToken.refreshTtl')
118+
const token = req.cookies[config.get('userToken.cookieName')]
119+
const { userId, iat } = authService.decodeAuthToken(token)
120+
const newToken = authService.generateAuthToken({ userId })
121+
const rdsUiUrl = new URL(config.get('services.rdsUi.baseUrl'))
122+
123+
// add new JWT to the response if it satisfies the refreshTtl time
124+
if (Math.floor(Date.now() / 1000) - iat <= refreshTtl) {
125+
res.cookie(config.get('userToken.cookieName'), newToken, {
126+
domain: rdsUiUrl.hostname,
127+
expires: new Date(Date.now() + config.get('userToken.ttl') * 1000),
128+
httpOnly: true,
129+
secure: true
130+
})
131+
132+
// add user data to `req.userData` for further use
133+
req.userData = await users.fetchUser({ userId })
134+
135+
return next()
136+
} else {
137+
return res.boom.unauthorized('Unauthenticated User')
138+
}
139+
} else {
140+
return res.boom.unauthorized('Unauthenticated User')
141+
}
142+
}
143+
}
144+
```
145+
146+
<br>
147+
148+
## Controllers
149+
150+
- Contains the business logic
151+
- Here the request and response are handled
152+
153+
👀 Example:
154+
155+
`getUsers Controller`
156+
157+
```JS
158+
const getUsers = async (req, res) => {
159+
try {
160+
const allUsers = await userQuery.fetchUsers(req.query)
161+
return res.json({
162+
message: 'Users returned successfully!',
163+
users: allUsers
164+
})
165+
} catch (error) {
166+
logger.error(`Error while fetching all users: ${error}`)
167+
return res.boom.serverUnavailable('Something went wrong please contact admin')
168+
}
169+
}
170+
```
171+
172+
<br>
173+
174+
## Models
175+
176+
- Interacts with the database, Ex. [Firebase](https://firebase.google.com/docs/guides "Firebase Docs")
177+
- Triggers database calls
178+
179+
👀 Example:
180+
181+
`fetchUsers Model`
182+
183+
```JS
184+
const fetchUsers = async (query) => {
185+
try {
186+
const snapshot = await userModel
187+
.limit(parseInt(query.size) || 100)
188+
.offset((parseInt(query.size) || 100) * (parseInt(query.page) || 0))
189+
.get()
190+
191+
const allUsers = []
192+
193+
snapshot.forEach((doc) => {
194+
allUsers.push({
195+
id: doc.id,
196+
...doc.data(),
197+
phone: undefined,
198+
email: undefined,
199+
tokens: undefined
200+
})
201+
})
202+
203+
return allUsers
204+
} catch (err) {
205+
logger.error('Error retrieving user data', err)
206+
throw err
207+
}
208+
}
209+
```
210+
211+
<br>
212+
213+
## config.js
214+
215+
- Configuring Environmental Variables
216+
<br>
217+
218+
💡 Know How: [Config](https://github.com/lorenwest/node-config/wiki/Configuration-Files "Setup the Configuration files")
219+
<br>
220+
221+
## test
222+
223+
<br>
224+
225+
> Includes Integration and Unit Test for the backend routes
226+
227+
Tests are written using:
228+
229+
- [mocha](https://mochajs.org/ "Mocha Framework") : Test Framework
230+
- [chai](https://www.chaijs.com/ "Chai Library") : Asserion Library
231+
- [sinon](https://sinonjs.org/ "Sinon") : JavaScript test spies, stubs and mocks
232+
- [nock](https://github.com/nock/nock/blob/main/README.md "Nock") : HTTP requests mocking
233+
234+
<br>
235+
236+
## package.json file
237+
238+
<br>
239+
240+
> Gives the overiew of the project requirements
241+
242+
- `scripts` : For different scripts needed for development & others
243+
- `Dependencies` : Modules needed for the project to work/ be functional
244+
- `devDependencies` : Dependencies only needed for the devlopment purpose
245+
246+
<br>
247+
248+
---
249+
250+
## Want to Contribute ??
251+
252+
[Guide](https://github.com/Real-Dev-Squad/website-backend/blob/develop/CONTRIBUTING.md "Follow the guidelines")

0 commit comments

Comments
 (0)