-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.js
124 lines (92 loc) · 3.82 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//@ts-check
import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import Fastify from 'fastify'
import './types.js'
import { makeGithubRouteHandler } from './github.js'
import { makeGitlabRouteHandler } from './gitlab.js'
import { htmlTemplate, allowlist } from './tools.js'
import { decryptOauthServicesContent } from './oauthServicesDecrypt.js'
const NO_DECRYPT_FLAG = '--no-decrypt-config'
let decryptConfig = true
if(process.argv.includes(NO_DECRYPT_FLAG)){
decryptConfig = false
console.log('Server starting without configuration')
}
if(decryptConfig && !process.env.OAUTH_SERVICES_DECRYPTION_KEY){
console.error(`Il manque la variable d'environnement OAUTH_SERVICES_DECRYPTION_KEY.`)
process.exit(1);
}
if(!process.env.TOCTOCTOC_ORIGIN){
console.error(`Il manque la variable d'environnement "TOCTOCTOC_ORIGIN".`)
process.exit(1);
}
const toctoctocOrigin = process.env.TOCTOCTOC_ORIGIN
const ENCRYPTED_OAUTH_SERVICES_FILE = './oauth-services.json.encrypted';
/** @type {import('./types.js').GithubOauthServiceConfiguration | undefined} */
let githubConfig;
/** @type {import('./types.js').GitlabOauthServiceConfiguration[] | undefined} */
let gitlabConfigs;
if(decryptConfig){
const encryptedOauthServicesConfigContent = await readFile(resolve(ENCRYPTED_OAUTH_SERVICES_FILE), { encoding: 'utf8' });
const oauthServicesConfigContent = await decryptOauthServicesContent(
encryptedOauthServicesConfigContent,
// @ts-ignore
process.env.OAUTH_SERVICES_DECRYPTION_KEY
)
console.log('Oauth services config (after decryption): ', oauthServicesConfigContent)
/** @type {import('./types.js').ToctoctocOauthServicesConfiguration} */
const oauthServicesConfig = JSON.parse(oauthServicesConfigContent)
// this will throw if the config is not proper JSON. This is intentional
const {github, gitlab} = oauthServicesConfig;
githubConfig = github;
gitlabConfigs = gitlab;
if(!githubConfig && !gitlabConfigs){
console.error('Missing github or gitlab configuration')
process.exit(1)
}
}
const port = process.env.PORT || 4000
const host = process.env.HOST || 'localhost'
const server = Fastify()
server.get('/' , (req, res) => {
res.header('Content-Type', 'text/html')
res.send(htmlTemplate(`
<h1>Serveur toctoctoc</h1>
<p>Le serveur toctoctoc est disponible</p>
<p>Tu peux créer un bouton "login with github/gitlab" où le <code>redirect_uri</code> contient un
paramètre <code>destination</code> vers l'un des domaines suivants :
<ul>
${[...allowlist].map(hostname => `<li>${hostname}</li>`).join('')}
</ul>
</p>
<p>Pour chiffrer le fichier de config, <a href="/oauth-services-config">c'est par ici</a></p>
`))
})
const oauth_services_config_html_content = await readFile(resolve('./oauth-services-config.html'), { encoding: 'utf8' })
const oauthServicesDecrypt_js_content = await readFile(resolve('./oauthServicesDecrypt.js'), { encoding: 'utf8' })
server.get('/oauth-services-config' , async (req, res) => {
res.header('Content-Type', 'text/html')
res.send(oauth_services_config_html_content)
})
server.get('/oauthServicesDecrypt.js' , async (req, res) => {
res.header('Content-Type', 'text/javascript')
res.send(oauthServicesDecrypt_js_content)
})
if(githubConfig){
server.get("/github-callback", makeGithubRouteHandler(githubConfig))
}
if(Array.isArray(gitlabConfigs)){
for(const gitlabConfig of gitlabConfigs){
const {origin} = gitlabConfig
server.get(
`/gitlab-callback/${origin}/`, makeGitlabRouteHandler(gitlabConfig),
)
}
}
// @ts-ignore
server.listen({ port, host }, (err, address) => {
console.log(`Server is listening on http://${host}:${port}`)
})
process.on('uncaughtException', e => console.error('uncaughtException', e))
process.on('unhandledRejection', e => console.error('unhandledRejection', e))