import { createTestClient } from 'apollo-server-testing' import createServer from '../server' import Factory, { cleanDatabase } from '../db/factories' import gql from 'graphql-tag' import { getDriver, getNeode } from '../db/neo4j' import CONFIG from '../config' const instance = getNeode() const driver = getDriver() let query, mutate, variables let authenticatedUser, owner, anotherRegularUser, administrator, moderator describe('authorization', () => { beforeAll(async () => { await cleanDatabase() const { server } = createServer({ context: () => ({ driver, instance, user: authenticatedUser, }), }) query = createTestClient(server).query mutate = createTestClient(server).mutate }) afterAll(async () => { await cleanDatabase() driver.close() }) // TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 afterEach(async () => { await cleanDatabase() }) describe('given an owner, an other user, an admin, a moderator', () => { beforeEach(async () => { ;[owner, anotherRegularUser, administrator, moderator] = await Promise.all([ Factory.build( 'user', { name: 'Owner', }, { email: 'owner@example.org', password: 'iamtheowner', }, ), Factory.build( 'user', { name: 'Another Regular User', }, { email: 'another.regular.user@example.org', password: 'else', }, ), Factory.build( 'user', { name: 'Admin', role: 'admin', }, { email: 'admin@example.org', password: 'admin', }, ), Factory.build( 'user', { name: 'Moderator', role: 'moderator', }, { email: 'moderator@example.org', password: 'moderator', }, ), ]) variables = {} }) describe('access email address', () => { const userQuery = gql` query ($name: String) { User(name: $name) { email } } ` describe('unauthenticated', () => { beforeEach(() => { authenticatedUser = null }) 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 Authorized!' }], data: { User: [null] }, }) }) }) 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, }) }) }) 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 Authorized!' }], data: { 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 Authorized!' }], data: { User: [null] }, }) }) }) describe('as an 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, }) }) }) }) }) describe('access Signup', () => { const signupMutation = gql` mutation ($email: String!, $inviteCode: String) { Signup(email: $email, inviteCode: $inviteCode) { email } } ` describe('admin invite only', () => { beforeEach(async () => { variables = { email: 'some@email.org', inviteCode: 'ABCDEF', } CONFIG.INVITE_REGISTRATION = false CONFIG.PUBLIC_REGISTRATION = false await Factory.build('inviteCode', { code: 'ABCDEF', }) }) describe('as user', () => { beforeEach(async () => { authenticatedUser = await anotherRegularUser.toJson() }) it('denies permission', async () => { await expect(mutate({ mutation: signupMutation, variables })).resolves.toMatchObject({ errors: [{ message: 'Not Authorized!' }], data: { Signup: null }, }) }) }) describe('as admin', () => { beforeEach(async () => { authenticatedUser = await administrator.toJson() }) it('returns an email', async () => { await expect(mutate({ mutation: signupMutation, variables })).resolves.toMatchObject({ errors: undefined, data: { Signup: { email: 'some@email.org' }, }, }) }) }) }) describe('public registration', () => { beforeEach(async () => { variables = { email: 'some@email.org', inviteCode: 'ABCDEF', } CONFIG.INVITE_REGISTRATION = false CONFIG.PUBLIC_REGISTRATION = true await Factory.build('inviteCode', { code: 'ABCDEF', }) }) describe('as anyone', () => { beforeEach(async () => { authenticatedUser = null }) it('returns an email', async () => { await expect(mutate({ mutation: signupMutation, variables })).resolves.toMatchObject({ errors: undefined, data: { Signup: { email: 'some@email.org' }, }, }) }) }) }) describe('invite registration', () => { beforeEach(async () => { CONFIG.INVITE_REGISTRATION = true CONFIG.PUBLIC_REGISTRATION = false await Factory.build('inviteCode', { code: 'ABCDEF', }) }) describe('as anyone with valid invite code', () => { beforeEach(async () => { variables = { email: 'some@email.org', inviteCode: 'ABCDEF', } authenticatedUser = null }) it('returns an email', async () => { await expect(mutate({ mutation: signupMutation, variables })).resolves.toMatchObject({ errors: undefined, data: { Signup: { email: 'some@email.org' }, }, }) }) }) describe('as anyone without valid invite', () => { beforeEach(async () => { variables = { email: 'some@email.org', inviteCode: 'no valid invite code', } authenticatedUser = null }) it('denies permission', async () => { await expect(mutate({ mutation: signupMutation, variables })).resolves.toMatchObject({ errors: [{ message: 'Not Authorized!' }], data: { Signup: null }, }) }) }) }) }) }) })