diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/apis/google/GoogleApiServerUtils.ts | 51 | ||||
| -rw-r--r-- | src/server/database.ts | 34 | ||||
| -rw-r--r-- | src/server/index.ts | 12 |
3 files changed, 52 insertions, 45 deletions
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts index 684a8081b..665dcf862 100644 --- a/src/server/apis/google/GoogleApiServerUtils.ts +++ b/src/server/apis/google/GoogleApiServerUtils.ts @@ -66,6 +66,15 @@ export namespace GoogleApiServerUtils { }); }; + export const RetrieveAccessToken = (information: CredentialInformation) => { + return new Promise<string>((resolve, reject) => { + RetrieveCredentials(information).then( + credentials => resolve(credentials.token.access_token!), + error => reject(`Error: unable to authenticate Google Photos API request.\n${error}`) + ); + }); + }; + export const RetrieveCredentials = (information: CredentialInformation) => { return new Promise<TokenResult>((resolve, reject) => { readFile(information.credentialsPath, async (err, credentials) => { @@ -78,15 +87,6 @@ export namespace GoogleApiServerUtils { }); }; - export const RetrieveAccessToken = (information: CredentialInformation) => { - return new Promise<string>((resolve, reject) => { - RetrieveCredentials(information).then( - credentials => resolve(credentials.token.access_token!), - error => reject(`Error: unable to authenticate Google Photos API request.\n${error}`) - ); - }); - }; - export const RetrievePhotosEndpoint = (paths: CredentialInformation) => { return new Promise<any>((resolve, reject) => { RetrieveAccessToken(paths).then( @@ -107,7 +107,7 @@ export namespace GoogleApiServerUtils { client_id, client_secret, redirect_uris[0]); return new Promise<TokenResult>((resolve, reject) => { - Database.Auxiliary.FetchGoogleAuthenticationToken(userId).then(token => { + Database.Auxiliary.GoogleAuthenticationToken.Fetch(userId).then(token => { // Check if we have previously stored a token for this userId. if (!token) { return getNewToken(oAuth2Client, userId).then(resolve, reject); @@ -123,8 +123,8 @@ export namespace GoogleApiServerUtils { } const refreshEndpoint = "https://oauth2.googleapis.com/token"; - const refreshToken = (credentials: Credentials, client_id: string, client_secret: string, oAuth2Client: OAuth2Client, token_path: string) => { - return new Promise<TokenResult>((resolve, reject) => { + const refreshToken = (credentials: Credentials, client_id: string, client_secret: string, oAuth2Client: OAuth2Client, userId: string) => { + return new Promise<TokenResult>(resolve => { let headerParameters = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }; let queryParameters = { refreshToken: credentials.refresh_token, @@ -133,19 +133,13 @@ export namespace GoogleApiServerUtils { grant_type: "refresh_token" }; let url = `${refreshEndpoint}?${qs.stringify(queryParameters)}`; - request.post(url, headerParameters).then(response => { + 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); - writeFile(token_path, JSON.stringify(credentials), (err) => { - if (err) { - console.error(err); - reject(err); - } - console.log('Refreshed token stored to', token_path); - oAuth2Client.setCredentials(credentials); - resolve({ token: credentials, client: oAuth2Client }); - }); + oAuth2Client.setCredentials(credentials); + await Database.Auxiliary.GoogleAuthenticationToken.Write(userId, credentials); + resolve({ token: credentials, client: oAuth2Client }); }); }); }; @@ -156,7 +150,7 @@ export namespace GoogleApiServerUtils { * @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) { + function getNewToken(oAuth2Client: OAuth2Client, userId: string) { return new Promise<TokenResult>((resolve, reject) => { const authUrl = oAuth2Client.generateAuthUrl({ access_type: 'offline', @@ -169,20 +163,13 @@ export namespace GoogleApiServerUtils { }); rl.question('Enter the code from that page here: ', (code) => { rl.close(); - oAuth2Client.getToken(code, (err, token) => { + oAuth2Client.getToken(code, async (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); - }); + await Database.Auxiliary.GoogleAuthenticationToken.Write(userId, token); resolve({ token, client: oAuth2Client }); }); }); diff --git a/src/server/database.ts b/src/server/database.ts index ce29478ad..890ac6b32 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -231,19 +231,37 @@ export namespace Database { const GoogleAuthentication = "GoogleAuthentication"; - const SanitizedSingletonQuery = async (query: { [key: string]: any }, collection: string) => { + const SanitizedCappedQuery = async (query: { [key: string]: any }, collection: string, cap: number) => { const cursor = await Instance.query(query, undefined, collection); - const existing = (await cursor.toArray())[0]; - if (existing) { - delete existing._id; - } - return existing; + const results = await cursor.toArray(); + const slice = results.slice(0, Math.min(cap, results.length)); + return slice.map(result => { + delete result._id; + return result; + }); + }; + + const SanitizedSingletonQuery = async (query: { [key: string]: any }, collection: string) => { + const results = await SanitizedCappedQuery(query, collection, 1); + return results.length ? results[0] : undefined; }; export const QueryUploadHistory = async (contentSize: number): Promise<Opt<DashUploadUtils.UploadInformation>> => { return SanitizedSingletonQuery({ contentSize }, AuxiliaryCollections.GooglePhotosUploadHistory); }; + export namespace GoogleAuthenticationToken { + + export const Fetch = async (userId: string) => { + return SanitizedSingletonQuery({ userId }, GoogleAuthentication); + }; + + export const Write = async (userId: string, token: any) => { + return Instance.insert({ userId, ...token }, GoogleAuthentication); + }; + + } + export const LogUpload = async (information: DashUploadUtils.UploadInformation) => { const bundle = { _id: Utils.GenerateDeterministicGuid(String(information.contentSize!)), @@ -258,10 +276,6 @@ export namespace Database { return Promise.all(pendingDeletions); }; - export const FetchGoogleAuthenticationToken = async (userId: string) => { - return SanitizedSingletonQuery({ userId }, GoogleAuthentication); - }; - } }
\ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index 386ecce4d..2ff63ab78 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -810,7 +810,7 @@ const EndpointHandlerMap = new Map<GoogleApiServerUtils.Action, GoogleApiServerU app.post(RouteStore.googleDocs + "/:sector/:action", (req, res) => { let sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service; let action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action; - GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], { credentialsPath, userId: req.body.userId }).then(endpoint => { + GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], { credentialsPath, userId: req.headers.userId as string }).then(endpoint => { let handler = EndpointHandlerMap.get(action); if (endpoint && handler) { let execute = handler(endpoint, req.body).then( @@ -824,10 +824,11 @@ app.post(RouteStore.googleDocs + "/:sector/:action", (req, res) => { }); }); -app.get(RouteStore.googlePhotosAccessToken, (req, res) => GoogleApiServerUtils.RetrieveAccessToken({ credentialsPath, userId: req.body.userId }).then(token => res.send(token))); +app.get(RouteStore.googlePhotosAccessToken, (req, res) => GoogleApiServerUtils.RetrieveAccessToken({ credentialsPath, userId: req.headers.userId as string }).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!"; +const userIdError = "Unable to parse the identification of the user!"; export interface NewMediaItem { description: string; @@ -837,7 +838,12 @@ export interface NewMediaItem { } app.post(RouteStore.googlePhotosMediaUpload, async (req, res) => { - const { userId, media } = req.body; + const { media } = req.body; + const { userId } = req.headers; + + if (!userId || Array.isArray(userId)) { + return _error(res, userIdError); + } await GooglePhotosUploadUtils.initialize({ credentialsPath, userId }); |
