Files
standardnotes-app-web/packages/snjs/mocha/vaults/invites.test.js
2023-08-06 15:23:31 -05:00

227 lines
8.6 KiB
JavaScript

import * as Factory from '../lib/factory.js'
import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('shared vault invites', function () {
this.timeout(Factory.TwentySecondTimeout)
let context
beforeEach(async function () {
localStorage.clear()
context = await Factory.createVaultsContextWithRealCrypto()
await context.launch()
await context.register()
})
afterEach(async function () {
await context.deinit()
localStorage.clear()
sinon.restore()
})
it('should invite contact to vault', async () => {
const sharedVault = await Collaboration.createSharedVault(context)
const { contactContext, deinitContactContext } = await Collaboration.createContactContext()
const contact = await Collaboration.createTrustedContactForUserOfContext(context, contactContext)
const vaultInvite = (
await context.vaultInvites.inviteContactToSharedVault(
sharedVault,
contact,
SharedVaultUserPermission.PERMISSIONS.Write,
)
).getValue()
expect(vaultInvite).to.not.be.undefined
expect(vaultInvite.shared_vault_uuid).to.equal(sharedVault.sharing.sharedVaultUuid)
expect(vaultInvite.user_uuid).to.equal(contact.contactUuid)
expect(vaultInvite.encrypted_message).to.not.be.undefined
expect(vaultInvite.permission).to.equal(SharedVaultUserPermission.PERMISSIONS.Write)
expect(vaultInvite.updated_at_timestamp).to.not.be.undefined
expect(vaultInvite.created_at_timestamp).to.not.be.undefined
await deinitContactContext()
})
it('invites from trusted contact should be pending as trusted', async () => {
const { contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithUnacceptedButTrustedInvite(context)
const invites = contactContext.vaultInvites.getCachedPendingInviteRecords()
expect(invites[0].trusted).to.be.true
await deinitContactContext()
})
it('invites from untrusted contact should be pending as untrusted', async () => {
const { contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithUnacceptedAndUntrustedInvite(context)
const invites = contactContext.vaultInvites.getCachedPendingInviteRecords()
expect(invites[0].trusted).to.be.false
await deinitContactContext()
})
it('invite should include delegated trusted contacts', async () => {
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
const { thirdPartyContext, deinitThirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
const invites = thirdPartyContext.vaultInvites.getCachedPendingInviteRecords()
const message = invites[0].message
const delegatedContacts = message.data.trustedContacts
expect(delegatedContacts.length).to.equal(2)
expect(delegatedContacts.some((contact) => contact.contactUuid === context.userUuid)).to.be.true
expect(delegatedContacts.some((contact) => contact.contactUuid === contactContext.userUuid)).to.be.true
await deinitThirdPartyContext()
await deinitContactContext()
})
it('should sync a shared vault from scratch after accepting an invitation', async () => {
const sharedVault = await Collaboration.createSharedVault(context)
const note = await context.createSyncedNote('foo', 'bar')
await Collaboration.moveItemToVault(context, sharedVault, note)
/** Create a mutually trusted contact */
const { contactContext, deinitContactContext } = await Collaboration.createContactContext()
const contact = await Collaboration.createTrustedContactForUserOfContext(context, contactContext)
await Collaboration.createTrustedContactForUserOfContext(contactContext, context)
/** Sync the contact context so that they wouldn't naturally receive changes made before this point */
await contactContext.sync()
await context.vaultInvites.inviteContactToSharedVault(
sharedVault,
contact,
SharedVaultUserPermission.PERMISSIONS.Write,
)
/** Contact should now sync and expect to find note */
const promise = contactContext.awaitNextSyncSharedVaultFromScratchEvent()
await contactContext.sync()
await Collaboration.acceptAllInvites(contactContext)
await promise
const receivedNote = contactContext.items.findItem(note.uuid)
expect(receivedNote).to.not.be.undefined
expect(receivedNote.title).to.equal('foo')
expect(receivedNote.text).to.equal(note.text)
await deinitContactContext()
})
it('received invites from untrusted contact should not be trusted', async () => {
await context.createSyncedNote('foo', 'bar')
const { contactContext, deinitContactContext } = await Collaboration.createContactContext()
const sharedVault = await Collaboration.createSharedVault(context)
const currentContextContact = await Collaboration.createTrustedContactForUserOfContext(context, contactContext)
await context.vaultInvites.inviteContactToSharedVault(
sharedVault,
currentContextContact,
SharedVaultUserPermission.PERMISSIONS.Write,
)
await contactContext.vaultInvites.downloadInboundInvites()
expect(contactContext.vaultInvites.getCachedPendingInviteRecords()[0].trusted).to.be.false
await deinitContactContext()
})
it('received invites from contact who becomes trusted after receipt of invite should be trusted', async () => {
await context.createSyncedNote('foo', 'bar')
const { contactContext, deinitContactContext } = await Collaboration.createContactContext()
const sharedVault = await Collaboration.createSharedVault(context)
const currentContextContact = await Collaboration.createTrustedContactForUserOfContext(context, contactContext)
await context.vaultInvites.inviteContactToSharedVault(
sharedVault,
currentContextContact,
SharedVaultUserPermission.PERMISSIONS.Write,
)
await contactContext.vaultInvites.downloadInboundInvites()
expect(contactContext.vaultInvites.getCachedPendingInviteRecords()[0].trusted).to.be.false
await Collaboration.createTrustedContactForUserOfContext(contactContext, context)
expect(contactContext.vaultInvites.getCachedPendingInviteRecords()[0].trusted).to.be.true
await deinitContactContext()
})
it('received items should contain the uuid of the contact who sent the item', async () => {
const { note, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInviteAndNote(context)
const receivedNote = contactContext.items.findItem(note.uuid)
expect(receivedNote).to.not.be.undefined
expect(receivedNote.user_uuid).to.equal(context.userUuid)
await deinitContactContext()
})
it('items should contain the uuid of the last person who edited it', async () => {
const { note, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInviteAndNote(context)
const receivedNote = contactContext.items.findItem(note.uuid)
expect(receivedNote.last_edited_by_uuid).to.not.be.undefined
expect(receivedNote.last_edited_by_uuid).to.equal(context.userUuid)
await contactContext.changeNoteTitleAndSync(receivedNote, 'new title')
await context.sync()
const updatedNote = context.items.findItem(note.uuid)
expect(updatedNote.last_edited_by_uuid).to.not.be.undefined
expect(updatedNote.last_edited_by_uuid).to.equal(contactContext.userUuid)
await deinitContactContext()
})
it('canceling an invite should remove it from recipient pending invites', async () => {
const { invite, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithUnacceptedButTrustedInvite(context)
const preInvites = await contactContext.vaultInvites.downloadInboundInvites()
expect(preInvites.length).to.equal(1)
await context.vaultInvites.deleteInvite(invite)
const postInvites = await contactContext.vaultInvites.downloadInboundInvites()
expect(postInvites.length).to.equal(0)
await deinitContactContext()
})
it('should delete all inbound invites after changing user password', async () => {
/** Invites to user are encrypted with old keypair and are no longer decryptable */
const { contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithUnacceptedButTrustedInvite(context)
const promise = contactContext.resolveWhenAllInboundSharedVaultInvitesAreDeleted()
await contactContext.changePassword('new-password')
await promise
const invites = await contactContext.vaultInvites.downloadInboundInvites()
expect(invites.length).to.equal(0)
await deinitContactContext()
})
})