From c33085f5401c117124db29849560cd8b903e5134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:36:11 +0200 Subject: [PATCH 1/5] Make cannot leave if not a member error into a warning --- frontend/model/contracts/chatroom.js | 5 +++-- frontend/model/contracts/manifests.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/model/contracts/chatroom.js b/frontend/model/contracts/chatroom.js index 72bc2092a7..f6d4cd8d21 100644 --- a/frontend/model/contracts/chatroom.js +++ b/frontend/model/contracts/chatroom.js @@ -300,11 +300,12 @@ sbp('chelonia/defineContract', { username: optional(string), // coming from the gi.contracts/group/leaveChatRoom member: string // username to be removed }), - process ({ data, meta, hash, id }, { state }) { + process ({ data, meta, hash, id, contractID }, { state }) { const { member } = data const isKicked = data.username && member !== data.username if (!state.onlyRenderMessage && !state.users[member]) { - throw new Error(`Can not leave the chatroom which ${member} is not part of`) + console.warn(`Can not leave the chatroom ${contractID} which ${member} is not part of`) + return } Vue.delete(state.users, member) diff --git a/frontend/model/contracts/manifests.json b/frontend/model/contracts/manifests.json index 569d5d17ee..b633da234d 100644 --- a/frontend/model/contracts/manifests.json +++ b/frontend/model/contracts/manifests.json @@ -1,6 +1,6 @@ { "manifests": { - "gi.contracts/chatroom": "21XWnNLtWByWqqxVAzC4hKTFBPeuc2WkiT72MivJcfYLizqHi1", + "gi.contracts/chatroom": "21XWnNJr1tLQM1XwNVBUxVCuKADSSJmXVK3DWShAEt6HJeAvD8", "gi.contracts/group": "21XWnNTihqK5Pwu1Fy9Bf3Eh4MN446oKu7QTSgnQD54q4R93Cy", "gi.contracts/identity": "21XWnNSxNrVFTMBCUVcZV3CG833gTbJ9V8ZyX7Fxgmpj9rNy4r" } From 44c85a2cc966e82d05e65a226968731e0f326b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Thu, 19 Oct 2023 19:20:10 +0200 Subject: [PATCH 2/5] Show login error prompt only for errors related to the identity contract itself --- frontend/controller/actions/identity.js | 93 +++++++++++++------------ 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/frontend/controller/actions/identity.js b/frontend/controller/actions/identity.js index 59e85ef618..feb996f5b5 100644 --- a/frontend/controller/actions/identity.js +++ b/frontend/controller/actions/identity.js @@ -389,9 +389,7 @@ export default (sbp('sbp/selectors/register', { ) })) } - if (!contractIDs.includes(identityContractID)) { - contractIDs.push(identityContractID) - } + await sbp('gi.db/settings/save', SETTING_CURRENT_USER, identityContractID) const loginAttributes = { identityContractID, encryptionParams, username } @@ -407,50 +405,11 @@ export default (sbp('sbp/selectors/register', { sbp('state/vuex/commit', 'login', loginAttributes) await sbp('chelonia/storeSecretKeys', () => transientSecretKeys) + // IMPORTANT: we avoid using 'await' on the syncs so that Vue.js can proceed // loading the website instead of stalling out. // See the TODO note in startApp (main.js) for why this is not awaited - sbp('chelonia/contract/sync', contractIDs).then(async function () { - // contract sync might've triggered an async call to /remove, so wait before proceeding - await sbp('chelonia/contract/wait', contractIDs) - // similarly, since removeMember may have triggered saveOurLoginState asynchronously, - // we must re-sync our identity contract again to ensure we don't rejoin a group we - // were just kicked out of - await sbp('chelonia/contract/sync', identityContractID, { force: true }) - await sbp('gi.actions/identity/updateLoginStateUponLogin') - await sbp('gi.actions/identity/saveOurLoginState') // will only update it if it's different - - // The state above might be null, so we re-grab it - const state = sbp('state/vuex/state') - - // Call 'gi.actions/group/join' on all groups which may need re-joining - await Promise.all(groupsToRejoin.map(groupId => { - return ( - // (1) Check whether the contract exists (may have been removed - // after sync) - state.contracts[groupId] && - // (2) Check whether the join process is still incomplete - // This needs to be re-checked because it may have changed after - // sync - !state.profiles?.[username] && - // (3) Call join - sbp('gi.actions/group/join', { contractID: groupId, contractName: 'gi.contracts/group' }) - ) - })) - - // update the 'lastLoggedIn' field in user's group profiles - sbp('state/vuex/getters').groupsByName - .map(entry => entry.contractID) - .forEach(cId => { - // We send this action only for groups we have fully joined (i.e., - // accepted an invite add added our profile) - if (state[cId]?.profiles?.[username]) { - sbp('gi.actions/group/updateLastLoggedIn', { contractID: cId }).catch(console.error) - } - }) - - sbp('okTurtles.events/emit', LOGIN, { username, identityContractID }) - }).catch((err) => { + sbp('chelonia/contract/sync', identityContractID, { force: true }).catch((err) => { sbp('okTurtles.events/emit', LOGIN_ERROR, { username, identityContractID, error: err }) const errMessage = err?.message || String(err) console.error('Error during login contract sync', errMessage) @@ -469,7 +428,51 @@ export default (sbp('sbp/selectors/register', { }).catch((e) => { console.error('Error at gi.ui/prompt', e) }) - }) + }).then(() => + sbp('chelonia/contract/sync', contractIDs).then(async function () { + // contract sync might've triggered an async call to /remove, so wait before proceeding + await sbp('chelonia/contract/wait', contractIDs) + // similarly, since removeMember may have triggered saveOurLoginState asynchronously, + // we must re-sync our identity contract again to ensure we don't rejoin a group we + // were just kicked out of + await sbp('chelonia/contract/sync', identityContractID, { force: true }) + await sbp('gi.actions/identity/updateLoginStateUponLogin') + await sbp('gi.actions/identity/saveOurLoginState') // will only update it if it's different + + // The state above might be null, so we re-grab it + const state = sbp('state/vuex/state') + + // Call 'gi.actions/group/join' on all groups which may need re-joining + await Promise.all(groupsToRejoin.map(groupId => { + return ( + // (1) Check whether the contract exists (may have been removed + // after sync) + state.contracts[groupId] && + // (2) Check whether the join process is still incomplete + // This needs to be re-checked because it may have changed after + // sync + !state.profiles?.[username] && + // (3) Call join + sbp('gi.actions/group/join', { contractID: groupId, contractName: 'gi.contracts/group' }) + ) + })) + + // update the 'lastLoggedIn' field in user's group profiles + sbp('state/vuex/getters').groupsByName + .map(entry => entry.contractID) + .forEach(cId => { + // We send this action only for groups we have fully joined (i.e., + // accepted an invite add added our profile) + if (state[cId]?.profiles?.[username]) { + sbp('gi.actions/group/updateLastLoggedIn', { contractID: cId }).catch(console.error) + } + }) + }).catch((err) => { + console.error('Error during contract sync upon login', err) + }).finally(() => { + sbp('okTurtles.events/emit', LOGIN, { username, identityContractID }) + }) + ) return identityContractID } catch (e) { console.error('gi.actions/identity/login failed!', e) From 976021db4d45340262d2e79c8ea79d331f3970f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Thu, 19 Oct 2023 20:57:13 +0200 Subject: [PATCH 3/5] Fix issue of removing two members (error on second removal) --- frontend/model/contracts/group.js | 1 + frontend/model/contracts/manifests.json | 2 +- shared/domains/chelonia/chelonia.js | 4 ++++ shared/domains/chelonia/internals.js | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/model/contracts/group.js b/frontend/model/contracts/group.js index ecb2b4ece5..db0b74f975 100644 --- a/frontend/model/contracts/group.js +++ b/frontend/model/contracts/group.js @@ -1040,6 +1040,7 @@ sbp('chelonia/defineContract', { // TODO: per #257 this will ,have to be encompassed in a recoverable transaction // however per #610 that might be handled in handleEvent (?), or per #356 might not be needed if (meta.username === loggedIn.username) { + if (!sbp('okTurtles.data/get', 'JOINING_GROUP-' + contractID)) return // we're the person who just accepted the group invite // so subscribe to founder's IdentityContract & everyone else's const lookupResult = await Promise.allSettled( diff --git a/frontend/model/contracts/manifests.json b/frontend/model/contracts/manifests.json index b633da234d..ba27b6118d 100644 --- a/frontend/model/contracts/manifests.json +++ b/frontend/model/contracts/manifests.json @@ -1,7 +1,7 @@ { "manifests": { "gi.contracts/chatroom": "21XWnNJr1tLQM1XwNVBUxVCuKADSSJmXVK3DWShAEt6HJeAvD8", - "gi.contracts/group": "21XWnNTihqK5Pwu1Fy9Bf3Eh4MN446oKu7QTSgnQD54q4R93Cy", + "gi.contracts/group": "21XWnNXzqXPZyURGHb7RXYLnwFNTZGTxSZWcsBLnzyueoMmuCw", "gi.contracts/identity": "21XWnNSxNrVFTMBCUVcZV3CG833gTbJ9V8ZyX7Fxgmpj9rNy4r" } } diff --git a/shared/domains/chelonia/chelonia.js b/shared/domains/chelonia/chelonia.js index d9fa0402c6..f11cd58856 100644 --- a/shared/domains/chelonia/chelonia.js +++ b/shared/domains/chelonia/chelonia.js @@ -448,6 +448,10 @@ export default (sbp('sbp/selectors/register', { [`${contract.manifest}/${action}/sideEffect`]: async (mutation: Object, state: ?Object) => { if (contract.actions[action].sideEffect) { state = state || contract.state(mutation.contractID) + if (!state) { + console.warn(`[${contract.manifest}/${action}/sideEffect]: Skipping side-effect since there is no contract state for contract ${mutation.contractID}`) + return + } const gProxy = gettersProxy(state, contract.getters) await contract.actions[action].sideEffect(mutation, { state, ...gProxy }) } diff --git a/shared/domains/chelonia/internals.js b/shared/domains/chelonia/internals.js index 5bac284a08..18b1362d91 100644 --- a/shared/domains/chelonia/internals.js +++ b/shared/domains/chelonia/internals.js @@ -666,6 +666,7 @@ export default (sbp('sbp/selectors/register', { if (!state._volatile.pendingKeyRevocations) config.reactiveSet(state._volatile, 'pendingKeyRevocations', Object.create(null)) const [updatedKeys, updatedMap] = validateKeyUpdatePermissions(contractID, signingKey, state, v) const keysToDelete = ((Object.values(updatedMap): any): string[]) + console.log('@@@KEY_UPDATE', cloneDeep({ contractID, updatedKeys, keysToDelete })) for (const keyId of keysToDelete) { if (has(state._volatile.pendingKeyRevocations, keyId)) { delete state._volatile.pendingKeyRevocations[keyId] @@ -676,8 +677,8 @@ export default (sbp('sbp/selectors/register', { for (const key of updatedKeys) { if (!has(state._vm.authorizedKeys, key.id)) { key._notBeforeHeight = height + config.reactiveSet(state._vm.authorizedKeys, key.id, cloneDeep(key)) } - config.reactiveSet(state._vm.authorizedKeys, key.id, cloneDeep(key)) } keyAdditionProcessor.call(self, (updatedKeys: any), state, contractID, signingKey) From cc98510b8f6811128741db25a5661e6da43c2a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:37:48 +0200 Subject: [PATCH 4/5] Update identity.js login logic, remove spurious sideEffect check --- frontend/controller/actions/identity.js | 111 ++++++++++++------------ frontend/model/contracts/group.js | 1 - 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/frontend/controller/actions/identity.js b/frontend/controller/actions/identity.js index feb996f5b5..c47b5cdadc 100644 --- a/frontend/controller/actions/identity.js +++ b/frontend/controller/actions/identity.js @@ -409,70 +409,73 @@ export default (sbp('sbp/selectors/register', { // IMPORTANT: we avoid using 'await' on the syncs so that Vue.js can proceed // loading the website instead of stalling out. // See the TODO note in startApp (main.js) for why this is not awaited - sbp('chelonia/contract/sync', identityContractID, { force: true }).catch((err) => { - sbp('okTurtles.events/emit', LOGIN_ERROR, { username, identityContractID, error: err }) - const errMessage = err?.message || String(err) - console.error('Error during login contract sync', errMessage) - - const promptOptions = { - heading: L('Login error'), - question: L('Do you want to log out? Error details: {err}.', { err: err.message }), - primaryButton: L('No'), - secondaryButton: L('Yes') - } - - sbp('gi.ui/prompt', promptOptions).then((result) => { - if (!result) { - sbp('gi.actions/identity/logout') + sbp('chelonia/contract/sync', identityContractID, { force: true }) + .catch((err) => { + sbp('okTurtles.events/emit', LOGIN_ERROR, { username, identityContractID, error: err }) + const errMessage = err?.message || String(err) + console.error('Error during login contract sync', errMessage) + + const promptOptions = { + heading: L('Login error'), + question: L('Do you want to log out? Error details: {err}.', { err: err.message }), + primaryButton: L('No'), + secondaryButton: L('Yes') } - }).catch((e) => { - console.error('Error at gi.ui/prompt', e) - }) - }).then(() => - sbp('chelonia/contract/sync', contractIDs).then(async function () { + + sbp('gi.ui/prompt', promptOptions).then((result) => { + if (!result) { + sbp('gi.actions/identity/logout') + } + }).catch((e) => { + console.error('Error at gi.ui/prompt', e) + }) + + throw new Error('Unable to sync identity contract') + }).then(() => + sbp('chelonia/contract/sync', contractIDs).then(async function () { // contract sync might've triggered an async call to /remove, so wait before proceeding - await sbp('chelonia/contract/wait', contractIDs) - // similarly, since removeMember may have triggered saveOurLoginState asynchronously, - // we must re-sync our identity contract again to ensure we don't rejoin a group we - // were just kicked out of - await sbp('chelonia/contract/sync', identityContractID, { force: true }) - await sbp('gi.actions/identity/updateLoginStateUponLogin') - await sbp('gi.actions/identity/saveOurLoginState') // will only update it if it's different - - // The state above might be null, so we re-grab it - const state = sbp('state/vuex/state') - - // Call 'gi.actions/group/join' on all groups which may need re-joining - await Promise.all(groupsToRejoin.map(groupId => { - return ( - // (1) Check whether the contract exists (may have been removed - // after sync) - state.contracts[groupId] && + await sbp('chelonia/contract/wait', contractIDs) + // similarly, since removeMember may have triggered saveOurLoginState asynchronously, + // we must re-sync our identity contract again to ensure we don't rejoin a group we + // were just kicked out of + await sbp('chelonia/contract/sync', identityContractID, { force: true }) + await sbp('gi.actions/identity/updateLoginStateUponLogin') + await sbp('gi.actions/identity/saveOurLoginState') // will only update it if it's different + + // The state above might be null, so we re-grab it + const state = sbp('state/vuex/state') + + // Call 'gi.actions/group/join' on all groups which may need re-joining + await Promise.all(groupsToRejoin.map(groupId => { + return ( + // (1) Check whether the contract exists (may have been removed + // after sync) + state.contracts[groupId] && // (2) Check whether the join process is still incomplete // This needs to be re-checked because it may have changed after // sync !state.profiles?.[username] && // (3) Call join sbp('gi.actions/group/join', { contractID: groupId, contractName: 'gi.contracts/group' }) - ) - })) - - // update the 'lastLoggedIn' field in user's group profiles - sbp('state/vuex/getters').groupsByName - .map(entry => entry.contractID) - .forEach(cId => { - // We send this action only for groups we have fully joined (i.e., - // accepted an invite add added our profile) - if (state[cId]?.profiles?.[username]) { - sbp('gi.actions/group/updateLastLoggedIn', { contractID: cId }).catch(console.error) - } - }) - }).catch((err) => { + ) + })) + + // update the 'lastLoggedIn' field in user's group profiles + sbp('state/vuex/getters').groupsByName + .map(entry => entry.contractID) + .forEach(cId => { + // We send this action only for groups we have fully joined (i.e., + // accepted an invite add added our profile) + if (state[cId]?.profiles?.[username]) { + sbp('gi.actions/group/updateLastLoggedIn', { contractID: cId }).catch(console.error) + } + }) + }).finally(() => { + sbp('okTurtles.events/emit', LOGIN, { username, identityContractID }) + }) + ).catch((err) => { console.error('Error during contract sync upon login', err) - }).finally(() => { - sbp('okTurtles.events/emit', LOGIN, { username, identityContractID }) }) - ) return identityContractID } catch (e) { console.error('gi.actions/identity/login failed!', e) diff --git a/frontend/model/contracts/group.js b/frontend/model/contracts/group.js index db0b74f975..ecb2b4ece5 100644 --- a/frontend/model/contracts/group.js +++ b/frontend/model/contracts/group.js @@ -1040,7 +1040,6 @@ sbp('chelonia/defineContract', { // TODO: per #257 this will ,have to be encompassed in a recoverable transaction // however per #610 that might be handled in handleEvent (?), or per #356 might not be needed if (meta.username === loggedIn.username) { - if (!sbp('okTurtles.data/get', 'JOINING_GROUP-' + contractID)) return // we're the person who just accepted the group invite // so subscribe to founder's IdentityContract & everyone else's const lookupResult = await Promise.allSettled( From 2cf36e56323d2f5c9ef69a566a3824fe8a14e479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:43:08 +0200 Subject: [PATCH 5/5] pin contracts --- contracts/0.2.0/chatroom-slim.js | 9 +-- contracts/0.2.0/chatroom.0.2.0.manifest.json | 2 +- contracts/0.2.0/chatroom.js | 9 +-- contracts/0.2.0/group-slim.js | 76 +++++++++++--------- contracts/0.2.0/group.0.2.0.manifest.json | 2 +- contracts/0.2.0/group.js | 76 +++++++++++--------- frontend/model/contracts/manifests.json | 2 +- 7 files changed, 95 insertions(+), 81 deletions(-) diff --git a/contracts/0.2.0/chatroom-slim.js b/contracts/0.2.0/chatroom-slim.js index 7724d4c00a..09522c22b4 100644 --- a/contracts/0.2.0/chatroom-slim.js +++ b/contracts/0.2.0/chatroom-slim.js @@ -7090,8 +7090,8 @@ ${this.getErrorInfo()}`; }); // shared/domains/chelonia/utils.js - var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight === void 0)?.id; - var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight === void 0 && k.foreignKey?.includes(contractID)).map((k) => k.id); + var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight == null)?.id; + var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.foreignKey?.includes(contractID)).map((k) => k.id); // frontend/model/contracts/shared/constants.js var CHATROOM_NAME_LIMITS_IN_CHARS = 50; @@ -7500,11 +7500,12 @@ ${this.getErrorInfo()}`; username: optional(string), member: string }), - process({ data, meta, hash, id }, { state }) { + process({ data, meta, hash, id, contractID }, { state }) { const { member } = data; const isKicked = data.username && member !== data.username; if (!state.onlyRenderMessage && !state.users[member]) { - throw new Error(`Can not leave the chatroom which ${member} is not part of`); + console.warn(`Can not leave the chatroom ${contractID} which ${member} is not part of`); + return; } import_common.Vue.delete(state.users, member); if (!state.onlyRenderMessage || state.attributes.type === CHATROOM_TYPES.DIRECT_MESSAGE) { diff --git a/contracts/0.2.0/chatroom.0.2.0.manifest.json b/contracts/0.2.0/chatroom.0.2.0.manifest.json index 741733921b..11509a6301 100644 --- a/contracts/0.2.0/chatroom.0.2.0.manifest.json +++ b/contracts/0.2.0/chatroom.0.2.0.manifest.json @@ -1 +1 @@ -{"head":{"manifestVersion":"1.0.0"},"body":"{\"version\":\"0.2.0\",\"contract\":{\"hash\":\"21XWnNP5tqDKeAYvG6eryALLv7QyKVsooZr42xvVpGKYgZE4ya\",\"file\":\"chatroom.js\"},\"authors\":[{\"cipher\":\"algo\",\"key\":\"\"},{\"cipher\":\"algo\",\"key\":\"\"}],\"contractSlim\":{\"file\":\"chatroom-slim.js\",\"hash\":\"21XWnNMFtepu694mgggFzcQTfVJHeZLrA6yCaQEs3EypSeC85T\"}}","signature":{"key":"","signature":""}} \ No newline at end of file +{"head":{"manifestVersion":"1.0.0"},"body":"{\"version\":\"0.2.0\",\"contract\":{\"hash\":\"21XWnNMSuCrnYWd5k4rfgiER52edE4n4ZsMuMxxgLB8tEXRfpQ\",\"file\":\"chatroom.js\"},\"authors\":[{\"cipher\":\"algo\",\"key\":\"\"},{\"cipher\":\"algo\",\"key\":\"\"}],\"contractSlim\":{\"file\":\"chatroom-slim.js\",\"hash\":\"21XWnNTNdo9ejZSdvNfCFHnh3kQPqNTXesNScNcXaezGTfJfYF\"}}","signature":{"key":"","signature":""}} \ No newline at end of file diff --git a/contracts/0.2.0/chatroom.js b/contracts/0.2.0/chatroom.js index 42e317f39b..ed1df256d5 100644 --- a/contracts/0.2.0/chatroom.js +++ b/contracts/0.2.0/chatroom.js @@ -16184,8 +16184,8 @@ ${this.getErrorInfo()}`; }); // shared/domains/chelonia/utils.js - var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight === void 0)?.id; - var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight === void 0 && k.foreignKey?.includes(contractID)).map((k) => k.id); + var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight == null)?.id; + var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.foreignKey?.includes(contractID)).map((k) => k.id); // frontend/model/contracts/shared/constants.js var CHATROOM_NAME_LIMITS_IN_CHARS = 50; @@ -16594,11 +16594,12 @@ ${this.getErrorInfo()}`; username: optional(string), member: string }), - process({ data, meta, hash: hash2, id }, { state }) { + process({ data, meta, hash: hash2, id, contractID }, { state }) { const { member } = data; const isKicked = data.username && member !== data.username; if (!state.onlyRenderMessage && !state.users[member]) { - throw new Error(`Can not leave the chatroom which ${member} is not part of`); + console.warn(`Can not leave the chatroom ${contractID} which ${member} is not part of`); + return; } vue_esm_default.delete(state.users, member); if (!state.onlyRenderMessage || state.attributes.type === CHATROOM_TYPES.DIRECT_MESSAGE) { diff --git a/contracts/0.2.0/group-slim.js b/contracts/0.2.0/group-slim.js index c04c3c3645..81e95c38fd 100644 --- a/contracts/0.2.0/group-slim.js +++ b/contracts/0.2.0/group-slim.js @@ -7721,8 +7721,8 @@ ${this.getErrorInfo()}`; }); // shared/domains/chelonia/utils.js - var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight === void 0)?.id; - var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight === void 0 && k.foreignKey?.includes(contractID)).map((k) => k.id); + var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight == null)?.id; + var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.foreignKey?.includes(contractID)).map((k) => k.id); // frontend/model/notifications/mutationKeys.js var REMOVE_NOTIFICATION = "removeNotification"; @@ -8424,7 +8424,7 @@ ${this.getErrorInfo()}`; } }).catch((e) => { console.error(`sideEffect(removeMember): ${e.name} thrown during queueEvent to ${contractID} by saveOurLoginState:`, e); - }).then(() => (0, import_sbp6.default)("gi.contracts/group/revokeGroupKeyAndRotateOurPEK", contractID)).catch((e) => { + }).then(() => (0, import_sbp6.default)("gi.contracts/group/revokeGroupKeyAndRotateOurPEK", contractID, true)).catch((e) => { console.error(`sideEffect(removeMember): ${e.name} thrown during revokeGroupKeyAndRotateOurPEK to ${contractID}:`, e); }); for (const notification of rootGetters.notificationsByGroup(contractID)) { @@ -8439,7 +8439,11 @@ ${this.getErrorInfo()}`; groupID: contractID, username: memberRemovedThemselves ? meta.username : data.member }); - (0, import_sbp6.default)("gi.contracts/group/rotateKeys", contractID, state); + (0, import_sbp6.default)("gi.contracts/group/rotateKeys", contractID, state).then(() => { + return (0, import_sbp6.default)("gi.contracts/group/revokeGroupKeyAndRotateOurPEK", contractID, false); + }).catch((e) => { + console.error("Error rotating group keys or our PEK", e); + }); const rootGetters2 = (0, import_sbp6.default)("state/vuex/getters"); const userID = rootGetters2.ourContactProfiles[data.member]?.contractID; if (userID) { @@ -8760,8 +8764,8 @@ ${this.getErrorInfo()}`; }, methods: { "gi.contracts/group/archiveProposal": async function(contractID, proposalHash, proposal) { - const { username } = (0, import_sbp6.default)("state/vuex/state").loggedIn; - const key = `proposals/${username}/${contractID}`; + const { identityContractID } = (0, import_sbp6.default)("state/vuex/state").loggedIn; + const key = `proposals/${identityContractID}/${contractID}`; const proposals2 = await (0, import_sbp6.default)("gi.db/archive/load", key) || []; proposals2.unshift([proposalHash, proposal]); while (proposals2.length > MAX_ARCHIVED_PROPOSALS) { @@ -8772,10 +8776,10 @@ ${this.getErrorInfo()}`; }, "gi.contracts/group/archivePayments": async function(contractID, archivingPayments) { const { paymentsByPeriod, payments } = archivingPayments; - const { username } = (0, import_sbp6.default)("state/vuex/state").loggedIn; - const archPaymentsByPeriodKey = `paymentsByPeriod/${username}/${contractID}`; + const { identityContractID, username } = (0, import_sbp6.default)("state/vuex/state").loggedIn; + const archPaymentsByPeriodKey = `paymentsByPeriod/${identityContractID}/${contractID}`; const archPaymentsByPeriod = await (0, import_sbp6.default)("gi.db/archive/load", archPaymentsByPeriodKey) || {}; - const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${username}/${contractID}`; + const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${identityContractID}/${contractID}`; const archSentOrReceivedPayments = await (0, import_sbp6.default)("gi.db/archive/load", archSentOrReceivedPaymentsKey) || { sent: [], received: [] }; const sortPayments = (payments2) => payments2.sort((f, l) => compareISOTimestamps(l.meta.createdDate, f.meta.createdDate)); for (const period of Object.keys(paymentsByPeriod).sort()) { @@ -8795,13 +8799,13 @@ ${this.getErrorInfo()}`; } archSentOrReceivedPayments.sent = [...sortPayments(newSentOrReceivedPayments.sent), ...archSentOrReceivedPayments.sent]; archSentOrReceivedPayments.received = [...sortPayments(newSentOrReceivedPayments.received), ...archSentOrReceivedPayments.received]; - const archPaymentsKey = `payments/${username}/${period}/${contractID}`; + const archPaymentsKey = `payments/${identityContractID}/${period}/${contractID}`; const hashes = paymentHashesFromPaymentPeriod(paymentsByPeriod[period]); const archPayments = Object.fromEntries(hashes.map((hash) => [hash, payments[hash]])); while (Object.keys(archPaymentsByPeriod).length > MAX_ARCHIVED_PERIODS) { const shouldBeDeletedPeriod = Object.keys(archPaymentsByPeriod).sort().shift(); const paymentHashes = paymentHashesFromPaymentPeriod(archPaymentsByPeriod[shouldBeDeletedPeriod]); - await (0, import_sbp6.default)("gi.db/archive/delete", `payments/${shouldBeDeletedPeriod}/${username}/${contractID}`); + await (0, import_sbp6.default)("gi.db/archive/delete", `payments/${shouldBeDeletedPeriod}/${identityContractID}/${contractID}`); delete archPaymentsByPeriod[shouldBeDeletedPeriod]; archSentOrReceivedPayments.sent = archSentOrReceivedPayments.sent.filter((payment) => !paymentHashes.includes(payment.hash)); archSentOrReceivedPayments.received = archSentOrReceivedPayments.received.filter((payment) => !paymentHashes.includes(payment.hash)); @@ -8813,17 +8817,17 @@ ${this.getErrorInfo()}`; (0, import_sbp6.default)("okTurtles.events/emit", PAYMENTS_ARCHIVED, { paymentsByPeriod, payments }); }, "gi.contracts/group/removeArchivedProposals": async function(contractID) { - const { username } = (0, import_sbp6.default)("state/vuex/state").loggedIn; - const key = `proposals/${username}/${contractID}`; + const { identityContractID } = (0, import_sbp6.default)("state/vuex/state").loggedIn; + const key = `proposals/${identityContractID}/${contractID}`; await (0, import_sbp6.default)("gi.db/archive/delete", key); }, "gi.contracts/group/removeArchivedPayments": async function(contractID) { - const { username } = (0, import_sbp6.default)("state/vuex/state").loggedIn; - const archPaymentsByPeriodKey = `paymentsByPeriod/${username}/${contractID}`; + const { identityContractID } = (0, import_sbp6.default)("state/vuex/state").loggedIn; + const archPaymentsByPeriodKey = `paymentsByPeriod/${identityContractID}/${contractID}`; const periods = Object.keys(await (0, import_sbp6.default)("gi.db/archive/load", archPaymentsByPeriodKey) || {}); - const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${username}/${contractID}`; + const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${identityContractID}/${contractID}`; for (const period of periods) { - const archPaymentsKey = `payments/${username}/${period}/${contractID}`; + const archPaymentsKey = `payments/${identityContractID}/${period}/${contractID}`; await (0, import_sbp6.default)("gi.db/archive/delete", archPaymentsKey); } await (0, import_sbp6.default)("gi.db/archive/delete", archPaymentsByPeriodKey); @@ -8873,11 +8877,11 @@ ${this.getErrorInfo()}`; const CEKid = findKeyIdByName(state, "cek"); import_common3.Vue.set(state._volatile.pendingKeyRevocations, CSKid, true); import_common3.Vue.set(state._volatile.pendingKeyRevocations, CEKid, true); - (0, import_sbp6.default)("chelonia/queueInvocation", contractID, ["gi.actions/out/rotateKeys", contractID, "gi.contracts/group", "pending", "gi.actions/group/shareNewKeys"]).catch((e) => { + return (0, import_sbp6.default)("chelonia/queueInvocation", contractID, ["gi.actions/out/rotateKeys", contractID, "gi.contracts/group", "pending", "gi.actions/group/shareNewKeys"]).catch((e) => { console.warn(`rotateKeys: ${e.name} thrown during queueEvent to ${contractID}:`, e); }); }, - "gi.contracts/group/revokeGroupKeyAndRotateOurPEK": (groupContractID) => { + "gi.contracts/group/revokeGroupKeyAndRotateOurPEK": (groupContractID, disconnectGroup) => { const rootState = (0, import_sbp6.default)("state/vuex/state"); const { identityContractID } = rootState.loggedIn; const state = rootState[identityContractID]; @@ -8886,25 +8890,27 @@ ${this.getErrorInfo()}`; const CSKid = findKeyIdByName(state, "csk"); const CEKid = findKeyIdByName(state, "cek"); const PEKid = findKeyIdByName(state, "pek"); - const groupCSKids = findForeignKeysByContractID(state, groupContractID); import_common3.Vue.set(state._volatile.pendingKeyRevocations, PEKid, true); - if (groupCSKids?.length) { - if (!CEKid) { - throw new Error("Identity CEK not found"); - } - (0, import_sbp6.default)("chelonia/queueInvocation", identityContractID, ["chelonia/out/keyDel", { - contractID: identityContractID, - contractName: "gi.contracts/identity", - data: groupCSKids, - signingKeyId: CSKid - }]).catch((e) => { - console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during keyDel to ${identityContractID}:`, e); + if (disconnectGroup) { + const groupCSKids = findForeignKeysByContractID(state, groupContractID); + if (groupCSKids?.length) { + if (!CEKid) { + throw new Error("Identity CEK not found"); + } + (0, import_sbp6.default)("chelonia/queueInvocation", identityContractID, ["chelonia/out/keyDel", { + contractID: identityContractID, + contractName: "gi.contracts/identity", + data: groupCSKids, + signingKeyId: CSKid + }]).catch((e) => { + console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during keyDel to ${identityContractID}:`, e); + }); + } + (0, import_sbp6.default)("chelonia/queueInvocation", identityContractID, ["chelonia/contract/disconnect", identityContractID, groupContractID]).catch((e) => { + console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during queueEvent to ${identityContractID}:`, e); }); } - (0, import_sbp6.default)("chelonia/queueInvocation", identityContractID, ["chelonia/contract/disconnect", identityContractID, groupContractID]).catch((e) => { - console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during queueEvent to ${identityContractID}:`, e); - }); - (0, import_sbp6.default)("chelonia/queueInvocation", identityContractID, ["gi.actions/out/rotateKeys", identityContractID, "gi.contracts/identity", "pending", "gi.actions/identity/shareNewPEK"]).catch((e) => { + return (0, import_sbp6.default)("chelonia/queueInvocation", identityContractID, ["gi.actions/out/rotateKeys", identityContractID, "gi.contracts/identity", "pending", "gi.actions/identity/shareNewPEK"]).catch((e) => { console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during queueEvent to ${identityContractID}:`, e); }); }, diff --git a/contracts/0.2.0/group.0.2.0.manifest.json b/contracts/0.2.0/group.0.2.0.manifest.json index be4ee6837f..dd9e3824ae 100644 --- a/contracts/0.2.0/group.0.2.0.manifest.json +++ b/contracts/0.2.0/group.0.2.0.manifest.json @@ -1 +1 @@ -{"head":{"manifestVersion":"1.0.0"},"body":"{\"version\":\"0.2.0\",\"contract\":{\"hash\":\"21XWnNL4g66rNK5wkSH9vZD6H6ZDJXJ84ecvCzPkBoaiCHkgmM\",\"file\":\"group.js\"},\"authors\":[{\"cipher\":\"algo\",\"key\":\"\"},{\"cipher\":\"algo\",\"key\":\"\"}],\"contractSlim\":{\"file\":\"group-slim.js\",\"hash\":\"21XWnNMhWKeNnBG1upPDBdvrKWuERWGaKdNpCUcyfQ7Bj6QG3y\"}}","signature":{"key":"","signature":""}} \ No newline at end of file +{"head":{"manifestVersion":"1.0.0"},"body":"{\"version\":\"0.2.0\",\"contract\":{\"hash\":\"21XWnNVqB5fYNAa2mufrsDVWZUsdeW82snkcx4pa4yWjvfTk3c\",\"file\":\"group.js\"},\"authors\":[{\"cipher\":\"algo\",\"key\":\"\"},{\"cipher\":\"algo\",\"key\":\"\"}],\"contractSlim\":{\"file\":\"group-slim.js\",\"hash\":\"21XWnNUmvc1AqRF86c4Wk9hixK64uyG7LHkNi8iNqVs1kXKKpg\"}}","signature":{"key":"","signature":""}} \ No newline at end of file diff --git a/contracts/0.2.0/group.js b/contracts/0.2.0/group.js index 7b0f3e2946..76337a0cbe 100644 --- a/contracts/0.2.0/group.js +++ b/contracts/0.2.0/group.js @@ -16842,8 +16842,8 @@ ${this.getErrorInfo()}`; }); // shared/domains/chelonia/utils.js - var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight === void 0)?.id; - var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight === void 0 && k.foreignKey?.includes(contractID)).map((k) => k.id); + var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight == null)?.id; + var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.foreignKey?.includes(contractID)).map((k) => k.id); // frontend/model/notifications/mutationKeys.js var REMOVE_NOTIFICATION = "removeNotification"; @@ -17545,7 +17545,7 @@ ${this.getErrorInfo()}`; } }).catch((e) => { console.error(`sideEffect(removeMember): ${e.name} thrown during queueEvent to ${contractID} by saveOurLoginState:`, e); - }).then(() => (0, import_sbp7.default)("gi.contracts/group/revokeGroupKeyAndRotateOurPEK", contractID)).catch((e) => { + }).then(() => (0, import_sbp7.default)("gi.contracts/group/revokeGroupKeyAndRotateOurPEK", contractID, true)).catch((e) => { console.error(`sideEffect(removeMember): ${e.name} thrown during revokeGroupKeyAndRotateOurPEK to ${contractID}:`, e); }); for (const notification of rootGetters.notificationsByGroup(contractID)) { @@ -17560,7 +17560,11 @@ ${this.getErrorInfo()}`; groupID: contractID, username: memberRemovedThemselves ? meta.username : data.member }); - (0, import_sbp7.default)("gi.contracts/group/rotateKeys", contractID, state); + (0, import_sbp7.default)("gi.contracts/group/rotateKeys", contractID, state).then(() => { + return (0, import_sbp7.default)("gi.contracts/group/revokeGroupKeyAndRotateOurPEK", contractID, false); + }).catch((e) => { + console.error("Error rotating group keys or our PEK", e); + }); const rootGetters2 = (0, import_sbp7.default)("state/vuex/getters"); const userID = rootGetters2.ourContactProfiles[data.member]?.contractID; if (userID) { @@ -17881,8 +17885,8 @@ ${this.getErrorInfo()}`; }, methods: { "gi.contracts/group/archiveProposal": async function(contractID, proposalHash, proposal) { - const { username } = (0, import_sbp7.default)("state/vuex/state").loggedIn; - const key = `proposals/${username}/${contractID}`; + const { identityContractID } = (0, import_sbp7.default)("state/vuex/state").loggedIn; + const key = `proposals/${identityContractID}/${contractID}`; const proposals2 = await (0, import_sbp7.default)("gi.db/archive/load", key) || []; proposals2.unshift([proposalHash, proposal]); while (proposals2.length > MAX_ARCHIVED_PROPOSALS) { @@ -17893,10 +17897,10 @@ ${this.getErrorInfo()}`; }, "gi.contracts/group/archivePayments": async function(contractID, archivingPayments) { const { paymentsByPeriod, payments } = archivingPayments; - const { username } = (0, import_sbp7.default)("state/vuex/state").loggedIn; - const archPaymentsByPeriodKey = `paymentsByPeriod/${username}/${contractID}`; + const { identityContractID, username } = (0, import_sbp7.default)("state/vuex/state").loggedIn; + const archPaymentsByPeriodKey = `paymentsByPeriod/${identityContractID}/${contractID}`; const archPaymentsByPeriod = await (0, import_sbp7.default)("gi.db/archive/load", archPaymentsByPeriodKey) || {}; - const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${username}/${contractID}`; + const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${identityContractID}/${contractID}`; const archSentOrReceivedPayments = await (0, import_sbp7.default)("gi.db/archive/load", archSentOrReceivedPaymentsKey) || { sent: [], received: [] }; const sortPayments = (payments2) => payments2.sort((f, l) => compareISOTimestamps(l.meta.createdDate, f.meta.createdDate)); for (const period of Object.keys(paymentsByPeriod).sort()) { @@ -17916,13 +17920,13 @@ ${this.getErrorInfo()}`; } archSentOrReceivedPayments.sent = [...sortPayments(newSentOrReceivedPayments.sent), ...archSentOrReceivedPayments.sent]; archSentOrReceivedPayments.received = [...sortPayments(newSentOrReceivedPayments.received), ...archSentOrReceivedPayments.received]; - const archPaymentsKey = `payments/${username}/${period}/${contractID}`; + const archPaymentsKey = `payments/${identityContractID}/${period}/${contractID}`; const hashes = paymentHashesFromPaymentPeriod(paymentsByPeriod[period]); const archPayments = Object.fromEntries(hashes.map((hash2) => [hash2, payments[hash2]])); while (Object.keys(archPaymentsByPeriod).length > MAX_ARCHIVED_PERIODS) { const shouldBeDeletedPeriod = Object.keys(archPaymentsByPeriod).sort().shift(); const paymentHashes = paymentHashesFromPaymentPeriod(archPaymentsByPeriod[shouldBeDeletedPeriod]); - await (0, import_sbp7.default)("gi.db/archive/delete", `payments/${shouldBeDeletedPeriod}/${username}/${contractID}`); + await (0, import_sbp7.default)("gi.db/archive/delete", `payments/${shouldBeDeletedPeriod}/${identityContractID}/${contractID}`); delete archPaymentsByPeriod[shouldBeDeletedPeriod]; archSentOrReceivedPayments.sent = archSentOrReceivedPayments.sent.filter((payment) => !paymentHashes.includes(payment.hash)); archSentOrReceivedPayments.received = archSentOrReceivedPayments.received.filter((payment) => !paymentHashes.includes(payment.hash)); @@ -17934,17 +17938,17 @@ ${this.getErrorInfo()}`; (0, import_sbp7.default)("okTurtles.events/emit", PAYMENTS_ARCHIVED, { paymentsByPeriod, payments }); }, "gi.contracts/group/removeArchivedProposals": async function(contractID) { - const { username } = (0, import_sbp7.default)("state/vuex/state").loggedIn; - const key = `proposals/${username}/${contractID}`; + const { identityContractID } = (0, import_sbp7.default)("state/vuex/state").loggedIn; + const key = `proposals/${identityContractID}/${contractID}`; await (0, import_sbp7.default)("gi.db/archive/delete", key); }, "gi.contracts/group/removeArchivedPayments": async function(contractID) { - const { username } = (0, import_sbp7.default)("state/vuex/state").loggedIn; - const archPaymentsByPeriodKey = `paymentsByPeriod/${username}/${contractID}`; + const { identityContractID } = (0, import_sbp7.default)("state/vuex/state").loggedIn; + const archPaymentsByPeriodKey = `paymentsByPeriod/${identityContractID}/${contractID}`; const periods = Object.keys(await (0, import_sbp7.default)("gi.db/archive/load", archPaymentsByPeriodKey) || {}); - const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${username}/${contractID}`; + const archSentOrReceivedPaymentsKey = `sentOrReceivedPayments/${identityContractID}/${contractID}`; for (const period of periods) { - const archPaymentsKey = `payments/${username}/${period}/${contractID}`; + const archPaymentsKey = `payments/${identityContractID}/${period}/${contractID}`; await (0, import_sbp7.default)("gi.db/archive/delete", archPaymentsKey); } await (0, import_sbp7.default)("gi.db/archive/delete", archPaymentsByPeriodKey); @@ -17994,11 +17998,11 @@ ${this.getErrorInfo()}`; const CEKid = findKeyIdByName(state, "cek"); vue_esm_default.set(state._volatile.pendingKeyRevocations, CSKid, true); vue_esm_default.set(state._volatile.pendingKeyRevocations, CEKid, true); - (0, import_sbp7.default)("chelonia/queueInvocation", contractID, ["gi.actions/out/rotateKeys", contractID, "gi.contracts/group", "pending", "gi.actions/group/shareNewKeys"]).catch((e) => { + return (0, import_sbp7.default)("chelonia/queueInvocation", contractID, ["gi.actions/out/rotateKeys", contractID, "gi.contracts/group", "pending", "gi.actions/group/shareNewKeys"]).catch((e) => { console.warn(`rotateKeys: ${e.name} thrown during queueEvent to ${contractID}:`, e); }); }, - "gi.contracts/group/revokeGroupKeyAndRotateOurPEK": (groupContractID) => { + "gi.contracts/group/revokeGroupKeyAndRotateOurPEK": (groupContractID, disconnectGroup) => { const rootState = (0, import_sbp7.default)("state/vuex/state"); const { identityContractID } = rootState.loggedIn; const state = rootState[identityContractID]; @@ -18007,25 +18011,27 @@ ${this.getErrorInfo()}`; const CSKid = findKeyIdByName(state, "csk"); const CEKid = findKeyIdByName(state, "cek"); const PEKid = findKeyIdByName(state, "pek"); - const groupCSKids = findForeignKeysByContractID(state, groupContractID); vue_esm_default.set(state._volatile.pendingKeyRevocations, PEKid, true); - if (groupCSKids?.length) { - if (!CEKid) { - throw new Error("Identity CEK not found"); - } - (0, import_sbp7.default)("chelonia/queueInvocation", identityContractID, ["chelonia/out/keyDel", { - contractID: identityContractID, - contractName: "gi.contracts/identity", - data: groupCSKids, - signingKeyId: CSKid - }]).catch((e) => { - console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during keyDel to ${identityContractID}:`, e); + if (disconnectGroup) { + const groupCSKids = findForeignKeysByContractID(state, groupContractID); + if (groupCSKids?.length) { + if (!CEKid) { + throw new Error("Identity CEK not found"); + } + (0, import_sbp7.default)("chelonia/queueInvocation", identityContractID, ["chelonia/out/keyDel", { + contractID: identityContractID, + contractName: "gi.contracts/identity", + data: groupCSKids, + signingKeyId: CSKid + }]).catch((e) => { + console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during keyDel to ${identityContractID}:`, e); + }); + } + (0, import_sbp7.default)("chelonia/queueInvocation", identityContractID, ["chelonia/contract/disconnect", identityContractID, groupContractID]).catch((e) => { + console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during queueEvent to ${identityContractID}:`, e); }); } - (0, import_sbp7.default)("chelonia/queueInvocation", identityContractID, ["chelonia/contract/disconnect", identityContractID, groupContractID]).catch((e) => { - console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during queueEvent to ${identityContractID}:`, e); - }); - (0, import_sbp7.default)("chelonia/queueInvocation", identityContractID, ["gi.actions/out/rotateKeys", identityContractID, "gi.contracts/identity", "pending", "gi.actions/identity/shareNewPEK"]).catch((e) => { + return (0, import_sbp7.default)("chelonia/queueInvocation", identityContractID, ["gi.actions/out/rotateKeys", identityContractID, "gi.contracts/identity", "pending", "gi.actions/identity/shareNewPEK"]).catch((e) => { console.error(`revokeGroupKeyAndRotateOurPEK: ${e.name} thrown during queueEvent to ${identityContractID}:`, e); }); }, diff --git a/frontend/model/contracts/manifests.json b/frontend/model/contracts/manifests.json index ba27b6118d..b633da234d 100644 --- a/frontend/model/contracts/manifests.json +++ b/frontend/model/contracts/manifests.json @@ -1,7 +1,7 @@ { "manifests": { "gi.contracts/chatroom": "21XWnNJr1tLQM1XwNVBUxVCuKADSSJmXVK3DWShAEt6HJeAvD8", - "gi.contracts/group": "21XWnNXzqXPZyURGHb7RXYLnwFNTZGTxSZWcsBLnzyueoMmuCw", + "gi.contracts/group": "21XWnNTihqK5Pwu1Fy9Bf3Eh4MN446oKu7QTSgnQD54q4R93Cy", "gi.contracts/identity": "21XWnNSxNrVFTMBCUVcZV3CG833gTbJ9V8ZyX7Fxgmpj9rNy4r" } }