From 26c3107750ef53243e26dd326b731a7fbebfbe3a Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 15 Jan 2021 15:39:51 +0100 Subject: [PATCH 01/14] setup for switch iser role as admin --- .../src/middleware/permissionsMiddleware.js | 1 + backend/src/schema/resolvers/users.js | 24 +++++++++++++++++++ backend/src/schema/types/type/User.gql | 2 ++ 3 files changed, 27 insertions(+) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index f4f8c654b..734931df2 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -149,6 +149,7 @@ export default shield( pinPost: isAdmin, unpinPost: isAdmin, UpdateDonations: isAdmin, + switchUserRole: isAdmin, }, User: { email: or(isMyOwn, isAdmin), diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index e276968e5..789ca2a37 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -244,6 +244,30 @@ export default { session.close() } }, + switchUserRole: async (object, args, context, resolveInfo) => { + const { role, id } = args + + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const switchUserRoleResponse = await transaction.run( + ` + MATCH (user:User {id: $id}) + SET user.role = $role + SET user.updatedAt = toString(datetime()) + RETURN user {.*} + `, + { id, role }, + ) + const [user] = switchUserRoleResponse.records.map((record) => record.get('user')) + return user + }) + try { + const user = await writeTxResultPromise + return user + } finally { + session.close() + } + }, }, User: { email: async (parent, params, context, resolveInfo) => { diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index e6e7191c5..17115c5ab 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -212,4 +212,6 @@ type Mutation { unmuteUser(id: ID!): User blockUser(id: ID!): User unblockUser(id: ID!): User + + switchUserRole(role: UserGroup!, id: ID!): User } From 78ed32fa4bc79be87d1a9c698df5dc1947799cc4 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 15 Jan 2021 15:39:51 +0100 Subject: [PATCH 02/14] setup for switch iser role as admin --- .../src/middleware/permissionsMiddleware.js | 1 + backend/src/schema/resolvers/users.js | 24 +++++++++++++++++++ backend/src/schema/types/type/User.gql | 2 ++ 3 files changed, 27 insertions(+) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index f4f8c654b..734931df2 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -149,6 +149,7 @@ export default shield( pinPost: isAdmin, unpinPost: isAdmin, UpdateDonations: isAdmin, + switchUserRole: isAdmin, }, User: { email: or(isMyOwn, isAdmin), diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index e276968e5..789ca2a37 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -244,6 +244,30 @@ export default { session.close() } }, + switchUserRole: async (object, args, context, resolveInfo) => { + const { role, id } = args + + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const switchUserRoleResponse = await transaction.run( + ` + MATCH (user:User {id: $id}) + SET user.role = $role + SET user.updatedAt = toString(datetime()) + RETURN user {.*} + `, + { id, role }, + ) + const [user] = switchUserRoleResponse.records.map((record) => record.get('user')) + return user + }) + try { + const user = await writeTxResultPromise + return user + } finally { + session.close() + } + }, }, User: { email: async (parent, params, context, resolveInfo) => { diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index e6e7191c5..17115c5ab 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -212,4 +212,6 @@ type Mutation { unmuteUser(id: ID!): User blockUser(id: ID!): User unblockUser(id: ID!): User + + switchUserRole(role: UserGroup!, id: ID!): User } From 190f9ba322eb1eddc9f052a6707bf1acfb1c09c3 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 15 Jan 2021 15:39:51 +0100 Subject: [PATCH 03/14] setup for switch iser role as admin --- .../src/middleware/permissionsMiddleware.js | 1 + backend/src/schema/resolvers/users.js | 24 +++++++++++++++++++ backend/src/schema/types/type/User.gql | 2 ++ 3 files changed, 27 insertions(+) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index f4f8c654b..734931df2 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -149,6 +149,7 @@ export default shield( pinPost: isAdmin, unpinPost: isAdmin, UpdateDonations: isAdmin, + switchUserRole: isAdmin, }, User: { email: or(isMyOwn, isAdmin), diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index e276968e5..789ca2a37 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -244,6 +244,30 @@ export default { session.close() } }, + switchUserRole: async (object, args, context, resolveInfo) => { + const { role, id } = args + + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const switchUserRoleResponse = await transaction.run( + ` + MATCH (user:User {id: $id}) + SET user.role = $role + SET user.updatedAt = toString(datetime()) + RETURN user {.*} + `, + { id, role }, + ) + const [user] = switchUserRoleResponse.records.map((record) => record.get('user')) + return user + }) + try { + const user = await writeTxResultPromise + return user + } finally { + session.close() + } + }, }, User: { email: async (parent, params, context, resolveInfo) => { diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index e6e7191c5..17115c5ab 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -212,4 +212,6 @@ type Mutation { unmuteUser(id: ID!): User blockUser(id: ID!): User unblockUser(id: ID!): User + + switchUserRole(role: UserGroup!, id: ID!): User } From d5e227a38ad1882dd2f1b0c9b818b4610252e824 Mon Sep 17 00:00:00 2001 From: narendra chandra Date: Sun, 24 Jan 2021 21:07:45 -0500 Subject: [PATCH 04/14] Added user role change feature --- webapp/graphql/admin/Roles.js | 25 +++++++++++++++++++++++++ webapp/pages/admin/users.vue | 29 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 webapp/graphql/admin/Roles.js diff --git a/webapp/graphql/admin/Roles.js b/webapp/graphql/admin/Roles.js new file mode 100644 index 000000000..4542708f3 --- /dev/null +++ b/webapp/graphql/admin/Roles.js @@ -0,0 +1,25 @@ +import gql from 'graphql-tag' + +export const FetchAllRoles = gql` + query { + __type(name: "UserGroup") { + name + enumValues { + name + } + } + } +` + +export const updateUserRole = (role, id) => { + return gql` + mutation { + switchUserRole(role: ${role}, id: "${id}" ) { + name + role + id + updatedAt + email + } + }` +} diff --git a/webapp/pages/admin/users.vue b/webapp/pages/admin/users.vue index 3d9a4f660..1b761770f 100644 --- a/webapp/pages/admin/users.vue +++ b/webapp/pages/admin/users.vue @@ -48,6 +48,23 @@ + + @@ -62,6 +79,7 @@ import gql from 'graphql-tag' import { isEmail } from 'validator' import normalizeEmail from '~/components/utils/NormalizeEmail' import PaginationButtons from '~/components/_new/generic/PaginationButtons/PaginationButtons' +import { FetchAllRoles, updateUserRole } from '~/graphql/admin/Roles' export default { components: { @@ -77,6 +95,7 @@ export default { hasNext: false, email: null, filter: null, + FetchAllRoles, form: { formData: { query: '', @@ -174,6 +193,16 @@ export default { } } }, + changeUserRole(id, event) { + const newRole = event.target.value + // this.role = ''; + // const id = this.User[0].id; + this.$apollo + .mutate({ + mutation: updateUserRole(newRole, id), + }) + .catch((error) => this.$toast.error(error.message)) + }, }, } From 0af45c015624a5cee700aa43dc0095e5afb750b4 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 29 Jan 2021 14:16:42 +0100 Subject: [PATCH 05/14] change role as admin tests added. current user cannot change own role --- backend/src/schema/resolvers/users.js | 1 + backend/src/schema/resolvers/users.spec.js | 80 ++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index 789ca2a37..55094f088 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -247,6 +247,7 @@ export default { switchUserRole: async (object, args, context, resolveInfo) => { const { role, id } = args + if (context.user.id === id) throw new Error('you-cannot-change-your-own-role') const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { const switchUserRoleResponse = await transaction.run( diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js index cce45ae6e..df0958342 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.js @@ -45,6 +45,18 @@ const deleteUserMutation = gql` } ` +const switchUserRoleMutation = gql` + mutation($role: UserGroup!, $id: ID!) { + switchUserRole(role: $role, id: $id) { + name + role + id + updatedAt + email + } + } +` + beforeAll(() => { const { server } = createServer({ context: () => { @@ -458,3 +470,71 @@ describe('Delete a User as admin', () => { }) }) }) + +describe('switch user role', () => { + beforeEach(async () => { + user = await Factory.build('user', { + id: 'user', + role: 'user', + }) + admin = await Factory.build('user', { + role: 'admin', + id: 'admin', + }) + }) + + describe('as simple user', () => { + it('cannot change the role', async () => { + authenticatedUser = await user.toJson() + variables = { + id: 'user', + role: 'admin', + } + await expect(mutate({ mutation: switchUserRoleMutation, variables })).resolves.toEqual( + expect.objectContaining({ + errors: [ + expect.objectContaining({ + message: 'Not Authorised!', + }), + ], + }), + ) + }) + }) + + describe('as admin', () => { + it('changes the role of other user', async () => { + authenticatedUser = await admin.toJson() + variables = { + id: 'user', + role: 'moderator', + } + await expect(mutate({ mutation: switchUserRoleMutation, variables })).resolves.toEqual( + expect.objectContaining({ + data: { + switchUserRole: expect.objectContaining({ + role: 'moderator', + }), + }, + }), + ) + }) + + it('cannot change own role', async () => { + authenticatedUser = await admin.toJson() + variables = { + id: 'admin', + role: 'moderator', + } + await expect(mutate({ mutation: switchUserRoleMutation, variables })).resolves.toEqual( + expect.objectContaining({ + errors: [ + expect.objectContaining({ + message: 'you-cannot-change-your-own-role', + }), + ], + }), + ) + }) + }) +}) From 4920a902c452b18c0862423519c57405a8ffa7e3 Mon Sep 17 00:00:00 2001 From: narendra chandra Date: Sat, 6 Feb 2021 17:12:24 -0500 Subject: [PATCH 06/14] User cannot change their own role --- webapp/pages/admin/users.vue | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/webapp/pages/admin/users.vue b/webapp/pages/admin/users.vue index 1b761770f..082ffde0d 100644 --- a/webapp/pages/admin/users.vue +++ b/webapp/pages/admin/users.vue @@ -49,7 +49,7 @@ {{ scope.row.createdAt | dateTime }} -