Skip to content

Commit 1adbb8a

Browse files
authored
Merge pull request #599 from looker-open-source/jonting/driveError
Add error info to google drive and fix dependencies
2 parents b69748c + dcb467a commit 1adbb8a

File tree

10 files changed

+163
-10
lines changed

10 files changed

+163
-10
lines changed

lib/actions/google/drive/google_drive.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ exports.GoogleDriveAction = void 0;
1313
const https = require("request-promise-native");
1414
const googleapis_1 = require("googleapis");
1515
const winston = require("winston");
16+
const http_errors_1 = require("../../../error_types/http_errors");
1617
const Hub = require("../../../hub");
18+
const action_response_1 = require("../../../hub/action_response");
1719
class GoogleDriveAction extends Hub.OAuthAction {
1820
constructor() {
1921
super(...arguments);
@@ -42,19 +44,34 @@ class GoogleDriveAction extends Hub.OAuthAction {
4244
const drive = yield this.driveClientFromRequest(stateJson.redirect, stateJson.tokens);
4345
const filename = request.formParams.filename || request.suggestedFilename();
4446
if (!filename) {
47+
const error = {
48+
http_code: http_errors_1.HTTP_ERROR.bad_request.code,
49+
status_code: http_errors_1.HTTP_ERROR.bad_request.status,
50+
message: `${http_errors_1.HTTP_ERROR.bad_request.description} Error creating filename from request`,
51+
location: "ActionContainer",
52+
documentation_url: "TODO",
53+
};
4554
resp.success = false;
46-
resp.message = "Error creating filename";
47-
winston.error("Error creating filename");
55+
resp.error = error;
56+
resp.message = error.message;
57+
resp.webhookId = request.webhookId;
58+
winston.error(`${error.message}`, { error, webhookId: request.webhookId });
4859
return resp;
4960
}
5061
try {
5162
yield this.sendData(filename, request, drive);
5263
resp.success = true;
5364
}
5465
catch (e) {
66+
let error = (0, action_response_1.errorWith)(http_errors_1.HTTP_ERROR.internal, "Error while sending data " + e.message);
67+
if (e.code && e.errors && e.errors[0] && e.errors[0].message) {
68+
error = Object.assign(Object.assign({}, error), { http_code: e.code, message: `${http_errors_1.HTTP_ERROR.internal.description} ${e.errors[0].message}` });
69+
}
5570
resp.success = false;
5671
resp.message = e.message;
57-
winston.error("Error while sending data " + e.message);
72+
resp.webhookId = request.webhookId;
73+
resp.error = error;
74+
winston.error(`${error.message}`, { error, webhookId: request.webhookId });
5875
}
5976
}
6077
else {

lib/error_types/http_errors.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,8 @@ export declare const HTTP_ERROR: {
7070
description: string;
7171
};
7272
};
73+
export interface HttpErrorInfo {
74+
status: string;
75+
code: number;
76+
description: string;
77+
}

lib/hub/action_response.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { HttpErrorInfo } from "../error_types/http_errors";
12
import { ActionState } from "./action_state";
23
export interface ValidationError {
34
field: string;
@@ -10,6 +11,7 @@ export interface Error {
1011
location: string;
1112
documentation_url: string;
1213
}
14+
export declare function errorWith(errorInfo: HttpErrorInfo, message: string): Error;
1315
export declare class ActionResponse {
1416
message?: string;
1517
refreshQuery: boolean;

lib/hub/action_response.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3-
exports.ActionResponse = void 0;
3+
exports.ActionResponse = exports.errorWith = void 0;
4+
function errorWith(errorInfo, message) {
5+
const error = {
6+
http_code: errorInfo.code,
7+
status_code: errorInfo.status,
8+
message: `${errorInfo.description} ${message}`,
9+
location: "ActionContainer",
10+
documentation_url: "TODO",
11+
};
12+
return error;
13+
}
14+
exports.errorWith = errorWith;
415
class ActionResponse {
516
constructor(fields) {
617
this.refreshQuery = false;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
"**/follow-redirects": "^1.14.8",
119119
"**/ssh2": "^1.4.0",
120120
"**/axios": "^1.2.1",
121-
"**/google-auth-library": "^7.14.0",
121+
"**/google-auth-library": "7.14.1",
122122
"**/pac-resolver": "^5.0.0",
123123
"**/mem": "^4.0.0",
124124
"**/formidable": "^3.2.4"

src/actions/google/drive/google_drive.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import {Credentials, OAuth2Client} from "google-auth-library"
55
import { drive_v3, google } from "googleapis"
66

77
import * as winston from "winston"
8+
import { HTTP_ERROR } from "../../../error_types/http_errors"
89
import * as Hub from "../../../hub"
10+
import { Error, errorWith } from "../../../hub/action_response"
911
import Drive = drive_v3.Drive
1012

1113
export class GoogleDriveAction extends Hub.OAuthAction {
@@ -36,18 +38,38 @@ export class GoogleDriveAction extends Hub.OAuthAction {
3638

3739
const filename = request.formParams.filename || request.suggestedFilename()
3840
if (!filename) {
41+
const error: Error = {
42+
http_code: HTTP_ERROR.bad_request.code,
43+
status_code: HTTP_ERROR.bad_request.status,
44+
message: `${HTTP_ERROR.bad_request.description} Error creating filename from request`,
45+
location: "ActionContainer",
46+
documentation_url: "TODO",
47+
}
3948
resp.success = false
40-
resp.message = "Error creating filename"
41-
winston.error("Error creating filename")
49+
resp.error = error
50+
resp.message = error.message
51+
resp.webhookId = request.webhookId
52+
winston.error(`${error.message}`, {error, webhookId: request.webhookId})
4253
return resp
4354
}
4455
try {
4556
await this.sendData(filename, request, drive)
4657
resp.success = true
4758
} catch (e: any) {
59+
let error: Error = errorWith(
60+
HTTP_ERROR.internal,
61+
"Error while sending data " + e.message,
62+
)
63+
64+
if (e.code && e.errors && e.errors[0] && e.errors[0].message) {
65+
error = {...error, http_code: e.code, message: `${HTTP_ERROR.internal.description} ${e.errors[0].message}`}
66+
}
67+
4868
resp.success = false
4969
resp.message = e.message
50-
winston.error("Error while sending data " + e.message)
70+
resp.webhookId = request.webhookId
71+
resp.error = error
72+
winston.error(`${error.message}`, {error, webhookId: request.webhookId})
5173
}
5274
} else {
5375
resp.success = false

src/actions/google/drive/test_google_drive.ts

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ describe(`${action.constructor.name} unit tests`, () => {
8888
state_url: "https://looker.state.url.com/action_hub_state/asdfasdfasdfasdf",
8989
state_json: JSON.stringify({tokens: "code", redirect: "url"}),
9090
}
91+
request.webhookId = "webhookId"
9192
const stubClient = sinon.stub(action as any, "driveClientFromRequest")
9293
.resolves({
9394
files: {
@@ -98,11 +99,79 @@ describe(`${action.constructor.name} unit tests`, () => {
9899
chai.expect(resp).to.eventually.deep.equal({
99100
success: false,
100101
message: undefined,
101-
// state: {data: "reset"},
102102
refreshQuery: false,
103103
validationErrors: [],
104+
error: {
105+
documentation_url: "TODO",
106+
http_code: 500,
107+
location: "ActionContainer",
108+
message: "Internal server error. Error while sending data undefined",
109+
status_code: "INTERNAL",
110+
},
111+
webhookId: "webhookId",
112+
}).and.notify(stubClient.restore).and.notify(done)
113+
})
114+
115+
it("sets state to reset if error in create contains code and reason", (done) => {
116+
const request = new Hub.ActionRequest()
117+
const dataBuffer = Buffer.from("Hello")
118+
request.type = Hub.ActionType.Query
119+
request.attachment = {dataBuffer, fileExtension: "csv"}
120+
request.formParams = {filename: stubFileName, folder: stubFolder}
121+
request.params = {
122+
state_url: "https://looker.state.url.com/action_hub_state/asdfasdfasdfasdf",
123+
state_json: JSON.stringify({tokens: "code", redirect: "url"}),
124+
}
125+
request.webhookId = "webhookId"
126+
const stubClient = sinon.stub(action as any, "driveClientFromRequest")
127+
.resolves({
128+
files: {
129+
create: async () => Promise.reject({
130+
code: 1234,
131+
errors: [
132+
{
133+
message: "testReason",
134+
},
135+
],
136+
}),
137+
},
138+
})
139+
const resp = action.validateAndExecute(request)
140+
chai.expect(resp).to.eventually.deep.equal({
141+
success: false,
142+
message: undefined,
143+
refreshQuery: false,
144+
validationErrors: [],
145+
error: {
146+
documentation_url: "TODO",
147+
http_code: 1234,
148+
location: "ActionContainer",
149+
message: "Internal server error. testReason",
150+
status_code: "INTERNAL",
151+
},
152+
webhookId: "webhookId",
104153
}).and.notify(stubClient.restore).and.notify(done)
105154
})
155+
156+
it("filename missing in request", () => {
157+
const request = new TestActionRequest()
158+
request.webhookId = "webhookId"
159+
const resp = action.validateAndExecute(request)
160+
chai.expect(resp).to.eventually
161+
.deep.equal({
162+
message: "Server cannot process request due to client request error. Error creating filename from request",
163+
refreshQuery: false,
164+
success: false,
165+
error: {
166+
http_code: 400,
167+
status_code: "BAD_REQUEST",
168+
message: "Server cannot process request due to client request error. Error creating filename from request",
169+
location: "ActionContainer",
170+
documentation_url: "TODO",
171+
},
172+
webhookId: "webhookId",
173+
})
174+
})
106175
})
107176

108177
describe("form", () => {
@@ -371,3 +440,9 @@ describe(`${action.constructor.name} unit tests`, () => {
371440
})
372441
})
373442
})
443+
444+
class TestActionRequest extends Hub.ActionRequest {
445+
suggestedFileName() {
446+
return null
447+
}
448+
}

src/error_types/http_errors.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,12 @@ export const HTTP_ERROR = {
7171
description: "Server is acting as a gateway and cannot get a response in time.",
7272
},
7373
}
74+
75+
export interface HttpErrorInfo {
76+
/* Status name */
77+
status: string,
78+
/* Http status code to be returned */
79+
code: number,
80+
/* Generic description of the issue */
81+
description: string,
82+
}

src/hub/action_response.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {HttpErrorInfo} from "../error_types/http_errors"
12
import {ActionState} from "./action_state"
23

34
export interface ValidationError {
@@ -18,6 +19,17 @@ export interface Error {
1819
documentation_url: string
1920
}
2021

22+
export function errorWith(errorInfo: HttpErrorInfo, message: string) {
23+
const error: Error = {
24+
http_code: errorInfo.code,
25+
status_code: errorInfo.status,
26+
message: `${errorInfo.description} ${message}`,
27+
location: "ActionContainer",
28+
documentation_url: "TODO",
29+
}
30+
return error
31+
}
32+
2133
export class ActionResponse {
2234
message?: string
2335
refreshQuery = false

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3096,7 +3096,7 @@ glogg@^1.0.0:
30963096
dependencies:
30973097
sparkles "^1.0.0"
30983098

3099-
google-auth-library@^1.3.1, google-auth-library@^6.0.0, google-auth-library@^7.0.0, google-auth-library@^7.14.0:
3099+
google-auth-library@7.14.1, google-auth-library@^1.3.1, google-auth-library@^6.0.0, google-auth-library@^7.0.0, google-auth-library@^7.14.0:
31003100
version "7.14.1"
31013101
resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.14.1.tgz#e3483034162f24cc71b95c8a55a210008826213c"
31023102
integrity sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==

0 commit comments

Comments
 (0)