Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit 1c61add

Browse files
RFE: remove pusher.com dependency
1 parent e852d00 commit 1c61add

28 files changed

+7855
-12
lines changed

Diff for: .env.example

+4
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ GITHUB_CLIENT_ID=redacted
1515
GITHUB_CLIENT_SECRET=redacted
1616
GITHUB_OAUTH_TOKEN=redacted
1717
HASH_SECRET=redacted
18+
COTURN_USERNAME=redacted
19+
COTURN_PASSWORD=redacted
20+
ACTIVE_PUB_SUB_GATEWAY=pusher
21+
ACTIVE_ICE_SERVER_PROVIDER=twilio

Diff for: .env.local.example

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
DATABASE_URL=postgres://teletype:password@localhost:5432/teletype-server-dev
2+
TEST_DATABASE_URL=postgres://teletype:password@localhost:5433/teletype-server-test
3+
PORT=3000
4+
PUSHER_APP_ID=348824
5+
PUSHER_KEY=redacted
6+
PUSHER_SECRET=redacted
7+
PUSHER_CLUSTER=mt1
8+
TWILIO_ACCOUNT=redacted
9+
TWILIO_AUTH_TOKEN=redacted
10+
NEW_RELIC_ENABLED=false
11+
NEW_RELIC_APP_NAME=atom-teletype-development
12+
NEW_RELIC_LICENSE_KEY=redacted
13+
GITHUB_API_URL=https://api.github.com
14+
GITHUB_CLIENT_ID=redacted
15+
GITHUB_CLIENT_SECRET=redacted
16+
GITHUB_OAUTH_TOKEN=redacted
17+
HASH_SECRET=redacted
18+
COTURN_USERNAME=teletype
19+
COTURN_PASSWORD=password
20+
ACTIVE_PUB_SUB_GATEWAY=socketcluster
21+
ACTIVE_ICE_SERVER_PROVIDER=coturn

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
.env
33
newrelic_agent.log
4+
redis

Diff for: README.md

+34
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,40 @@ To run teletype-server locally, you'll first need to have:
4343
npm test
4444
```
4545
46+
### Running locally using docker
47+
48+
This allows to deploy teletype-server to a full private solution.
49+
Coturn is used instead of Twilio and SocketCluster instead of Pusher.
50+
51+
1. Clone and bootstrap
52+
53+
```
54+
git clone https://github.com/atom/teletype-server.git
55+
cd teletype-server
56+
cp .env.local.example .env
57+
docker-compose build
58+
docker-compose up -d
59+
createdb teletype-server-dev
60+
createdb teletype-server-test
61+
npm install
62+
npm run migrate up
63+
```
64+
65+
2. Copy the client ID and client secret for your OAuth app on github.com, and set those values in your `.env` file
66+
67+
3. Start the server
68+
69+
```
70+
./script/server
71+
```
72+
73+
4. Run the tests
74+
75+
```
76+
npm test
77+
```
78+
79+
4680
## Deploying
4781
4882
Atom core team members can use [this guide](./docs/deployment.md) to test pull requests and deploy changes to production.

Diff for: app.json

+12
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@
4040
},
4141
"TWILIO_AUTH_TOKEN": {
4242
"required": true
43+
},
44+
"COTURN_USERNAME": {
45+
"required": true
46+
},
47+
"COTURN_PASSWORD": {
48+
"required": true
49+
},
50+
"ACTIVE_PUB_SUB_GATEWAY": {
51+
"required": true
52+
},
53+
"ACTIVE_ICE_SERVER_PROVIDER": {
54+
"required": true
4355
}
4456
},
4557
"formation": {},

Diff for: coturn/Dockerfile

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM ubuntu:18.04
2+
3+
RUN apt-get update
4+
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y coturn
5+
6+
ADD turnserver.conf /etc/turnserver.conf
7+
8+
EXPOSE 3478
9+
10+
CMD exec /bin/bash -c "trap : TERM INT; /usr/bin/turnserver -c /etc/turnserver.conf -v"

Diff for: coturn/turnserver.conf

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
no-stun
2+
verbose
3+
fingerprint
4+
lt-cred-mech
5+
user=teletype:password
6+
realm=teletype

Diff for: docker-compose.yml

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
version: '3'
2+
3+
services:
4+
database:
5+
image: postgres
6+
ports:
7+
- 5432:5432
8+
volumes:
9+
- ./database:/var/lib/postgresql/data
10+
restart: always
11+
environment:
12+
POSTGRES_USER: teletype
13+
POSTGRES_PASSWORD: password
14+
POSTGRES_DB: teletype-server-dev
15+
networks:
16+
teletype:
17+
18+
test-database:
19+
image: postgres
20+
ports:
21+
- 5433:5432
22+
volumes:
23+
- ./test-database:/var/lib/postgresql/data
24+
restart: always
25+
environment:
26+
POSTGRES_USER: teletype
27+
POSTGRES_PASSWORD: password
28+
POSTGRES_DB: teletype-server-test
29+
networks:
30+
teletype:
31+
32+
coturn:
33+
image: coturn
34+
build:
35+
context: coturn
36+
dockerfile: Dockerfile
37+
ports:
38+
- 3478:3478
39+
restart: always
40+
networks:
41+
teletype:
42+
aliases:
43+
- coturn
44+
45+
socketcluster:
46+
image: socketcluster
47+
build:
48+
context: socketcluster
49+
dockerfile: Dockerfile
50+
ports:
51+
- 8000:8000
52+
restart: always
53+
networks:
54+
teletype:
55+
aliases:
56+
- socketcluster
57+
58+
networks:
59+
teletype:

Diff for: index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ async function startServer (id) {
2525
githubOauthToken: process.env.GITHUB_OAUTH_TOKEN,
2626
boomtownSecret: process.env.BOOMTOWN_SECRET,
2727
hashSecret: process.env.HASH_SECRET,
28-
port: process.env.PORT || 3000
28+
port: process.env.PORT || 3000,
29+
coturnUsername: process.env.COTURN_USERNAME,
30+
coturnPassword: process.env.COTURN_PASSWORD,
31+
activePubSubGateway: process.env.ACTIVE_PUB_SUB_GATEWAY,
32+
activeIceServerProvider: process.env.ACTIVE_ICE_SERVER_PROVIDER
2933
})
3034
await server.start()
3135
console.log(`Worker ${id} (pid: ${process.pid}): listening on port ${server.port}`)

Diff for: lib/coturn-ice-server-provider.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module.exports =
2+
class CoturnIceServerProvider {
3+
constructor ({coturnUsername, coturnPassword}) {
4+
this.coturnUsername = coturnUsername
5+
this.coturnPassword = coturnPassword
6+
}
7+
8+
async fetchICEServers () {
9+
return {ttl: 86400, servers: [
10+
{
11+
'urls': 'stun:stun.l.google.com:19302'
12+
},
13+
{
14+
'urls': 'turn:localhost:3478?transport=udp',
15+
'username': this.coturnUsername,
16+
'credential': this.coturnPassword
17+
},
18+
{
19+
'urls': 'turn:localhost:3478?transport=tcp',
20+
'username': this.coturnUsername,
21+
'credential': this.coturnPassword
22+
}
23+
]
24+
}
25+
26+
}
27+
}

Diff for: lib/server.js

+45-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ const pgp = require('pg-promise')()
33
const request = require('request-promise-native')
44
const IdentityProvider = require('./identity-provider')
55
const ModelLayer = require('./model-layer')
6-
const PubSubGateway = require('./pusher-pub-sub-gateway')
6+
const PusherPubSubGateway = require('./pusher-pub-sub-gateway')
7+
const SocketClusterPubSubGateway = require('./socketcluster-pub-sub-gateway')
8+
const TwilioIceServerProvider = require('./twilio-ice-server-provider')
9+
const CoturnIceServerProvider = require('./coturn-ice-server-provider')
710

811
module.exports =
912
class Server {
@@ -21,7 +24,11 @@ class Server {
2124
this.githubOauthToken = options.githubOauthToken
2225
this.boomtownSecret = options.boomtownSecret
2326
this.hashSecret = options.hashSecret
24-
this.port = options.port
27+
this.port = options.port,
28+
this.coturnUsername = options.coturnUsername,
29+
this.coturnPassword = options.coturnPassword,
30+
this.activePubSubGateway = options.activePubSubGateway,
31+
this.activeIceServerProvider = options.activeIceServerProvider
2532
}
2633

2734
async start () {
@@ -33,23 +40,50 @@ class Server {
3340
clientSecret: this.githubClientSecret,
3441
oauthToken: this.githubOauthToken
3542
})
36-
const pubSubGateway = new PubSubGateway({
37-
appId: this.pusherAppId,
38-
key: this.pusherKey,
39-
secret: this.pusherSecret,
40-
cluster: this.pusherCluster
41-
})
4243

43-
const twilioICEServerURL = `https://${this.twilioAccount}:${this.twilioAuthToken}@api.twilio.com/2010-04-01/Accounts/${this.twilioAccount}/Tokens.json`
44+
var pubSubGateway
45+
46+
switch(this.activePubSubGateway) {
47+
case 'socketcluster':
48+
pubSubGateway = new SocketClusterPubSubGateway({})
49+
break;
50+
51+
case 'pusher':
52+
default:
53+
pubSubGateway = new PusherPubSubGateway({
54+
appId: this.pusherAppId,
55+
key: this.pusherKey,
56+
secret: this.pusherSecret,
57+
cluster: this.pusherCluster
58+
})
59+
break;
60+
}
61+
62+
var iceServerProvider
63+
switch(this.activeIceServerProvider) {
64+
case 'coturn':
65+
iceServerProvider = new CoturnIceServerProvider({
66+
coturnUsername: this.coturnUsername,
67+
coturnPassword: this.coturnPassword
68+
})
69+
break;
70+
71+
case 'twilio':
72+
default:
73+
iceServerProvider = new TwilioIceServerProvider({
74+
twilioAccount: this.twilioAccount,
75+
twilioAuthToken: this.twilioAuthToken
76+
})
77+
break;
78+
}
4479

4580
const controllerLayer = buildControllerLayer({
4681
modelLayer,
4782
pubSubGateway,
4883
identityProvider,
4984
boomtownSecret: this.boomtownSecret,
5085
fetchICEServers: async () => {
51-
const response = JSON.parse(await request.post(twilioICEServerURL))
52-
return {ttl: parseInt(response.ttl), servers: response.ice_servers}
86+
iceServerProvider.fetchICEServers()
5387
}
5488
})
5589

Diff for: lib/socketcluster-pub-sub-gateway.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const socketCluster = require('socketcluster-client');
2+
3+
module.exports =
4+
class SocketClusterPubSubGateway {
5+
constructor ({appId, key, secret, cluster}) {
6+
var options = {
7+
port: 8000,
8+
autoConnect: true,
9+
autoReconnect: true
10+
};
11+
12+
this.socket = socketCluster.create(options);
13+
this.socket.on('error', function (error) {
14+
});
15+
}
16+
17+
broadcast (channelName, eventName, data) {
18+
channelName = channelName.replace(/\//g, '.')
19+
var message = {
20+
channel: `${channelName}.${eventName}`,
21+
data: data
22+
}
23+
this.socket.emit('publish', message);
24+
}
25+
26+
async isOperational () {
27+
return new Promise((resolve) => {
28+
resolve(this.socket.state == this.socket.OPEN)
29+
})
30+
}
31+
}

Diff for: lib/twilio-ice-server-provider.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports =
2+
class TwilioIceServerProvider {
3+
constructor ({twilioAccount, twilioAuthToken}) {
4+
this.twilioAccount = twilioAccount
5+
this.twilioAuthToken = twilioAuthToken
6+
}
7+
8+
async fetchICEServers () {
9+
const twilioICEServerURL = `https://${this.twilioAccount}:${this.twilioAuthToken}@api.twilio.com/2010-04-01/Accounts/${this.twilioAccount}/Tokens.json`
10+
11+
const response = JSON.parse(await request.post(twilioICEServerURL))
12+
return {ttl: parseInt(response.ttl), servers: response.ice_servers}
13+
14+
}
15+
}

0 commit comments

Comments
 (0)