-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathembed.js
155 lines (147 loc) · 5.36 KB
/
embed.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
const axios = require('axios');
const jws = require('jws');
const {ACCESS_TOKEN_URL, EMBED_TOKEN_URL, EMBED_URL} = require('./constants.js');
function getEmbedToken(req, res, next, config) {
return new Promise((resolve, reject) => {
console.log('getting embed token');
if (config.embedToken && config.embedTokenExpiration && config.embedTokenExpiration > secondsSinceEpoch()) {
resolve();
} else {
console.log('embed token is expired');
getAccessToken(req, res, next, config).then(() => {
console.log('creating new embed token');
axios.post(EMBED_TOKEN_URL,
{
"sessionLength": 1440,
"authorizations": [
{
"token": config.embedId,
"permissions": ["READ", "FILTER", "EXPORT"],
"filters": config.filters,
"policies": config.policies,
}
]
},
{
headers: {
'Authorization': 'Bearer ' + config.accessToken,
'content-type': 'application/json; chartset=utf-8',
'accept': '*/*'
}
})
.then(function (response) {
if (response.data.error) {
console.log(response.data);
next(Error(response.data.error));
}
else {
config.embedToken = response.data.authentication;
const decodedToken = jws.decode(config.embedToken);
if (decodedToken.payload.emb.length === 0) {
next(Error('The emb field in the embed token is empty. This usually means the user associated with the clientid/clientsecret does not have access to this card.'));
} else {
// We'll say it expires 60 seconds before it actually does so that we aren't using an invalid embed token
config.embedTokenExpiration = decodedToken.payload.exp - 60;
console.log(`embed token created: valid until ${config.embedTokenExpiration}`);
resolve();
}
}
}
)
.catch(function (error) {
console.log('error', error);
next(Error(error));
})
});
}
});
}
function getAccessToken(req, res, next, config) {
return new Promise((resolve, reject) => {
console.log('getting access token');
if (config.accessToken && config.accessTokenExpiration > secondsSinceEpoch()) {
console.log(`access token is not expired: still valid for ${config.accessTokenExpiration - secondsSinceEpoch()} seconds`);
resolve();
} else {
console.log('access token is expired');
console.log('creating new access token');
axios.get(ACCESS_TOKEN_URL,
{
headers: {
"Authorization": "Basic " + Buffer.from(config.clientId + ":" + config.clientSecret).toString("base64")
}
})
.then(function(response) {
try {
// console.log('response for access token is = ', response.data);
const data = response.data;
config.userId = data.userId;
config.accessToken = data.access_token;
// We'll say it's expired 60 seconds before it actually does to make sure we aren't using an invalid access token.
config.accessTokenExpiration = Math.floor(Date.now() / 1000) + (data.expires_in - 60);
console.log('access token created: valid until ' + config.accessTokenExpiration);
resolve();
} catch (e) {
console.log('Exception trying to parse access token response: response = ', response.data, e);
next('Exception trying to parse access token response: response = ', response.data, e);
}
})
.catch(function (error) {
console.log('error', error);
next(Error(error));
})
}
});
}
function secondsSinceEpoch(){ return Math.floor( Date.now() / 1000 ) }
function returnEmbedInfo(req, res, config) {
console.log('returning embed info');
if (process.env.USE_XHR) {
res.send(`{"embedToken": "${config.embedToken}", "embedUrl": "${EMBED_URL}${config.embedId}"}`);
} else {
res.send(`
<html>
<body>
<form id="form" action="${EMBED_URL}${config.embedId}?referenceId=${req.params.itemId}" method="post">
<input type="hidden" name="embedToken" value='${config.embedToken}'>
</form>
<script>
document.getElementById("form").submit();
</script>
</body>
</html>`);
}
}
function handleRequest(req, res, next, config) {
getEmbedToken(req, res, next, config).then(() => {
returnEmbedInfo(req, res, config);
});
}
function showFilters(req, res) {
const query = req.query;
console.log(`query = `, query);
let message = `Transitioning content based on mouse click for the following filter:`;
res.send(`
<html>
<body>
<div style="margin: 20px; font-size: 24px; line-height: 30px;">
${message}
<pre id="filters" style="line-height: 20px; font-size: 16px; color: lightslategrey; "></pre>
</div>
</body>
<script>
const filters = ${req.query.filters};
const el = document.getElementById("filters");
el.innerText = JSON.stringify(filters, undefined, 4);
</script>
</html>
`);
}
function refreshEmbedToken(req, res, next, config) {
return getEmbedToken(req, res, next, config);
}
module.exports = {
handleRequest,
refreshEmbedToken,
showFilters,
}