Skip to content

Commit 23e2d83

Browse files
committed
some refactors
1 parent d715ed8 commit 23e2d83

11 files changed

Lines changed: 254 additions & 50 deletions

File tree

docs/hds-lib.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/hds-lib.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/appTemplates/AppClientAccount.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class AppClientAccount extends Application {
7777
for (const event of eventRes.events) {
7878
const collectorClient = new CollectorClient(this, event);
7979
if (accessHDSCollectorMap[collectorClient.key] != null) collectorClient.accessData = accessHDSCollectorMap[collectorClient.key];
80+
// temp process - might be removed
81+
await collectorClient.checkConsistency();
8082
this.cache.collectorClientsMap[collectorClient.key] = collectorClient;
8183
}
8284

src/appTemplates/Collector.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { HDSLibError } = require('../errors');
2+
const { waitUntilFalse } = require('../utils');
23
const CollectorInvite = require('./CollectorInvite');
34

45
const COLLECTOR_STREAMID_SUFFIXES = {
@@ -173,9 +174,9 @@ class Collector {
173174
}
174175

175176
async #initInvites (forceRefresh) {
176-
while (this.#cache.invitesInitializing) (await new Promise((resolve) => { setTimeout(resolve, 100); }));
177-
this.#cache.invitesInitializing = true;
177+
await waitUntilFalse(() => (this.#cache.invitesInitializing));
178178
if (!forceRefresh && this.#cache.invitesInitialized) return;
179+
this.#cache.invitesInitializing = true;
179180
const queryParams = { types: ['invite/collector-v1'], streams: [this.streamId], fromTime: 0, toTime: 8640000000000000, limit: 10000 };
180181
try {
181182
await this.appManaging.connection.getEventsStreamed(queryParams, (eventData) => {

src/appTemplates/CollectorClient.js

Lines changed: 123 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const pryv = require('pryv');
22
const { HDSLibError } = require('../errors');
3+
const logger = require('../logger');
34

45
/**
56
* Client App in relation to an AppManagingAccount/Collector
@@ -19,24 +20,29 @@ class CollectorClient {
1920
/** @type {Object} - when active or deactivated - there is a link with accessData */
2021
accessData;
2122

23+
/** @property {String} - identified within user's account - can be used to retreive a Collector Client from an app */
2224
get key () {
2325
return CollectorClient.keyFromInfo(this.eventData.content.accessInfo);
2426
}
2527

28+
/** @property {String} - id matching an event within requester's account - used as a reference to communicate with requester */
2629
get requesterEventId () {
2730
return this.eventData.content.requesterEventId;
2831
}
2932

33+
/** @property {Object} - full content of the request */
3034
get requestData () {
3135
return this.eventData.content.requesterEventData.content;
3236
}
3337

38+
/** @property {string} - one of 'Incoming', 'Active', 'Deactivated', 'Refused' */
3439
get status () {
35-
if (!this.accessData) {
36-
return CollectorClient.STATUSES.active;
40+
const eventStatus = this.eventData.content.status;
41+
if (this.accessData && !this.accessData.deleted && this.eventData.content.status !== CollectorClient.STATUSES.active) {
42+
console.log(this.accessData);
43+
throw new HDSLibError('Should be active, try checkConsiency()');
3744
}
38-
if (this.accessData) return CollectorClient.STATUSES.active;
39-
return CollectorClient.STATUSES.incoming;
45+
return eventStatus;
4046
}
4147

4248
constructor (app, eventData, accessData = null) {
@@ -63,38 +69,98 @@ class CollectorClient {
6369
apiEndpoint,
6470
requesterEventId,
6571
requesterEventData: requesterEvents[0],
66-
accessInfo
72+
accessInfo,
73+
status: CollectorClient.STATUSES.incoming
6774
}
6875
};
6976
const event = await app.connection.apiOne('events.create', eventData, 'event');
7077
return new CollectorClient(app, event);
7178
}
7279

7380
/**
74-
* Accept current request
81+
* Update business event with new status
82+
* @param {string} newStatus
83+
* @param {Object} [extraData] - if given this will be added to content ⚠️ - This can ovveride content!
7584
*/
76-
async accept () {
77-
// create access for requester
78-
if (this.accessData != null) throw new HDSLibError('Access Info already set');
79-
// create access
80-
const cleanedPermissions = this.requestData.permissions.map((p) => {
81-
if (p.streamId) return { streamId: p.streamId, level: p.level };
82-
return p;
83-
});
84-
const accessCreateData = {
85-
name: this.key,
86-
type: 'shared',
87-
permissions: cleanedPermissions,
88-
clientData: {
89-
hdsCollectorClient: {
90-
version: 0,
91-
eventData: this.eventData
92-
}
85+
async #updateStatus (newStatus, extraData = null) {
86+
const newContent = structuredClone(this.eventData.content);
87+
newContent.status = newStatus;
88+
if (extraData !== null) Object.assign(newContent, extraData);
89+
const eventData = await this.app.connection.apiOne('events.update', {
90+
id: this.eventData.id,
91+
update: {
92+
content: newContent
93+
}
94+
}, 'event');
95+
this.eventData = eventData;
96+
}
97+
98+
/**
99+
* Refuse current request
100+
*/
101+
async refuse () {
102+
if (this.status !== 'Incoming') throw new HDSLibError('Cannot only refuse incoming requests');
103+
// sent access credentials to requester
104+
// check content of accessInfo
105+
const publicStreamId = this.eventData.content.accessInfo.clientData.hdsCollector.inbox.streamId;
106+
const requesterEventId = this.requesterEventId;
107+
const requestrerApiEndpoint = this.eventData.content.apiEndpoint;
108+
109+
// refuseEvent to be sent to requester
110+
const refuseEvent = {
111+
type: 'refusal/collector-v1',
112+
streamIds: [publicStreamId],
113+
content: {
114+
eventId: requesterEventId
93115
}
94116
};
95-
const accessData = await this.app.connection.apiOne('accesses.create', accessCreateData, 'access');
96-
this.accessData = accessData;
97-
if (!this.accessData.apiEndpoint) throw new HDSLibError('Failed creating request access', accessData);
117+
118+
const requesterConnection = new pryv.Connection(requestrerApiEndpoint);
119+
const requesterEvent = await requesterConnection.apiOne('events.create', refuseEvent, 'event');
120+
121+
await this.#updateStatus(CollectorClient.STATUSES.refused);
122+
return { requesterEvent };
123+
}
124+
125+
/**
126+
* Revoke current request
127+
* @param {boolean} forceAndSkipAccessCreation - internal temporary option,
128+
*/
129+
async revoke () {
130+
if (this.status !== 'Active') throw new HDSLibError('Cannot only revoke an Active CollectorClient');
131+
132+
console.log('Do something for revoke');
133+
}
134+
135+
/**
136+
* Accept current request
137+
* @param {boolean} forceAndSkipAccessCreation - internal temporary option,
138+
*/
139+
async accept (forceAndSkipAccessCreation = false) {
140+
if (forceAndSkipAccessCreation) {
141+
if (!this.accessData?.apiEndpoint || this.accessData?.delete) throw new HDSLibError('Cannot force accept with empty or deleted accessData', this.accessData);
142+
} else {
143+
if (this.status === 'Active') throw new HDSLibError('Cannot accept an Active CollectorClient');
144+
// create access for requester
145+
const cleanedPermissions = this.requestData.permissions.map((p) => {
146+
if (p.streamId) return { streamId: p.streamId, level: p.level };
147+
return p;
148+
});
149+
const accessCreateData = {
150+
name: this.key,
151+
type: 'shared',
152+
permissions: cleanedPermissions,
153+
clientData: {
154+
hdsCollectorClient: {
155+
version: 0,
156+
eventData: this.eventData
157+
}
158+
}
159+
};
160+
const accessData = await this.app.connection.apiOne('accesses.create', accessCreateData, 'access');
161+
this.accessData = accessData;
162+
if (!this.accessData?.apiEndpoint) throw new HDSLibError('Failed creating request access', accessData);
163+
}
98164

99165
// sent access credentials to requester
100166
// check content of accessInfo
@@ -112,10 +178,38 @@ class CollectorClient {
112178
}
113179
};
114180

115-
const requesterConnection = new pryv.Connection(requestrerApiEndpoint);
116-
const requesterEvent = await requesterConnection.apiOne('events.create', acceptEvent, 'event');
181+
try {
182+
const requesterConnection = new pryv.Connection(requestrerApiEndpoint);
183+
const requesterEvent = await requesterConnection.apiOne('events.create', acceptEvent, 'event');
184+
await this.#updateStatus(CollectorClient.STATUSES.active);
185+
return { accessData: this.accessData, requesterEvent };
186+
} catch (e) {
187+
const deactivatedDetail = {
188+
type: 'error',
189+
message: e.message
190+
};
191+
if (e.innerObject) deactivatedDetail.data = e.innerObject;
192+
logger.error('Failed activating', deactivatedDetail);
193+
await this.#updateStatus(CollectorClient.STATUSES.deactivated, { deactivatedDetail });
194+
return false;
195+
}
196+
}
117197

118-
return { accessData, requesterEvent };
198+
/**
199+
* Probable temporary internal to fix possible inconsenticies during lib early stages
200+
*/
201+
async checkConsistency () {
202+
// accessData but not active
203+
if (this.accessData && this.eventData.content.status == null) {
204+
logger.info('Found discrepency with accessData and status not active, fixing it');
205+
if (this.accessData.deleted) {
206+
await this.accept(true);
207+
} else {
208+
await this.revoke();
209+
}
210+
} else {
211+
logger.debug('CollectorClient:checkConsistency', this.accessData);
212+
}
119213
}
120214

121215
/**

src/index-webpack.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import HDSModel from './HDSModel/HDSModel';
22
import appTemplates from './appTemplates/appTemplates';
33
import pryv from './patchedPryv';
44
import { localizeText, setPreferredLocale } from './localizeText';
5+
import logger from './logger';
56
const l = localizeText;
7+
68
/**
79
* Export for webpack build
810
*/
@@ -12,5 +14,6 @@ export {
1214
pryv,
1315
localizeText,
1416
setPreferredLocale,
15-
l
17+
l,
18+
logger
1619
};

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ module.exports = {
66
pryv: require('./patchedPryv'),
77
localizeText,
88
setPreferredLocale,
9-
l: localizeText
9+
l: localizeText,
10+
logger: require('./logger')
1011
};

src/logger.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Basic logger
3+
*/
4+
module.exports = {
5+
setLogger,
6+
info,
7+
error,
8+
debug
9+
};
10+
11+
let logger = {
12+
info: log('info'),
13+
error: log('error'),
14+
debug: log('error')
15+
};
16+
17+
function setLogger (newLogger) {
18+
logger = newLogger;
19+
}
20+
21+
function info () { logger.info(...arguments); }
22+
function error () { logger.error(...arguments); }
23+
function debug () { logger.debug(...arguments); }
24+
25+
function log (type) {
26+
return function () {
27+
console.log(`Logger: [${type}]`, ...arguments);
28+
};
29+
}

src/utils.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,21 @@
33
*/
44

55
module.exports = {
6-
deepFreeze
6+
deepFreeze,
7+
waitUntilFalse
78
};
89

10+
/**
11+
* Timed semaphore
12+
*/
13+
async function waitUntilFalse (callBackToReturnFalse, maxWaitMs = 5000) {
14+
const started = Date.now();
15+
while (callBackToReturnFalse()) {
16+
await new Promise((resolve) => { setTimeout(resolve, 100); });
17+
if (Date.now() - started > maxWaitMs) throw new Error(`Timeout after ${maxWaitMs}ms`);
18+
}
19+
}
20+
921
/**
1022
* Recursively make immutable an object
1123
* @param {*} object

0 commit comments

Comments
 (0)