Skip to content

Instantly share code, notes, and snippets.

@brianlovin
Created September 12, 2017 17:07
Show Gist options
  • Save brianlovin/5572d1b729363d1c1eda9655602690d4 to your computer and use it in GitHub Desktop.
Save brianlovin/5572d1b729363d1c1eda9655602690d4 to your computer and use it in GitHub Desktop.
Resolving downstream info
/*
On Spectrum we store permissions within communities in a table called `usersCommunities`.
This table returns records that look like:
{
id: ID
userId: ID
communityId: ID
isMember: Boolean
isModerator: Boolean
isOwner: Boolean
reputation: Int
}
There are times on Spectrum where I'm viewing different contexts and would like to fetch these permissions for
every user being rendered on the client.
For example, when viewing a thread -
(https://spectrum.chat/thread/d7b90e8a-7de7-4266-8e4a-0b7c58725f5b)
we want to render badges next to each username to show if they are a moderator in that community, and also show a
small count for each user's reputation within the community where that thread was posted.
Let's take a look at how we get thread messages info:
*/
// schema
type Thread {
...
messageConnection(first: Int, after: String): ThreadMessagesConnection!
}
type ThreadMessagesConnection {
pageInfo: PageInfo!
edges: [ThreadMessageEdge!]
}
type ThreadMessageEdge {
cursor: String!
node: Message!
}
type Message {
...
sender: User!
}
/*
So you can see that when we query for a thread's messages, we return a cursor-paginated
list and use the `sender` field to resolve a User.
The problem is that by the time the sender hits the User resolver, we've now lost the original query variable
containing the thread id:
*/
query getThreadMessages($id: ID!, $after: String) {
thread(id: $id) {
id
...threadMessages
}
}
fragment threadMessages on Thread {
messageConnection(after: $after) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
node {
...messageInfo
}
}
}
}
fragment messageInfo on Message {
...
sender {
...userInfo
contextPermissions {
reputation
isOwner
isModerator
}
}
/*
In order to get that `contextPermissions` field, I need to know a few things in the resolver:
1. The threadId that is being viewed
2. The communityId where that thread was posted
Unfortunately I don't know how to get that context so far downstream in the resolver flow.
But I realized I could use the fourth `info` argument to possibly hack around this. Here's my solution:
*/
contextPermissions: (user, _, __, info) => {
const queryName = info.operation.name.value;
const handleCheck = async () => {
switch (queryName) {
case 'getThreadMessages': {
const threadId = info.variableValues.id;
const { communityId } = await getThread(threadId);
const {
reputation,
isModerator,
isOwner,
} = await getUserPermissionsInCommunity(communityId, user.id);
return {
reputation,
isModerator,
isOwner,
};
}
}
};
return handleCheck();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment