Skip to content

Commit

Permalink
Add action to download forms from google drive
Browse files Browse the repository at this point in the history
Closes #3
  • Loading branch information
alxndrsn committed Nov 10, 2017
1 parent 672a2bc commit 8fb9fc9
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 6 deletions.
129 changes: 124 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "medic-conf",
"version": "1.7.8",
"version": "1.8.0",
"description": "Configure Medic Mobile deployments",
"main": "index.js",
"scripts": {
Expand All @@ -27,6 +27,7 @@
"dependencies": {
"canonical-json": "0.0.4",
"csv-parse": "^1.2.4",
"googleapis": "^22.2.0",
"mkdirp": "^0.5.1",
"pouchdb-adapter-http": "^6.3.4",
"pouchdb-core": "^6.3.4",
Expand Down
1 change: 1 addition & 0 deletions src/cli/supported-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = [
'convert-contact-forms',
'csv-to-docs',
'delete-all-forms',
'fetch-forms-from-google-drive',
'initialise-project-layout',
'upload-app-forms',
'upload-app-settings',
Expand Down
49 changes: 49 additions & 0 deletions src/fn/fetch-forms-from-google-drive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const fs = require('../lib/sync-fs');
const google = require('googleapis');
const googleAuth = require('../lib/google-auth');
const info = require('../lib/log').info;

module.exports = projectDir => {
return googleAuth()
.then(auth => {
const drive = google.drive({
version: 'v3',
auth: auth,
});

const forms = fs.readJson(`${projectDir}/forms-on-google-drive.json`);

return Object.keys(forms)
.reduce(fetchForm, Promise.resolve());

function fetchForm(promiseChain, localName) {
return promiseChain
.then(() => new Promise((resolve, reject) => {
const remoteName = forms[localName];

const fetchOpts = {
auth: auth,
fileId: forms[localName],
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
};

const formDir = 'forms';
fs.mkdir(formDir);
const target = `${formDir}/${localName}`;

info(`Exporting ${remoteName} from google drive to ${target}…`);

drive.files.export(fetchOpts, (err, buffer) => {
if(err) return reject(err);
try {
fs.writeBinary(target, buffer);
info(`Successfully wrote ${target}.`);
resolve();
} catch(e) {
reject(e);
}
});
}));
}
});
};
65 changes: 65 additions & 0 deletions src/lib/google-auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const child_process = require('child_process');
const fs = require('../lib/sync-fs');
const google = require('googleapis');
const info = require('../lib/log').info;
const readline = require('readline-sync');
const warn = require('../lib/log').warn;

const SECRETS_FILE = './.gdrive.secrets.json';

module.exports = () => {
const client = oauthClient();

const authUrl = client.generateAuthUrl({
scope: 'https://www.googleapis.com/auth/drive.readonly'
});

openBrowserAt(authUrl);
const accessCode = readline.question(`Enter access code from browser: `);

return new Promise((resolve, reject) => {
client.getToken(accessCode, function (err, tokens) {
if(err) return reject(err);

client.setCredentials(tokens);

resolve(client);
});
});
};

function oauthClient() {
let configFile;
try {
configFile = fs.readJson(SECRETS_FILE);
} catch(e) {
info('Failed to load google drive secrets from file.', e);
configFile = {};
}

const clientId = process.env.GOOGLE_CLIENT_ID || configFile.client_id;
const clientSecret = process.env.GOOGLE_CLIENT_SECRET || configFile.client_secret;
const redirectUri = process.env.GOOGLE_REDIRECT_URI ||
(configFile.redirect_uris && configFile.redirect_uris[0]);

const missingConfig =
checkRequred(clientId, 'client_id', 'GOOGLE_CLIENT_ID') |
checkRequred(clientSecret, 'client_secret', 'GOOGLE_CLIENT_SECRET') |
checkRequred(redirectUri, 'redirect_uris', 'GOOGLE_REDIRECT_URI');

if(missingConfig) throw new Error('Missing required config for google drive access. Please check warnings.');

return new google.auth.OAuth2(clientId, clientSecret, redirectUri);
}

function openBrowserAt(url) {
info(`Should open browser at: ${url}`);
child_process.exec(`open "${url}" || firefox "${url}" || chromium-browser "${url}" || chrome "${url}"`);
}

function checkRequred(value, jsonKey, envVar) {
if(value) return;

warn(`Missing .${jsonKey} in ${SECRETS_FILE} or env var ${envVar}!`);
return true;
}
1 change: 1 addition & 0 deletions test/bin/shell-completion.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('shell-completion', () => {
'convert-contact-forms',
'csv-to-docs',
'delete-all-forms',
'fetch-forms-from-google-drive',
'initialise-project-layout',
'upload-app-forms',
'upload-app-settings',
Expand Down

0 comments on commit 8fb9fc9

Please sign in to comment.