aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-09-26 22:17:15 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-09-26 22:17:15 -0400
commit20540a35be82c34cc3962de4f957d1aa43f8a2b0 (patch)
treea4d67686a1d323bab947fcf3a6d6c2575b576c3e /src
parente95387732e1fbff49ec035c3bec4b03324d814c8 (diff)
finally transferred google credential management to database
Diffstat (limited to 'src')
-rw-r--r--src/client/Network.ts46
-rw-r--r--src/client/apis/google_docs/GooglePhotosClientUtils.ts17
-rw-r--r--src/client/documents/Documents.ts22
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx5
-rw-r--r--src/client/views/nodes/DocumentView.tsx7
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts27
-rw-r--r--src/server/database.ts32
-rw-r--r--src/server/index.ts6
8 files changed, 93 insertions, 69 deletions
diff --git a/src/client/Network.ts b/src/client/Network.ts
index cb46105f8..75ccb5e99 100644
--- a/src/client/Network.ts
+++ b/src/client/Network.ts
@@ -2,24 +2,32 @@ import { Utils } from "../Utils";
import { CurrentUserUtils } from "../server/authentication/models/current_user_utils";
import requestPromise = require('request-promise');
-export async function PostToServer(relativeRoute: string, body?: any) {
- let options = {
- uri: Utils.prepend(relativeRoute),
- method: "POST",
- headers: { userId: CurrentUserUtils.id },
- body,
- json: true
- };
- return requestPromise.post(options);
-}
+export namespace Identified {
+
+ export async function FetchFromServer(relativeRoute: string) {
+ return (await fetch(relativeRoute, { headers: { userId: CurrentUserUtils.id } })).text();
+ }
+
+ export async function PostToServer(relativeRoute: string, body?: any) {
+ let options = {
+ uri: Utils.prepend(relativeRoute),
+ method: "POST",
+ headers: { userId: CurrentUserUtils.id },
+ body,
+ json: true
+ };
+ return requestPromise.post(options);
+ }
+
+ export async function PostFormDataToServer(relativeRoute: string, formData: FormData) {
+ const parameters = {
+ method: 'POST',
+ headers: { userId: CurrentUserUtils.id },
+ body: formData,
+ };
+ const response = await fetch(relativeRoute, parameters);
+ const text = await response.json();
+ return text;
+ }
-export async function PostFormDataToServer(relativeRoute: string, formData: FormData) {
- const parameters = {
- method: 'POST',
- headers: { userId: CurrentUserUtils.id },
- body: formData,
- };
- const response = await fetch(relativeRoute, parameters);
- const text = await response.json();
- return text;
} \ No newline at end of file
diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
index b1b29210a..29cc042b6 100644
--- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts
+++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
@@ -14,11 +14,14 @@ import { NewMediaItemResult, MediaItem } from "../../../server/apis/google/Share
import { AssertionError } from "assert";
import { DocumentView } from "../../views/nodes/DocumentView";
import { DocumentManager } from "../../util/DocumentManager";
-import { PostToServer } from "../../Network";
+import { Identified } from "../../Network";
export namespace GooglePhotos {
- const endpoint = async () => new Photos(await PostToServer(RouteStore.googlePhotosAccessToken));
+ const endpoint = async () => {
+ const accessToken = await Identified.FetchFromServer(RouteStore.googlePhotosAccessToken);
+ return new Photos(accessToken);
+ };
export enum MediaType {
ALL_MEDIA = 'ALL_MEDIA',
@@ -296,7 +299,7 @@ export namespace GooglePhotos {
};
export const WriteMediaItemsToServer = async (body: { mediaItems: any[] }): Promise<UploadInformation[]> => {
- const uploads = await PostToServer(RouteStore.googlePhotosMediaDownload, body);
+ const uploads = await Identified.PostToServer(RouteStore.googlePhotosMediaDownload, body);
return uploads;
};
@@ -316,7 +319,7 @@ export namespace GooglePhotos {
album = await Create.Album(album.title);
}
const media: MediaInput[] = [];
- sources.forEach(source => {
+ for (let source of sources) {
const data = Cast(Doc.GetProto(source).data, ImageField);
if (!data) {
return;
@@ -324,11 +327,11 @@ export namespace GooglePhotos {
const url = data.url.href;
const target = Doc.MakeAlias(source);
const description = parseDescription(target, descriptionKey);
- DocumentView.makeCustomViewClicked(target, undefined);
+ await DocumentView.makeCustomViewClicked(target, undefined);
media.push({ url, description });
- });
+ }
if (media.length) {
- const uploads: NewMediaItemResult[] = await PostToServer(RouteStore.googlePhotosMediaUpload, { media, album });
+ const uploads: NewMediaItemResult[] = await Identified.PostToServer(RouteStore.googlePhotosMediaUpload, { media, album });
return uploads;
}
};
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a7a006f47..0369e89a6 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -337,16 +337,18 @@ export namespace Docs {
let extension = path.extname(target);
target = `${target.substring(0, target.length - extension.length)}_o${extension}`;
}
- requestImageSize(target)
- .then((size: any) => {
- let aspect = size.height / size.width;
- if (!inst.proto!.nativeWidth) {
- inst.proto!.nativeWidth = size.width;
- }
- inst.proto!.nativeHeight = Number(inst.proto!.nativeWidth!) * aspect;
- inst.proto!.height = NumCast(inst.proto!.width) * aspect;
- })
- .catch((err: any) => console.log(err));
+ if (target !== "http://www.cs.brown.edu/") {
+ requestImageSize(target)
+ .then((size: any) => {
+ let aspect = size.height / size.width;
+ if (!inst.proto!.nativeWidth) {
+ inst.proto!.nativeWidth = size.width;
+ }
+ inst.proto!.nativeHeight = Number(inst.proto!.nativeWidth!) * aspect;
+ inst.proto!.height = NumCast(inst.proto!.width) * aspect;
+ })
+ .catch((err: any) => console.log(err));
+ }
return inst;
}
export function PresDocument(initial: List<Doc> = new List(), options: DocumentOptions = {}) {
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index d0291aec4..de5287456 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx
@@ -21,7 +21,7 @@ import { GooglePhotos } from "../../apis/google_docs/GooglePhotosClientUtils";
import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
import "./DirectoryImportBox.scss";
import BatchedArray from "array-batcher";
-import { PostFormDataToServer } from "../../Network";
+import { Identified } from "../../Network";
const unsupported = ["text/html", "text/plain"];
interface FileResponse {
@@ -114,7 +114,7 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
formData.append(Utils.GenerateGuid(), file);
});
- const responses = await PostFormDataToServer(RouteStore.upload, formData);
+ const responses = await Identified.PostFormDataToServer(RouteStore.upload, formData);
runInAction(() => this.completed += batch.length);
return responses as FileResponse[];
});
@@ -279,7 +279,6 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
}} />
<label
htmlFor={"selector"}
- onClick={console.log}
style={{
opacity: isEditing ? 0 : 1,
pointerEvents: isEditing ? "none" : "all",
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 78fcaad27..a6d350ca2 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -295,10 +295,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument && this.props.removeDocument(this.props.Document); }
@undoBatch
- static makeNativeViewClicked = (doc: Doc): void => { swapViews(doc, "layoutNative", "layoutCustom"); }
+ static makeNativeViewClicked = async (doc: Doc): Promise<void> => swapViews(doc, "layoutNative", "layoutCustom")
- @undoBatch
static makeCustomViewClicked = async (doc: Doc, dataDoc: Opt<Doc>) => {
+ const batch = UndoManager.StartBatch("CustomViewClicked");
if (doc.layoutCustom === undefined) {
Doc.GetProto(dataDoc || doc).layoutNative = Doc.MakeTitled("layoutNative");
await swapViews(doc, "", "layoutNative");
@@ -320,8 +320,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
Doc.ApplyTemplateTo(docTemplate, doc, undefined);
Doc.GetProto(dataDoc || doc).layoutCustom = Doc.MakeTitled("layoutCustom");
} else {
- swapViews(doc, "layoutCustom", "layoutNative");
+ await swapViews(doc, "layoutCustom", "layoutNative");
}
+ batch.end();
}
@undoBatch
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
index 665dcf862..f2ce51395 100644
--- a/src/server/apis/google/GoogleApiServerUtils.ts
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -103,21 +103,21 @@ export namespace GoogleApiServerUtils {
*/
export function authorize(credentials: any, userId: string): Promise<TokenResult> {
const { client_secret, client_id, redirect_uris } = credentials.installed;
- const oAuth2Client = new google.auth.OAuth2(
- client_id, client_secret, redirect_uris[0]);
-
+ const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
return new Promise<TokenResult>((resolve, reject) => {
+ // Attempting to authorize user (${userId})
Database.Auxiliary.GoogleAuthenticationToken.Fetch(userId).then(token => {
- // Check if we have previously stored a token for this userId.
if (!token) {
+ // No token registered, so awaiting input from user
return getNewToken(oAuth2Client, userId).then(resolve, reject);
}
- let parsed: Credentials = parseBuffer(token);
- if (parsed.expiry_date! < new Date().getTime()) {
- return refreshToken(parsed, client_id, client_secret, oAuth2Client, userId).then(resolve, reject);
+ if (token.expiry_date < new Date().getTime()) {
+ // Token has expired, so submitting a request for a refreshed access token
+ return refreshToken(token, client_id, client_secret, oAuth2Client, userId).then(resolve, reject);
}
- oAuth2Client.setCredentials(parsed);
- resolve({ token: parsed, client: oAuth2Client });
+ // Authentication successful!
+ oAuth2Client.setCredentials(token);
+ resolve({ token, client: oAuth2Client });
});
});
}
@@ -134,11 +134,12 @@ export namespace GoogleApiServerUtils {
};
let url = `${refreshEndpoint}?${qs.stringify(queryParameters)}`;
request.post(url, headerParameters).then(async response => {
- let parsed = JSON.parse(response);
- credentials.access_token = parsed.access_token;
- credentials.expiry_date = new Date().getTime() + (parsed.expires_in * 1000);
+ let { access_token, expires_in } = JSON.parse(response);
+ const expiry_date = new Date().getTime() + (expires_in * 1000);
+ await Database.Auxiliary.GoogleAuthenticationToken.Update(userId, access_token, expiry_date);
+ credentials.access_token = access_token;
+ credentials.expiry_date = expiry_date;
oAuth2Client.setCredentials(credentials);
- await Database.Auxiliary.GoogleAuthenticationToken.Write(userId, credentials);
resolve({ token: credentials, client: oAuth2Client });
});
});
diff --git a/src/server/database.ts b/src/server/database.ts
index 890ac6b32..bc9a9ab23 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -1,7 +1,7 @@
import * as mongodb from 'mongodb';
import { Transferable } from './Message';
import { Opt } from '../new_fields/Doc';
-import { Utils } from '../Utils';
+import { Utils, emptyFunction } from '../Utils';
import { DashUploadUtils } from './DashUploadUtils';
export namespace Database {
@@ -21,7 +21,7 @@ export namespace Database {
});
}
- public update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = Database.DocumentsCollection) {
+ public async update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = Database.DocumentsCollection) {
if (this.db) {
let collection = this.db.collection(collectionName);
const prom = this.currentWrites[id];
@@ -40,6 +40,7 @@ export namespace Database {
};
newProm = prom ? prom.then(run) : run();
this.currentWrites[id] = newProm;
+ return newProm;
} else {
this.onConnect.push(() => this.update(id, value, callback, upsert, collectionName));
}
@@ -226,23 +227,22 @@ export namespace Database {
export namespace Auxiliary {
export enum AuxiliaryCollections {
- GooglePhotosUploadHistory = "UploadedFromGooglePhotos"
+ GooglePhotosUploadHistory = "uploadedFromGooglePhotos"
}
- const GoogleAuthentication = "GoogleAuthentication";
- const SanitizedCappedQuery = async (query: { [key: string]: any }, collection: string, cap: number) => {
+ const SanitizedCappedQuery = async (query: { [key: string]: any }, collection: string, cap: number, removeId = true) => {
const cursor = await Instance.query(query, undefined, collection);
const results = await cursor.toArray();
const slice = results.slice(0, Math.min(cap, results.length));
- return slice.map(result => {
+ return removeId ? slice.map(result => {
delete result._id;
return result;
- });
+ }) : slice;
};
- const SanitizedSingletonQuery = async (query: { [key: string]: any }, collection: string) => {
- const results = await SanitizedCappedQuery(query, collection, 1);
+ const SanitizedSingletonQuery = async (query: { [key: string]: any }, collection: string, removeId = true) => {
+ const results = await SanitizedCappedQuery(query, collection, 1, removeId);
return results.length ? results[0] : undefined;
};
@@ -252,14 +252,24 @@ export namespace Database {
export namespace GoogleAuthenticationToken {
- export const Fetch = async (userId: string) => {
- return SanitizedSingletonQuery({ userId }, GoogleAuthentication);
+ const GoogleAuthentication = "googleAuthentication";
+
+ export const Fetch = async (userId: string, removeId = true) => {
+ return SanitizedSingletonQuery({ userId }, GoogleAuthentication, removeId);
};
export const Write = async (userId: string, token: any) => {
return Instance.insert({ userId, ...token }, GoogleAuthentication);
};
+ export const Update = async (userId: string, access_token: string, expiry_date: number) => {
+ const entry = await Fetch(userId, false);
+ if (entry) {
+ const parameters = { $set: { access_token, expiry_date } };
+ return Instance.update(entry._id, parameters, emptyFunction, true, GoogleAuthentication);
+ }
+ };
+
}
export const LogUpload = async (information: DashUploadUtils.UploadInformation) => {
diff --git a/src/server/index.ts b/src/server/index.ts
index 2ff63ab78..33d098e2c 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -824,7 +824,7 @@ app.post(RouteStore.googleDocs + "/:sector/:action", (req, res) => {
});
});
-app.get(RouteStore.googlePhotosAccessToken, (req, res) => GoogleApiServerUtils.RetrieveAccessToken({ credentialsPath, userId: req.headers.userId as string }).then(token => res.send(token)));
+app.get(RouteStore.googlePhotosAccessToken, (req, res) => GoogleApiServerUtils.RetrieveAccessToken({ credentialsPath, userId: req.header("userId")! }).then(token => res.send(token)));
const tokenError = "Unable to successfully upload bytes for all images!";
const mediaError = "Unable to convert all uploaded bytes to media items!";
@@ -839,9 +839,9 @@ export interface NewMediaItem {
app.post(RouteStore.googlePhotosMediaUpload, async (req, res) => {
const { media } = req.body;
- const { userId } = req.headers;
+ const userId = req.header("userId");
- if (!userId || Array.isArray(userId)) {
+ if (!userId) {
return _error(res, userIdError);
}