@questwork/q-utilities 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,254 +0,0 @@
1
- // 'use strict'
2
-
3
- /* eslint-disable new-cap */
4
- /* eslint-disable camelcase */
5
- /* eslint-disable no-mixed-operators */
6
- /* eslint-disable no-useless-escape */
7
- /* eslint-disable no-param-reassign */
8
-
9
- /* eslint func-names: 0 */
10
-
11
- const Buffer = require('buffer/').Buffer
12
-
13
- const EXPIRY = 3600 // in second
14
- const ALGORITHM = 'HS256'
15
- const SECRET = 'ab1234cd'
16
-
17
- const jwtHelper = {
18
- create(obj, { secret, algorithm, expiry } = {}) {
19
- const sAlgorithm = algorithm || ALGORITHM
20
- const sSecret = secret || SECRET
21
- const exp = expiry || getTimeInSecond() + EXPIRY
22
- const payload = {
23
- ...obj,
24
- exp
25
- }
26
- return encode(payload, sSecret, sAlgorithm)
27
- },
28
- createByUser(loginAccount) {
29
- const exp = getTimeInSecond() + EXPIRY
30
- const payload = {
31
- loginAccount,
32
- exp
33
- }
34
- return this.encode(payload)
35
- },
36
- encode(payload, algorithm) {
37
- return encode(payload, SECRET, algorithm)
38
- },
39
- decode(token, algorithm) {
40
- const noVerify = !this.verify(token)
41
- return decode(token, SECRET, noVerify, algorithm) // if noVerify = true, may skip verification
42
- },
43
- getPayload(token) {
44
- const payload = getPayload(token)
45
- return {
46
- payload
47
- }
48
- },
49
- getPayloadIdByKey(token, key) {
50
- const payload = getPayload(token)
51
- const id = payload[key] ? payload[key].id : null
52
- return {
53
- id,
54
- jwtToken: token
55
- }
56
- },
57
- resolve(token, secret, algorithm) {
58
- const sSecret = secret || SECRET
59
- return decode(token, sSecret, false, algorithm) // need verification
60
- },
61
- verify(token) {
62
- const payload = getPayload(token)
63
- const today = getTimeInSecond()
64
- return (payload.exp && (today <= payload.exp)) || false
65
- }
66
- }
67
-
68
- /**
69
- * Private functions
70
- */
71
-
72
- const getPayload = (token) => decode(token, SECRET, true)
73
-
74
- const getTimeInSecond = () => Math.floor(Date.now() / 1000)
75
-
76
- /**
77
- * Private functions, based on jwt-simple 0.2.0
78
- */
79
-
80
- const { cryptoHelper } = require('../cryptoHelper')
81
-
82
- const algorithmMap = {
83
- HS256: 'sha256',
84
- HS384: 'sha384',
85
- HS512: 'sha512',
86
- RS256: 'RSA-SHA256'
87
- }
88
-
89
- const typeMap = {
90
- HS256: 'hmac',
91
- HS384: 'hmac',
92
- HS512: 'hmac',
93
- RS256: 'sign'
94
- }
95
-
96
-
97
- /**
98
- * Decode jwt
99
- *
100
- * @param {Object} token
101
- * @param {String} key
102
- * @param {Boolean} noVerify
103
- * @param {String} algorithm
104
- * @return {Object} payload
105
- * @api public
106
- */
107
- const decode = function jwt_decode(token, key, noVerify, algorithm) {
108
- // check token
109
- if (!token) {
110
- throw new Error('No token supplied')
111
- }
112
- // check segments
113
- const segments = token.split('.')
114
- if (segments.length !== 3) {
115
- throw new Error('Not enough or too many segments')
116
- }
117
-
118
- // All segment should be base64
119
- const headerSeg = segments[0]
120
- const payloadSeg = segments[1]
121
- const signatureSeg = segments[2]
122
-
123
- // base64 decode and parse JSON
124
- const header = JSON.parse(base64urlDecode(headerSeg))
125
-
126
- const payload = JSON.parse(base64urlDecode(payloadSeg))
127
-
128
- if (!noVerify) {
129
- const signingMethod = algorithmMap[algorithm || header.alg]
130
- const signingType = typeMap[algorithm || header.alg]
131
- if (!signingMethod || !signingType) {
132
- throw new Error('Algorithm not supported')
133
- }
134
-
135
- // verify signature. `sign` will return base64 string.
136
- const signingInput = [headerSeg, payloadSeg].join('.')
137
- if (!verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
138
- throw new Error('Signature verification failed')
139
- }
140
- }
141
-
142
- return payload
143
- }
144
-
145
-
146
- /**
147
- * Encode jwt
148
- *
149
- * @param {Object} payload
150
- * @param {String} key
151
- * @param {String} algorithm
152
- * @return {String} token
153
- * @api public
154
- */
155
- const encode = function jwt_encode(payload, key, algorithm) {
156
- // Check key
157
- if (!key) {
158
- throw new Error('Require key')
159
- }
160
-
161
- // Check algorithm, default is HS256
162
- if (!algorithm) {
163
- algorithm = ALGORITHM
164
- }
165
-
166
- const signingMethod = algorithmMap[algorithm]
167
- const signingType = typeMap[algorithm]
168
- if (!signingMethod || !signingType) {
169
- throw new Error('Algorithm not supported')
170
- }
171
-
172
- // header, typ is fixed value.
173
- const header = { typ: 'JWT', alg: algorithm }
174
-
175
- // create segments, all segments should be base64 string
176
- const segments = []
177
- segments.push(base64urlEncode(JSON.stringify(header)))
178
- segments.push(base64urlEncode(JSON.stringify(payload)))
179
- segments.push(sign(segments.join('.'), key, signingMethod, signingType))
180
-
181
- return segments.join('.')
182
- }
183
-
184
-
185
- /**
186
- * private util functions
187
- */
188
-
189
- function verify(input, key, method, type, signature) {
190
- if (type === 'hmac') {
191
- return (signature === sign(input, key, method, type))
192
- } else if (type === 'sign') {
193
- try {
194
- return cryptoHelper.createStringVerify({
195
- algorithm: method,
196
- data: input,
197
- object: key,
198
- signature: base64urlUnescape(signature),
199
- signatureEncoding: 'base64'
200
- })
201
- } catch (error) {
202
- throw new Error('createStringVerify failed')
203
- }
204
- }
205
- throw new Error('Algorithm type not recognized')
206
- }
207
-
208
- function sign(input, key, method, type) {
209
- let base64str
210
- if (type === 'hmac') {
211
- base64str = cryptoHelper.createStringHmac({
212
- algorithm: method,
213
- key,
214
- data: input,
215
- outputEncoding: 'base64'
216
- })
217
- } else if (type === 'sign') {
218
- try {
219
- base64str = cryptoHelper.createSignature({
220
- algorithm: method,
221
- data: input,
222
- privateKey: key,
223
- outputEncoding: 'base64'
224
- })
225
- } catch (error) {
226
- throw new Error('createSignature failed')
227
- }
228
- } else {
229
- throw new Error('Algorithm type not recognized')
230
- }
231
- return base64urlEscape(base64str)
232
- }
233
-
234
- function base64urlDecode(str) {
235
- // fixed bug if decode string is incorrect
236
- return (new Buffer.from(base64urlUnescape(str), 'base64')).toString() || '{}'
237
- }
238
-
239
- function base64urlUnescape(str) {
240
- str += new Array(5 - str.length % 4).join('=')
241
- return str.replace(/\-/g, '+').replace(/_/g, '/')
242
- }
243
-
244
- function base64urlEncode(str) {
245
- return base64urlEscape(new Buffer.from((str)).toString('base64'))
246
- }
247
-
248
- function base64urlEscape(str) {
249
- return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
250
- }
251
-
252
- module.exports = {
253
- jwtHelper
254
- }
@@ -1 +0,0 @@
1
- export { KeyValueObject } from './keyValueObject'
@@ -1,163 +0,0 @@
1
- 'use strict'
2
-
3
- class KeyValueObject {
4
- constructor(options = {}) {
5
- options = options || {}
6
- this.key = options.key || null
7
- this.value = (typeof options.value !== 'undefined') ? options.value : ''
8
- }
9
-
10
- // Class methods
11
-
12
- static addItem(arr, key, value) {
13
- arr.push(
14
- { key, value }
15
- )
16
- }
17
- static addRecord(arr = [], key, value) {
18
- const self = this
19
- if (!KeyValueObject.hasKeyValue(arr, key, value)) {
20
- arr.push(self.init({ key, value }))
21
- }
22
- return arr
23
- }
24
-
25
- static fromObject(options = {}) {
26
- const self = this
27
- return Object.keys(options).reduce((acc, key) => {
28
- acc.push(self.init({ key, value: options[key] }))
29
- return acc
30
- }, [])
31
- }
32
-
33
- static removeByKey(arr, key) {
34
- return arr.reduce((acc, item) => {
35
- if (item.key !== key) {
36
- acc.push(item)
37
- }
38
- return acc
39
- }, [])
40
- }
41
-
42
- static getValuesByKey(arr = [], key) {
43
- return arr.reduce((acc, item) => {
44
- if (item.key === key) {
45
- acc.push(item.value)
46
- }
47
- return acc
48
- }, [])
49
- }
50
-
51
- static hasKeyValue(arr = [], key, value) {
52
- if (typeof value === 'undefined') {
53
- return arr.filter((item) => item.key === key).length > 0
54
- }
55
- return arr.filter((item) => (item.key === key && item.value === value)).length > 0
56
- }
57
-
58
- static init(options = {}) {
59
- if (options instanceof KeyValueObject) {
60
- return options
61
- }
62
- const kvObject = new KeyValueObject(options)
63
- return kvObject.isValid ? kvObject : null
64
- }
65
-
66
- static initFromArray(arr = []) {
67
- const self = this
68
- if (Array.isArray(arr)) {
69
- return arr.map(self.init)
70
- }
71
- return []
72
- }
73
-
74
- static initOnlyValidFromArray(arr = []) {
75
- return this.initFromArray(arr).filter((i) => i)
76
- }
77
-
78
- static keys(arr = []) {
79
- if (Array.isArray(arr)) {
80
- return arr.reduce((acc, item) => {
81
- acc.push(item.key)
82
- return acc
83
- }, [])
84
- }
85
- return []
86
- }
87
-
88
- static toObject(arr = []) {
89
- if (Array.isArray(arr)) {
90
- return arr.reduce((acc, item) => {
91
- acc[item.key] = item.value
92
- return acc
93
- }, {})
94
- }
95
- return {}
96
- }
97
-
98
- static toString(arr = [], delimiter = '; ') {
99
- if (Array.isArray(arr)) {
100
- return arr.reduce((acc, item) => {
101
- acc.push(`${item.key}: ${item.value}`)
102
- return acc
103
- }, []).join(delimiter)
104
- }
105
- return ''
106
- }
107
-
108
- static updateRecord(arr = [], key, value) {
109
- return arr.map((item) => {
110
- if (item.key === key) {
111
- item.value = value
112
- }
113
- return item
114
- })
115
- }
116
-
117
- static updateOrInsertRecord(arr = [], key, value) {
118
- const self = this
119
- let copy = [...arr]
120
- if (!self.hasKeyValue(arr, key)) {
121
- copy.push(self.init({ key, value }))
122
- } else {
123
- copy = self.updateRecord(arr, key, value)
124
- }
125
- return copy
126
- }
127
-
128
- static updateRecordsFromArray(arr = [], updateArr = []) {
129
- if (Array.isArray(arr) && Array.isArray(updateArr)) {
130
- const obj1 = KeyValueObject.toObject(arr)
131
- const obj2 = KeyValueObject.toObject(updateArr)
132
- return KeyValueObject.fromObject(Object.assign({}, obj1, obj2))
133
- }
134
- return []
135
- }
136
-
137
- static values(arr = []) {
138
- if (Array.isArray(arr)) {
139
- return arr.reduce((acc, item) => {
140
- acc.push(item.value)
141
- return acc
142
- }, [])
143
- }
144
- return []
145
- }
146
-
147
- // getters
148
- get isValid() {
149
- return !!this.key
150
- }
151
-
152
- get toObject() {
153
- const obj = {}
154
- if (this.isValid) {
155
- obj[this.key] = this.value
156
- }
157
- return obj
158
- }
159
- }
160
-
161
- export {
162
- KeyValueObject
163
- }