1 | const fs = require('fs');
|
2 | const merge = require('lodash.merge');
|
3 | const stripIndent = require('common-tags/lib/stripIndent');
|
4 | const utils = require('../server/helpers/utils');
|
5 | const logger = require('../server/logger');
|
6 | const crypto = require('crypto');
|
7 |
|
8 | const { version } = require('../../package.json');
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | exports.getCompanionOptions = (options = {}) => {
|
16 | return merge({}, getConfigFromEnv(), getConfigFromFile(), options);
|
17 | };
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | const getConfigFromEnv = () => {
|
24 | const uploadUrls = process.env.COMPANION_UPLOAD_URLS;
|
25 | const domains = process.env.COMPANION_DOMAINS || process.env.COMPANION_DOMAIN || null;
|
26 | const validHosts = domains ? domains.split(',') : [];
|
27 | return {
|
28 | providerOptions: {
|
29 | drive: {
|
30 | key: process.env.COMPANION_GOOGLE_KEY,
|
31 | secret: getSecret('COMPANION_GOOGLE_SECRET')
|
32 | },
|
33 | dropbox: {
|
34 | key: process.env.COMPANION_DROPBOX_KEY,
|
35 | secret: getSecret('COMPANION_DROPBOX_SECRET')
|
36 | },
|
37 | box: {
|
38 | key: process.env.COMPANION_BOX_KEY,
|
39 | secret: getSecret('COMPANION_BOX_SECRET')
|
40 | },
|
41 | instagram: {
|
42 | key: process.env.COMPANION_INSTAGRAM_KEY,
|
43 | secret: getSecret('COMPANION_INSTAGRAM_SECRET')
|
44 | },
|
45 | facebook: {
|
46 | key: process.env.COMPANION_FACEBOOK_KEY,
|
47 | secret: getSecret('COMPANION_FACEBOOK_SECRET')
|
48 | },
|
49 | onedrive: {
|
50 | key: process.env.COMPANION_ONEDRIVE_KEY,
|
51 | secret: getSecret('COMPANION_ONEDRIVE_SECRET')
|
52 | },
|
53 | zoom: {
|
54 | key: process.env.COMPANION_ZOOM_KEY,
|
55 | secret: getSecret('COMPANION_ZOOM_SECRET'),
|
56 | verificationToken: getSecret('COMPANION_ZOOM_VERIFICATION_TOKEN')
|
57 | },
|
58 | searchProviders: {
|
59 | unsplash: {
|
60 | key: process.env.COMPANION_UNSPLASH_KEY
|
61 | }
|
62 | },
|
63 | s3: {
|
64 | key: process.env.COMPANION_AWS_KEY,
|
65 | secret: getSecret('COMPANION_AWS_SECRET'),
|
66 | bucket: process.env.COMPANION_AWS_BUCKET,
|
67 | endpoint: process.env.COMPANION_AWS_ENDPOINT,
|
68 | region: process.env.COMPANION_AWS_REGION,
|
69 | useAccelerateEndpoint: process.env.COMPANION_AWS_USE_ACCELERATE_ENDPOINT === 'true',
|
70 | expires: parseInt(process.env.COMPANION_AWS_EXPIRES || '300', 10),
|
71 | acl: process.env.COMPANION_AWS_ACL || 'public-read'
|
72 | }
|
73 | },
|
74 | server: {
|
75 | host: process.env.COMPANION_DOMAIN,
|
76 | protocol: process.env.COMPANION_PROTOCOL,
|
77 | path: process.env.COMPANION_PATH,
|
78 | implicitPath: process.env.COMPANION_IMPLICIT_PATH,
|
79 | oauthDomain: process.env.COMPANION_OAUTH_DOMAIN,
|
80 | validHosts: validHosts
|
81 | },
|
82 | filePath: process.env.COMPANION_DATADIR,
|
83 | redisUrl: process.env.COMPANION_REDIS_URL,
|
84 |
|
85 |
|
86 | redisOptions: {},
|
87 | sendSelfEndpoint: process.env.COMPANION_SELF_ENDPOINT,
|
88 | uploadUrls: uploadUrls ? uploadUrls.split(',') : null,
|
89 | secret: getSecret('COMPANION_SECRET') || generateSecret(),
|
90 | debug: process.env.NODE_ENV && process.env.NODE_ENV !== 'production',
|
91 |
|
92 |
|
93 | cookieDomain: process.env.COMPANION_COOKIE_DOMAIN,
|
94 | multipleInstances: true
|
95 | };
|
96 | };
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | const getSecret = (baseEnvVar) => {
|
106 | const secretFile = process.env[`${baseEnvVar}_FILE`];
|
107 | return secretFile
|
108 | ? fs.readFileSync(secretFile).toString()
|
109 | : process.env[baseEnvVar];
|
110 | };
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 | const generateSecret = () => {
|
117 | logger.warn('auto-generating server secret because none was specified', 'startup.secret');
|
118 | return crypto.randomBytes(64).toString('hex');
|
119 | };
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | const getConfigFromFile = () => {
|
126 | const path = getConfigPath();
|
127 | if (!path)
|
128 | return {};
|
129 | const rawdata = fs.readFileSync(getConfigPath());
|
130 |
|
131 | return JSON.parse(rawdata);
|
132 | };
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 | const getConfigPath = () => {
|
139 | let configPath;
|
140 | for (let i = process.argv.length - 1; i >= 0; i--) {
|
141 | const isConfigFlag = process.argv[i] === '-c' || process.argv[i] === '--config';
|
142 | const flagHasValue = i + 1 <= process.argv.length;
|
143 | if (isConfigFlag && flagHasValue) {
|
144 | configPath = process.argv[i + 1];
|
145 | break;
|
146 | }
|
147 | }
|
148 | return configPath;
|
149 | };
|
150 |
|
151 |
|
152 |
|
153 |
|
154 | exports.hasProtocol = (url) => {
|
155 | return url.startsWith('http://') || url.startsWith('https://');
|
156 | };
|
157 | exports.buildHelpfulStartupMessage = (companionOptions) => {
|
158 | const buildURL = utils.getURLBuilder(companionOptions);
|
159 | const callbackURLs = [];
|
160 | Object.keys(companionOptions.providerOptions).forEach((providerName) => {
|
161 |
|
162 | if (providerName === 's3') {
|
163 | return;
|
164 | }
|
165 | callbackURLs.push(buildURL(`/connect/${providerName}/callback`, true));
|
166 | });
|
167 | return stripIndent `
|
168 | Welcome to Companion v${version}
|
169 | ===================================
|
170 |
|
171 | Congratulations on setting up Companion! Thanks for joining our cause, you have taken
|
172 | the first step towards the future of file uploading! We
|
173 | hope you are as excited about this as we are!
|
174 |
|
175 | While you did an awesome job on getting Companion running, this is just the welcome
|
176 | message, so let's talk about the places that really matter:
|
177 |
|
178 | - Be sure to add ${callbackURLs.join(', ')} as your Oauth redirect uris on their corresponding developer interfaces.
|
179 | - The URL ${buildURL('/metrics', true)} is available for statistics to keep Companion running smoothly
|
180 | - https://github.com/transloadit/uppy/issues - report your bugs here
|
181 |
|
182 | So quit lollygagging, start uploading and experience the future!
|
183 | `;
|
184 | };
|