@pryv/delegation 3.14.2 → 3.16.0

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/README.md CHANGED
@@ -103,6 +103,8 @@ const created = await delegation.createAccount({
103
103
 
104
104
  ## Detach requires a genuine login on B
105
105
 
106
+ When the delegate accepted cross-account consents for the account, the owner may keep some of them: `detachDelegate('parent-b', { keepAccessIds: ['<grant id>'] })` (core 2.0.0-rc.31 or later; each id must be a consent grant given through this relationship, else `delegation-invalid-keep-list` and nothing changes). The others are withdrawn and their requesters told.
107
+
106
108
  `detachDelegate` and `cancelInvite` remove a delegation relationship, so they require the account owner to be **genuinely logged in** to the controlled account — a delegate PAT or a control token is rejected. A delegated session therefore cannot walk away with, or tear down, the relationship on its own.
107
109
 
108
110
  The rejection surfaces as a typed [`DelegationError`](#typed-errors) with `id === delegationErrorIds.GENUINE_LOGIN_REQUIRED`. Surface it distinctly in your UI:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pryv/delegation",
3
- "version": "3.14.2",
3
+ "version": "3.16.0",
4
4
  "description": "Account-delegation client helpers for Pryv.io",
5
5
  "keywords": [
6
6
  "Pryv",
package/src/index.d.ts CHANGED
@@ -137,7 +137,8 @@ declare module '@pryv/delegation' {
137
137
  requestAttach(delegateUsername: string): Promise<DelegationRecord>;
138
138
  cancelInvite(delegateUsername: string): Promise<void>;
139
139
  listDelegates(): Promise<DelegateRecord[]>;
140
- detachDelegate(delegateUsername: string): Promise<void>;
140
+ /** `opts.keepAccessIds`: consent grants the delegate gave that the owner keeps (core 2.0.0-rc.31+). */
141
+ detachDelegate(delegateUsername: string, opts?: { keepAccessIds?: string[] }): Promise<void>;
141
142
 
142
143
  // A side (the delegate)
143
144
  acceptAttach(controlledUsername: string): Promise<DelegationRecord>;
package/src/index.js CHANGED
@@ -243,11 +243,23 @@ class Delegation {
243
243
  * — surface it distinctly so the UI can explain the account owner must log
244
244
  * in directly (not through a delegated session) to remove a delegate.
245
245
  *
246
+ * The account owner may keep consent grants the delegate gave (core
247
+ * 2.0.0-rc.31 or later): `opts.keepAccessIds` lists them; every other
248
+ * consent grant of the relationship is withdrawn. Each id must be such a
249
+ * grant, else `delegation-invalid-keep-list` and nothing is changed. An
250
+ * older core ignores the list and withdraws them all.
251
+ *
246
252
  * @param {string} delegateUsername the delegate to detach.
253
+ * @param {Object} [opts]
254
+ * @param {string[]} [opts.keepAccessIds] consent grants the owner keeps.
247
255
  * @returns {Promise<void>}
248
256
  */
249
- async detachDelegate (delegateUsername) {
250
- await this._apiOne('delegations.detachDelegate', { username: delegateUsername });
257
+ async detachDelegate (delegateUsername, opts) {
258
+ const params = { username: delegateUsername };
259
+ if (opts != null && Array.isArray(opts.keepAccessIds) && opts.keepAccessIds.length > 0) {
260
+ params.keepAccessIds = opts.keepAccessIds.slice();
261
+ }
262
+ await this._apiOne('delegations.detachDelegate', params);
251
263
  }
252
264
 
253
265
  // ---- A side (the delegate) --------------------------------------------
@@ -168,6 +168,15 @@ describe('[DELM] @pryv/delegation method → endpoint mapping', function () {
168
168
  expect(conn.calls[0].method).to.equal('delegations.detachDelegate');
169
169
  expect(conn.calls[0].params).to.deep.equal({ username: 'bob' });
170
170
  });
171
+
172
+ it('[LCI2] detachDelegate passes keepAccessIds through, and sends none for an empty list', async function () {
173
+ const conn = makeStubConnection({ handlers: { 'delegations.detachDelegate': function () { return {}; } } });
174
+ const d = Delegation.fromConnection(conn);
175
+ await d.detachDelegate('bob', { keepAccessIds: ['g1', 'g2'] });
176
+ expect(conn.calls[0].params).to.deep.equal({ username: 'bob', keepAccessIds: ['g1', 'g2'] });
177
+ await d.detachDelegate('bob', { keepAccessIds: [] });
178
+ expect(conn.calls[1].params).to.deep.equal({ username: 'bob' });
179
+ });
171
180
  });
172
181
 
173
182
  describe('[DELMA] A-side (delegate)', function () {