Skip to content

Commit cd5363e

Browse files
committed
feat: user management public api (wip)
1 parent 916e579 commit cd5363e

File tree

8 files changed

+63
-82
lines changed

8 files changed

+63
-82
lines changed

integration-tests/testkit/flow.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -205,16 +205,18 @@ export function getOrganizationMembers(selector: OrganizationSelectorInput, auth
205205
query getOrganizationMembers($selector: OrganizationSelectorInput!) {
206206
organization(reference: { bySelector: $selector }) {
207207
members {
208-
nodes {
209-
id
210-
user {
211-
id
212-
email
213-
}
214-
role {
208+
edges {
209+
node {
215210
id
216-
name
217-
permissions
211+
user {
212+
id
213+
email
214+
}
215+
role {
216+
id
217+
name
218+
permissions
219+
}
218220
}
219221
}
220222
}

integration-tests/testkit/seed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export function initSeed() {
202202
ownerToken,
203203
).then(r => r.expectNoGraphQLErrors());
204204

205-
const members = membersResult.organization?.members?.nodes;
205+
const members = membersResult.organization?.members?.edges?.map(edge => edge.node);
206206

207207
if (!members) {
208208
throw new Error(`Could not get members for org ${organization.slug}`);

packages/services/api/src/modules/organization/module.graphql.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,11 @@ export default gql`
274274
organization: Organization!
275275
}
276276
277+
input MemberReferenceInput @oneOf {
278+
byId: ID
279+
byEmail: String
280+
}
281+
277282
type Organization {
278283
"""
279284
Unique UUID of the organization
@@ -287,7 +292,11 @@ export default gql`
287292
name: String! @deprecated(reason: "Use the 'slug' field instead.")
288293
owner: Member!
289294
me: Member!
290-
members: MemberConnection
295+
member(reference: MemberReferenceInput!): Member
296+
members(
297+
first: Int! @tag(name: "public")
298+
after: String @tag(name: "public")
299+
): MemberConnection! @tag(name: "public")
291300
invitations: OrganizationInvitationConnection
292301
getStarted: OrganizationGetStarted!
293302
memberRoles: [MemberRole!]
@@ -585,8 +594,13 @@ export default gql`
585594
}
586595
587596
type MemberConnection {
588-
nodes: [Member!]!
589-
total: Int!
597+
edges: [MemberEdge!]! @tag(name: "public")
598+
pageInfo: PageInfo! @tag(name: "public")
599+
}
600+
601+
type MemberEdge {
602+
cursor: String! @tag(name: "public")
603+
node: Member! @tag(name: "public")
590604
}
591605
592606
input AppDeploymentResourceAssignmentInput {

packages/services/api/src/modules/organization/resolvers/MemberConnection.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ const connection = createConnection<ResolversTypes['Member']>();
66
export const MemberConnection: MemberConnectionResolvers = {
77
nodes: connection.nodes,
88
total: connection.total,
9+
edges: async (_parent, _arg, _ctx) => {
10+
/* MemberConnection.edges resolver is required because MemberConnection.edges exists but MemberConnectionMapper.edges does not */
11+
},
12+
pageInfo: async (_parent, _arg, _ctx) => {
13+
/* MemberConnection.pageInfo resolver is required because MemberConnection.pageInfo exists but MemberConnectionMapper.pageInfo does not */
14+
},
915
};

packages/services/api/src/modules/shared/providers/storage.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ export interface Storage {
169169
},
170170
): Promise<void>;
171171

172-
getOrganizationMembers(_: OrganizationSelector): Promise<readonly Member[] | never>;
173172
countOrganizationMembers(_: OrganizationSelector): Promise<number>;
174173

175174
getOrganizationInvitations(_: OrganizationSelector): Promise<readonly OrganizationInvitation[]>;

packages/services/storage/src/index.ts

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -878,49 +878,6 @@ export async function createStorage(
878878

879879
return total;
880880
},
881-
getOrganizationMembers: batch(async selectors => {
882-
const organizations = selectors.map(s => s.organizationId);
883-
const allMembers = await pool.query<
884-
users &
885-
Pick<organization_member, 'scopes' | 'organization_id' | 'connected_to_zendesk'> & {
886-
is_owner: boolean;
887-
} & MemberRoleColumns & {
888-
provider: string | null;
889-
}
890-
>(
891-
sql`/* getOrganizationMembers */
892-
SELECT
893-
${userFields(sql`"u".`, sql`"stu".`)},
894-
omr.scopes as scopes,
895-
om.organization_id,
896-
om.connected_to_zendesk,
897-
CASE WHEN o.user_id = om.user_id THEN true ELSE false END AS is_owner,
898-
omr.id as role_id,
899-
omr.name as role_name,
900-
omr.locked as role_locked,
901-
omr.scopes as role_scopes,
902-
omr.description as role_description
903-
FROM organization_member as om
904-
LEFT JOIN organizations as o ON (o.id = om.organization_id)
905-
LEFT JOIN users as u ON (u.id = om.user_id)
906-
LEFT JOIN organization_member_roles as omr ON (omr.organization_id = o.id AND omr.id = om.role_id)
907-
LEFT JOIN supertokens_thirdparty_users as stu ON (stu.user_id = u.supertoken_user_id)
908-
WHERE om.organization_id = ANY(${sql.array(
909-
organizations,
910-
'uuid',
911-
)}) ORDER BY u.created_at DESC`,
912-
);
913-
914-
return organizations.map(organization => {
915-
const members = allMembers.rows.filter(row => row.organization_id === organization);
916-
917-
if (members) {
918-
return Promise.resolve(members.map(transformMember));
919-
}
920-
921-
return Promise.reject(new Error(`Members not found (organization=${organization})`));
922-
});
923-
}),
924881
getOrganizationMember: batch(async selectors => {
925882
const membersResult = await pool.query<
926883
users &

packages/web/app/src/components/organization/members/list.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ const OrganizationMemberRow_DeleteMember = graphql(`
6161
organization {
6262
id
6363
members {
64-
total
65-
nodes {
66-
...OrganizationMemberRow_MemberFragment
64+
edges {
65+
node {
66+
...OrganizationMemberRow_MemberFragment
67+
}
6768
}
6869
}
6970
}
@@ -286,18 +287,19 @@ const OrganizationMembers_OrganizationFragment = graphql(`
286287
id
287288
}
288289
members {
289-
nodes {
290-
id
291-
user {
292-
displayName
293-
}
294-
role {
290+
edges {
291+
node {
295292
id
296-
name
293+
user {
294+
displayName
295+
}
296+
role {
297+
id
298+
name
299+
}
300+
...OrganizationMemberRow_MemberFragment
297301
}
298-
...OrganizationMemberRow_MemberFragment
299302
}
300-
total
301303
}
302304
viewerCanManageInvitations
303305
...MemberInvitationForm_OrganizationFragment
@@ -310,7 +312,7 @@ export function OrganizationMembers(props: {
310312
refetchMembers(): void;
311313
}) {
312314
const organization = useFragment(OrganizationMembers_OrganizationFragment, props.organization);
313-
const members = organization.members?.nodes;
315+
const members = organization.members?.edges?.map(edge => edge.node);
314316
const [orderDirection, setOrderDirection] = useState<'asc' | 'desc' | null>(null);
315317
const [sortByKey, setSortByKey] = useState<'name' | 'role'>('name');
316318

packages/web/app/src/components/v2/modals/transfer-organization-ownership.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,19 @@ const TransferOrganizationOwnership_Members = graphql(`
3333
id
3434
slug
3535
members {
36-
nodes {
37-
id
38-
isOwner
39-
...MemberFields
40-
user {
36+
edges {
37+
node {
4138
id
42-
fullName
43-
displayName
44-
email
39+
isOwner
40+
...MemberFields
41+
user {
42+
id
43+
fullName
44+
displayName
45+
email
46+
}
4547
}
4648
}
47-
total
4849
}
4950
}
5051
}
@@ -159,9 +160,9 @@ export const TransferOrganizationOwnershipModal = ({
159160
[setSelected, setFieldValue],
160161
);
161162

162-
const members = (query.data?.organization?.members?.nodes ?? []).filter(
163-
member => !member.isOwner,
164-
);
163+
const members = (query.data?.organization?.members?.edges ?? [])
164+
.map(edge => edge.node)
165+
.filter(member => !member.isOwner);
165166

166167
const filteredMembers = (
167168
searchPhrase === ''

0 commit comments

Comments
 (0)