Skip to content

Commit 274710c

Browse files
authoredApr 13, 2021
feat: add button to remove all users from organization (#937)
Reviewed-by: @ben-pr-p
1 parent 8dbd3bc commit 274710c

File tree

4 files changed

+117
-1
lines changed

4 files changed

+117
-1
lines changed
 

‎src/api/schema.js

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ const rootSchema = `
292292
joinOrganization(organizationUuid: String!): Organization!
293293
editOrganizationMembership(id: String!, level: RequestAutoApprove, role: String): OrganizationMembership!
294294
editOrganizationSettings(id: String!, input: OrganizationSettingsInput!): OranizationSettings!
295+
purgeOrganizationUsers(organizationId: String!): Int!
295296
editUser(organizationId: String!, userId: Int!, userData:UserInput): User
296297
resetUserPassword(organizationId: String!, userId: Int!): String!
297298
changeUserPassword(userId: Int!, formData: UserPasswordChange): User

‎src/containers/AdminPeople/AdminPeople.tsx

+56
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Button from "@material-ui/core/Button";
12
import { css, StyleSheet } from "aphrodite";
23
import { ApolloQueryResult } from "apollo-client";
34
import gql from "graphql-tag";
@@ -99,6 +100,11 @@ export interface AdminPeopleMutations {
99100
resetUserPassword: string;
100101
}>
101102
>;
103+
removeUsers: () => Promise<
104+
ApolloQueryResult<{
105+
purgeOrganizationUsers: number;
106+
}>
107+
>;
102108
}
103109

104110
interface AdminPeopleRouteParams {
@@ -132,6 +138,9 @@ interface AdminPeopleState {
132138
filter: {
133139
nameSearch: string;
134140
};
141+
removeUsers: {
142+
open: boolean;
143+
};
135144
password: {
136145
open: boolean;
137146
hash: string;
@@ -161,6 +170,9 @@ class AdminPeople extends React.Component<
161170
filter: {
162171
nameSearch: ""
163172
},
173+
removeUsers: {
174+
open: false
175+
},
164176
password: {
165177
open: false,
166178
hash: ""
@@ -239,6 +251,25 @@ class AdminPeople extends React.Component<
239251
confirmSuperadmin: { superadminMembershipId, open: true }
240252
}));
241253

254+
handleCloseRemoveUsersDialog = () =>
255+
this.setState({
256+
removeUsers: { open: false }
257+
});
258+
259+
handleConfirmRemoveUsers = async () => {
260+
this.handleCloseRemoveUsersDialog();
261+
try {
262+
await this.props.mutations.removeUsers();
263+
} catch (err) {
264+
this.setState({
265+
error: {
266+
message: `Couldn't remove users: ${err.message}`,
267+
seen: false
268+
}
269+
});
270+
}
271+
};
272+
242273
handleResetPassword = async (userId: string) => {
243274
const { organizationId } = this.props.match.params;
244275
if (!organizationId) return;
@@ -312,6 +343,13 @@ class AdminPeople extends React.Component<
312343
}}
313344
/>
314345
</div>
346+
<Button
347+
variant="contained"
348+
color="primary"
349+
onClick={() => this.setState({ removeUsers: { open: true } })}
350+
>
351+
Remove Users
352+
</Button>
315353
</div>
316354

317355
<PeopleTable
@@ -350,6 +388,11 @@ class AdminPeople extends React.Component<
350388
onClose={this.handleCloseSuperadminDialog}
351389
handleConfirmSuperadmin={this.handleConfirmSuperadmin}
352390
/>
391+
<Dialogs.ConfirmRemoveUsers
392+
open={this.state.removeUsers.open}
393+
onClose={this.handleCloseRemoveUsersDialog}
394+
onConfirmRemoveUsers={this.handleConfirmRemoveUsers}
395+
/>
353396
<Snackbar
354397
open={this.state.error.message.length > 0 && !this.state.error.seen}
355398
message={this.state.error.message}
@@ -469,6 +512,19 @@ const mutations: MutationMap<AdminPeopleExtendedProps> = {
469512
userId
470513
}
471514
};
515+
},
516+
removeUsers: (ownProps) => () => {
517+
return {
518+
mutation: gql`
519+
mutation PurgeOrganizationUsers($organizationId: String!) {
520+
purgeOrganizationUsers(organizationId: $organizationId)
521+
}
522+
`,
523+
variables: {
524+
organizationId: ownProps.organizationData.organization.id
525+
},
526+
refetchQueries: ["getPeople"]
527+
};
472528
}
473529
};
474530

‎src/containers/AdminPeople/Dialogs.tsx

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Button from "@material-ui/core/Button";
12
import Dialog from "@material-ui/core/Dialog";
23
import DialogActions from "@material-ui/core/DialogActions";
34
import DialogContent from "@material-ui/core/DialogContent";
@@ -135,10 +136,45 @@ const ConfirmSuperAdmin: React.StatelessComponent<ConfirmSuperAdminProps> = ({
135136
</div>
136137
);
137138

139+
interface ConfirmRemoveUsersProps {
140+
open: boolean;
141+
onClose: () => Promise<void> | void;
142+
onConfirmRemoveUsers: () => Promise<void> | void;
143+
}
144+
145+
const ConfirmRemoveUsers: React.FC<ConfirmRemoveUsersProps> = ({
146+
open,
147+
onClose,
148+
onConfirmRemoveUsers
149+
}) => (
150+
<Dialog open={open} onClose={onClose}>
151+
<DialogTitle>Confirm Remove Users</DialogTitle>
152+
<DialogContent>
153+
This will remove all users from the organization who are not Superadmins.
154+
Are you sure you would like to do this?
155+
</DialogContent>
156+
<DialogActions>
157+
<Button {...dataTest("removeUsersCancel")} onClick={onClose}>
158+
Cancel
159+
</Button>
160+
<Button
161+
{...dataTest("removeUsersOk")}
162+
onClick={onConfirmRemoveUsers}
163+
variant="contained"
164+
color="primary"
165+
autoFocus
166+
>
167+
Confirm
168+
</Button>
169+
</DialogActions>
170+
</Dialog>
171+
);
172+
138173
const Dialogs = {
139174
InvitePerson,
140175
EditPerson,
141176
ResetPassword,
142-
ConfirmSuperAdmin
177+
ConfirmSuperAdmin,
178+
ConfirmRemoveUsers
143179
};
144180
export default Dialogs;

‎src/server/api/schema.js

+23
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,29 @@ const rootMutations = {
984984
return orgMembership;
985985
},
986986

987+
purgeOrganizationUsers: async (
988+
_root,
989+
{ organizationId },
990+
{ user: authUser, db }
991+
) => {
992+
const orgId = parseInt(organizationId, 10);
993+
await accessRequired(authUser, orgId, "OWNER", true);
994+
const { rowCount } = await db.primary.raw(
995+
`
996+
delete
997+
from user_organization uo
998+
using public.user u
999+
where
1000+
u.id = uo.user_id
1001+
and u.is_superadmin is not true
1002+
and uo.organization_id = ?
1003+
and uo.role <> 'OWNER'
1004+
`,
1005+
[orgId]
1006+
);
1007+
return rowCount;
1008+
},
1009+
9871010
editOrganizationSettings: async (
9881011
_root,
9891012
{ id, input },

0 commit comments

Comments
 (0)
Please sign in to comment.