aboutsummaryrefslogtreecommitdiff
path: root/src/server/apis/google/GoogleApiServerUtils.ts
diff options
context:
space:
mode:
authorAbdullah Ahmed <abdullah_ahmed@brown.edu>2019-08-28 21:06:02 -0400
committerAbdullah Ahmed <abdullah_ahmed@brown.edu>2019-08-28 21:06:02 -0400
commit38c8b841dcf3f42b96b3d93e7bcc2fc6c9495613 (patch)
tree9b0773f05ff9db5b67b47da398f2c16c2511f0bb /src/server/apis/google/GoogleApiServerUtils.ts
parente03a1b2cc90e0fdb7789f4826e482e9040aa7075 (diff)
parent4b7672c75fe5cdf6afe534e67213917b24980c3e (diff)
merged, docview still weird
Diffstat (limited to 'src/server/apis/google/GoogleApiServerUtils.ts')
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
new file mode 100644
index 000000000..8785cd974
--- /dev/null
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -0,0 +1,130 @@
+import { google, docs_v1, slides_v1 } from "googleapis";
+import { createInterface } from "readline";
+import { readFile, writeFile } from "fs";
+import { OAuth2Client } from "google-auth-library";
+import { Opt } from "../../../new_fields/Doc";
+import { GlobalOptions } from "googleapis-common";
+import { GaxiosResponse } from "gaxios";
+
+/**
+ * Server side authentication for Google Api queries.
+ */
+export namespace GoogleApiServerUtils {
+
+ // If modifying these scopes, delete token.json.
+ const prefix = 'https://www.googleapis.com/auth/';
+ const SCOPES = [
+ 'documents.readonly',
+ 'documents',
+ 'presentations',
+ 'presentations.readonly',
+ 'drive',
+ 'drive.file',
+ ];
+
+ export const parseBuffer = (data: Buffer) => JSON.parse(data.toString());
+
+ export enum Service {
+ Documents = "Documents",
+ Slides = "Slides"
+ }
+
+
+ export interface CredentialPaths {
+ credentials: string;
+ token: string;
+ }
+
+ export type ApiResponse = Promise<GaxiosResponse>;
+ export type ApiRouter = (endpoint: Endpoint, paramters: any) => ApiResponse;
+ export type ApiHandler = (parameters: any) => ApiResponse;
+ export type Action = "create" | "retrieve" | "update";
+
+ export type Endpoint = { get: ApiHandler, create: ApiHandler, batchUpdate: ApiHandler };
+ export type EndpointParameters = GlobalOptions & { version: "v1" };
+
+ export const GetEndpoint = async (sector: string, paths: CredentialPaths) => {
+ return new Promise<Opt<Endpoint>>((resolve, reject) => {
+ readFile(paths.credentials, (err, credentials) => {
+ if (err) {
+ reject(err);
+ return console.log('Error loading client secret file:', err);
+ }
+ return authorize(parseBuffer(credentials), paths.token).then(auth => {
+ let routed: Opt<Endpoint>;
+ let parameters: EndpointParameters = { auth, version: "v1" };
+ switch (sector) {
+ case Service.Documents:
+ routed = google.docs(parameters).documents;
+ break;
+ case Service.Slides:
+ routed = google.slides(parameters).presentations;
+ break;
+ }
+ resolve(routed);
+ });
+ });
+ });
+ };
+
+
+ /**
+ * Create an OAuth2 client with the given credentials, and returns the promise resolving to the authenticated client
+ * @param {Object} credentials The authorization client credentials.
+ */
+ export function authorize(credentials: any, token_path: string): Promise<OAuth2Client> {
+ const { client_secret, client_id, redirect_uris } = credentials.installed;
+ const oAuth2Client = new google.auth.OAuth2(
+ client_id, client_secret, redirect_uris[0]);
+
+ return new Promise<OAuth2Client>((resolve, reject) => {
+ readFile(token_path, (err, token) => {
+ // Check if we have previously stored a token.
+ if (err) {
+ return getNewToken(oAuth2Client, token_path).then(resolve, reject);
+ }
+ oAuth2Client.setCredentials(parseBuffer(token));
+ resolve(oAuth2Client);
+ });
+ });
+ }
+
+ /**
+ * Get and store new token after prompting for user authorization, and then
+ * execute the given callback with the authorized OAuth2 client.
+ * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
+ * @param {getEventsCallback} callback The callback for the authorized client.
+ */
+ function getNewToken(oAuth2Client: OAuth2Client, token_path: string) {
+ return new Promise<OAuth2Client>((resolve, reject) => {
+ const authUrl = oAuth2Client.generateAuthUrl({
+ access_type: 'offline',
+ scope: SCOPES.map(relative => prefix + relative),
+ });
+ console.log('Authorize this app by visiting this url:', authUrl);
+ const rl = createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ });
+ rl.question('Enter the code from that page here: ', (code) => {
+ rl.close();
+ oAuth2Client.getToken(code, (err, token) => {
+ if (err || !token) {
+ reject(err);
+ return console.error('Error retrieving access token', err);
+ }
+ oAuth2Client.setCredentials(token);
+ // Store the token to disk for later program executions
+ writeFile(token_path, JSON.stringify(token), (err) => {
+ if (err) {
+ console.error(err);
+ reject(err);
+ }
+ console.log('Token stored to', token_path);
+ });
+ resolve(oAuth2Client);
+ });
+ });
+ });
+ }
+} \ No newline at end of file