Skip to content

Commit 9def6ac

Browse files
committed
Enforce new code style via TSLint
1 parent 422622a commit 9def6ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+3059
-2687
lines changed

.editorconfig

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ root = true
55
[*]
66
charset = utf-8
77
end_of_line = lf
8-
indent_size = 4
9-
indent_style = space
8+
indent_size = 2
9+
indent_style = tab
1010
insert_final_newline = true
1111
trim_trailing_whitespace = true
1212

1313
[*.md]
14-
trim_trailing_whitespace = false
14+
trim_trailing_whitespace = true
1515

1616
[*.json]
1717
indent_size = 2

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ _**API** - Core services_
99
* [Status](#status)
1010
* [Codebase](#codebase)
1111
* [Folder Structure](#folder-structure)
12+
* [Code Style](#code-style)
1213
* [First time setup](#first-time-setup)
1314
* [Installation](#installation)
1415
* [Running the app locally](#running-the-app-locally)
@@ -29,6 +30,13 @@ The codebase for `@cryb/api` is written in JavaScript, utilising TypeScript and
2930

3031
MongoDB is used as the primary database, while Redis is used for cache and PUB/SUB.
3132

33+
### Code Style
34+
We ask that you follow our [code style guidelines](https://github.com/crybapp/library/blob/master/code-style/STYLE.md) when contributing to this repository.
35+
36+
We use TSLint in order to lint our code. Run `yarn lint` before committing any code to ensure it's clean.
37+
38+
*Note: while we have most rules covered in our `tslint.json` config, it's good practice to familarise yourself with our code style guidelines*
39+
3240
### Folder Structure
3341
```
3442
cryb/api/

package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"scripts": {
1010
"start": "node dist",
1111
"dev": "tsc-watch --outDir ./dist --onSuccess \"yarn start\" --compiler typescript/bin/tsc",
12-
"build": "tsc"
12+
"build": "tsc",
13+
"lint": "tslint src/**/*.ts{,x}"
1314
},
1415
"dependencies": {
1516
"axios": "^0.19.0",
@@ -39,6 +40,7 @@
3940
"devDependencies": {
4041
"@types/chance": "^1.0.6",
4142
"@types/cors": "^2.8.6",
43+
"@types/dotenv": "^8.2.0",
4244
"@types/express": "^4.17.0",
4345
"@types/ioredis": "^4.0.17",
4446
"@types/lodash": "^4.14.144",
@@ -48,6 +50,7 @@
4850
"@types/passport": "^1.0.0",
4951
"@types/passport-discord": "^0.1.3",
5052
"@types/passport-jwt": "^3.0.1",
51-
"@types/ws": "^6.0.1"
53+
"@types/ws": "^6.0.1",
54+
"tslint": "^5.20.1"
5255
}
5356
}

src/config/defaults.ts

+28-18
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
export default {
2-
/**
3-
* The amount of members a room needs to hit for a Portal (VM) to be created / queued (default 2)
4-
*/
5-
min_member_portal_creation_count: parseInt(process.env.MIN_MEMBER_PORTAL_CREATION_COUNT || '2'),
2+
/**
3+
* The amount of members a room needs to hit for a Portal (VM) to be created / queued (default 2)
4+
*/
5+
min_member_portal_creation_count: parseInt(process.env.MIN_MEMBER_PORTAL_CREATION_COUNT || '2'),
66

7-
/**
8-
* The maximum amount of members a room can have (default 10)
9-
*/
10-
max_room_member_count: parseInt(process.env.MAX_ROOM_MEMBER_COUNT || '10'),
7+
/**
8+
* The maximum amount of members a room can have (default 10)
9+
*/
10+
max_room_member_count: parseInt(process.env.MAX_ROOM_MEMBER_COUNT || '10'),
1111

12-
/**
13-
* Whenever destroy portals when room gets empty
14-
*/
15-
destroy_portal_when_empty: typeof process.env.DESTROY_PORTAL_WHEN_EMPTY !== 'undefined' ?
16-
(process.env.DESTROY_PORTAL_WHEN_EMPTY === 'true') : true,
12+
/**
13+
* Whenever destroy portals when room gets empty
14+
*/
15+
destroy_portal_when_empty: typeof process.env.DESTROY_PORTAL_WHEN_EMPTY !== 'undefined' ?
16+
(process.env.DESTROY_PORTAL_WHEN_EMPTY === 'true') : true,
1717

18-
/**
19-
* The timeout before an empty room gets their portal destroyed in seconds (default 5)
20-
*/
21-
empty_room_portal_destroy: parseInt(process.env.EMPTY_ROOM_PORTAL_DESTROY || '5')
22-
}
18+
/**
19+
* The timeout before an empty room gets their portal destroyed in seconds (default 5)
20+
*/
21+
empty_room_portal_destroy: parseInt(process.env.EMPTY_ROOM_PORTAL_DESTROY || '5'),
22+
23+
/**
24+
* The user IDs that are allowed to create rooms, comma (,) separated
25+
*/
26+
room_whitelist: (process.env.ROOM_WHITELIST === 'true'),
27+
28+
/**
29+
* The user IDs that are allowed to create rooms, comma (,) separated
30+
*/
31+
allowed_user_ids: (process.env.ALLOWED_USER_IDS || '').split(',')
32+
}

src/config/passport.config.ts

+49-47
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,76 @@
11
import axios from 'axios'
2+
import { NextFunction, Request, Response } from 'express'
23
import passport from 'passport'
3-
import { Strategy, ExtractJwt } from 'passport-jwt'
4-
import { Request, Response, NextFunction } from 'express'
5-
4+
import { ExtractJwt, Strategy } from 'passport-jwt'
65
import User from '../models/user'
76

8-
import { handleError, UserNoAuth } from '../utils/errors.utils'
7+
import { handleError, UserBanned, UserNoAuth } from '../utils/errors.utils'
98

109
passport.serializeUser((user, done) => done(null, user))
1110
passport.deserializeUser((id, done) => done(null, id))
1211

1312
passport.use(new Strategy({
14-
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
15-
secretOrKey: process.env.JWT_KEY
13+
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
14+
secretOrKey: process.env.JWT_KEY
1615
}, async ({ id }, done) => {
17-
try {
18-
const user = await new User().load(id)
16+
try {
17+
const user = await new User().load(id)
1918

20-
return done(null, user)
21-
} catch(error) {
22-
done(error)
23-
}
19+
return done(null, user)
20+
} catch (error) {
21+
done(error)
22+
}
2423
}))
2524

2625
const BAN_SAFE_ENDPOINTS = [
27-
'GET /user/me'
26+
'GET /user/me'
2827
]
2928

3029
const fetchEndpoint = (req: Request) => `${req.method} ${req.baseUrl}${req.route.path}`
3130

32-
const fetchUser = async (req: Request, res: Response, next: NextFunction) => new Promise<User>(async (resolve, reject) => {
33-
try {
34-
if(process.env.AUTH_BASE_URL) {
35-
const { authorization } = req.headers,
36-
token = authorization.split(' ')[1],
37-
{ data } = await axios.post(process.env.AUTH_BASE_URL, { token }),
38-
user = new User(data)
39-
40-
resolve(user)
41-
} else {
42-
passport.authenticate('jwt', { session: false }, async (err, user: User) => {
43-
if(err) return res.sendStatus(500)
44-
if(!user) return res.sendStatus(401)
45-
46-
resolve(user)
47-
})(req, res, next)
48-
}
49-
} catch(error) {
50-
reject(error)
51-
}
31+
const fetchUser = async (
32+
req: Request,
33+
res: Response,
34+
next: NextFunction
35+
) => new Promise<User>(async (resolve, reject) => {
36+
try {
37+
if (process.env.AUTH_BASE_URL) {
38+
const { authorization } = req.headers,
39+
token = authorization.split(' ')[1],
40+
{ data } = await axios.post(process.env.AUTH_BASE_URL, { token }),
41+
user = new User(data)
42+
43+
resolve(user)
44+
} else
45+
passport.authenticate('jwt', { session: false }, async (err, user: User) => {
46+
if (err) return res.sendStatus(500)
47+
if (!user) return handleError(UserNoAuth, res)
48+
49+
resolve(user)
50+
})(req, res, next)
51+
} catch (error) {
52+
reject(error)
53+
}
5254
})
5355

5456
export const authenticate = async (req: Request, res: Response, next: NextFunction) => {
55-
try {
56-
const user = await fetchUser(req, res, next),
57-
endpoint = fetchEndpoint(req),
58-
ban = await user.fetchBan()
59-
60-
if(ban && BAN_SAFE_ENDPOINTS.indexOf(endpoint) > -1)
61-
return handleError('UserBanned', res)
57+
try {
58+
const user = await fetchUser(req, res, next),
59+
endpoint = fetchEndpoint(req),
60+
ban = await user.fetchBan()
61+
62+
if (ban && BAN_SAFE_ENDPOINTS.indexOf(endpoint) > -1)
63+
return handleError(UserBanned, res)
6264

63-
if(req.baseUrl === '/admin' && user.roles.indexOf('admin') === -1)
64-
return handleError(UserNoAuth, res)
65+
if (req.baseUrl === '/admin' && user.roles.indexOf('admin') === -1)
66+
return handleError(UserNoAuth, res)
6567

66-
req.user = user
68+
req.user = user
6769

68-
next()
69-
} catch(error) {
70-
handleError(error, res)
71-
}
70+
next()
71+
} catch (error) {
72+
handleError(error, res)
73+
}
7274
}
7375

7476
export default passport

src/config/redis.config.ts

+27-27
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
1-
import { URL } from 'url'
21
import Redis from 'ioredis'
2+
import { URL } from 'url'
33

4-
interface Sentinel {
5-
host: string
6-
port: number
4+
interface ISentinel {
5+
host: string
6+
port: number
77
}
88

99
const parseSentinels = (sentinels: string) =>
10-
sentinels.split(',').map(uri => ({
11-
host: uri.split(':')[1].replace('//', ''),
12-
port: parseInt(uri.split(':')[2])
13-
} as Sentinel)), // Parse sentinels from process env
14-
getOptions = () => { // Get Options Method
15-
if(!process.env.REDIS_URI && !process.env.REDIS_SENTINELS)
16-
throw 'No value was found for REDIS_URI or REDIS_SENTINELS - make sure .env is setup correctly!'
17-
18-
if(process.env.REDIS_SENTINELS)
19-
return {
20-
sentinels: parseSentinels(process.env.REDIS_SENTINELS),
21-
name: 'mymaster'
22-
} as Redis.RedisOptions
10+
sentinels.split(',').map(uri => ({
11+
host: uri.split(':')[1].replace('//', ''),
12+
port: parseInt(uri.split(':')[2])
13+
} as ISentinel)), // Parse sentinels from process env
14+
getOptions = () => { // Get Options Method
15+
if (!process.env.REDIS_URI && !process.env.REDIS_SENTINELS)
16+
throw new Error('No value was found for REDIS_URI or REDIS_SENTINELS - make sure .env is setup correctly!')
17+
18+
if (process.env.REDIS_SENTINELS)
19+
return {
20+
sentinels: parseSentinels(process.env.REDIS_SENTINELS),
21+
name: 'mymaster'
22+
} as Redis.RedisOptions
2323

24-
if(process.env.REDIS_URI) {
25-
const uri = new URL(process.env.REDIS_URI)
24+
if (process.env.REDIS_URI) {
25+
const uri = new URL(process.env.REDIS_URI)
2626

27-
return {
28-
host: uri.hostname || 'localhost',
29-
port: parseInt(uri.port) || 6379,
30-
db: parseInt(uri.pathname) || 0,
31-
password: uri.password ? decodeURIComponent(uri.password) : null
32-
} as Redis.RedisOptions
33-
}
34-
}
27+
return {
28+
host: uri.hostname || 'localhost',
29+
port: parseInt(uri.port) || 6379,
30+
db: parseInt(uri.pathname) || 0,
31+
password: uri.password ? decodeURIComponent(uri.password) : null
32+
} as Redis.RedisOptions
33+
}
34+
}
3535

3636
export const createPubSubClient = () => new Redis(getOptions())
3737

0 commit comments

Comments
 (0)