-
Notifications
You must be signed in to change notification settings - Fork 2
/
connection.js
120 lines (95 loc) · 3.22 KB
/
connection.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"use strict";
var events = require("events")
var extend = require("extend")
var fs = require("fs")
var GoogleToken = require("gtoken")
var request = require("request")
var Token = require("./token")
var util = require("util")
var METADATA_TOKEN_URL = "http://metadata/computeMetadata/v1/instance/service-accounts/default/token"
function Connection(options) {
if (!(this instanceof Connection)) return new Connection(options)
events.EventEmitter.call(this)
this.setMaxListeners(0)
options = options || {}
this.credentials = options.credentials
this.keyFile = options.keyFile
this.scopes = options.scopes || []
if (this.credentials && (!this.credentials.client_email || !this.credentials.private_key))
throw new Error("A credentials object must contain the following keys: client_email, private_key")
}
util.inherits(Connection, events.EventEmitter)
Connection.prototype.connect = function (callback) {
if (this.token && !this.token.isExpired()) return setImmediate(callback)
this.once("connected", callback)
if (this.isConnecting) return
this.isConnecting = true
this.fetchToken(function (err, token) {
this.isConnecting = false
if (err) return this.emit("connected", err)
this.token = token
this.emit("connected")
}.bind(this))
}
Connection.prototype.createAuthorizedRequest = function (requestOptions, callback) {
if (typeof requestOptions === "function") {
callback = requestOptions
requestOptions = {}
}
this.getToken(function (err, token) {
if (err) return callback(err)
callback(null, extend(true, {}, requestOptions, {
headers: {
Authorization: "Bearer " + token
}
}))
})
}
Connection.prototype.fetchServiceAccountToken = function (callback) {
var gtoken = new GoogleToken({
iss: this.credentials.client_email,
key: this.credentials.private_key,
scope: this.scopes
})
gtoken.getToken(function (err, token) {
if (err) return callback(err)
var exp = new Date(gtoken.expires_at)
callback(null, new Token(token, exp))
})
}
Connection.prototype.fetchToken = function (callback) {
if (/*G[AC]E*/!this.keyFile && !this.credentials)
return request({
method: "get",
uri: METADATA_TOKEN_URL,
headers: {
"Metadata-Flavor": "Google"
},
json: true
}, function (err, res, body) {
if (err || !body.access_token) return callback(err)
var exp = new Date(Date.now() + body.expires_in * 1000)
callback(null, new Token(body.access_token, exp))
})
if (!this.credentials)
return fs.readFile(this.keyFile, function (err, data) {
if (err) return callback(err)
this.credentials = JSON.parse(data)
this.fetchServiceAccountToken(callback)
}.bind(this))
this.fetchServiceAccountToken(callback)
}
Connection.prototype.getCredentials = function (callback) {
if (this.credentials) return setImmediate(callback, null, this.credentials)
this.connect(function (err) {
if (err) return callback(err)
callback(null, this.credentials)
}.bind(this))
}
Connection.prototype.getToken = function (callback) {
this.connect(function (err) {
if (err) return callback(err)
callback(null, this.token.accessToken)
}.bind(this))
}
module.exports = Connection