Commit 747976ce authored by Jure's avatar Jure Committed by Giannis Kopanas

feat(authsome): add collabra-authsome mode

parent d77a2e57
This diff is collapsed.
......@@ -4,7 +4,7 @@ const logger = require('winston')
module.exports = {
authsome: {
mode: require.resolve('xpub-collabra-authsome'),
mode: path.resolve(__dirname, 'authsome.js'),
teams: {
seniorEditor: {
name: 'Senior Editors',
......
const { deferConfig } = require('config/defer')
const winston = require('winston')
module.exports = {
'pubsweet-server': {
db: { database: 'test' },
db: {
// temporary database name set by jest-environment-db
database: global.__testDbName || 'test',
},
ignoreTerminatedConnectionError: true,
logger: new winston.Logger({
level: 'warn',
transports: [new winston.transports.Console()],
}),
port: 4000,
baseUrl: deferConfig(
cfg => `http://localhost:${cfg['pubsweet-server'].port}`,
),
secret: 'secret-string',
},
secret: 'test',
pubsweet: {
components: [], // There is something weird going on if there are components present.
},
baseUrl: deferConfig(
cfg => `http://localhost:${cfg['pubsweet-server'].port}`,
),
'password-reset': deferConfig(
cfg => `http://localhost:${cfg['pubsweet-server'].port}/password-reset`,
),
mailer: {
transport: {
sendmail: false,
......
......@@ -26,20 +26,20 @@
"moment": "^2.18.1",
"prop-types": "^15.5.10",
"pubsweet": "^2.0.0",
"pubsweet-client": "^2.1.1",
"pubsweet-client": "^2.3.1",
"pubsweet-component-ink-backend": "^0.1.1",
"pubsweet-component-ink-frontend": "^1.0.0",
"pubsweet-component-login": "^1.0.1",
"pubsweet-component-signup": "^1.0.0",
"pubsweet-component-teams-manager": "^1.0.6",
"pubsweet-component-users-manager": "^1.0.1",
"pubsweet-component-teams-manager": "^1.1.0",
"pubsweet-component-users-manager": "^2.0.0",
"pubsweet-component-xpub-dashboard": "^0.2.1",
"pubsweet-component-xpub-find-reviewers": "^0.0.6",
"pubsweet-component-xpub-manuscript": "^0.0.12",
"pubsweet-component-xpub-review": "^0.2.0",
"pubsweet-component-xpub-review-backend": "^0.2.0",
"pubsweet-component-xpub-submit": "^0.1.0",
"pubsweet-server": "^2.0.0",
"pubsweet-server": "^3.0.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router-dom": "^4.2.2",
......@@ -63,18 +63,10 @@
"clean-webpack-plugin": "^0.1.17",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.5",
"html-webpack-plugin": "^2.24.0",
"joi-browser": "^10.0.6",
"jest-cli": "^22.1.4",
"jest-environment-db": "^1.0.0",
"node-sass": "^4.5.3",
"react-hot-loader": "^3.1.1",
"sass-loader": "^6.0.6",
"string-replace-loader": "^1.3.0",
"style-loader": "^0.19.0",
"uglifyjs-webpack-plugin": "^1.1.2",
"webpack": "^3.8.1",
"webpack-dev-middleware": "^1.12.0",
"eslint": "^4.12.0",
"eslint-config-pubsweet": "^0.0.6",
"eslint-plugin-import": "^2.8.0",
......@@ -121,6 +113,13 @@
"server": "pubsweet server",
"build": "NODE_ENV=production pubsweet build"
},
"jest": {
"testEnvironment": "jest-environment-db",
"testRegex": "/test/.*.test.js$",
"collectCoverage": true,
"collectCoverageFrom": ["src/**/*.js", "config/authsome.js"],
"setupTestFrameworkScriptFile": "<rootDir>/test/helpers/jest-setup.js"
},
"lint-staged": {
"*.js": [
"prettier --write",
......
const Authsome = require('authsome')
const authsomeConfig = require('config').get('authsome')
const collections = [
{
id: 'collection1',
},
{
id: 'collection2',
},
]
const teams = [
{
id: 'team1',
teamType: 'handlingEditor',
object: {
id: 'collection2',
type: 'collection',
},
},
{
id: 'team2',
teamType: 'seniorEditor',
object: {
id: 'collection1',
type: 'collection',
},
},
{
id: 'team3',
teamType: 'managingEditor',
// No associated object means this is a global team
},
]
const users = [
{
id: 'user1',
username: 'handlingEditor1',
teams: ['team1'],
},
{
id: 'user2',
username: 'seniorEditor1',
teams: ['team2'],
},
{
id: 'user3',
username: 'managingEditor1',
teams: ['team3'],
},
{
id: 'adminId',
username: 'admin',
admin: true,
},
]
const authsome = new Authsome(
{ ...authsomeConfig, mode: require('../../config/authsome.js') },
{
models: {
User: { find: id => users.find(user => user.id === id) },
Team: { find: id => teams.find(team => team.id === id) },
},
},
)
describe('admin', () => {
it('allows everything to an admin', async () => {
const permission = await authsome.can(
'adminId',
'DELETE',
'thisSensitiveThing',
)
expect(permission).toBe(true)
})
})
describe('Handling Editor', () => {
it('lists only collections where user is a member of the handling editors team', async () => {
const permission = await authsome.can('user1', 'GET', {
path: '/collections',
})
const filteredCollections = await permission.filter(collections)
expect(filteredCollections).toEqual([collections[1]])
})
})
describe('Senior Editor', () => {
it('lists only collections where user is a member of the senior editors team', async () => {
const permission = await authsome.can('user2', 'GET', {
path: '/collections',
})
const filteredCollections = await permission.filter(collections)
expect(filteredCollections).toEqual([collections[0]])
})
})
describe('Managing Editor', () => {
it('can list all collections', async () => {
const permission = await authsome.can('user3', 'GET', {
path: '/collections',
})
expect(permission).toBe(true)
})
})
const {
User,
Collection,
Team,
Fragment,
} = require('pubsweet-server/src/models')
// Perhaps these should be exported from server together?
const cleanDB = require('pubsweet-server/test/helpers/db_cleaner')
const fixtures = require('pubsweet-server/test/fixtures/fixtures')
const api = require('pubsweet-server/test/helpers/api')
const authentication = require('pubsweet-server/src/authentication')
let adminToken
let userToken
let admin
let user
const collectionPaper1 = {
title: 'Paper 1',
status: 'submitted',
}
describe('server integration', () => {
beforeEach(async () => {
await cleanDB()
admin = await new User(fixtures.adminUser).save()
user = await new User(fixtures.user).save()
adminToken = authentication.token.create(admin)
userToken = authentication.token.create(user)
})
describe('admin', () => {
it('can create a collection with REST', async () => {
const collection = await api.collections
.create(collectionPaper1, adminToken)
.expect(201)
.then(res => res.body)
expect(collection.type).toEqual(fixtures.collection.type)
})
it('can create a collection through GraphQL', async () => {
const { body } = await api.graphql.query(
`mutation($input: String) {
createCollection(input: $input) { id, title, status }
}`,
{
input: JSON.stringify(collectionPaper1),
},
adminToken,
)
expect(body.data.createCollection.title).toEqual(collectionPaper1.title)
})
})
describe('user', () => {
describe('REST', () => {
it('can create users', async () => {
await api.users
.post({
username: 'test',
email: 'test3@example.com',
password: 'testpassword',
})
.expect(201)
.then(res => res.body)
})
it('can create a collection with REST', async () => {
const collection = await api.collections
.create(collectionPaper1, userToken)
.expect(201)
.then(res => res.body)
expect(collection.type).toEqual(fixtures.collection.type)
})
it('can create a fragment', async () => {
await api.fragments
.post({
fragment: { version: 3, fragmentType: 'version' },
token: userToken,
})
.expect(201)
})
it('can create a fragment in a collection', async () => {
const collection = await new Collection({
title: 'Test',
owners: [user.id],
}).save()
await api.fragments
.post({
fragment: { version: 4, fragmentType: 'version' },
collection: { id: collection.id },
token: userToken,
})
.expect(201)
})
it('can read own user', async () => {
const userResponse = await api.users
.get({ userId: user.id, token: userToken })
.expect(200)
.then(res => res.body)
expect(userResponse.id).toEqual(user.id)
})
it('can only read certain properties of other users', async () => {
const userResponse = await api.users
.get({ userId: admin.id, token: userToken })
.expect(200)
.then(res => res.body)
expect(Object.keys(userResponse).sort()).toEqual([
'id',
'type',
'username',
])
})
it('can list users', async () => {
const response = await api.users
.get({ token: userToken })
.expect(200)
.then(res => res.body)
expect(response.users).toHaveLength(2)
})
})
describe('GraphQL', () => {
it('can create a collection with GraphQL', async () => {
const { body } = await api.graphql.query(
`mutation($input: String) {
createCollection(input: $input) {
id
title
status
}
}`,
{ input: JSON.stringify(collectionPaper1) },
userToken,
)
expect(body.data.createCollection.title).toEqual(collectionPaper1.title)
})
it('can read a collection with GraphQL', async () => {
const collection = await new Collection({
title: 'Test',
owners: [user.id],
}).save()
const { body } = await api.graphql.query(
`query($id: ID) {
collection(id: $id) {
title
owners {
id
}
}
}`,
{ id: collection.id },
userToken,
)
expect(body).toEqual({
data: { collection: { title: 'Test', owners: [{ id: user.id }] } },
})
})
})
})
describe('managing editor', () => {
describe('REST', () => {
let editorToken
let paperA
let paperB
beforeEach(async () => {
const editor = await new User(
Object.assign({}, fixtures.user, {
username: 'testeditor',
email: 'testeditor@example.com',
}),
).save()
await new Team({
name: 'Managing Editors',
teamType: 'managingEditor',
members: [editor.id],
}).save()
const versionA1 = await new Fragment({
fragmentType: 'version',
version: 1,
owners: [user.id],
}).save()
const versionB1 = await new Fragment({
fragmentType: 'version',
version: 2,
owners: [admin.id],
}).save()
paperA = new Collection({
title: 'Project Paper A',
owners: [user.id],
fragments: [versionA1.id],
})
paperB = new Collection({
title: 'Project Paper B',
owners: [admin.id],
fragments: [versionB1.id],
})
await paperA.save()
await paperB.save()
editorToken = authentication.token.create(editor)
})
it('can list all projects (collections)', async () => {
const collections = await api.collections
.list(editorToken)
.expect(200)
.then(res => res.body)
expect(collections).toHaveLength(2)
})
it('can list all versions (fragments) of a project (collection)', async () => {
const fragments = await api.fragments
.get({ collection: paperA, token: editorToken })
.expect(200)
.then(res => res.body)
expect(fragments).toHaveLength(1)
})
})
})
})
const path = require('path')
process.env.NODE_CONFIG_DIR = path.resolve(__dirname, '..', '..', 'config')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment