UNPKG

3.99 kBJavaScriptView Raw
1//
2
3const ObservedRemoveMap = require('./map');
4const getVerifier = require('./verifier');
5const { InvalidSignatureError } = require('./signed-error');
6
7
8
9
10
11
12
13
14class SignedObservedRemoveMap extends ObservedRemoveMap {
15 constructor(entries , options ) {
16 super([], options);
17 if (!options || !options.key) {
18 throw new Error('Missing required options.key parameter');
19 }
20 this.verify = getVerifier(options.key, options.format);
21 this.insertionSignatureMap = new Map();
22 this.deletionSignatureMap = new Map();
23 if (!entries) {
24 return;
25 }
26 for (const [key, value, id, signature] of entries) {
27 this.setSigned(key, value, id, signature);
28 }
29 }
30
31
32
33
34
35 dump() {
36 const [insertQueue, deleteQueue] = super.dump();
37 const signedInsertQueue = insertQueue.map(([key, [id, value]]) => {
38 const signature = this.insertionSignatureMap.get(id);
39 if (!signature) {
40 throw new Error(`Missing signature for insertion key "${JSON.stringify(key)}" with id "${id}" and value "${JSON.stringify(value)}"`);
41 }
42 return [signature, id, key, value];
43 });
44 const signedDeleteQueue = deleteQueue.map(([id, key]) => {
45 const signature = this.deletionSignatureMap.get(id);
46 if (!signature) {
47 throw new Error(`Missing signature for deletion key "${JSON.stringify(key)}" with id "${id}"`);
48 }
49 return [signature, id, key];
50 });
51 const queue = [signedInsertQueue, signedDeleteQueue];
52 return queue;
53 }
54
55 flush() {
56 const now = Date.now();
57 for (const [id] of this.deletions) {
58 const timestamp = parseInt(id.slice(0, 9), 36);
59 if (now - timestamp >= this.maxAge) {
60 this.deletions.delete(id);
61 this.deletionSignatureMap.delete(id);
62 }
63 }
64 }
65
66 process(signedQueue , skipFlush = false) {
67 const [signedInsertQueue, signedDeleteQueue] = signedQueue;
68 const insertQueue = signedInsertQueue.map(([signature, id, key, value]) => {
69 if (!this.verify(signature, key, value, id)) {
70 throw new InvalidSignatureError(`Signature does not match for key "${key}" with value ${JSON.stringify(value)}`);
71 }
72 this.insertionSignatureMap.set(id, signature);
73 return [key, [id, value]];
74 });
75 const deleteQueue = signedDeleteQueue.map(([signature, id, key]) => {
76 if (!this.verify(signature, key, id)) {
77 throw new InvalidSignatureError(`Signature does not match for id ${JSON.stringify(id)}`);
78 }
79 this.deletionSignatureMap.set(id, signature);
80 return [id, key];
81 });
82 const queue = [insertQueue, deleteQueue];
83 super.process(queue, skipFlush);
84 for (const [signature, id, key] of signedInsertQueue) { // eslint-disable-line no-unused-vars
85 const pair = this.pairs.get(key);
86 if (!pair || pair[0] !== id) {
87 this.insertionSignatureMap.delete(id);
88 }
89 }
90 }
91
92 setSigned(key , value , id , signature ) {
93 const message = [signature, id, key, value];
94 this.process([[message], []], true);
95 this.insertQueue.push(message);
96 this.dequeue();
97 return this;
98 }
99
100 deleteSigned(key , id , signature ) {
101 const message = [signature, id, key];
102 this.process([[], [message]], true);
103 this.deleteQueue.push(message);
104 this.dequeue();
105 }
106
107 clear() {
108 throw new Error('Unsupported method clear()');
109 }
110
111 set() {
112 throw new Error('Unsupported method set(), use setSigned()');
113 }
114
115 delete() {
116 throw new Error('Unsupported method delete(), use deleteSignedId()');
117 }
118}
119
120module.exports = SignedObservedRemoveMap;