Skip to content
This repository was archived by the owner on Jan 2, 2024. It is now read-only.

Commit cc90db6

Browse files
committed
Keep LibCal API creds secret
All together now... * dotenv [1] * axios module [2] * proxy module [3] * serverMiddleware [4] * body-parser [5] Go team. Heavily based on modify-post example [6] from http-proxy-middleware. The need to restream the parsed body prior to proxying [7 - 9] was a special treat. [1] https://github.com/motdotla/dotenv [2] https://axios.nuxtjs.org/ [3] https://github.com/nuxt-community/proxy-module [4] https://nuxtjs.org/api/configuration-servermiddleware [5] https://github.com/expressjs/body-parser [6] https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/modify-post.md [7] chimurai/http-proxy-middleware#40 (comment) [8] http-party/node-http-proxy#1027 [9] http-party/node-http-proxy#1264
1 parent 145a7d6 commit cc90db6

File tree

7 files changed

+121
-18
lines changed

7 files changed

+121
-18
lines changed

.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copy this file to .env before editing any values
2+
3+
# LibCal API 1.1 credentials
4+
LIBCAL_CLIENT_ID=CHANGEME
5+
LIBCAL_CLIENT_SECRET=CHANGEME

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ npm-debug.log
99

1010
# Nuxt generate
1111
dist
12+
13+
# Environment variables via dotenv
14+
.env

nuxt.config.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,58 @@
1+
// Use .env in nuxt config only (keep secrets on the dl)
2+
// -- https://github.com/nuxt/nuxt.js/issues/2033#issuecomment-398820574
3+
// -- https://github.com/nuxt-community/dotenv-module#using-env-file-in-nuxtconfigjs
4+
require('dotenv').config()
5+
6+
// Body parser middleware needed to inject required fields for LibCal API auth
7+
const bodyParser = require('body-parser')
8+
9+
const libcalApi = 'https://api2.libcal.com'
10+
const libcalApiPath = '/api/libcal/'
11+
const libcalHoursApi = 'https://api3.libcal.com'
12+
const libcalHoursApiPath = '/api/libcal-hours/'
13+
114
module.exports = {
215
modules: [
316
'@nuxtjs/axios'
417
],
18+
serverMiddleware: [
19+
// Parse request body so it can be manipulated by proxy middleware
20+
// -- https://nuxtjs.org/api/configuration-servermiddleware
21+
{ path: libcalApiPath, handler: bodyParser.json() }
22+
],
23+
axios: {
24+
prefix: '/api/',
25+
proxy: true
26+
},
27+
proxy: {
28+
[libcalApiPath]: {
29+
target: libcalApi,
30+
pathRewrite: { [`^${libcalApiPath}`]: '' },
31+
onProxyReq: (proxyReq, req, res) => {
32+
if (req.method === 'POST' && req.body) {
33+
// Build object for POST request to obtain access token
34+
let body = {
35+
client_id: process.env.LIBCAL_CLIENT_ID,
36+
client_secret: process.env.LIBCAL_CLIENT_SECRET,
37+
grant_type: 'client_credentials'
38+
}
39+
40+
body = JSON.stringify(body)
41+
42+
// Update headers
43+
proxyReq.setHeader('Content-Type', 'application/json')
44+
proxyReq.setHeader('Content-Length', Buffer.byteLength(body))
45+
46+
// Write new body to the proxyReq stream
47+
proxyReq.write(body)
48+
}
49+
}
50+
},
51+
[libcalHoursApiPath]: {
52+
target: libcalHoursApi,
53+
pathRewrite: { [`^${libcalHoursApiPath}`]: '' }
54+
}
55+
},
556
/*
657
** Headers of the page
758
*/

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
},
1313
"dependencies": {
1414
"@nuxtjs/axios": "^5.1.1",
15+
"body-parser": "^1.18.3",
16+
"dotenv": "^6.0.0",
1517
"jsonp-promise": "^0.1.2",
1618
"lodash": "^4.17.4",
1719
"nuxt": "^1.4.0"

utils/libcal-schema.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
const baseUrl = 'https://api2.libcal.com/'
2-
const baseUrlHours = 'https://api3.libcal.com/'
3-
41
export default {
52
endpoints: {
6-
auth: baseUrl + '1.1/oauth/token',
7-
hours: baseUrlHours + 'api_hours_date.php?iid=973&format=json&nocache=1&lid=',
3+
auth: 'libcal/1.1/oauth/token',
4+
hours: 'libcal-hours/api_hours_date.php?iid=973&format=json&nocache=1&lid=',
85
spaces: {
9-
bookings: baseUrl + '1.1/space/bookings?'
6+
bookings: 'libcal/1.1/space/bookings?'
107
}
118
},
129
desks: {

utils/libcal.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,6 @@ const libCal = {
3030

3131
return moment().isSameOrAfter(lastClosing)
3232
},
33-
authenticate: function (axios) {
34-
// TODO: Handle sensitive LibCal oAuth (potentially via dotenv)
35-
// -- https://spaces.library.cornell.edu/admin_api.php?action=authentication
36-
// -- https://github.com/nuxt-community/dotenv-module
37-
return axios.$post(api.endpoints.auth, {
38-
client_id: 'changeMe',
39-
client_secret: 'changeMe',
40-
grant_type: 'client_credentials'
41-
})
42-
},
4333
availableSlot: function (start, end) {
4434
// QUESTION: Unique ID necessary for available slots?
4535
return {
@@ -166,8 +156,8 @@ const libCal = {
166156

167157
// console.log('where to?', url)
168158

169-
let authorize = await libCal.authenticate(axios)
170-
axios.setHeader('Authorization', 'Bearer ' + authorize.access_token)
159+
let authorize = await axios.$post(api.endpoints.auth)
160+
axios.setToken(authorize.access_token, 'Bearer')
171161

172162
return axios.$get(url)
173163
},

yarn.lock

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,21 @@ [email protected]:
10441044
raw-body "2.3.2"
10451045
type-is "~1.6.15"
10461046

1047+
body-parser@^1.18.3:
1048+
version "1.18.3"
1049+
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
1050+
dependencies:
1051+
bytes "3.0.0"
1052+
content-type "~1.0.4"
1053+
debug "2.6.9"
1054+
depd "~1.1.2"
1055+
http-errors "~1.6.3"
1056+
iconv-lite "0.4.23"
1057+
on-finished "~2.3.0"
1058+
qs "6.5.2"
1059+
raw-body "2.3.3"
1060+
type-is "~1.6.16"
1061+
10471062
boolbase@~1.0.0:
10481063
version "1.0.0"
10491064
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
@@ -2055,6 +2070,10 @@ [email protected]:
20552070
dom-serializer "0"
20562071
domelementtype "1"
20572072

2073+
dotenv@^6.0.0:
2074+
version "6.0.0"
2075+
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.0.0.tgz#24e37c041741c5f4b25324958ebbc34bca965935"
2076+
20582077
duplexer@^0.1.1:
20592078
version "0.1.1"
20602079
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
@@ -3163,6 +3182,15 @@ [email protected], http-errors@~1.6.2:
31633182
setprototypeof "1.0.3"
31643183
statuses ">= 1.3.1 < 2"
31653184

3185+
[email protected], http-errors@~1.6.3:
3186+
version "1.6.3"
3187+
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
3188+
dependencies:
3189+
depd "~1.1.2"
3190+
inherits "2.0.3"
3191+
setprototypeof "1.1.0"
3192+
statuses ">= 1.4.0 < 2"
3193+
31663194
http-proxy-middleware@^0.17.4:
31673195
version "0.17.4"
31683196
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833"
@@ -3203,6 +3231,12 @@ [email protected], iconv-lite@^0.4.17, iconv-lite@~0.4.13:
32033231
version "0.4.19"
32043232
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
32053233

3234+
3235+
version "0.4.23"
3236+
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
3237+
dependencies:
3238+
safer-buffer ">= 2.1.2 < 3"
3239+
32063240
icss-replace-symbols@^1.1.0:
32073241
version "1.1.0"
32083242
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
@@ -5380,6 +5414,10 @@ [email protected], qs@~6.5.1:
53805414
version "6.5.1"
53815415
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
53825416

5417+
5418+
version "6.5.2"
5419+
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
5420+
53835421
qs@~6.3.0:
53845422
version "6.3.2"
53855423
resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
@@ -5436,6 +5474,15 @@ [email protected]:
54365474
iconv-lite "0.4.19"
54375475
unpipe "1.0.0"
54385476

5477+
5478+
version "2.3.3"
5479+
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
5480+
dependencies:
5481+
bytes "3.0.0"
5482+
http-errors "1.6.3"
5483+
iconv-lite "0.4.23"
5484+
unpipe "1.0.0"
5485+
54395486
rc@^1.1.7:
54405487
version "1.2.6"
54415488
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092"
@@ -5848,6 +5895,10 @@ safe-regex@^1.1.0:
58485895
dependencies:
58495896
ret "~0.1.10"
58505897

5898+
"safer-buffer@>= 2.1.2 < 3":
5899+
version "2.1.2"
5900+
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
5901+
58515902
sass-graph@^2.2.4:
58525903
version "2.2.4"
58535904
resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
@@ -6195,6 +6246,10 @@ static-extend@^0.1.1:
61956246
version "1.4.0"
61966247
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
61976248

6249+
"statuses@>= 1.4.0 < 2":
6250+
version "1.5.0"
6251+
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
6252+
61986253
statuses@~1.3.1:
61996254
version "1.3.1"
62006255
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"

0 commit comments

Comments
 (0)