Skip to content

Commit

Permalink
feat(group-management): update / handle group management for token ga…
Browse files Browse the repository at this point in the history
…ted social channels (#2213)

* feat(group-management): update / handle group management for token gated social channels

* refactor: handle group management for social channels in chat container state
  • Loading branch information
domw30 authored Aug 28, 2024
1 parent fb9db5d commit 8bff7b7
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 15 deletions.
135 changes: 124 additions & 11 deletions src/components/messenger/chat/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,35 @@ describe(DirectMessageChat, () => {
describe('mapState', () => {
describe('canLeaveRoom', () => {
it('is false when only when one other member', () => {
const state = new StoreBuilder().withActiveConversation(stubConversation({ otherMembers: [stubUser()] }));
const state = new StoreBuilder().withActiveConversation(
stubConversation({ otherMembers: [stubUser()], isSocialChannel: false })
);

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canLeaveRoom: false }));
});

it('is false when user is admin', () => {
const state = new StoreBuilder()
.withActiveConversation(
stubConversation({ otherMembers: [stubUser(), stubUser()], adminMatrixIds: ['current-user-matrix-id'] })
stubConversation({
otherMembers: [stubUser(), stubUser()],
adminMatrixIds: ['current-user-matrix-id'],
isSocialChannel: false,
})
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canLeaveRoom: false }));
});

it('is false when user is admin and conversation is social channel', () => {
const state = new StoreBuilder()
.withActiveConversation(
stubConversation({
otherMembers: [stubUser(), stubUser()],
adminMatrixIds: ['current-user-matrix-id'],
isSocialChannel: true,
})
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

Expand All @@ -217,73 +237,166 @@ describe(DirectMessageChat, () => {

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canLeaveRoom: true }));
});

it('is true when the conversation is a social channel and has multiple members', () => {
const state = new StoreBuilder()
.withActiveConversation(stubConversation({ otherMembers: [stubUser(), stubUser()], isSocialChannel: true }))
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canLeaveRoom: true }));
});

it('is false when the conversation is a social channel and has only one member', () => {
const state = new StoreBuilder()
.withActiveConversation(stubConversation({ otherMembers: [stubUser()], isSocialChannel: true }))
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canLeaveRoom: false }));
});
});

describe('canEdit', () => {
it('is false when one on one conversation', () => {
const state = new StoreBuilder().withActiveConversation(stubConversation({ isOneOnOne: true }));
const state = new StoreBuilder().withActiveConversation(
stubConversation({ isOneOnOne: true, isSocialChannel: false })
);

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canEdit: false }));
});

it('is false when current user is not room admin', () => {
const state = new StoreBuilder()
.withActiveConversation(stubConversation({ isOneOnOne: false, adminMatrixIds: ['other-user-matrix-id'] }))
.withActiveConversation(
stubConversation({ isOneOnOne: false, adminMatrixIds: ['other-user-matrix-id'], isSocialChannel: false })
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canEdit: false }));
});

it('is true when current user is room admin', () => {
const state = new StoreBuilder()
.withActiveConversation(stubConversation({ isOneOnOne: false, adminMatrixIds: ['current-user-matrix-id'] }))
.withActiveConversation(
stubConversation({ isOneOnOne: false, adminMatrixIds: ['current-user-matrix-id'], isSocialChannel: false })
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canEdit: true }));
});

it('is true when current user is room moderator', () => {
const state = new StoreBuilder()
.withActiveConversation(stubConversation({ isOneOnOne: false, moderatorIds: ['current-user-id'] }))
.withActiveConversation(
stubConversation({ isOneOnOne: false, moderatorIds: ['current-user-id'], isSocialChannel: false })
)
.withCurrentUser(stubAuthenticatedUser({ id: 'current-user-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canEdit: true }));
});

it('is true when the conversation is a social channel and user is an admin', () => {
const state = new StoreBuilder()
.withActiveConversation(
stubConversation({
isOneOnOne: true,
adminMatrixIds: ['current-user-matrix-id'],
isSocialChannel: true,
})
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canEdit: true }));
});

it('is false when the conversation is a social channel and current user is not room admin', () => {
const state = new StoreBuilder()
.withActiveConversation(
stubConversation({ isOneOnOne: false, adminMatrixIds: ['other-user-matrix-id'], isSocialChannel: true })
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canEdit: false }));
});
});

describe('canAddMembers', () => {
it('is false when one on one conversation', () => {
const state = new StoreBuilder().withActiveConversation(stubConversation({ isOneOnOne: true }));
const state = new StoreBuilder().withActiveConversation(
stubConversation({ isOneOnOne: true, isSocialChannel: false })
);

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canAddMembers: false }));
});

it('is false when current user is not room admin', () => {
const state = new StoreBuilder()
.withActiveConversation(stubConversation({ isOneOnOne: false, adminMatrixIds: ['other-user-matrix-id'] }))
.withActiveConversation(
stubConversation({ isOneOnOne: false, adminMatrixIds: ['other-user-matrix-id'], isSocialChannel: false })
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canAddMembers: false }));
});

it('is true when current user is room admin', () => {
const state = new StoreBuilder()
.withActiveConversation(stubConversation({ isOneOnOne: false, adminMatrixIds: ['current-user-matrix-id'] }))
.withActiveConversation(
stubConversation({ isOneOnOne: false, adminMatrixIds: ['current-user-matrix-id'], isSocialChannel: false })
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canAddMembers: true }));
});

it('is true when the conversation is a social channel and user is an admin', () => {
const state = new StoreBuilder()
.withActiveConversation(
stubConversation({
isOneOnOne: true,
adminMatrixIds: ['current-user-matrix-id'],
isSocialChannel: true,
})
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canAddMembers: true }));
});

it('is false when the conversation is a social channel and current user is not room admin', () => {
const state = new StoreBuilder()
.withActiveConversation(
stubConversation({ isOneOnOne: false, adminMatrixIds: ['other-user-matrix-id'], isSocialChannel: true })
)
.withCurrentUser(stubAuthenticatedUser({ matrixId: 'current-user-matrix-id' }));

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canAddMembers: false }));
});
});

describe('canViewDetails', () => {
it('is false when one on one conversation', () => {
const state = new StoreBuilder().withActiveConversation(stubConversation({ isOneOnOne: true }));
const state = new StoreBuilder().withActiveConversation(
stubConversation({ isOneOnOne: true, isSocialChannel: false })
);

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canViewDetails: false }));
});

it('is true when not a one on one conversation', () => {
const state = new StoreBuilder().withActiveConversation(stubConversation({ isOneOnOne: false }));
const state = new StoreBuilder().withActiveConversation(
stubConversation({ isOneOnOne: false, isSocialChannel: false })
);

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canViewDetails: true }));
});

it('is true when the conversation is a social channel', () => {
const state = new StoreBuilder().withActiveConversation(
stubConversation({
isOneOnOne: false,
isSocialChannel: true,
})
);

expect(DirectMessageChat.mapState(state.build())).toEqual(expect.objectContaining({ canViewDetails: true }));
});
Expand Down
12 changes: 8 additions & 4 deletions src/components/messenger/chat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,16 @@ export class Container extends React.Component<Properties> {

const directMessage = denormalize(activeConversationId, state);
const currentUser = currentUserSelector(state);
const hasMultipleMembers = (directMessage?.otherMembers || []).length > 1;
const isSocialChannel = directMessage?.isSocialChannel;
const isCurrentUserRoomAdmin = directMessage?.adminMatrixIds?.includes(currentUser?.matrixId) ?? false;
const isCurrentUserRoomModerator = directMessage?.moderatorIds?.includes(currentUser?.id) ?? false;
const canLeaveRoom = !isCurrentUserRoomAdmin && (directMessage?.otherMembers || []).length > 1;
const canEdit = (isCurrentUserRoomAdmin || isCurrentUserRoomModerator) && !directMessage?.isOneOnOne;
const canAddMembers = isCurrentUserRoomAdmin && !directMessage?.isOneOnOne;
const canViewDetails = !directMessage?.isOneOnOne;

const canLeaveRoom = !isCurrentUserRoomAdmin && hasMultipleMembers;
const canEdit =
(isCurrentUserRoomAdmin || isCurrentUserRoomModerator) && (!directMessage?.isOneOnOne || isSocialChannel);
const canAddMembers = isCurrentUserRoomAdmin && (!directMessage?.isOneOnOne || isSocialChannel);
const canViewDetails = !directMessage?.isOneOnOne || isSocialChannel;
const channel = rawChannelSelector(activeConversationId)(state);

return {
Expand Down

0 comments on commit 8bff7b7

Please sign in to comment.