diff --git a/packages/auth/src/connection/Connection.ts b/packages/auth/src/connection/Connection.ts index 8405cf0af..4d58d43c2 100644 --- a/packages/auth/src/connection/Connection.ts +++ b/packages/auth/src/connection/Connection.ts @@ -325,9 +325,15 @@ export class Connection extends EventEmitter { assert(roles) assert(userId) - if (!roles!.includes(MEMBER) && context.server == null && !team!.hasServer(userId!)) { - team!.addMemberRole(userId!, MEMBER) + const hasMemberMarker = team.memberHasRoleMarker(userId, MEMBER) + const hasMemberRole = team.memberHasRole(userId, MEMBER) + if (!hasMemberRole && (hasMemberMarker || roles.includes(MEMBER))) { + this.logger.warn(`Peer had marker for ${MEMBER} but lacked the appropriate lockboxes, this may be malicious or we are missing syncable data`) + } else if (!hasMemberRole && !roles.includes(MEMBER) && context.server == null && !team.hasServer(userId)) { + this.logger.debug(`Assigning ${MEMBER} role to peer`) + team.addMemberRole(userId, MEMBER) } + this.#queueMessage('ACCEPT_IDENTITY') }, diff --git a/packages/auth/src/connection/test/authentication.test.ts b/packages/auth/src/connection/test/authentication.test.ts index 2a5db0e45..848cbbe80 100644 --- a/packages/auth/src/connection/test/authentication.test.ts +++ b/packages/auth/src/connection/test/authentication.test.ts @@ -31,6 +31,36 @@ describe('connection', () => { await disconnect(alice, bob) }) + it('connects two members and assigns member role', async () => { + const { alice, bob } = setup('alice', { user: 'bob', admin: false, member: false, addToTeam: true }) + + // đŸ‘©đŸŸ đŸ‘šđŸ»â€đŸŠČ Alice and Bob both join the channel + await connect(alice, bob) + + // đŸ‘©đŸŸ đŸ‘šđŸ»â€đŸŠČ Alice and Bob both leave the channel + await disconnect(alice, bob) + + expect(alice.team.memberHasRole(bob.userId, MEMBER)).toBe(true) + expect(bob.team.memberHasRole(bob.userId, MEMBER)).toBe(true) + }) + + it(`connects two members and doesn't assign member role when marker exists but no lockboxes`, async () => { + const { alice, bob } = setup('alice', { user: 'bob', admin: false, member: false, rolesWithoutLockboxes: [MEMBER] }) + expect(alice.team.memberHasRole(bob.userId, MEMBER)).toBe(false) + expect(bob.team.memberHasRole(bob.userId, MEMBER)).toBe(false) + expect(alice.team.memberHasRoleMarker(bob.userId, MEMBER)).toBe(true) + expect(bob.team.memberHasRoleMarker(bob.userId, MEMBER)).toBe(true) + + // đŸ‘©đŸŸ đŸ‘šđŸ»â€đŸŠČ Alice and Bob both join the channel + await connect(alice, bob) + + // đŸ‘©đŸŸ đŸ‘šđŸ»â€đŸŠČ Alice and Bob both leave the channel + await disconnect(alice, bob) + + expect(alice.team.memberHasRole(bob.userId, MEMBER)).toBe(false) + expect(bob.team.memberHasRole(bob.userId, MEMBER)).toBe(false) + }) + it("doesn't connect with a member who has been removed", async () => { const { alice, bob } = setup('alice', 'bob')