11const pryv = require ( 'pryv' ) ;
22const { 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 /**
0 commit comments