feat: Add groups and group permissions (#1204)

* WIP - got one API test to pass yay

* adds group update endpoint

* added group policies

* adds groups.list API

* adds groups.info

* remove comment

* WIP

* tests for delete

* adds group membership list

* adds tests for groups list

* add and remove user endpoints for group

* ask some questions

* fix up some issues around primary keys

* remove export from group permissions

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* remove random file

* only create events on actual updates, add tests to ensure

* adds uniqueness validation to group name

* throw validation errors on model and let it pass through the controller

* fix linting

* WIP

* WIP

* WIP

* WIP

* WIP basic edit and delete

* basic CRUD for groups and memberships in place

* got member counts working

* add member count and limit the number of users sent over teh wire to 6

* factor avatar with AvatarWithPresence into its own class

* wip

* WIP avatars in group lists

* WIP collection groups

* add and remove group endpoints

* wip add collection groups

* wip get group adding to collections to work

* wip get updating collection group memberships to work

* wip get new group modal working

* add tests for collection index

* include collection groups in the withmemberships scope

* tie permissions to group memberships

* remove unused import

* Update app/components/GroupListItem.js

update title copy

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update server/migrations/20191211044318-create-groups.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update server/api/groups.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update server/api/groups.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/menus/CollectionMenu.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update server/models/Group.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* minor fixes

* Update app/scenes/CollectionMembers/AddGroupsToCollection.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/menus/GroupMenu.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/menus/GroupMenu.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/menus/GroupMenu.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/Collection.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/CollectionMembers/CollectionMembers.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/GroupNew.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/GroupNew.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/Settings/Groups.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update server/api/documents.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/CollectionMembers/components/CollectionGroupMemberListItem.js

Co-Authored-By: Tom Moor <tom.moor@gmail.com>

* address comments

* WIP - getting websocket stuff up and running

* socket event for group deletion

* wrapped up cascading deletes

* lint

* flow

* fix: UI feedback

* fix: Facepile size

* fix: Lots of missing await's

* Allow clicking facepile on group list item to open members

* remove unused route push, grammar

* fix: Remove bad analytics events
feat: Add group events to audit log

* collection. -> collections.

* Add groups to entity websocket events (sync create/update/delete) between clients

* fix: Users should not be able to see groups they are not a member of

* fix: Not caching errors in UI when changing group memberships

* fix: Hide unusable UI

* test

* fix: Tweak language

* feat: Automatically open 'add member' modal after creating group

Co-authored-by: Tom Moor <tom.moor@gmail.com>
This commit is contained in:
Nan Yu
2020-03-14 20:48:32 -07:00
committed by GitHub
parent 6c451a34d4
commit 142303b3de
81 changed files with 4259 additions and 257 deletions

View File

@@ -0,0 +1,135 @@
// @flow
import * as React from 'react';
import styled from 'styled-components';
import { inject, observer } from 'mobx-react';
import { observable } from 'mobx';
import { debounce } from 'lodash';
import Button from 'components/Button';
import Flex from 'shared/components/Flex';
import HelpText from 'components/HelpText';
import Input from 'components/Input';
import Modal from 'components/Modal';
import Empty from 'components/Empty';
import PaginatedList from 'components/PaginatedList';
import GroupNew from 'scenes/GroupNew';
import Collection from 'models/Collection';
import UiStore from 'stores/UiStore';
import AuthStore from 'stores/AuthStore';
import GroupsStore from 'stores/GroupsStore';
import CollectionGroupMembershipsStore from 'stores/CollectionGroupMembershipsStore';
import GroupListItem from 'components/GroupListItem';
type Props = {
ui: UiStore,
auth: AuthStore,
collection: Collection,
collectionGroupMemberships: CollectionGroupMembershipsStore,
groups: GroupsStore,
onSubmit: () => void,
};
@observer
class AddGroupsToCollection extends React.Component<Props> {
@observable newGroupModalOpen: boolean = false;
@observable query: string = '';
handleNewGroupModalOpen = () => {
this.newGroupModalOpen = true;
};
handleNewGroupModalClose = () => {
this.newGroupModalOpen = false;
};
handleFilter = (ev: SyntheticInputEvent<HTMLInputElement>) => {
this.query = ev.target.value;
this.debouncedFetch();
};
debouncedFetch = debounce(() => {
this.props.groups.fetchPage({
query: this.query,
});
}, 250);
handleAddGroup = group => {
try {
this.props.collectionGroupMemberships.create({
collectionId: this.props.collection.id,
groupId: group.id,
permission: 'read_write',
});
this.props.ui.showToast(`${group.name} was added to the collection`);
} catch (err) {
this.props.ui.showToast('Could not add user');
console.error(err);
}
};
render() {
const { groups, collection, auth } = this.props;
const { user, team } = auth;
if (!user || !team) return null;
return (
<Flex column>
<HelpText>
Cant find the group youre looking for?{' '}
<a role="button" onClick={this.handleNewGroupModalOpen}>
Create a group
</a>.
</HelpText>
<Input
type="search"
placeholder="Search by group name…"
value={this.query}
onChange={this.handleFilter}
label="Search groups"
labelHidden
flex
/>
<PaginatedList
empty={
this.query ? (
<Empty>No groups matching your search</Empty>
) : (
<Empty>No groups left to add</Empty>
)
}
items={groups.notInCollection(collection.id, this.query)}
fetch={this.query ? undefined : groups.fetchPage}
renderItem={item => (
<GroupListItem
key={item.id}
group={item}
showFacepile
renderActions={() => (
<ButtonWrap>
<Button onClick={() => this.handleAddGroup(item)} neutral>
Add
</Button>
</ButtonWrap>
)}
/>
)}
/>
<Modal
title="Create a group"
onRequestClose={this.handleNewGroupModalClose}
isOpen={this.newGroupModalOpen}
>
<GroupNew onSubmit={this.handleNewGroupModalClose} />
</Modal>
</Flex>
);
}
}
const ButtonWrap = styled.div`
margin-left: 6px;
`;
export default inject('auth', 'groups', 'collectionGroupMemberships', 'ui')(
AddGroupsToCollection
);