diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js
index 59ae06c07..8343443c9 100644
--- a/backend/src/middleware/permissionsMiddleware.js
+++ b/backend/src/middleware/permissionsMiddleware.js
@@ -174,7 +174,7 @@ const permissions = shield(
VerifyEmailAddress: isAuthenticated,
},
User: {
- email: isMyOwn,
+ email: or(isMyOwn, isAdmin),
},
},
{
diff --git a/backend/src/middleware/permissionsMiddleware.spec.js b/backend/src/middleware/permissionsMiddleware.spec.js
index 6cf9dc302..da703fb11 100644
--- a/backend/src/middleware/permissionsMiddleware.spec.js
+++ b/backend/src/middleware/permissionsMiddleware.spec.js
@@ -1,22 +1,63 @@
-import { GraphQLClient } from 'graphql-request'
+import { createTestClient } from 'apollo-server-testing'
+import createServer from '../server'
import Factory from '../seed/factories'
-import { host, login } from '../jest/helpers'
+import { gql } from '../jest/helpers'
+import { getDriver, neode as getNeode } from '../bootstrap/neo4j'
const factory = Factory()
+const instance = getNeode()
+const driver = getDriver()
+
+let query, authenticatedUser, owner, anotherRegularUser, administrator, variables, moderator
+
+const userQuery = gql`
+ query($name: String) {
+ User(name: $name) {
+ email
+ }
+ }
+`
describe('authorization', () => {
+ beforeAll(async () => {
+ await factory.cleanDatabase()
+ const { server } = createServer({
+ context: () => ({
+ driver,
+ instance,
+ user: authenticatedUser,
+ }),
+ })
+ query = createTestClient(server).query
+ })
+
describe('given two existing users', () => {
beforeEach(async () => {
- await factory.create('User', {
- email: 'owner@example.org',
- name: 'Owner',
- password: 'iamtheowner',
- })
- await factory.create('User', {
- email: 'someone@example.org',
- name: 'Someone else',
- password: 'else',
- })
+ ;[owner, anotherRegularUser, administrator, moderator] = await Promise.all([
+ factory.create('User', {
+ email: 'owner@example.org',
+ name: 'Owner',
+ password: 'iamtheowner',
+ }),
+ factory.create('User', {
+ email: 'another.regular.user@example.org',
+ name: 'Another Regular User',
+ password: 'else',
+ }),
+ factory.create('User', {
+ email: 'admin@example.org',
+ name: 'Admin',
+ password: 'admin',
+ role: 'admin',
+ }),
+ factory.create('User', {
+ email: 'moderator@example.org',
+ name: 'Moderator',
+ password: 'moderator',
+ role: 'moderator',
+ }),
+ ])
+ variables = {}
})
afterEach(async () => {
@@ -24,66 +65,77 @@ describe('authorization', () => {
})
describe('access email address', () => {
- let headers = {}
- let loginCredentials = null
- const action = async () => {
- if (loginCredentials) {
- headers = await login(loginCredentials)
- }
- const graphQLClient = new GraphQLClient(host, { headers })
- return graphQLClient.request('{User(name: "Owner") { email } }')
- }
-
- describe('not logged in', () => {
- it('rejects', async () => {
- await expect(action()).rejects.toThrow('Not Authorised!')
- })
-
- it("does not expose the owner's email address", async () => {
- let response = {}
- try {
- await action()
- } catch (error) {
- response = error.response.data
- } finally {
- expect(response).toEqual({ User: [null] })
- }
- })
- })
-
- describe('as owner', () => {
+ describe('unauthenticated', () => {
beforeEach(() => {
- loginCredentials = {
- email: 'owner@example.org',
- password: 'iamtheowner',
- }
+ authenticatedUser = null
})
-
- it("exposes the owner's email address", async () => {
- await expect(action()).resolves.toEqual({ User: [{ email: 'owner@example.org' }] })
+ it("throws an error and does not expose the owner's email address", async () => {
+ await expect(
+ query({ query: userQuery, variables: { name: 'Owner' } }),
+ ).resolves.toMatchObject({
+ errors: [{ message: 'Not Authorised!' }],
+ data: { User: [null] },
+ })
})
})
- describe('authenticated as another user', () => {
- beforeEach(async () => {
- loginCredentials = {
- email: 'someone@example.org',
- password: 'else',
- }
+ describe('authenticated', () => {
+ describe('as the owner', () => {
+ beforeEach(async () => {
+ authenticatedUser = await owner.toJson()
+ })
+
+ it("exposes the owner's email address", async () => {
+ variables = { name: 'Owner' }
+ await expect(query({ query: userQuery, variables })).resolves.toMatchObject({
+ data: { User: [{ email: 'owner@example.org' }] },
+ errors: undefined,
+ })
+ })
})
- it('rejects', async () => {
- await expect(action()).rejects.toThrow('Not Authorised!')
+ describe('as another regular user', () => {
+ beforeEach(async () => {
+ authenticatedUser = await anotherRegularUser.toJson()
+ })
+
+ it("throws an error and does not expose the owner's email address", async () => {
+ await expect(
+ query({ query: userQuery, variables: { name: 'Owner' } }),
+ ).resolves.toMatchObject({
+ errors: [{ message: 'Not Authorised!' }],
+ data: { User: [null] },
+ })
+ })
})
- it("does not expose the owner's email address", async () => {
- let response
- try {
- await action()
- } catch (error) {
- response = error.response.data
- }
- expect(response).toEqual({ User: [null] })
+ describe('as a moderator', () => {
+ beforeEach(async () => {
+ authenticatedUser = await moderator.toJson()
+ })
+
+ it("throws an error and does not expose the owner's email address", async () => {
+ await expect(
+ query({ query: userQuery, variables: { name: 'Owner' } }),
+ ).resolves.toMatchObject({
+ errors: [{ message: 'Not Authorised!' }],
+ data: { User: [null] },
+ })
+ })
+ })
+
+ describe('administrator', () => {
+ beforeEach(async () => {
+ authenticatedUser = await administrator.toJson()
+ })
+
+ it("exposes the owner's email address", async () => {
+ variables = { name: 'Owner' }
+ await expect(query({ query: userQuery, variables })).resolves.toMatchObject({
+ data: { User: [{ email: 'owner@example.org' }] },
+ errors: undefined,
+ })
+ })
})
})
})
diff --git a/webapp/locales/de.json b/webapp/locales/de.json
index b6ee3f320..c282533b7 100644
--- a/webapp/locales/de.json
+++ b/webapp/locales/de.json
@@ -280,6 +280,7 @@
"columns": {
"number": "Nr.",
"name": "Name",
+ "email": "E-mail",
"slug": "Slug",
"role": "Rolle",
"createdAt": "Erstellt am"
diff --git a/webapp/locales/en.json b/webapp/locales/en.json
index b243e39a3..f099cdbbc 100644
--- a/webapp/locales/en.json
+++ b/webapp/locales/en.json
@@ -281,6 +281,7 @@
"columns": {
"number": "No.",
"name": "Name",
+ "email": "E-mail",
"slug": "Slug",
"role": "Role",
"createdAt": "Created at"
diff --git a/webapp/pages/admin/users.vue b/webapp/pages/admin/users.vue
index e58b413aa..d5590f474 100644
--- a/webapp/pages/admin/users.vue
+++ b/webapp/pages/admin/users.vue
@@ -33,6 +33,11 @@
{{ scope.row.name | truncate(20) }}
+
+
+ {{ scope.row.email }}
+
+