diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..7e57fe62 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ + sample EditorConfig file +# indicate this is the root of the project +root = true + +[*] +indent_style = space +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +indent_size = 4 \ No newline at end of file diff --git a/domain/group/endpoint.go b/domain/group/endpoint.go index 00e45cac..3ed98dff 100644 --- a/domain/group/endpoint.go +++ b/domain/group/endpoint.go @@ -202,6 +202,7 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) { return } + // Delete group and associated membership data _, err = h.Store.Group.Delete(ctx, g.RefID) if err != nil { ctx.Transaction.Rollback() @@ -210,6 +211,15 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) { return } + // Delete permissions associated with group + _, err = h.Store.Permission.DeleteGroupPermissions(ctx, groupID) + if err != nil { + ctx.Transaction.Rollback() + response.WriteServerError(w, method, err) + h.Runtime.Log.Error(method, err) + return + } + ctx.Transaction.Commit() h.Store.Audit.Record(ctx, audit.EventTypeGroupDelete) diff --git a/domain/permission/mysql/store.go b/domain/permission/mysql/store.go index 90658517..173084fb 100644 --- a/domain/permission/mysql/store.go +++ b/domain/permission/mysql/store.go @@ -289,3 +289,13 @@ func (s Scope) DeleteSpaceCategoryPermissions(ctx domain.RequestContext, spaceID return b.DeleteWhere(ctx.Transaction, sql) } + +// DeleteGroupPermissions removes all roles for the specified group +func (s Scope) DeleteGroupPermissions(ctx domain.RequestContext, groupID string) (rows int64, err error) { + b := mysql.BaseQuery{} + + sql := fmt.Sprintf("DELETE FROM permission WHERE orgid='%s' AND who='role' AND whoid='%s'", + ctx.OrgID, groupID) + + return b.DeleteWhere(ctx.Transaction, sql) +} diff --git a/domain/storer.go b/domain/storer.go index 42f91e14..41087cb9 100644 --- a/domain/storer.go +++ b/domain/storer.go @@ -88,17 +88,18 @@ type PermissionStorer interface { AddPermissions(ctx RequestContext, r permission.Permission, actions ...permission.Action) (err error) GetUserSpacePermissions(ctx RequestContext, spaceID string) (r []permission.Permission, err error) GetSpacePermissions(ctx RequestContext, spaceID string) (r []permission.Permission, err error) - DeleteSpacePermissions(ctx RequestContext, spaceID string) (rows int64, err error) - DeleteUserSpacePermissions(ctx RequestContext, spaceID, userID string) (rows int64, err error) - DeleteUserPermissions(ctx RequestContext, userID string) (rows int64, err error) - DeleteCategoryPermissions(ctx RequestContext, categoryID string) (rows int64, err error) - DeleteSpaceCategoryPermissions(ctx RequestContext, spaceID string) (rows int64, err error) GetCategoryPermissions(ctx RequestContext, catID string) (r []permission.Permission, err error) GetCategoryUsers(ctx RequestContext, catID string) (u []user.User, err error) GetUserCategoryPermissions(ctx RequestContext, userID string) (r []permission.Permission, err error) GetUserDocumentPermissions(ctx RequestContext, documentID string) (r []permission.Permission, err error) GetDocumentPermissions(ctx RequestContext, documentID string) (r []permission.Permission, err error) DeleteDocumentPermissions(ctx RequestContext, documentID string) (rows int64, err error) + DeleteSpacePermissions(ctx RequestContext, spaceID string) (rows int64, err error) + DeleteUserSpacePermissions(ctx RequestContext, spaceID, userID string) (rows int64, err error) + DeleteUserPermissions(ctx RequestContext, userID string) (rows int64, err error) + DeleteCategoryPermissions(ctx RequestContext, categoryID string) (rows int64, err error) + DeleteSpaceCategoryPermissions(ctx RequestContext, spaceID string) (rows int64, err error) + DeleteGroupPermissions(ctx RequestContext, groupID string) (rows int64, err error) } // UserStorer defines required methods for user management diff --git a/gui/app/components/customize/user-groups.js b/gui/app/components/customize/user-groups.js index 2b166ea9..9c6a0276 100644 --- a/gui/app/components/customize/user-groups.js +++ b/gui/app/components/customize/user-groups.js @@ -33,9 +33,11 @@ export default Component.extend(AuthProvider, ModalMixin, { }, loadGroups() { - this.get('groupSvc').getAll().then((groups) => { - this.set('groups', groups); - }); + this.get('groupSvc') + .getAll() + .then(groups => { + this.set('groups', groups); + }); }, setDefaults() { @@ -43,54 +45,70 @@ export default Component.extend(AuthProvider, ModalMixin, { }, loadGroupInfo() { - let groupId = this.get('membersGroup.id'); + let groupId = this.get('membersGroup.id'); let searchText = this.get('searchText'); - this.get('groupSvc').getGroupMembers(groupId).then((members) => { - this.set('members', members); + this.get('groupSvc') + .getGroupMembers(groupId) + .then(members => { + this.set('members', members); - this.get('userSvc').matchUsers(searchText).then((users) => { - users.forEach((user) => { - let m = members.findBy('userId', user.get('id')); - user.set('isMember', is.not.undefined(m)); - }) + this.get('userSvc') + .matchUsers(searchText) + .then(users => { + users.forEach(user => { + let m = members.findBy('userId', user.get('id')); + user.set('isMember', is.not.undefined(m)); + }); - if (this.get('showMembers') && members.length === 0) { - this.set('showMembers', false); - this.set('showUsers', true); - } - - this.set('users', users); + if (this.get('showMembers') && members.length === 0) { + this.set('showMembers', false); + this.set('showUsers', true); + } + + this.set('users', users); + }); }); - }); }, actions: { onOpenGroupModal() { - this.modalOpen("#add-group-modal", {"show": true}, '#new-group-name'); + this.modalOpen( + '#add-group-modal', + { show: true }, + '#new-group-name' + ); }, onAddGroup(e) { e.preventDefault(); let newGroup = this.get('newGroup'); - + if (is.empty(newGroup.name)) { - $("#new-group-name").addClass("is-invalid").focus(); + $('#new-group-name') + .addClass('is-invalid') + .focus(); return; } - this.get('groupSvc').add(newGroup).then(() => { - this.loadGroups(); - }); + this.get('groupSvc') + .add(newGroup) + .then(() => { + this.loadGroups(); + }); - this.modalClose("#add-group-modal"); + this.modalClose('#add-group-modal'); this.setDefaults(); }, onShowDeleteModal(groupId) { this.set('deleteGroup', { name: '', id: groupId }); - this.modalOpen("#delete-group-modal", {"show": true}, '#delete-group-name'); + this.modalOpen( + '#delete-group-modal', + { show: true }, + '#delete-group-name' + ); }, onDeleteGroup(e) { @@ -99,22 +117,33 @@ export default Component.extend(AuthProvider, ModalMixin, { let deleteGroup = this.get('deleteGroup'); let group = this.get('groups').findBy('id', deleteGroup.id); - if (is.empty(deleteGroup.name) || group.get('name') !== deleteGroup.name) { - $("#delete-group-name").addClass("is-invalid").focus(); + if ( + is.empty(deleteGroup.name) || + group.get('name') !== deleteGroup.name + ) { + $('#delete-group-name') + .addClass('is-invalid') + .focus(); return; } - this.get('groupSvc').delete(deleteGroup.id).then(() => { - this.loadGroups(); - }); + this.get('groupSvc') + .delete(deleteGroup.id) + .then(() => { + this.loadGroups(); + }); - this.modalClose("#delete-group-modal"); + this.modalClose('#delete-group-modal'); this.set('deleteGroup', { name: '', id: '' }); }, onShowEditModal(groupId) { this.set('editGroup', this.get('groups').findBy('id', groupId)); - this.modalOpen("#edit-group-modal", {"show": true}, '#edit-group-name'); + this.modalOpen( + '#edit-group-modal', + { show: true }, + '#edit-group-name' + ); }, onEditGroup(e) { @@ -123,21 +152,29 @@ export default Component.extend(AuthProvider, ModalMixin, { let group = this.get('editGroup'); if (is.empty(group.get('name'))) { - $("#edit-group-name").addClass("is-invalid").focus(); + $('#edit-group-name') + .addClass('is-invalid') + .focus(); return; } - this.get('groupSvc').update(group).then(() => { - this.load(); - }); + this.get('groupSvc') + .update(group) + .then(() => { + this.load(); + }); - this.modalClose("#edit-group-modal"); + this.modalClose('#edit-group-modal'); this.set('editGroup', null); }, onShowMembersModal(groupId) { this.set('membersGroup', this.get('groups').findBy('id', groupId)); - this.modalOpen("#group-members-modal", {"show": true}, '#group-members-search'); + this.modalOpen( + '#group-members-modal', + { show: true }, + '#group-members-search' + ); this.set('members', null); this.set('users', null); this.set('showMembers', true); @@ -146,36 +183,44 @@ export default Component.extend(AuthProvider, ModalMixin, { }, onSearch() { - debounce(this, function() { - let searchText = this.get('searchText'); - this.loadGroupInfo(); + debounce( + this, + function() { + let searchText = this.get('searchText'); + this.loadGroupInfo(); - if (is.not.empty(searchText)) { - this.set('showMembers', false); - this.set('showUsers', true); - } else { - this.set('showMembers', true); - this.set('showUsers', false); - } - }, 250); + if (is.not.empty(searchText)) { + this.set('showMembers', false); + this.set('showUsers', true); + } else { + this.set('showMembers', true); + this.set('showUsers', false); + } + }, + 250 + ); }, onLeaveGroup(userId) { let groupId = this.get('membersGroup.id'); - this.get('groupSvc').leave(groupId, userId).then(() => { - this.loadGroupInfo(); - this.loadGroups(); - }); + this.get('groupSvc') + .leave(groupId, userId) + .then(() => { + this.loadGroupInfo(); + this.loadGroups(); + }); }, onJoinGroup(userId) { let groupId = this.get('membersGroup.id'); - this.get('groupSvc').join(groupId, userId).then(() => { - this.loadGroupInfo(); - this.loadGroups(); - }); + this.get('groupSvc') + .join(groupId, userId) + .then(() => { + this.loadGroupInfo(); + this.loadGroups(); + }); } } }); diff --git a/gui/app/router.js b/gui/app/router.js index a998e02a..8e4304cf 100644 --- a/gui/app/router.js +++ b/gui/app/router.js @@ -16,7 +16,7 @@ var Router = EmberRouter.extend({ location: config.locationType }); -export default Router.map(function () { +export default Router.map(function() { this.route('folders', { path: '/' }); @@ -25,53 +25,65 @@ export default Router.map(function () { path: 'dashboard' }); - this.route('folder', { - path: 's/:folder_id/:folder_slug' - }, function() { - this.route('category', { - path: 'category' - }) - }); + this.route( + 'folder', + { + path: 's/:folder_id/:folder_slug' + }, + function() { + this.route('category', { + path: 'category' + }); + } + ); - this.route('document', { - path: 's/:folder_id/:folder_slug/d/:document_id/:document_slug' - }, function () { - this.route('section', { - path: 'section/:page_id' - }); - this.route('block', { - path: 'block/:block_id' - }); - }); + this.route( + 'document', + { + path: 's/:folder_id/:folder_slug/d/:document_id/:document_slug' + }, + function() { + this.route('section', { + path: 'section/:page_id' + }); + this.route('block', { + path: 'block/:block_id' + }); + } + ); - this.route('customize', { - path: 'settings' - }, function () { - this.route('general', { - path: 'general' - }); - this.route('groups', { - path: 'groups' - }); - this.route('users', { - path: 'users' - }); - this.route('folders', { - path: 'folders' - }); - this.route('smtp', { - path: 'smtp' - }); - this.route('license', { - path: 'license' - }); - this.route('auth', { - path: 'auth' - }); - this.route('audit', { - path: 'audit' - }); - }); + this.route( + 'customize', + { + path: 'settings' + }, + function() { + this.route('general', { + path: 'general' + }); + this.route('groups', { + path: 'groups' + }); + this.route('users', { + path: 'users' + }); + this.route('folders', { + path: 'folders' + }); + this.route('smtp', { + path: 'smtp' + }); + this.route('license', { + path: 'license' + }); + this.route('auth', { + path: 'auth' + }); + this.route('audit', { + path: 'audit' + }); + } + ); this.route('setup', { path: 'setup' @@ -81,31 +93,35 @@ export default Router.map(function () { path: 'secure/:token' }); - this.route('auth', { - path: 'auth' - }, function () { - this.route('sso', { - path: 'sso/:token' - }); - this.route('keycloak', { - path: 'keycloak' - }); - this.route('login', { - path: 'login' - }); - this.route('forgot', { - path: 'forgot' - }); - this.route('reset', { - path: 'reset/:token' - }); - this.route('logout', { - path: 'logout' - }); - this.route('share', { - path: 'share/:id/:slug/:serial' - }); - }); + this.route( + 'auth', + { + path: 'auth' + }, + function() { + this.route('sso', { + path: 'sso/:token' + }); + this.route('keycloak', { + path: 'keycloak' + }); + this.route('login', { + path: 'login' + }); + this.route('forgot', { + path: 'forgot' + }); + this.route('reset', { + path: 'reset/:token' + }); + this.route('logout', { + path: 'logout' + }); + this.route('share', { + path: 'share/:id/:slug/:serial' + }); + } + ); this.route('profile', { path: 'profile' diff --git a/gui/app/templates/components/customize/user-groups.hbs b/gui/app/templates/components/customize/user-groups.hbs index a020795a..61e182d5 100644 --- a/gui/app/templates/components/customize/user-groups.hbs +++ b/gui/app/templates/components/customize/user-groups.hbs @@ -11,7 +11,7 @@
@@ -55,8 +55,10 @@ - {{else}} -