2018-01-30 11:53:12 -05:00
|
|
|
|
const cookie = require('cookie');
|
|
|
|
|
const defaults = require('lodash.defaults');
|
|
|
|
|
const xhr = require('xhr');
|
|
|
|
|
const pako = require('pako');
|
2015-10-15 23:05:57 -04:00
|
|
|
|
|
2016-01-14 10:25:03 -05:00
|
|
|
|
/**
|
|
|
|
|
* Module that handles coookie interactions.
|
|
|
|
|
* (Cookies?!?! Jar?!?! Get it?!?! WE'RE AMAZING!!!!)
|
|
|
|
|
*
|
|
|
|
|
* get(name, callback) – can be sync or async, as callback is optional
|
|
|
|
|
* set(name, value) – synchronously sets the cookie
|
|
|
|
|
* use(name, uri, callback) – can by sync or async, gets cookie from the uri if not there.
|
|
|
|
|
*/
|
2018-01-30 11:53:12 -05:00
|
|
|
|
const Jar = {
|
|
|
|
|
unsign: (value, callback) => {
|
2016-03-23 10:02:20 -04:00
|
|
|
|
// Return the usable content portion of a signed, compressed cookie generated by
|
|
|
|
|
// Django's signing module
|
|
|
|
|
// https://github.com/django/django/blob/stable/1.8.x/django/core/signing.py
|
2016-06-30 11:27:46 -04:00
|
|
|
|
if (typeof value === 'undefined') return callback(null, value);
|
|
|
|
|
|
2015-12-08 15:14:16 -05:00
|
|
|
|
try {
|
2018-01-30 11:53:12 -05:00
|
|
|
|
let b64Data = value.split(':')[0];
|
|
|
|
|
let decompress = false;
|
2015-12-08 15:14:16 -05:00
|
|
|
|
if (b64Data[0] === '.') {
|
|
|
|
|
decompress = true;
|
|
|
|
|
b64Data = b64Data.substring(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Django makes its base64 strings url safe by replacing + and / with - and _ respectively
|
2016-03-23 10:02:20 -04:00
|
|
|
|
// using base64.urlsafe_b64encode
|
|
|
|
|
// https://docs.python.org/2/library/base64.html#base64.b64encode
|
2018-01-30 11:53:12 -05:00
|
|
|
|
b64Data = b64Data.replace(
|
|
|
|
|
/[-_]/g,
|
|
|
|
|
c => ({
|
|
|
|
|
'-': '+',
|
|
|
|
|
'_': '/'
|
|
|
|
|
}[c])
|
|
|
|
|
);
|
|
|
|
|
let strData = atob(b64Data);
|
2015-12-08 15:14:16 -05:00
|
|
|
|
|
|
|
|
|
if (decompress) {
|
2018-01-30 11:53:12 -05:00
|
|
|
|
const charData = strData.split('').map(c => (c.charCodeAt(0)));
|
|
|
|
|
const binData = new Uint8Array(charData);
|
|
|
|
|
const data = pako.inflate(binData);
|
2015-12-08 15:14:16 -05:00
|
|
|
|
strData = String.fromCharCode.apply(null, new Uint16Array(data));
|
|
|
|
|
}
|
|
|
|
|
return callback(null, strData);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return callback(e);
|
|
|
|
|
}
|
|
|
|
|
},
|
2018-01-30 11:53:12 -05:00
|
|
|
|
get: (name, callback) => {
|
2016-03-23 09:50:41 -04:00
|
|
|
|
// Get cookie by name
|
2018-01-30 11:53:12 -05:00
|
|
|
|
const obj = cookie.parse(document.cookie) || {};
|
2015-10-15 23:05:57 -04:00
|
|
|
|
|
2015-12-07 17:43:04 -05:00
|
|
|
|
// Handle optional callback
|
|
|
|
|
if (typeof callback === 'function') {
|
|
|
|
|
if (typeof obj === 'undefined') return callback('Cookie not found.');
|
|
|
|
|
return callback(null, obj[name]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return obj[name];
|
|
|
|
|
},
|
2018-01-30 11:53:12 -05:00
|
|
|
|
use: (name, uri, callback) => {
|
2015-12-07 17:43:04 -05:00
|
|
|
|
// Attempt to get cookie
|
2018-01-30 11:53:12 -05:00
|
|
|
|
Jar.get(name, (err, obj) => {
|
2015-12-07 17:43:04 -05:00
|
|
|
|
if (typeof obj !== 'undefined') return callback(null, obj);
|
|
|
|
|
|
|
|
|
|
// Make XHR request to cookie setter uri
|
|
|
|
|
xhr({
|
|
|
|
|
uri: uri
|
2018-01-30 11:53:12 -05:00
|
|
|
|
}, e => {
|
|
|
|
|
if (e) return callback(e);
|
2015-12-07 17:43:04 -05:00
|
|
|
|
Jar.get(name, callback);
|
|
|
|
|
});
|
2015-10-15 23:05:57 -04:00
|
|
|
|
});
|
2015-12-07 17:43:04 -05:00
|
|
|
|
},
|
2018-01-30 11:53:12 -05:00
|
|
|
|
set: (name, value, opts) => {
|
2017-09-18 14:40:52 -04:00
|
|
|
|
opts = opts || {};
|
2016-09-08 12:52:22 -04:00
|
|
|
|
defaults(opts, {
|
2020-08-05 10:50:06 -04:00
|
|
|
|
expires: new Date(new Date().setYear(new Date().getFullYear() + 1)),
|
|
|
|
|
sameSite: 'Lax' // cookie library requires this capitialization of sameSite
|
2016-09-08 12:52:22 -04:00
|
|
|
|
});
|
2017-09-18 11:44:06 -04:00
|
|
|
|
opts.path = '/';
|
2018-01-30 11:53:12 -05:00
|
|
|
|
const obj = cookie.serialize(name, value, opts);
|
2016-09-08 12:52:22 -04:00
|
|
|
|
document.cookie = obj;
|
2016-06-08 13:47:11 -04:00
|
|
|
|
},
|
2018-01-30 11:53:12 -05:00
|
|
|
|
getUnsignedValue: (cookieName, signedValue, callback) => {
|
2016-06-08 13:47:11 -04:00
|
|
|
|
// Get a value from a signed object
|
2018-01-30 11:53:12 -05:00
|
|
|
|
Jar.get(cookieName, (err, value) => {
|
2016-06-08 13:47:11 -04:00
|
|
|
|
if (err) return callback(err);
|
2016-06-30 11:40:05 -04:00
|
|
|
|
if (typeof value === 'undefined') return callback(null, value);
|
|
|
|
|
|
2018-01-30 11:53:12 -05:00
|
|
|
|
Jar.unsign(value, (e, contents) => {
|
|
|
|
|
if (e) return callback(e);
|
2016-06-30 11:27:46 -04:00
|
|
|
|
|
2016-06-08 13:47:11 -04:00
|
|
|
|
try {
|
2018-01-30 11:53:12 -05:00
|
|
|
|
const data = JSON.parse(contents);
|
|
|
|
|
return callback(null, data[signedValue]);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return callback(error);
|
2016-06-08 13:47:11 -04:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
2015-12-07 17:43:04 -05:00
|
|
|
|
}
|
2015-10-16 10:59:55 -04:00
|
|
|
|
};
|
2015-10-16 15:10:17 -04:00
|
|
|
|
|
|
|
|
|
module.exports = Jar;
|