Skip to content

Commit

Permalink
Various bugfixes, related to #2064 and #2066
Browse files Browse the repository at this point in the history
* eventsAfter: Reject early if the contractID is not set
* Fix instances causing such unset contractIDs
* Fix group members list to include members with only a contractID
* Don't set an empty contract state when receiving OP_KEY_SHARE
* Files: laxer validation when removing to process individual files separately
  • Loading branch information
corrideat committed Jun 17, 2024
1 parent 80c3ffd commit 9d1ea65
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 18 deletions.
13 changes: 11 additions & 2 deletions frontend/controller/actions/identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ export default (sbp('sbp/selectors/register', {
const rootGetters = sbp('state/vuex/getters')
const { identityContractID } = sbp('state/vuex/state').loggedIn
const { shouldDeleteFile, shouldDeleteToken } = option
let deleteResult

if (shouldDeleteFile) {
const credentials = Object.fromEntries(manifestCids.map(cid => {
Expand All @@ -770,15 +771,23 @@ export default (sbp('sbp/selectors/register', {
: { billableContractID: identityContractID }
return [cid, credential]
}))
await sbp('chelonia/fileDelete', manifestCids, credentials)
deleteResult = await sbp('chelonia/fileDelete', manifestCids, credentials)
}

if (shouldDeleteToken) {
await sbp('gi.actions/identity/removeFileDeleteToken', {
contractID: identityContractID,
data: { manifestCids }
data: {
manifestCids: deleteResult ? manifestCids.filter((_, i) => {

Check failure on line 781 in frontend/controller/actions/identity.js

View workflow job for this annotation

GitHub Actions / build

Expected newline between test and consequent of ternary expression

Check failure on line 781 in frontend/controller/actions/identity.js

View workflow job for this annotation

GitHub Actions / build

Expected newline between consequent and alternate of ternary expression
return deleteResult[i].status === 'fulfilled'

Check failure on line 782 in frontend/controller/actions/identity.js

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
}) : manifestCids
}
})
}

if (deleteResult?.some(r => r.status === 'rejected')) {
throw new Error('[gi.actions/identity/removeFiles] Some CIDs could not be deleted')
}
},
'gi.actions/identity/fetchChatRoomUnreadMessages': async () => {
const { ourIdentityContractId } = sbp('state/vuex/getters')
Expand Down
2 changes: 1 addition & 1 deletion frontend/model/contracts/chatroom.js
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ sbp('chelonia/defineContract', {
shouldDeleteToken: me === data.messageSender
}
deleteEncryptedFiles(data.manifestCids, option).catch(e => {
console.error(`[gi.contracts/chatroom/deleteMessage/sideEffect] (${contractID}):`, e)
console.warn(`[gi.contracts/chatroom/deleteMessage/sideEffect] (${contractID}):`, e)
})
}

Expand Down
4 changes: 2 additions & 2 deletions frontend/model/notifications/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,12 @@ export default ({
},
PAYMENT_THANKYOU_SENT (data: { creatorID: string, fromMemberID: string, toMemberID: string }) {
return {
avatarUserID: data.creatorID,
avatarUserID: data.fromMemberID,
body: L('{name} sent you a {strong_}thank you note{_strong} for your contribution.', {
name: strong(userDisplayNameFromID(data.fromMemberID)),
...LTags('strong')
}),
creatorID: data.creatorID,
creatorID: data.fromMemberID,
icon: '',
level: 'info',
linkTo: `/payments?modal=ThankYouNoteModal&from=${data.fromMemberID}&to=${data.toMemberID}`,
Expand Down
2 changes: 1 addition & 1 deletion frontend/model/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ const getters = {
.filter(memberID => getters.groupProfiles[memberID] ||
getters.groupMembersPending[memberID].expires >= Date.now())
.map(memberID => {
const { contractID, displayName, username } = getters.globalProfile(memberID) || groupMembersPending[memberID] || {}
const { contractID, displayName, username } = getters.globalProfile(memberID) || groupMembersPending[memberID] || (getters.groupProfiles[memberID] ? { contractID: memberID } : {})
return {
id: memberID, // common unique ID: it can be either the contract ID or the invite key
contractID,
Expand Down
4 changes: 3 additions & 1 deletion frontend/views/components/AvatarUser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export default ({
picture: {
type: [String, Object]
},
contractID: String,
contractID: {
type: String
},
alt: {
type: String,
default: ''
Expand Down
19 changes: 9 additions & 10 deletions shared/domains/chelonia/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,26 +369,25 @@ export default (sbp('sbp/selectors/register', {
throw new TypeError('A manifest CID must be provided')
}
if (!Array.isArray(manifestCid)) manifestCid = [manifestCid]
// Validation
manifestCid.forEach((cid) => {
return await Promise.allSettled(manifestCid.map(async (cid) => {
const hasCredential = has(credentials, cid)
const hasToken = has(credentials[cid], 'token')
const hasBillableContractID = has(credentials[cid], 'billableContractID')
const hasToken = has(credentials[cid], 'token') && credentials[cid].token
const hasBillableContractID = has(credentials[cid], 'billableContractID') && credentials[cid].billableContractID
if (!hasCredential || (!hasToken && hasToken === hasBillableContractID)) {
throw new TypeError(`Either a token or a billable contract ID must be provided for ${cid}`)
}
})
return await Promise.all(manifestCid.map(async (cid) => {
const { token, billableContractID } = credentials[cid]

const response = await fetch(`${this.config.connectionURL}/deleteFile/${cid}`, {
method: 'POST',
signal: this.abortController.signal,
headers: new Headers([
['authorization',
token
? `bearer ${token}`
hasToken
// $FlowFixMe[incompatible-type]
? `bearer ${credentials[cid].token}`
// $FlowFixMe[incompatible-type]
// $FlowFixMe[incompatible-call]
: buildShelterAuthorizationHeader.call(this, billableContractID)]
: buildShelterAuthorizationHeader.call(this, credentials[cid].billableContractID)]
])
})
if (!response.ok) {
Expand Down
2 changes: 1 addition & 1 deletion shared/domains/chelonia/internals.js
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ export default (sbp('sbp/selectors/register', {
const cheloniaState = sbp(self.config.stateSelector)

if (!cheloniaState[v.contractID]) {
config.reactiveSet(cheloniaState, v.contractID, Object.create(null))
return
}
const targetState = cheloniaState[v.contractID]

Expand Down
5 changes: 5 additions & 0 deletions shared/domains/chelonia/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,11 @@ export const getContractIDfromKeyId = (contractID: string, signingKeyId: ?string
}

export function eventsAfter (contractID: string, sinceHeight: number, limit?: number, sinceHash?: string): ReadableStream {
if (!contractID) {
// Avoid making a network roundtrip to tell us what we already know
throw new Error('Missing contract ID')
}

const fetchEventsStreamReader = async () => {
requestLimit = Math.min(limit ?? MAX_EVENTS_AFTER, remainingEvents)
const eventsResponse = await fetch(`${this.config.connectionURL}/eventsAfter/${contractID}/${sinceHeight}${Number.isInteger(requestLimit) ? `/${requestLimit}` : ''}`, { signal })
Expand Down

0 comments on commit 9d1ea65

Please sign in to comment.