diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 906285d12..9aef8646b 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -122,37 +122,41 @@ const isAllowedToChangeGroupMemberRole = rule({ cache: 'no_cache', })(async (_parent, args, { user, driver }) => { if (!(user && user.id)) return false - const adminId = user.id + const currentUserId = user.id const { groupId, userId, roleInGroup } = args - if (adminId === userId) return false + if (currentUserId === userId) return false const session = driver.session() const readTxPromise = session.readTransaction(async (transaction) => { const transactionResponse = await transaction.run( ` - MATCH (admin:User {id: $adminId})-[adminMembership:MEMBER_OF]->(group:Group {id: $groupId}) + MATCH (currentUser:User {id: $currentUserId})-[currentUserMembership:MEMBER_OF]->(group:Group {id: $groupId}) OPTIONAL MATCH (group)<-[userMembership:MEMBER_OF]-(member:User {id: $userId}) - RETURN group {.*}, admin {.*, myRoleInGroup: adminMembership.role}, member {.*, myRoleInGroup: userMembership.role} + RETURN group {.*}, currentUser {.*, myRoleInGroup: currentUserMembership.role}, member {.*, myRoleInGroup: userMembership.role} `, - { groupId, adminId, userId }, + { groupId, currentUserId, userId }, ) return { - admin: transactionResponse.records.map((record) => record.get('admin'))[0], + currentUser: transactionResponse.records.map((record) => record.get('currentUser'))[0], group: transactionResponse.records.map((record) => record.get('group'))[0], member: transactionResponse.records.map((record) => record.get('member'))[0], } }) try { - const { admin, group, member } = await readTxPromise + const { currentUser, group, member } = await readTxPromise + const groupExists = !!group + const currentUserExists = !!currentUser + const userIsMember = !!member + const sameUserRoleInGroup = member && member.myRoleInGroup === roleInGroup + const userIsOwner = member && ['owner'].includes(member.myRoleInGroup) + const currentUserIsAdmin = currentUser && ['admin'].includes(currentUser.myRoleInGroup) + const adminCanSetRole = ['pending', 'usual', 'admin'].includes(roleInGroup) + const currentUserIsOwner = currentUser && ['owner'].includes(currentUser.myRoleInGroup) + const ownerCanSetRole = ['pending', 'usual', 'admin', 'owner'].includes(roleInGroup) return ( - !!group && - !!admin && - (!member || - (!!member && - (member.myRoleInGroup === roleInGroup || !['owner'].includes(member.myRoleInGroup)))) && - ((['admin'].includes(admin.myRoleInGroup) && - ['pending', 'usual', 'admin'].includes(roleInGroup)) || - (['owner'].includes(admin.myRoleInGroup) && - ['pending', 'usual', 'admin', 'owner'].includes(roleInGroup))) + groupExists && + currentUserExists && + (!userIsMember || (userIsMember && (sameUserRoleInGroup || !userIsOwner))) && + ((currentUserIsAdmin && adminCanSetRole) || (currentUserIsOwner && ownerCanSetRole)) ) } catch (error) { throw new Error(error) diff --git a/webapp/components/Group/GroupMember.vue b/webapp/components/Group/GroupMember.vue index db5635c1f..830318767 100644 --- a/webapp/components/Group/GroupMember.vue +++ b/webapp/components/Group/GroupMember.vue @@ -179,12 +179,17 @@ export default { }, async addMemberToGroup() { const newRole = 'usual' + if (this.groupMembers.find((member) => member.id === this.slugUser[0].id)) { + this.$toast.error( + this.$t('group.errors.userAlreadyMember', { slug: this.slugUser[0].slug }), + ) + return + } try { await this.$apollo.mutate({ mutation: changeGroupMemberRoleMutation(), variables: { groupId: this.groupId, userId: this.slugUser[0].id, roleInGroup: newRole }, }) - // this.$apollo.queries.GroupMembers.refetch() this.$emit('loadGroupMembers') this.slugUser = [] this.form.query = '' diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 39fd2de9f..31a514470 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -422,6 +422,9 @@ "groupName": "Einstellungen für „{name}“", "title": "Meine Gruppe ändern" }, + "errors": { + "userAlreadyMember": "Nutzer @{slug} ist bereits Mitglied" + }, "follow": "Folge", "foundation": "Gründung", "general": "Allgemein", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 18b579df4..4b63033c1 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -422,6 +422,9 @@ "groupName": "Settings Of “{name}”", "title": "Edit My Group" }, + "errors": { + "userAlreadyMember": "User @{slug} is already a member" + }, "follow": "Follow", "foundation": "Foundation", "general": "General",