@boxyhq/saml-jackson 0.2.3-beta.207 → 0.2.3-beta.219
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.
- package/.eslintrc.js +13 -0
- package/package.json +3 -3
- package/prettier.config.js +4 -0
- package/src/controller/api.ts +226 -0
- package/src/controller/error.ts +13 -0
- package/src/controller/oauth/allowed.ts +22 -0
- package/src/controller/oauth/code-verifier.ts +11 -0
- package/src/controller/oauth/redirect.ts +12 -0
- package/src/controller/oauth.ts +333 -0
- package/src/controller/utils.ts +17 -0
- package/src/db/db.ts +100 -0
- package/src/db/encrypter.ts +38 -0
- package/src/db/mem.ts +128 -0
- package/src/db/mongo.ts +110 -0
- package/src/db/redis.ts +103 -0
- package/src/db/sql/entity/JacksonIndex.ts +44 -0
- package/src/db/sql/entity/JacksonStore.ts +43 -0
- package/src/db/sql/entity/JacksonTTL.ts +17 -0
- package/src/db/sql/model/JacksonIndex.ts +3 -0
- package/src/db/sql/model/JacksonStore.ts +8 -0
- package/src/db/sql/sql.ts +184 -0
- package/src/db/store.ts +49 -0
- package/src/db/utils.ts +26 -0
- package/src/env.ts +42 -0
- package/src/index.ts +79 -0
- package/src/jackson.ts +171 -0
- package/src/read-config.ts +29 -0
- package/src/saml/claims.js +40 -0
- package/src/saml/saml.ts +234 -0
- package/src/saml/x509.js +48 -0
- package/src/test/api.test.ts.disabled +271 -0
- package/src/test/data/metadata/boxyhq.js +6 -0
- package/src/test/data/metadata/boxyhq.xml +30 -0
- package/src/test/data/saml_response +1 -0
- package/src/test/db.test.ts +318 -0
- package/src/test/oauth.test.ts.disabled +353 -0
- package/src/typings.ts +167 -0
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +26 -0
- package/.nyc_output/522d751d-0cf8-42cc-9e6b-7c4f2c2ab0d4.json +0 -1
- package/.nyc_output/93c45454-d3b6-48a7-9885-209592dc290a.json +0 -1
- package/.nyc_output/da9b997e-732d-4bf2-a4e8-4b0568635c06.json +0 -1
- package/.nyc_output/processinfo/522d751d-0cf8-42cc-9e6b-7c4f2c2ab0d4.json +0 -1
- package/.nyc_output/processinfo/93c45454-d3b6-48a7-9885-209592dc290a.json +0 -1
- package/.nyc_output/processinfo/da9b997e-732d-4bf2-a4e8-4b0568635c06.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
package/src/db/db.ts
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
import {
|
2
|
+
DatabaseDriver,
|
3
|
+
DatabaseOption,
|
4
|
+
Encrypted,
|
5
|
+
EncryptionKey,
|
6
|
+
Index,
|
7
|
+
Storable,
|
8
|
+
} from 'saml-jackson';
|
9
|
+
import * as encrypter from './encrypter';
|
10
|
+
import mem from './mem';
|
11
|
+
import mongo from './mongo';
|
12
|
+
import redis from './redis';
|
13
|
+
import sql from './sql/sql';
|
14
|
+
import store from './store';
|
15
|
+
|
16
|
+
const decrypt = (res: Encrypted, encryptionKey: EncryptionKey): any => {
|
17
|
+
if (res.iv && res.tag) {
|
18
|
+
return JSON.parse(
|
19
|
+
encrypter.decrypt(res.value, res.iv, res.tag, encryptionKey)
|
20
|
+
);
|
21
|
+
}
|
22
|
+
|
23
|
+
return JSON.parse(res.value);
|
24
|
+
};
|
25
|
+
|
26
|
+
class DB implements DatabaseDriver {
|
27
|
+
private db: any;
|
28
|
+
private encryptionKey: EncryptionKey;
|
29
|
+
|
30
|
+
constructor(db: any, encryptionKey: EncryptionKey) {
|
31
|
+
this.db = db;
|
32
|
+
this.encryptionKey = encryptionKey;
|
33
|
+
}
|
34
|
+
|
35
|
+
async get(namespace: string, key: string): Promise<any> {
|
36
|
+
const res = await this.db.get(namespace, key);
|
37
|
+
|
38
|
+
if (!res) {
|
39
|
+
return null;
|
40
|
+
}
|
41
|
+
|
42
|
+
return decrypt(res, this.encryptionKey);
|
43
|
+
}
|
44
|
+
|
45
|
+
async getByIndex(namespace: string, idx: Index): Promise<any> {
|
46
|
+
const res = await this.db.getByIndex(namespace, idx);
|
47
|
+
const encryptionKey = this.encryptionKey;
|
48
|
+
return res.map((r) => {
|
49
|
+
return decrypt(r, encryptionKey);
|
50
|
+
});
|
51
|
+
}
|
52
|
+
|
53
|
+
// ttl is in seconds
|
54
|
+
async put(
|
55
|
+
namespace: string,
|
56
|
+
key: string,
|
57
|
+
val: any,
|
58
|
+
ttl: number = 0,
|
59
|
+
...indexes: any[]
|
60
|
+
): Promise<any> {
|
61
|
+
if (ttl > 0 && indexes && indexes.length > 0) {
|
62
|
+
throw new Error('secondary indexes not allow on a store with ttl');
|
63
|
+
}
|
64
|
+
|
65
|
+
const dbVal = this.encryptionKey
|
66
|
+
? encrypter.encrypt(JSON.stringify(val), this.encryptionKey)
|
67
|
+
: { value: JSON.stringify(val) };
|
68
|
+
|
69
|
+
return await this.db.put(namespace, key, dbVal, ttl, ...indexes);
|
70
|
+
}
|
71
|
+
|
72
|
+
async delete(namespace: string, key: string): Promise<any> {
|
73
|
+
return await this.db.delete(namespace, key);
|
74
|
+
}
|
75
|
+
|
76
|
+
store(namespace: string, ttl: number = 0): Storable {
|
77
|
+
return store.new(namespace, this, ttl);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
export = {
|
82
|
+
new: async (options: DatabaseOption) => {
|
83
|
+
const encryptionKey = options.encryptionKey
|
84
|
+
? Buffer.from(options.encryptionKey, 'latin1')
|
85
|
+
: null;
|
86
|
+
|
87
|
+
switch (options.engine) {
|
88
|
+
case 'redis':
|
89
|
+
return new DB(await redis.new(options), encryptionKey);
|
90
|
+
case 'sql':
|
91
|
+
return new DB(await sql.new(options), encryptionKey);
|
92
|
+
case 'mongo':
|
93
|
+
return new DB(await mongo.new(options), encryptionKey);
|
94
|
+
case 'mem':
|
95
|
+
return new DB(await mem.new(options), encryptionKey);
|
96
|
+
default:
|
97
|
+
throw new Error('unsupported db engine: ' + options.engine);
|
98
|
+
}
|
99
|
+
},
|
100
|
+
};
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import crypto from 'crypto';
|
2
|
+
import { Encrypted, EncryptionKey } from 'saml-jackson';
|
3
|
+
|
4
|
+
const ALGO = 'aes-256-gcm';
|
5
|
+
const BLOCK_SIZE = 16; // 128 bit
|
6
|
+
|
7
|
+
export const encrypt = (text: string, key: EncryptionKey): Encrypted => {
|
8
|
+
const iv = crypto.randomBytes(BLOCK_SIZE);
|
9
|
+
const cipher = crypto.createCipheriv(ALGO, key, iv);
|
10
|
+
|
11
|
+
let ciphertext = cipher.update(text, 'utf8', 'base64');
|
12
|
+
ciphertext += cipher.final('base64');
|
13
|
+
|
14
|
+
return {
|
15
|
+
iv: iv.toString('base64'),
|
16
|
+
tag: cipher.getAuthTag().toString('base64'),
|
17
|
+
value: ciphertext,
|
18
|
+
};
|
19
|
+
};
|
20
|
+
|
21
|
+
export const decrypt = (
|
22
|
+
ciphertext: string,
|
23
|
+
iv: string,
|
24
|
+
tag: string,
|
25
|
+
key: EncryptionKey
|
26
|
+
): string => {
|
27
|
+
const decipher = crypto.createDecipheriv(
|
28
|
+
ALGO,
|
29
|
+
key,
|
30
|
+
Buffer.from(iv, 'base64')
|
31
|
+
);
|
32
|
+
decipher.setAuthTag(Buffer.from(tag, 'base64'));
|
33
|
+
|
34
|
+
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
|
35
|
+
cleartext += decipher.final('utf8');
|
36
|
+
|
37
|
+
return cleartext;
|
38
|
+
};
|
package/src/db/mem.ts
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
// This is an in-memory implementation to be used with testing and prototyping only
|
2
|
+
|
3
|
+
import { DatabaseDriver, DatabaseOption, Index } from 'saml-jackson';
|
4
|
+
import * as dbutils from './utils';
|
5
|
+
|
6
|
+
class Mem implements DatabaseDriver {
|
7
|
+
private options: DatabaseOption;
|
8
|
+
private store: any;
|
9
|
+
private indexes: any;
|
10
|
+
private cleanup: any;
|
11
|
+
private ttlStore: any;
|
12
|
+
private ttlCleanup: any;
|
13
|
+
private timerId: any;
|
14
|
+
|
15
|
+
constructor(options: DatabaseOption) {
|
16
|
+
this.options = options;
|
17
|
+
}
|
18
|
+
|
19
|
+
async init(): Promise<Mem> {
|
20
|
+
this.store = {}; // map of key, value
|
21
|
+
this.indexes = {}; // map of key, Set
|
22
|
+
this.cleanup = {}; // map of indexes for cleanup when store key is deleted
|
23
|
+
this.ttlStore = {}; // map of key to ttl
|
24
|
+
|
25
|
+
if (this.options.ttl) {
|
26
|
+
this.ttlCleanup = async () => {
|
27
|
+
const now = Date.now();
|
28
|
+
for (const k in this.ttlStore) {
|
29
|
+
if (this.ttlStore[k].expiresAt < now) {
|
30
|
+
await this.delete(this.ttlStore[k].namespace, this.ttlStore[k].key);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
if (this.options.ttl) {
|
35
|
+
this.timerId = setTimeout(this.ttlCleanup, this.options.ttl * 1000);
|
36
|
+
}
|
37
|
+
};
|
38
|
+
|
39
|
+
this.timerId = setTimeout(this.ttlCleanup, this.options.ttl * 1000);
|
40
|
+
}
|
41
|
+
|
42
|
+
return this;
|
43
|
+
}
|
44
|
+
|
45
|
+
async get(namespace: string, key: string): Promise<any> {
|
46
|
+
let res = this.store[dbutils.key(namespace, key)];
|
47
|
+
if (res) {
|
48
|
+
return res;
|
49
|
+
}
|
50
|
+
|
51
|
+
return null;
|
52
|
+
}
|
53
|
+
|
54
|
+
async getByIndex(namespace: string, idx: Index): Promise<any> {
|
55
|
+
const dbKeys = await this.indexes[dbutils.keyForIndex(namespace, idx)];
|
56
|
+
|
57
|
+
const ret: string[] = [];
|
58
|
+
for (const dbKey of dbKeys || []) {
|
59
|
+
ret.push(await this.get(namespace, dbKey));
|
60
|
+
}
|
61
|
+
|
62
|
+
return ret;
|
63
|
+
}
|
64
|
+
|
65
|
+
async put(
|
66
|
+
namespace: string,
|
67
|
+
key: string,
|
68
|
+
val: string,
|
69
|
+
ttl: number = 0,
|
70
|
+
...indexes: any[]
|
71
|
+
): Promise<any> {
|
72
|
+
const k = dbutils.key(namespace, key);
|
73
|
+
|
74
|
+
this.store[k] = val;
|
75
|
+
|
76
|
+
if (ttl) {
|
77
|
+
this.ttlStore[k] = {
|
78
|
+
namespace,
|
79
|
+
key,
|
80
|
+
expiresAt: Date.now() + ttl * 1000,
|
81
|
+
};
|
82
|
+
}
|
83
|
+
|
84
|
+
// no ttl support for secondary indexes
|
85
|
+
for (const idx of indexes || []) {
|
86
|
+
const idxKey = dbutils.keyForIndex(namespace, idx);
|
87
|
+
let set = this.indexes[idxKey];
|
88
|
+
if (!set) {
|
89
|
+
set = new Set();
|
90
|
+
this.indexes[idxKey] = set;
|
91
|
+
}
|
92
|
+
|
93
|
+
set.add(key);
|
94
|
+
|
95
|
+
const cleanupKey = dbutils.keyFromParts(dbutils.indexPrefix, k);
|
96
|
+
let cleanup = this.cleanup[cleanupKey];
|
97
|
+
if (!cleanup) {
|
98
|
+
cleanup = new Set();
|
99
|
+
this.cleanup[cleanupKey] = cleanup;
|
100
|
+
}
|
101
|
+
|
102
|
+
cleanup.add(idxKey);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
async delete(namespace: string, key: string): Promise<any> {
|
107
|
+
const k = dbutils.key(namespace, key);
|
108
|
+
|
109
|
+
delete this.store[k];
|
110
|
+
|
111
|
+
const idxKey = dbutils.keyFromParts(dbutils.indexPrefix, k);
|
112
|
+
// delete secondary indexes and then the mapping of the seconary indexes
|
113
|
+
const dbKeys = this.cleanup[idxKey];
|
114
|
+
|
115
|
+
for (const dbKey of dbKeys || []) {
|
116
|
+
this.indexes[dbKey] && this.indexes[dbKey].delete(key);
|
117
|
+
}
|
118
|
+
|
119
|
+
delete this.cleanup[idxKey];
|
120
|
+
delete this.ttlStore[k];
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
export default {
|
125
|
+
new: async (options: DatabaseOption) => {
|
126
|
+
return await new Mem(options).init();
|
127
|
+
},
|
128
|
+
};
|
package/src/db/mongo.ts
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
import { MongoClient } from 'mongodb';
|
2
|
+
import { DatabaseDriver, DatabaseOption, Index } from 'saml-jackson';
|
3
|
+
import * as dbutils from './utils';
|
4
|
+
|
5
|
+
type Document = {
|
6
|
+
value: string;
|
7
|
+
expiresAt: Date;
|
8
|
+
indexes: string[];
|
9
|
+
};
|
10
|
+
|
11
|
+
class Mongo implements DatabaseDriver {
|
12
|
+
private options: DatabaseOption;
|
13
|
+
private client!: MongoClient;
|
14
|
+
private collection: any;
|
15
|
+
private db: any;
|
16
|
+
|
17
|
+
constructor(options: DatabaseOption) {
|
18
|
+
this.options = options;
|
19
|
+
}
|
20
|
+
|
21
|
+
async init(): Promise<Mongo> {
|
22
|
+
this.client = new MongoClient(this.options.url);
|
23
|
+
|
24
|
+
await this.client.connect();
|
25
|
+
|
26
|
+
this.db = this.client.db();
|
27
|
+
this.collection = this.db.collection('jacksonStore');
|
28
|
+
|
29
|
+
await this.collection.createIndex({ indexes: 1 });
|
30
|
+
await this.collection.createIndex(
|
31
|
+
{ expiresAt: 1 },
|
32
|
+
{ expireAfterSeconds: 1 }
|
33
|
+
);
|
34
|
+
|
35
|
+
return this;
|
36
|
+
}
|
37
|
+
|
38
|
+
async get(namespace: string, key: string): Promise<any> {
|
39
|
+
let res = await this.collection.findOne({
|
40
|
+
_id: dbutils.key(namespace, key),
|
41
|
+
});
|
42
|
+
if (res && res.value) {
|
43
|
+
return res.value;
|
44
|
+
}
|
45
|
+
|
46
|
+
return null;
|
47
|
+
}
|
48
|
+
|
49
|
+
async getByIndex(namespace: string, idx: Index): Promise<any> {
|
50
|
+
const docs = await this.collection
|
51
|
+
.find({
|
52
|
+
indexes: dbutils.keyForIndex(namespace, idx),
|
53
|
+
})
|
54
|
+
.toArray();
|
55
|
+
|
56
|
+
const ret: string[] = [];
|
57
|
+
for (const doc of docs || []) {
|
58
|
+
ret.push(doc.value);
|
59
|
+
}
|
60
|
+
|
61
|
+
return ret;
|
62
|
+
}
|
63
|
+
|
64
|
+
async put(
|
65
|
+
namespace: string,
|
66
|
+
key: string,
|
67
|
+
val: string,
|
68
|
+
ttl: number = 0,
|
69
|
+
...indexes: any[]
|
70
|
+
): Promise<void> {
|
71
|
+
const doc = <Document>{
|
72
|
+
value: val,
|
73
|
+
};
|
74
|
+
|
75
|
+
if (ttl) {
|
76
|
+
doc.expiresAt = new Date(Date.now() + ttl * 1000);
|
77
|
+
}
|
78
|
+
|
79
|
+
// no ttl support for secondary indexes
|
80
|
+
for (const idx of indexes || []) {
|
81
|
+
const idxKey = dbutils.keyForIndex(namespace, idx);
|
82
|
+
|
83
|
+
if (!doc.indexes) {
|
84
|
+
doc.indexes = [];
|
85
|
+
}
|
86
|
+
|
87
|
+
doc.indexes.push(idxKey);
|
88
|
+
}
|
89
|
+
|
90
|
+
await this.collection.updateOne(
|
91
|
+
{ _id: dbutils.key(namespace, key) },
|
92
|
+
{
|
93
|
+
$set: doc,
|
94
|
+
},
|
95
|
+
{ upsert: true }
|
96
|
+
);
|
97
|
+
}
|
98
|
+
|
99
|
+
async delete(namespace: string, key: string): Promise<any> {
|
100
|
+
return await this.collection.deleteOne({
|
101
|
+
_id: dbutils.key(namespace, key),
|
102
|
+
});
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
export default {
|
107
|
+
new: async (options: DatabaseOption): Promise<Mongo> => {
|
108
|
+
return await new Mongo(options).init();
|
109
|
+
},
|
110
|
+
};
|
package/src/db/redis.ts
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
import * as redis from 'redis';
|
2
|
+
import { DatabaseDriver, DatabaseOption, Index } from 'saml-jackson';
|
3
|
+
import * as dbutils from './utils';
|
4
|
+
|
5
|
+
class Redis implements DatabaseDriver {
|
6
|
+
private options: DatabaseOption;
|
7
|
+
private client!: any;
|
8
|
+
|
9
|
+
constructor(options: DatabaseOption) {
|
10
|
+
this.options = options;
|
11
|
+
}
|
12
|
+
|
13
|
+
async init(): Promise<Redis> {
|
14
|
+
let opts = {};
|
15
|
+
|
16
|
+
if (this.options && this.options.url) {
|
17
|
+
opts['socket'] = {
|
18
|
+
url: this.options.url,
|
19
|
+
};
|
20
|
+
}
|
21
|
+
|
22
|
+
this.client = redis.createClient(opts);
|
23
|
+
this.client.on('error', (err: any) =>
|
24
|
+
console.log('Redis Client Error', err)
|
25
|
+
);
|
26
|
+
|
27
|
+
await this.client.connect();
|
28
|
+
|
29
|
+
return this;
|
30
|
+
}
|
31
|
+
|
32
|
+
async get(namespace: string, key: string): Promise<any> {
|
33
|
+
let res = await this.client.get(dbutils.key(namespace, key));
|
34
|
+
if (res) {
|
35
|
+
return JSON.parse(res);
|
36
|
+
}
|
37
|
+
|
38
|
+
return null;
|
39
|
+
}
|
40
|
+
|
41
|
+
async getByIndex(namespace: string, idx: Index): Promise<any> {
|
42
|
+
const dbKeys = await this.client.sMembers(
|
43
|
+
dbutils.keyForIndex(namespace, idx)
|
44
|
+
);
|
45
|
+
|
46
|
+
const ret: string[] = [];
|
47
|
+
for (const dbKey of dbKeys || []) {
|
48
|
+
ret.push(await this.get(namespace, dbKey));
|
49
|
+
}
|
50
|
+
|
51
|
+
return ret;
|
52
|
+
}
|
53
|
+
|
54
|
+
async put(
|
55
|
+
namespace: string,
|
56
|
+
key: string,
|
57
|
+
val: string,
|
58
|
+
ttl: number = 0,
|
59
|
+
...indexes: any[]
|
60
|
+
): Promise<void> {
|
61
|
+
let tx = this.client.multi();
|
62
|
+
const k = dbutils.key(namespace, key);
|
63
|
+
|
64
|
+
tx = tx.set(k, JSON.stringify(val));
|
65
|
+
|
66
|
+
if (ttl) {
|
67
|
+
tx = tx.expire(k, ttl);
|
68
|
+
}
|
69
|
+
|
70
|
+
// no ttl support for secondary indexes
|
71
|
+
for (const idx of indexes || []) {
|
72
|
+
const idxKey = dbutils.keyForIndex(namespace, idx);
|
73
|
+
tx = tx.sAdd(idxKey, key);
|
74
|
+
tx = tx.sAdd(dbutils.keyFromParts(dbutils.indexPrefix, k), idxKey);
|
75
|
+
}
|
76
|
+
|
77
|
+
await tx.exec();
|
78
|
+
}
|
79
|
+
|
80
|
+
async delete(namespace: string, key: string): Promise<any> {
|
81
|
+
let tx = this.client.multi();
|
82
|
+
const k = dbutils.key(namespace, key);
|
83
|
+
tx = tx.del(k);
|
84
|
+
|
85
|
+
const idxKey = dbutils.keyFromParts(dbutils.indexPrefix, k);
|
86
|
+
// delete secondary indexes and then the mapping of the seconary indexes
|
87
|
+
const dbKeys = await this.client.sMembers(idxKey);
|
88
|
+
|
89
|
+
for (const dbKey of dbKeys || []) {
|
90
|
+
tx.sRem(dbKey, key);
|
91
|
+
}
|
92
|
+
|
93
|
+
tx.del(idxKey);
|
94
|
+
|
95
|
+
return await tx.exec();
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
export default {
|
100
|
+
new: async (options: DatabaseOption): Promise<Redis> => {
|
101
|
+
return await new Redis(options).init();
|
102
|
+
},
|
103
|
+
};
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { EntitySchema } from 'typeorm';
|
2
|
+
import { JacksonIndex } from '../model/JacksonIndex';
|
3
|
+
import { JacksonStore } from '../model/JacksonStore';
|
4
|
+
|
5
|
+
export default new EntitySchema({
|
6
|
+
name: 'JacksonIndex',
|
7
|
+
target: JacksonIndex,
|
8
|
+
columns: {
|
9
|
+
id: {
|
10
|
+
primary: true,
|
11
|
+
generated: true,
|
12
|
+
type: 'int',
|
13
|
+
},
|
14
|
+
key: {
|
15
|
+
type: 'varchar',
|
16
|
+
length: 1500,
|
17
|
+
},
|
18
|
+
storeKey: {
|
19
|
+
type: 'varchar',
|
20
|
+
length: 1500,
|
21
|
+
},
|
22
|
+
},
|
23
|
+
relations: {
|
24
|
+
// TODO: Remove the below line to see the error
|
25
|
+
// @ts-ignore
|
26
|
+
store: {
|
27
|
+
target: () => JacksonStore,
|
28
|
+
type: 'many-to-one',
|
29
|
+
inverseSide: 'indexes',
|
30
|
+
eager: true,
|
31
|
+
onDelete: 'CASCADE',
|
32
|
+
},
|
33
|
+
},
|
34
|
+
indices: [
|
35
|
+
{
|
36
|
+
name: '_jackson_index_key',
|
37
|
+
columns: ['key'],
|
38
|
+
},
|
39
|
+
{
|
40
|
+
name: '_jackson_index_key_store',
|
41
|
+
columns: ['key', 'storeKey'],
|
42
|
+
},
|
43
|
+
],
|
44
|
+
});
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { DatabaseType } from 'saml-jackson';
|
2
|
+
import { ColumnType, EntitySchema } from 'typeorm';
|
3
|
+
import { JacksonStore } from '../model/JacksonStore';
|
4
|
+
|
5
|
+
const valueType = (type: DatabaseType): ColumnType => {
|
6
|
+
switch (type) {
|
7
|
+
case 'postgres':
|
8
|
+
case 'cockroachdb':
|
9
|
+
return 'text';
|
10
|
+
case 'mysql':
|
11
|
+
case 'mariadb':
|
12
|
+
return 'mediumtext';
|
13
|
+
default:
|
14
|
+
return 'varchar';
|
15
|
+
}
|
16
|
+
};
|
17
|
+
|
18
|
+
export default (type: DatabaseType) => {
|
19
|
+
return new EntitySchema({
|
20
|
+
name: 'JacksonStore',
|
21
|
+
target: JacksonStore,
|
22
|
+
columns: {
|
23
|
+
key: {
|
24
|
+
primary: true,
|
25
|
+
type: 'varchar',
|
26
|
+
length: 1500,
|
27
|
+
},
|
28
|
+
value: {
|
29
|
+
type: valueType(type),
|
30
|
+
},
|
31
|
+
iv: {
|
32
|
+
type: 'varchar',
|
33
|
+
length: 64,
|
34
|
+
nullable: true,
|
35
|
+
},
|
36
|
+
tag: {
|
37
|
+
type: 'varchar',
|
38
|
+
length: 64,
|
39
|
+
nullable: true,
|
40
|
+
},
|
41
|
+
},
|
42
|
+
});
|
43
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Entity, Column, Index } from 'typeorm';
|
2
|
+
|
3
|
+
@Entity()
|
4
|
+
export class JacksonTTL {
|
5
|
+
@Column({
|
6
|
+
primary: true,
|
7
|
+
type: 'varchar',
|
8
|
+
length: 1500,
|
9
|
+
})
|
10
|
+
key!: string;
|
11
|
+
|
12
|
+
@Index('_jackson_ttl_expires_at')
|
13
|
+
@Column({
|
14
|
+
type: 'bigint',
|
15
|
+
})
|
16
|
+
expiresAt!: number;
|
17
|
+
}
|