internal: incomplete vault systems behind feature flag (#2340)
This commit is contained in:
229
packages/snjs/mocha/vaults/invites.test.js
Normal file
229
packages/snjs/mocha/vaults/invites.test.js
Normal file
@@ -0,0 +1,229 @@
|
||||
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
|
||||
let sharedVaults
|
||||
|
||||
afterEach(async function () {
|
||||
await context.deinit()
|
||||
localStorage.clear()
|
||||
})
|
||||
|
||||
beforeEach(async function () {
|
||||
localStorage.clear()
|
||||
|
||||
context = await Factory.createAppContextWithRealCrypto()
|
||||
await context.launch()
|
||||
await context.register()
|
||||
|
||||
sharedVaults = context.sharedVaults
|
||||
})
|
||||
|
||||
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 sharedVaults.inviteContactToSharedVault(sharedVault, contact, SharedVaultPermission.Write)
|
||||
|
||||
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.permissions).to.equal(SharedVaultPermission.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.sharedVaults.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.sharedVaults.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.sharedVaults.getCachedPendingInviteRecords()
|
||||
|
||||
const message = invites[0].message
|
||||
const delegatedContacts = message.data.trustedContacts
|
||||
expect(delegatedContacts.length).to.equal(1)
|
||||
expect(delegatedContacts[0].contactUuid).to.equal(contactContext.userUuid)
|
||||
|
||||
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 sharedVaults.inviteContactToSharedVault(sharedVault, contact, SharedVaultPermission.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 sharedVaults.inviteContactToSharedVault(sharedVault, currentContextContact, SharedVaultPermission.Write)
|
||||
|
||||
await contactContext.sharedVaults.downloadInboundInvites()
|
||||
expect(contactContext.sharedVaults.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 sharedVaults.inviteContactToSharedVault(sharedVault, currentContextContact, SharedVaultPermission.Write)
|
||||
|
||||
await contactContext.sharedVaults.downloadInboundInvites()
|
||||
expect(contactContext.sharedVaults.getCachedPendingInviteRecords()[0].trusted).to.be.false
|
||||
|
||||
await Collaboration.createTrustedContactForUserOfContext(contactContext, context)
|
||||
|
||||
expect(contactContext.sharedVaults.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.sharedVaults.downloadInboundInvites()
|
||||
expect(preInvites.length).to.equal(1)
|
||||
|
||||
await sharedVaults.deleteInvite(invite)
|
||||
|
||||
const postInvites = await contactContext.sharedVaults.downloadInboundInvites()
|
||||
expect(postInvites.length).to.equal(0)
|
||||
|
||||
await deinitContactContext()
|
||||
})
|
||||
|
||||
it('when inviter keypair changes, recipient should still be able to trust and decrypt previous invite', async () => {
|
||||
console.error('TODO: implement test')
|
||||
})
|
||||
|
||||
it('should delete all inbound invites after changing user password', async () => {
|
||||
/** Invites to user are encrypted with old keypair and are no longer decryptable */
|
||||
console.error('TODO: implement test')
|
||||
})
|
||||
|
||||
it('sharing a vault with user inputted and ephemeral password should share the key as synced for the recipient', async () => {
|
||||
const privateVault = await context.vaults.createUserInputtedPasswordVault({
|
||||
name: 'My Private Vault',
|
||||
userInputtedPassword: 'password',
|
||||
storagePreference: KeySystemRootKeyStorageMode.Ephemeral,
|
||||
})
|
||||
|
||||
const note = await context.createSyncedNote('foo', 'bar')
|
||||
await context.vaults.moveItemToVault(privateVault, note)
|
||||
|
||||
const sharedVault = await context.sharedVaults.convertVaultToSharedVault(privateVault)
|
||||
|
||||
const { thirdPartyContext, deinitThirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
|
||||
context,
|
||||
sharedVault,
|
||||
)
|
||||
|
||||
await Collaboration.acceptAllInvites(thirdPartyContext)
|
||||
|
||||
const contextNote = thirdPartyContext.items.findItem(note.uuid)
|
||||
expect(contextNote).to.not.be.undefined
|
||||
expect(contextNote.title).to.equal('foo')
|
||||
expect(contextNote.text).to.equal(note.text)
|
||||
|
||||
await deinitThirdPartyContext()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user