Commit e4c7d737 authored by Giannis Kopanas's avatar Giannis Kopanas

Authsome view page permissions

parent 030d288d
import React from 'react'
import styled from 'styled-components'
import { compose } from 'recompose'
import { compose, withState, withHandlers, lifecycle } from 'recompose'
import { connect } from 'react-redux'
import Authorize from 'pubsweet-client/src/helpers/Authorize'
import withAuthsome from 'pubsweet-client/src/helpers/withAuthsome'
import { withRouter, matchPath } from 'react-router-dom'
// import PropTypes from 'prop-types'
......@@ -27,6 +27,7 @@ const Root = styled.div`
`
const App = ({
authorized,
children,
currentUser,
journal,
......@@ -48,13 +49,13 @@ const App = ({
links = showLinks
? [
<Action
active={window.location.pathname === submitLink}
active={(window.location.pathname === submitLink).toString()}
to={submitLink}
>
Summary Info
</Action>,
<Action
active={window.location.pathname === manuscriptLink}
active={(window.location.pathname === manuscriptLink).toString()}
to={manuscriptLink}
>
Manuscript
......@@ -63,13 +64,16 @@ const App = ({
: null
}
links.push(
<Authorize object={{}} operation="can view teams menu">
<Action active={window.location.pathname === '/teams'} to="/teams">
if (authorized) {
links.push(
<Action
active={(window.location.pathname === '/teams').toString()}
to="/teams"
>
Team Manager
</Action>
</Authorize>,
)
</Action>,
)
}
return (
<Root disableLinks={disableLinks}>
......@@ -93,6 +97,21 @@ export default compose(
}),
{ logoutUser: actions.logoutUser },
),
withAuthsome(),
withState('authorized', 'authorizeCheck', false),
withHandlers({
authorizeCheckfn: ({ authorizeCheck, currentUser, authsome }) => () =>
authsome
.can(currentUser && currentUser.id, 'can view teams menu', {})
.then(result => authorizeCheck(() => result)),
}),
withJournal,
withRouter,
lifecycle({
componentDidUpdate(prevProps) {
if (prevProps.currentUser !== this.props.currentUser) {
this.props.authorizeCheckfn()
}
},
}),
)(App)
......@@ -134,8 +134,8 @@ class XpubCollabraMode {
*
* @returns {boolean}
*/
isManagingEditor() {
return this.isTeamMember('managingEditor')
isManagingEditor(object) {
return this.isTeamMember('managingEditor', object)
}
/**
......@@ -179,12 +179,12 @@ class XpubCollabraMode {
this.user = await this.context.models.User.find(this.userId)
if (await this.isManagingEditor()) {
const collection = this.object
if (await this.isManagingEditor(collection)) {
return true
}
const collection = this.object
let permission = this.checkTeamMembers(
['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
collection,
......@@ -254,12 +254,30 @@ class XpubCollabraMode {
if (!this.isAuthenticated()) {
return false
}
this.user = await this.context.models.User.find(this.userId)
const fragment = this.object
let permission = this.isAuthor(fragment)
permission = permission ? true : this.isAssignedReviewerEditor(fragment)
permission = permission
? true
: await this.isAssignedReviewerEditor(fragment)
permission = permission ? true : this.isAssignedManagingEditor(fragment)
permission = permission
? true
: await this.checkTeamMembers(
[
'isAssignedSeniorEditor',
'isAssignedHandlingEditor',
'isManagingEditor',
],
{ id: fragment.collections[0] },
)
// permission = permission
// ? true
// : await this.isAssignedManagingEditor(fragment)
// Caveat: this means every logged-in user can read every fragment (but needs its UUID)
// Ideally we'd check if the fragment (version) belongs to a collection (project)
// where the user is a member of a team with the appropriate rights. However there is no
......@@ -278,15 +296,16 @@ class XpubCollabraMode {
}
this.user = await this.context.models.User.find(this.userId)
if (await this.isManagingEditor()) {
return true
}
return {
filter: async collections => {
const filteredCollections = await Promise.all(
collections.map(async collection => {
let condition = await this.checkTeamMembers(
['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
[
'isAssignedSeniorEditor',
'isAssignedHandlingEditor',
'isManagingEditor',
],
collection,
)
condition = condition
......@@ -436,6 +455,16 @@ class XpubCollabraMode {
return true
}
/**
* Checks if a user can lists fragments
*
* @returns {boolean}
*/
// eslint-disable-next-line
async canListFragments() {
return true
}
/**
* Checks if a user can update a fragment
*
......@@ -564,7 +593,7 @@ class XpubCollabraMode {
return this.checkPageReview(params)
}
if (path === '/projects/:project/versions/:version/decision/:project') {
if (path === '/projects/:project/versions/:version/decisions/:decision') {
return this.checkPageDecision(params)
}
......@@ -591,21 +620,28 @@ class XpubCollabraMode {
return permission
}
async checkPageReview(params) {
async checkPageDecision(params) {
const collection = this.context.models.Collection.find(params.project)
const version = this.context.models.Fragment.find(params.version)
if (this.isAuthor(collection)) return false
let permission = await this.checkTeamMembers(
const permission = await this.checkTeamMembers(
['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
collection,
)
// set object to Fragment so can validate on canReadFragment
this.object = version
permission = permission ? true : await this.canReadFragment()
return permission
}
async checkPageReview(params) {
const collection = this.context.models.Collection.find(params.project)
if (this.isAuthor(collection)) return false
const permission = await this.checkTeamMembers(
['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
collection,
)
return permission
}
......@@ -638,6 +674,7 @@ module.exports = {
},
GET: (userId, operation, object, context) => {
const mode = new XpubCollabraMode(userId, operation, object, context)
// GET /api/collections
if (mode.object && mode.object.path === '/collections') {
return mode.canListCollections()
......
......@@ -33,7 +33,10 @@ const teams = [
{
id: 'team3',
teamType: 'managingEditor',
// No associated object means this is a global team
object: {
id: 'collection1',
type: 'collection',
},
},
{
id: 'team4',
......@@ -43,6 +46,14 @@ const teams = [
type: 'fragment',
},
},
{
id: 'team5',
teamType: 'managingEditor',
object: {
id: 'collection2',
type: 'collection',
},
},
]
const users = [
......@@ -59,7 +70,7 @@ const users = [
{
id: 'user3',
username: 'managingEditor1',
teams: ['team3'],
teams: ['team3', 'team5'],
},
{
id: 'user4',
......@@ -133,6 +144,8 @@ describe('Managing Editor', () => {
const permission = await authsome.can('user3', 'GET', {
path: '/collections',
})
expect(permission).toBe(true)
const filteredCollections = await permission.filter(collections)
expect(filteredCollections).toEqual(collections)
})
})
......@@ -194,12 +194,6 @@ describe('server integration', () => {
}),
).save()
await new Team({
name: 'Managing Editors',
teamType: 'managingEditor',
members: [editor.id],
}).save()
const versionA1 = await new Fragment({
fragmentType: 'version',
version: 1,
......@@ -225,6 +219,19 @@ describe('server integration', () => {
await paperA.save()
await paperB.save()
await versionA1.updateProperties({ collections: [paperA.id] })
await versionA1.save()
await new Team({
name: 'Managing Editors',
teamType: 'managingEditor',
members: [editor.id],
object: {
id: paperA.id,
type: 'collection',
},
}).save()
editorToken = authentication.token.create(editor)
})
......@@ -234,7 +241,7 @@ describe('server integration', () => {
.expect(200)
.then(res => res.body)
expect(collections).toHaveLength(2)
expect(collections).toHaveLength(1)
})
it('can list all versions (fragments) of a project (collection)', async () => {
......
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