diff --git a/app/scenes/Settings/People.js b/app/scenes/Settings/People.js index 7eb87048..baa5d836 100644 --- a/app/scenes/Settings/People.js +++ b/app/scenes/Settings/People.js @@ -40,6 +40,10 @@ class People extends React.Component { this.inviteModalOpen = false; }; + fetchPage = params => { + return this.props.users.fetchPage({ ...params, includeSuspended: true }); + }; + render() { const { auth, policies, match } = this.props; const { filter } = match.params; @@ -110,7 +114,7 @@ class People extends React.Component { No people to see here.} - fetch={this.props.users.fetchPage} + fetch={this.fetchPage} renderItem={item => ( { return filter(this.orderedData, user => user.isSuspended); } + @computed + get activeOrInvited(): User[] { + return filter(this.orderedData, user => !user.isSuspended); + } + @computed get invited(): User[] { return filter(this.orderedData, user => !user.lastActiveAt); @@ -81,7 +86,10 @@ export default class UsersStore extends BaseStore { member => member.collectionId === collectionId ); const userIds = memberships.map(member => member.userId); - const users = filter(this.orderedData, user => !userIds.includes(user.id)); + const users = filter( + this.activeOrInvited, + user => !userIds.includes(user.id) + ); if (!query) return users; return queriedUsers(users, query); @@ -93,7 +101,9 @@ export default class UsersStore extends BaseStore { member => member.collectionId === collectionId ); const userIds = memberships.map(member => member.userId); - const users = filter(this.orderedData, user => userIds.includes(user.id)); + const users = filter(this.activeOrInvited, user => + userIds.includes(user.id) + ); if (!query) return users; return queriedUsers(users, query); @@ -105,7 +115,10 @@ export default class UsersStore extends BaseStore { member => member.groupId === groupId ); const userIds = memberships.map(member => member.userId); - const users = filter(this.orderedData, user => !userIds.includes(user.id)); + const users = filter( + this.activeOrInvited, + user => !userIds.includes(user.id) + ); if (!query) return users; return queriedUsers(users, query); @@ -117,7 +130,9 @@ export default class UsersStore extends BaseStore { member => member.groupId === groupId ); const userIds = groupMemberships.map(member => member.userId); - const users = filter(this.orderedData, user => userIds.includes(user.id)); + const users = filter(this.activeOrInvited, user => + userIds.includes(user.id) + ); if (!query) return users; return queriedUsers(users, query); diff --git a/server/api/users.js b/server/api/users.js index e6c102e9..f6c1607a 100644 --- a/server/api/users.js +++ b/server/api/users.js @@ -21,13 +21,22 @@ const { authorize } = policy; const router = new Router(); router.post('users.list', auth(), pagination(), async ctx => { - const { query } = ctx.body; + const { query, includeSuspended = false } = ctx.body; const user = ctx.state.user; let where = { teamId: user.teamId, }; + if (!includeSuspended) { + where = { + ...where, + suspendedAt: { + [Op.eq]: null, + }, + }; + } + if (query) { where = { ...where, diff --git a/server/api/users.test.js b/server/api/users.test.js index 4c127538..3457b2f5 100644 --- a/server/api/users.test.js +++ b/server/api/users.test.js @@ -14,6 +14,13 @@ describe('#users.list', async () => { it('should allow filtering by user name', async () => { const user = await buildUser({ name: 'Tester' }); + // suspended user should not be returned + await buildUser({ + name: 'Tester', + teamId: user.teamId, + suspendedAt: new Date(), + }); + const res = await server.post('/api/users.list', { body: { query: 'test', @@ -27,6 +34,27 @@ describe('#users.list', async () => { expect(body.data[0].id).toEqual(user.id); }); + it('should allow including suspended', async () => { + const user = await buildUser({ name: 'Tester' }); + await buildUser({ + name: 'Tester', + teamId: user.teamId, + suspendedAt: new Date(), + }); + + const res = await server.post('/api/users.list', { + body: { + query: 'test', + includeSuspended: true, + token: user.getJwtToken(), + }, + }); + const body = await res.json(); + + expect(res.status).toEqual(200); + expect(body.data.length).toEqual(2); + }); + it('should return teams paginated user list', async () => { const { admin, user } = await seed();