Skip to content

Commit

Permalink
fix: ensure that allChatScopes provides all scopes needed (#2844)
Browse files Browse the repository at this point in the history
allChatScopes provides all scopes that may be need when using chat component.
uses the current config for the person card to determine some of the scopes
  • Loading branch information
gavinbarron committed Nov 13, 2023
1 parent 080a733 commit 9c84955
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
2 changes: 1 addition & 1 deletion packages/mgt-chat/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* -------------------------------------------------------------------------------------------
*/

import { allChatScopes } from './statefulClient/graph.chat';
import { allChatScopes } from './statefulClient/chatOperationScopes';

import { appSettings } from './statefulClient/GraphNotificationClient';

Expand Down
22 changes: 22 additions & 0 deletions packages/mgt-chat/src/statefulClient/chatOperationScopes.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expect } from '@open-wc/testing';
import { allChatScopes } from './chatOperationScopes';

describe('chatOperationScopes tests', () => {
it('should have a minimal permission set', () => {
const expectedScopes = [
'User.Read',
'User.ReadBasic.All',
'User.Read.All',
'People.Read',
'People.Read.All',
'Presence.Read.All',
'Sites.Read.All',
'Mail.Read',
'Mail.ReadBasic',
'Contacts.Read',
'Chat.ReadWrite',
'ChatMember.ReadWrite'
];
expect(allChatScopes).to.have.members(expectedScopes);
});
});
55 changes: 51 additions & 4 deletions packages/mgt-chat/src/statefulClient/chatOperationScopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,65 @@
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/
import { getMgtPersonCardScopes } from '@microsoft/mgt-components/dist/es6/exports';

/**
* The lowest count of scopes required to perform all chat operations
*/
export const minimalChatScopesList = ['ChatMember.ReadWrite', 'Chat.ReadWrite'];

/**
* Object mapping chat operations to the scopes required to perform them
*/
export const chatOperationScopes: Record<string, string[]> = {
loadChat: ['Chat.ReadBasic', 'Chat.Read', 'Chat.ReadWrite'],
loadChatMessages: ['Chat.Read', 'Chat.ReadWrite'],
loadChatImage: ['Chat.Read', 'Chat.ReadWrite'],
sendChatMessage: ['ChatMessage.Send', 'Chat.ReadWrite'],
loadChat: ['Chat.ReadWrite'],
loadChatMessages: ['Chat.ReadWrite'],
loadChatImage: ['Chat.ReadWrite'],
sendChatMessage: ['Chat.ReadWrite'],
updateChatMessage: ['Chat.ReadWrite'],
deleteChatMessage: ['Chat.ReadWrite'],
removeChatMember: ['ChatMember.ReadWrite'],
addChatMember: ['ChatMember.ReadWrite'],
createChat: ['Chat.ReadWrite']
};

/**
* Object mapping chat operations to the scopes required to perform them
* This should be used when we migrate this code to use scope aware requests
*/
export const chatOperationScopesFullListing: Record<string, string[]> = {
loadChat: ['Chat.ReadBasic', 'Chat.Read', 'Chat.ReadWrite'],
loadChatMessages: ['Chat.Read', 'Chat.ReadWrite'],
loadChatImage: ['ChannelMessage.Read.All', 'Chat.Read', 'Chat.ReadWrite', 'Group.Read.All', 'Group.ReadWrite.All'],
sendChatMessage: ['ChatMessage.Send', 'ChatMessage.Send', 'Chat.ReadWrite', 'Group.ReadWrite.All'],
updateChatMessage: ['ChannelMessage.ReadWrite', 'Chat.ReadWrite', 'Group.ReadWrite.All'],
deleteChatMessage: ['ChannelMessage.ReadWrite', 'Chat.ReadWrite'],
removeChatMember: ['ChatMember.ReadWrite'],
addChatMember: ['ChatMember.ReadWrite', 'Chat.ReadWrite'],
createChat: ['Chat.Create', 'Chat.ReadWrite']
};

/**
* The permission set required to use the people picker to search for users
* as defined in docs: https://learn.microsoft.com/en-us/graph/toolkit/components/people-picker#microsoft-graph-permissions
* N.B. presence permissions not currently documented
*/
export const peoplePickerScopes: Record<string, string[]> = {
loadPresence: ['Presence.Read.All'],
searchUsers: ['User.ReadBasic.All'],
searchPeople: ['People.Read']
};

/**
* Provides an array of the distinct scopes required for all chat operations
*/
export const allChatScopes = Array.from(
[['User.Read']]
.concat([minimalChatScopesList])
.concat(Object.values(peoplePickerScopes))
.concat([getMgtPersonCardScopes()])
.reduce((acc, scopes) => {
scopes.forEach(s => acc.add(s));
return acc;
}, new Set<string>())
);
14 changes: 2 additions & 12 deletions packages/mgt-chat/src/statefulClient/graph.chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,6 @@ export interface GraphCollection<T = any> {
*/
export type MessageCollection = GraphCollection<ChatMessage>;

/**
* Provides an array of the distinct scopes required for all chat operations
*/
export const allChatScopes = Array.from(
Object.values(chatOperationScopes).reduce((acc, scopes) => {
scopes.forEach(s => acc.add(s));
return acc;
}, new Set<string>())
);

/**
* Load the specified chat from graph with the members expanded
*
Expand Down Expand Up @@ -188,7 +178,7 @@ export const deleteChatMessage = async (graph: IGraph, chatId: string, messageId
export const removeChatMember = async (graph: IGraph, chatId: string, membershipId: string): Promise<void> => {
await graph
.api(`/chats/${chatId}/members/${membershipId}`)
.middlewareOptions(prepScopes(...chatOperationScopes.deleteChatMessage))
.middlewareOptions(prepScopes(...chatOperationScopes.removeChatMember))
.delete();
};

Expand Down Expand Up @@ -299,7 +289,7 @@ export const createChatThread = async (

const chat = (await graph
.api('/chats')
.middlewareOptions(prepScopes(...chatOperationScopes.loadChatImage))
.middlewareOptions(prepScopes(...chatOperationScopes.createChat))
.post(body)) as Chat;
if (!chat?.id) throw new Error('Chat id not returned from create chat thread');
if (chatMessage) {
Expand Down
2 changes: 1 addition & 1 deletion samples/react-chat/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ChatListTemplate from './components/ChatListTemplate/ChatListTemplate';

const ChatList = memo(({ chatSelected }: { chatSelected: (e: GraphChat) => void }) => {
return (
<Get resource="me/chats?$expand=members" scopes={['chat.read']} cacheEnabled={false}>
<Get resource="me/chats?$expand=members" scopes={['Chat.ReadWrite']} cacheEnabled={false}>
<ChatListTemplate template="default" onSelected={chatSelected} />
</Get>
);
Expand Down

0 comments on commit 9c84955

Please sign in to comment.