Skip to content

Commit 85cee30

Browse files
authored
Merge pull request #192 from madfish-solutions/TW-1733-evm-integrate-google-auth-for-import-create-wallet-flows-in-extension
TW-1733 Create a proxy for requests to Google API
2 parents c3d2bc6 + 9ed53ca commit 85cee30

File tree

4 files changed

+98
-1
lines changed

4 files changed

+98
-1
lines changed

.env.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ ADMIN_PASSWORD=
1313
TEMPLE_TAP_API_URL=
1414
EVM_API_URL=
1515
WERT_API_KEY=
16+
GOOGLE_DRIVE_API_KEY=

src/config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export const EnvVars = {
1515
ADMIN_PASSWORD: getEnv('ADMIN_PASSWORD'),
1616
TEMPLE_TAP_API_URL: getEnv('TEMPLE_TAP_API_URL'),
1717
EVM_API_URL: getEnv('EVM_API_URL'),
18-
WERT_API_KEY: getEnv('WERT_API_KEY')
18+
WERT_API_KEY: getEnv('WERT_API_KEY'),
19+
GOOGLE_DRIVE_API_KEY: getEnv('GOOGLE_DRIVE_API_KEY')
1920
};
2021

2122
for (const name in EnvVars) {

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { getParsedContent } from './notifications/utils/get-parsed-content.util'
2121
import { getPlatforms } from './notifications/utils/get-platforms.util';
2222
import { redisClient } from './redis';
2323
import { evmRouter } from './routers/evm';
24+
import { googleDriveRouter } from './routers/google-drive';
2425
import { adRulesRouter } from './routers/slise-ad-rules';
2526
import { templeWalletAdsRouter } from './routers/temple-wallet-ads';
2627
import { getSigningNonce, tezosSigAuthMiddleware } from './sig-auth';
@@ -350,6 +351,8 @@ app.use('/api/slise-ad-rules', adRulesRouter);
350351

351352
app.use('/api/evm', evmRouter);
352353

354+
app.use('/api/google-drive', googleDriveRouter);
355+
353356
app.use('/api/temple-wallet-ads', templeWalletAdsRouter);
354357

355358
app.post('/api/magic-square-quest/start', async (req, res) => {

src/routers/google-drive.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import axios, { AxiosRequestHeaders, AxiosResponse } from 'axios';
2+
import { Router } from 'express';
3+
import { IncomingHttpHeaders } from 'http';
4+
import { omit } from 'lodash';
5+
import { object as objectSchema, mixed as mixedSchema, string as stringSchema } from 'yup';
6+
7+
import { EnvVars } from '../config';
8+
import { isDefined } from '../utils/helpers';
9+
import logger from '../utils/logger';
10+
11+
export const googleDriveRouter = Router();
12+
13+
const googleDriveApi = axios.create({
14+
baseURL: 'https://www.googleapis.com'
15+
});
16+
17+
class NotAllowedMethodError extends Error {
18+
constructor(message: string) {
19+
super(message);
20+
this.name = 'NotAllowedMethodError';
21+
}
22+
}
23+
24+
const allowedBodyMethods = ['post', 'patch'];
25+
const isAllowedBodyMethod = (method: string): method is 'post' | 'patch' => allowedBodyMethods.includes(method);
26+
const allowedNoBodyMethods = ['get', 'delete'];
27+
const isAllowedNoBodyMethod = (method: string): method is 'get' | 'delete' => allowedNoBodyMethods.includes(method);
28+
29+
const toAxiosRequestHeaders = (headers: IncomingHttpHeaders): AxiosRequestHeaders => {
30+
const axiosHeaders: AxiosRequestHeaders = {};
31+
for (const key in headers) {
32+
if (key !== 'host') {
33+
const value = headers[key];
34+
if (value === undefined) continue;
35+
36+
axiosHeaders[key] = typeof value === 'string' ? value : value.join(', ');
37+
}
38+
}
39+
40+
return axiosHeaders;
41+
};
42+
43+
const wrappedBodySchema = objectSchema({
44+
body: mixedSchema(),
45+
contentType: stringSchema().required()
46+
}).required();
47+
48+
googleDriveRouter.use(async (req, res) => {
49+
const methodName = req.method.toLowerCase();
50+
try {
51+
const commonRequestConfig = {
52+
params: {
53+
...req.query,
54+
key: req.path.startsWith('/oauth2') ? undefined : EnvVars.GOOGLE_DRIVE_API_KEY
55+
},
56+
headers: omit(toAxiosRequestHeaders(req.headers), 'connection', 'Connection', 'content-length', 'Content-Length')
57+
};
58+
59+
let response: AxiosResponse;
60+
if (isAllowedNoBodyMethod(methodName)) {
61+
response = await googleDriveApi[methodName](req.path, commonRequestConfig);
62+
} else if (isAllowedBodyMethod(methodName)) {
63+
const requestConfig = { ...commonRequestConfig };
64+
let body = req.body;
65+
try {
66+
const { body: newBody, contentType } = await wrappedBodySchema.validate(req.body);
67+
body = newBody;
68+
const headersContentTypeKey = isDefined(req.headers['content-type']) ? 'content-type' : 'Content-Type';
69+
requestConfig.headers[headersContentTypeKey] = contentType;
70+
} catch {}
71+
response = await googleDriveApi[methodName](req.path, body, requestConfig);
72+
} else {
73+
throw new NotAllowedMethodError('Method Not Allowed');
74+
}
75+
76+
// TODO: add setting headers to response if needed
77+
res.status(response.status).send(response.data);
78+
} catch (error) {
79+
logger.error('Google Drive API error', error);
80+
81+
if (error instanceof NotAllowedMethodError) {
82+
return res.status(405).json({ error: 'Method Not Allowed' });
83+
}
84+
85+
if (axios.isAxiosError(error) && error.response) {
86+
// TODO: add setting headers to response if needed
87+
res.status(error.response.status).send(error.response.data);
88+
} else {
89+
res.status(500).json({ error: 'Internal Server Error' });
90+
}
91+
}
92+
});

0 commit comments

Comments
 (0)