From ee322e9f635083de68f62449a48f7742f0e3ebdf Mon Sep 17 00:00:00 2001
From: Jure Triglav <juretriglav@gmail.com>
Date: Thu, 5 Dec 2019 01:12:31 +0100
Subject: [PATCH] fix: several bugfixes

---
 app/components/App.js                         |   2 +
 .../src/components/Reviews.js                 |   2 +-
 .../src/components/sections/EditorItem.js     |   1 +
 .../src/components/sections/ReviewerItem.js   |   1 +
 .../src/components/DecisionPage.js            |   2 +-
 .../src/components/ReviewPage.js              |  39 +-
 .../src/components/ReviewersPage.js           |  24 +-
 .../components/assignEditors/AssignEditor.js  |   7 +-
 .../src/components/review/ReviewForm.js       |  39 +-
 .../src/components/review/ReviewLayout.js     |   7 +-
 .../src/components/SubmitPage.js              |  16 +-
 app/config/journal/metadata.js                |   4 +-
 app/routes.js                                 |   7 +-
 config/authsome.js                            | 494 +++++------
 config/authsomeGraphql.js                     | 789 ------------------
 config/default.js                             |   2 +-
 cypress/integration/upload_spec.js            | 149 +++-
 scripts/clearAndSeed.js                       |  30 +
 server/manuscript/src/resolvers.js            |   3 +-
 server/manuscript/src/typeDefs.js             |   2 +-
 20 files changed, 461 insertions(+), 1159 deletions(-)
 delete mode 100644 config/authsomeGraphql.js

diff --git a/app/components/App.js b/app/components/App.js
index 0126f13780..549bd167a9 100644
--- a/app/components/App.js
+++ b/app/components/App.js
@@ -102,6 +102,8 @@ const App = ({ authorized, children, history, match }) => {
     <Root converting={conversion.converting}>
       <AppBar
         brand={journal.metadata.name}
+        brandLink="/dashboard"
+        loginLink="/login?next=/dashboard"
         navLinkComponents={links}
         onLogoutClick={() => logoutUser(client)}
         user={currentUser}
diff --git a/app/components/component-xpub-dashboard/src/components/Reviews.js b/app/components/component-xpub-dashboard/src/components/Reviews.js
index b2bb5ab11b..1ba09e86e1 100644
--- a/app/components/component-xpub-dashboard/src/components/Reviews.js
+++ b/app/components/component-xpub-dashboard/src/components/Reviews.js
@@ -52,7 +52,7 @@ const Reviews = ({ version, journal }) => (
     <JournalContext.Consumer>
       {journal =>
         journal.reviewStatus.map(status => (
-          <BadgeContainer key={status}>
+          <BadgeContainer key={status} data-testid={status}>
             <Badge count={countStatus(version, status)} label={status} />
           </BadgeContainer>
         ))
diff --git a/app/components/component-xpub-dashboard/src/components/sections/EditorItem.js b/app/components/component-xpub-dashboard/src/components/sections/EditorItem.js
index 4cb8d02403..381df9490a 100644
--- a/app/components/component-xpub-dashboard/src/components/sections/EditorItem.js
+++ b/app/components/component-xpub-dashboard/src/components/sections/EditorItem.js
@@ -34,6 +34,7 @@ const EditorItemLinks = ({ version, journals }) => (
       Summary Info
     </Action>
     <Action
+      data-testid="control-panel"
       to={`/journals/${journals.id}/versions/${version.id}/decisions/${version.id}`}
     >
       {version.decision && version.decision.status === 'submitted'
diff --git a/app/components/component-xpub-dashboard/src/components/sections/ReviewerItem.js b/app/components/component-xpub-dashboard/src/components/sections/ReviewerItem.js
index 9b017adf1e..3fb7e1b159 100644
--- a/app/components/component-xpub-dashboard/src/components/sections/ReviewerItem.js
+++ b/app/components/component-xpub-dashboard/src/components/sections/ReviewerItem.js
@@ -65,6 +65,7 @@ const ReviewerItem = ({ version, journals, currentUser, reviewerRespond }) => {
             <Actions>
               <ActionContainer>
                 <Button
+                  data-testid="accept-review"
                   onClick={() => {
                     reviewerRespond({
                       variables: {
diff --git a/app/components/component-xpub-review/src/components/DecisionPage.js b/app/components/component-xpub-review/src/components/DecisionPage.js
index 7310071acb..0a93823b09 100644
--- a/app/components/component-xpub-review/src/components/DecisionPage.js
+++ b/app/components/component-xpub-review/src/components/DecisionPage.js
@@ -216,7 +216,7 @@ export default compose(
             }),
           },
         }).then(() => {
-          history.push('/')
+          history.push('/dashboard')
         })
       },
     }),
diff --git a/app/components/component-xpub-review/src/components/ReviewPage.js b/app/components/component-xpub-review/src/components/ReviewPage.js
index 65493408ca..35fe9955d8 100644
--- a/app/components/component-xpub-review/src/components/ReviewPage.js
+++ b/app/components/component-xpub-review/src/components/ReviewPage.js
@@ -3,7 +3,7 @@ import { graphql } from '@apollo/react-hoc'
 import { gql } from 'apollo-client-preset'
 import { withFormik } from 'formik'
 import { withLoader } from 'pubsweet-client'
-import { cloneDeep } from 'lodash'
+import { cloneDeep, debounce } from 'lodash'
 import { getCommentContent } from './review/util'
 import ReviewLayout from '../components/review/ReviewLayout'
 
@@ -264,12 +264,16 @@ export default compose(
             input: reviewData,
           },
           update: (proxy, { data: { updateReview } }) => {
-            const data = proxy.readQuery({
-              query,
-              variables: {
-                id: manuscript.id,
-              },
-            })
+            const data = JSON.parse(
+              JSON.stringify(
+                proxy.readQuery({
+                  query,
+                  variables: {
+                    id: manuscript.id,
+                  },
+                }),
+              ),
+            )
             let reviewIndex = data.manuscript.reviews.findIndex(
               review => review.id === updateReview.id,
             )
@@ -300,14 +304,12 @@ export default compose(
         const team = cloneDeep(manuscript.teams).find(
           team => team.role === 'reviewerEditor',
         )
-        team.members = team.members
-          .map(m => {
-            if (m.user.id === currentUser.id) {
-              return { user: { id: m.user.id }, status: 'completed' }
-            }
-            return undefined
-          })
-          .filter(m => m)
+        team.members = team.members.map(m => {
+          if (m.user.id === currentUser.id) {
+            return { user: { id: m.user.id }, status: 'completed' }
+          }
+          return { user: { id: m.user.id }, status: m.status }
+        })
 
         updateTeam({
           variables: {
@@ -317,15 +319,16 @@ export default compose(
             },
           },
         }).then(() => {
-          history.push('/')
+          history.push('/dashboard')
         })
       },
     }),
   ),
   withFormik({
-    enableReinitialize: true,
     mapPropsToValues: props =>
-      props.manuscript.reviews.find(review => !review.isDecision) || {
+      props.manuscript.reviews.find(
+        review => review.user.id === props.currentUser.id && !review.isDecision,
+      ) || {
         id: null,
         comments: [],
         recommendation: null,
diff --git a/app/components/component-xpub-review/src/components/ReviewersPage.js b/app/components/component-xpub-review/src/components/ReviewersPage.js
index 42b05b69f0..54f5b799dd 100644
--- a/app/components/component-xpub-review/src/components/ReviewersPage.js
+++ b/app/components/component-xpub-review/src/components/ReviewersPage.js
@@ -107,12 +107,16 @@ const query = gql`
 `
 
 const update = match => (proxy, { data: { updateTeam, createTeam } }) => {
-  const data = proxy.readQuery({
-    query,
-    variables: {
-      id: match.params.version,
-    },
-  })
+  const data = JSON.parse(
+    JSON.stringify(
+      proxy.readQuery({
+        query,
+        variables: {
+          id: match.params.version,
+        },
+      }),
+    ),
+  )
 
   if (updateTeam) {
     const teamIndex = data.teams.findIndex(team => team.id === updateTeam.id)
@@ -148,7 +152,13 @@ const handleSubmit = (
   if (team.id) {
     const newTeam = {
       ...omit(team, ['object', 'id', '__typename']),
-      members: cloneDeep(team.members),
+      // TODO: Find a cleaner way of updating members
+      members: team.members.map(member => ({
+        user: {
+          id: member.user.id,
+        },
+        status: member.status,
+      })),
     }
 
     newTeam.members.push({ user: { id: user.id }, status: 'invited' })
diff --git a/app/components/component-xpub-review/src/components/assignEditors/AssignEditor.js b/app/components/component-xpub-review/src/components/assignEditors/AssignEditor.js
index 11811a22ec..127f5d9ffc 100644
--- a/app/components/component-xpub-review/src/components/assignEditors/AssignEditor.js
+++ b/app/components/component-xpub-review/src/components/assignEditors/AssignEditor.js
@@ -65,6 +65,7 @@ const AssignEditor = ({
   options,
 }) => (
   <Menu
+    data-testid={`assign${teamRole}`}
     label={teamName}
     onChange={user => {
       if (value) {
@@ -91,7 +92,7 @@ export default compose(
           variables: {
             id: team.id,
             input: {
-              members: [{ id: userId }],
+              members: [{ user: { id: userId } }],
             },
           },
         })
@@ -111,7 +112,7 @@ export default compose(
           name:
             teamRole === 'seniorEditor' ? 'Senior Editor' : 'Handling Editor',
           role: teamRole,
-          members: [{ id: userId }],
+          members: [{ user: { id: userId } }],
         }
 
         mutate({
@@ -137,7 +138,7 @@ export default compose(
     return {
       teamName,
       options: optionUsers,
-      value: members.length > 0 ? members[0].id : undefined,
+      value: members.length > 0 ? members[0].user.id : undefined,
     }
   }),
   withLoader(),
diff --git a/app/components/component-xpub-review/src/components/review/ReviewForm.js b/app/components/component-xpub-review/src/components/review/ReviewForm.js
index 1eefa22857..8d5ce88681 100644
--- a/app/components/component-xpub-review/src/components/review/ReviewForm.js
+++ b/app/components/component-xpub-review/src/components/review/ReviewForm.js
@@ -57,15 +57,16 @@ const AttachmentsInput = ({
 
 const NoteInput = ({
   field,
-  form: { values, setFieldValue },
+  form: { values, setFieldValue, setTouched },
   updateReview,
+  ...rest
 }) => (
   <NoteEditor
     key="note-comment"
     placeholder="Enter your review…"
     title="Comments to the Author"
     {...field}
-    onChange={value => {
+    onBlur={value => {
       const { comment } = createComments(
         values,
         {
@@ -94,7 +95,7 @@ const ConfidentialInput = ({
     placeholder="Enter a confidential note to the editor (optional)…"
     title="Confidential Comments to Editor (Optional)"
     {...field}
-    onChange={value => {
+    onBlur={value => {
       const { comment } = createComments(
         values,
         {
@@ -132,11 +133,9 @@ const ReviewComment = props => (
   <>
     <AdminSection>
       <div name="note">
-        <Field
-          component={extraProps => <NoteInput {...props} {...extraProps} />}
-          key="noteField"
-          name="comments.0.content"
-        />
+        <Field key="noteField" name="comments.0.content">
+          {extraProps => <NoteInput {...props} {...extraProps} />}
+        </Field>
         <Field
           component={extraProps => (
             <AttachmentsInput type="note" {...props} {...extraProps} />
@@ -146,13 +145,9 @@ const ReviewComment = props => (
     </AdminSection>
     <AdminSection>
       <div name="confidential">
-        <Field
-          component={extraProps => (
-            <ConfidentialInput {...props} {...extraProps} />
-          )}
-          key="confidentialField"
-          name="comments.1.content"
-        />
+        <Field key="confidentialField" name="comments.1.content">
+          {extraProps => <ConfidentialInput {...props} {...extraProps} />}
+        </Field>
         <Field
           component={extraProps => (
             <AttachmentsInput type="confidential" {...props} {...extraProps} />
@@ -174,21 +169,23 @@ const ReviewForm = ({
   review,
 }) => (
   <form onSubmit={handleSubmit}>
-    <ReviewComment updateReview={updateReview} uploadFile={uploadFile} />
+    <ReviewComment
+      review={review}
+      updateReview={updateReview}
+      uploadFile={uploadFile}
+    />
     <AdminSection>
       <div name="Recommendation">
         <Title>Recommendation</Title>
-        <Field
-          component={props => (
+        <Field name="recommendation" updateReview={updateReview}>
+          {props => (
             <RecommendationInput
               journal={journal}
               updateReview={updateReview}
               {...props}
             />
           )}
-          name="recommendation"
-          updateReview={updateReview}
-        />
+        </Field>
       </div>
     </AdminSection>
 
diff --git a/app/components/component-xpub-review/src/components/review/ReviewLayout.js b/app/components/component-xpub-review/src/components/review/ReviewLayout.js
index 3872593897..0153dc0168 100644
--- a/app/components/component-xpub-review/src/components/review/ReviewLayout.js
+++ b/app/components/component-xpub-review/src/components/review/ReviewLayout.js
@@ -29,6 +29,7 @@ const ReviewLayout = ({
   const reviewSections = []
   const editorSections = []
   const manuscriptVersions = manuscript.manuscriptVersions || []
+
   manuscriptVersions.forEach(manuscript => {
     const label = moment().format('YYYY-MM-DD')
     reviewSections.push({
@@ -36,7 +37,11 @@ const ReviewLayout = ({
         <div>
           <ReviewMetadata manuscript={manuscript} />
           <Review
-            review={manuscript.reviews.find(review => !review.isDecision) || {}}
+            review={manuscript.reviews.find(review => {
+              return (
+                (review.user.id === currentUser.id && !review.isDecision) || {}
+              )
+            })}
           />
         </div>
       ),
diff --git a/app/components/component-xpub-submit/src/components/SubmitPage.js b/app/components/component-xpub-submit/src/components/SubmitPage.js
index 1e63f237a8..1bc4c31b54 100644
--- a/app/components/component-xpub-submit/src/components/SubmitPage.js
+++ b/app/components/component-xpub-submit/src/components/SubmitPage.js
@@ -1,4 +1,4 @@
-import { throttle, cloneDeep, isEmpty, set } from 'lodash'
+import { debounce, cloneDeep, isEmpty, set } from 'lodash'
 import { compose, withProps, withState, withHandlers } from 'recompose'
 import { graphql } from '@apollo/react-hoc'
 import { gql } from 'apollo-client-preset'
@@ -186,20 +186,24 @@ export default compose(
   }),
   graphql(updateMutation, {
     props: ({ mutate, ownProps }) => {
-      const updateManuscript = (value, path) => {
+      const debouncers = {}
+      const onChange = (value, path) => {
         const input = {}
         set(input, path, value)
+        debouncers[path] = debouncers[path] || debounce(updateManuscript, 300)
+        return debouncers[path](input)
+      }
+
+      const updateManuscript = input =>
         mutate({
           variables: {
             id: ownProps.match.params.version,
             input: JSON.stringify(emptyToUndefined(input)),
           },
         })
-      }
 
       return {
-        // TODO: do this on blur, rather than on every keystroke?
-        onChange: throttle(updateManuscript, 1000, { trailing: false }),
+        onChange,
       }
     },
   }),
@@ -216,7 +220,7 @@ export default compose(
             input: JSON.stringify(updateManuscript),
           },
         }).then(() => {
-          history.push('/')
+          history.push('/dashboard')
         })
       },
     }),
diff --git a/app/config/journal/metadata.js b/app/config/journal/metadata.js
index eee1ed1efe..bdb2ef3289 100644
--- a/app/config/journal/metadata.js
+++ b/app/config/journal/metadata.js
@@ -1,4 +1,4 @@
 export default {
-  issn: '2474-7394',
-  name: 'Collabra: Psychology',
+  issn: '0000-0001',
+  name: 'SimpleJ',
 }
diff --git a/app/routes.js b/app/routes.js
index ba04b64b51..86e18426d1 100644
--- a/app/routes.js
+++ b/app/routes.js
@@ -19,9 +19,8 @@ import FormBuilderPage from './components/component-xpub-formbuilder/src/compone
 
 import App from './components/App'
 
-const createReturnUrl = ({ pathname, search = '' }) => pathname + search
-
-const loginUrl = location => `/login?next=${createReturnUrl(location)}`
+// const createReturnUrl = ({ pathname, search = '' }) => pathname + search
+// const loginUrl = location => `/login?next=${createReturnUrl(location)}`
 
 const PrivateRoute = ({ component: Component, ...rest }) => (
   <Route
@@ -30,7 +29,7 @@ const PrivateRoute = ({ component: Component, ...rest }) => (
       localStorage.getItem('token') ? (
         <Component {...props} />
       ) : (
-        <Redirect to={loginUrl(props.location)} />
+        <Redirect to="/login?next=/dashboard" />
       )
     }
   />
diff --git a/config/authsome.js b/config/authsome.js
index 08646dbc3a..5bd2973bae 100644
--- a/config/authsome.js
+++ b/config/authsome.js
@@ -1,8 +1,8 @@
 const { pickBy } = require('lodash')
 
-class XpubCollabraMode {
+class SimpleJMode {
   /**
-   * Creates a new instance of XpubCollabraMode
+   * Creates a new instance of SimpleJMode
    *
    * @param {string} userId A user's UUID
    * @param {string} operation The operation you're authorizing for
@@ -12,7 +12,7 @@ class XpubCollabraMode {
    */
   constructor(userId, operation, object, context) {
     this.userId = userId
-    this.operation = XpubCollabraMode.mapOperation(operation)
+    this.operation = SimpleJMode.mapOperation(operation)
     this.object = object
     this.context = context
   }
@@ -42,6 +42,7 @@ class XpubCollabraMode {
    * @returns {boolean}
    */
   async isTeamMember(role, object) {
+    console.log(this.user, this.user.teams)
     if (!this.user || !Array.isArray(this.user.teams)) {
       return false
     }
@@ -49,17 +50,23 @@ class XpubCollabraMode {
     let membershipCondition
     if (object) {
       // We're asking if a user is a member of a team for a specific object
-      membershipCondition = team =>
-        team.role === role && team.object && team.object.id === object.id
+      membershipCondition = team => {
+        // TODO: This needs to be fixed...
+        const objectId = team.objectId || (team.object && team.object.objectId)
+        return team.role === role && objectId === object.id
+      }
     } else {
       // We're asking if a user is a member of a global team
-      membershipCondition = team => team.role === role && !team.object
+      membershipCondition = team => team.role === role && team.global
     }
 
     const memberships = await Promise.all(
       this.user.teams.map(async teamId => {
-        const team = await this.context.models.Team.find(teamId)
+        // TODO: This needs to be fixed...
+        const id = teamId.id ? teamId.id : teamId
+        const team = await this.context.models.Team.find(id)
         if (!team) return [false]
+
         return membershipCondition(team)
       }),
     )
@@ -79,33 +86,22 @@ class XpubCollabraMode {
   }
 
   /**
-   * Checks if the user is an author, as represented with the owners
+   * Checks if the user is an admin, as represented with the owners
    * relationship
    *
-   * @param {any} object
    * @returns {boolean}
    */
-  isAuthor(object) {
-    if (!object || !object.owners || !this.user) {
-      return false
-    }
-
-    const authorCheck = object.owners.includes(this.user.id)
-    if (authorCheck) {
-      return true
-    }
-
-    return object.owners.some(user => user.id === this.user.id)
+  isAdmin() {
+    return this.user && this.user.admin
   }
 
   /**
-   * Checks if the user is an admin, as represented with the owners
-   * relationship
+   * Checks if user is a author editor (member of a team of type author) for an object
    *
    * @returns {boolean}
    */
-  isAdmin() {
-    return this.user && this.user.admin
+  isAuthor(object) {
+    return this.isTeamMember('author', object)
   }
 
   /**
@@ -141,7 +137,7 @@ class XpubCollabraMode {
    * @returns {boolean}
    */
   isAssignedReviewerEditor(object) {
-    return this.isTeamMember('reviewer', object)
+    return this.isTeamMember('reviewerEditor', object)
   }
 
   /**
@@ -169,43 +165,34 @@ class XpubCollabraMode {
    * @returns {boolean}
    *
    */
-  async canReadCollection() {
+  async canReadManuscript() {
     if (!this.isAuthenticated()) {
       return false
     }
 
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
 
-    const collection = this.object
+    const manuscript = this.object
 
-    if (await this.isManagingEditor(collection)) {
-      return true
-    }
+    // TODO: Enable more team types
+    // if (await this.isManagingEditor(manuscript)) {
+    //   return true
+    // }
 
-    let permission = this.checkTeamMembers(
-      ['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-      collection,
+    let permission = await this.checkTeamMembers(
+      [
+        'isAssignedSeniorEditor',
+        'isAssignedHandlingEditor',
+        'isAssignedReviewerEditor',
+      ],
+      manuscript,
     )
 
-    permission = permission
-      ? true
-      : await this.canReadatLeastOneFragmentOfCollection(collection, [
-          'isAssignedReviewerEditor',
-        ])
+    permission = permission ? true : await this.isAuthor(manuscript)
 
-    permission = permission ? true : await this.isAuthor(collection)
     return permission
   }
 
-  async canReadatLeastOneFragmentOfCollection(collection, teamMembers) {
-    const permission = await Promise.all(
-      collection.fragments.map(async fragmentId =>
-        this.checkTeamMembers(teamMembers, { id: fragmentId }),
-      ),
-    )
-    return permission.includes(true)
-  }
-
   /**
    * Checks if a user can list users
    *
@@ -216,7 +203,7 @@ class XpubCollabraMode {
       return false
     }
 
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
 
     return true
   }
@@ -231,7 +218,7 @@ class XpubCollabraMode {
       return false
     }
 
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
 
     if (this.user.id === this.object.id) {
       return true
@@ -252,7 +239,7 @@ class XpubCollabraMode {
       return false
     }
 
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
 
     const fragment = this.object
     let permission = this.isAuthor(fragment)
@@ -283,43 +270,45 @@ class XpubCollabraMode {
   }
 
   /**
-   * Checks if a user can list collections
+   * Checks if a user can list Manuscripts
    *
    * @returns {boolean}
    */
-  async canListCollections() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-    this.user = await this.context.models.User.find(this.userId)
-
-    return {
-      filter: async collections => {
-        const filteredCollections = await Promise.all(
-          collections.map(async collection => {
-            let condition = await this.checkTeamMembers(
-              [
-                'isAssignedSeniorEditor',
-                'isAssignedHandlingEditor',
-                'isManagingEditor',
-              ],
-              collection,
-            )
-            condition = condition
-              ? true
-              : await this.canReadatLeastOneFragmentOfCollection(collection, [
-                  'isAssignedReviewerEditor',
-                ])
-
-            condition = condition ? true : await this.isAuthor(collection)
-            return condition ? collection : false
-          }),
-        )
-
-        return filteredCollections.filter(collection => collection)
-      },
-    }
-  }
+  // async canListManuscripts() {
+  //   if (!this.isAuthenticated()) {
+  //     return false
+  //   }
+
+  //   this.user = await getUserAndTeams(this.userId, this.context)
+
+  //   return {
+  //     filter: async manuscripts => {
+  //       const filteredManuscripts = await Promise.all(
+  //         manuscripts.map(async manuscript => {
+  //           let condition = await this.checkTeamMembers(
+  //             [
+  //               'isAssignedSeniorEditor',
+  //               'isAssignedHandlingEditor',
+  //               'isManagingEditor',
+  //               'isAssignedReviewerEditor',
+  //             ],
+  //             manuscript,
+  //           )
+  //           // condition = condition
+  //           //   ? true
+  //           //   : await this.canReadatLeastOneFragmentOfCollection(collection, [
+  //           //       'isAssignedReviewerEditor',
+  //           //     ])
+
+  //           condition = condition ? true : await this.isAuthor(manuscript)
+  //           return condition ? manuscript : false
+  //         }),
+  //       )
+
+  //       return filteredManuscripts.filter(manuscript => manuscript)
+  //     },
+  //   }
+  // }
 
   /**
    * Checks if a user can create fragments
@@ -343,7 +332,7 @@ class XpubCollabraMode {
       return false
     }
 
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
 
     const { collection } = this.object
     if (collection) {
@@ -367,7 +356,7 @@ class XpubCollabraMode {
       return false
     }
 
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
 
     const { collection } = this.object
     if (collection) {
@@ -396,13 +385,13 @@ class XpubCollabraMode {
    * Checks if a user can create a team
    *
    * @returns {boolean}
-   * @memberof XpubCollabraMode
+   * @memberof SimpleJMode
    */
   async canCreateTeam() {
     if (!this.isAuthenticated()) {
       return false
     }
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
 
     const { role, object } = this.object.team
     if (role === 'handlingEditor') {
@@ -412,16 +401,6 @@ class XpubCollabraMode {
     return false
   }
 
-  /**
-   * Checks if a user can delete a collection
-   *
-   * @returns {boolean}
-   */
-  async canDeleteCollection() {
-    this.user = await this.context.models.User.find(this.userId)
-    return this.isAuthor(this.object) && this.object.status !== 'revising'
-  }
-
   /**
    * Checks if a user can read a team
    *
@@ -463,20 +442,20 @@ class XpubCollabraMode {
   }
 
   /**
-   * Checks if a user can update a fragment
+   * Checks if a user can update a manuscript
    *
    * @returns {boolean}
    */
-  async canUpdateFragment() {
+  async canUpdateManuscript() {
     const { update, current } = this.object
-    this.user = await this.context.models.User.find(this.userId)
-    const collection = await this.context.models.Collection.find(
-      current.collections[0],
-    )
+    this.user = await getUserAndTeams(this.userId, this.context)
+    const collection = await this.context.models.Manuscript.find(current.id)
+
     const schemaEditors = ['decision', 'id', 'reviewers']
     const schemaReviewers = ['id', 'reviewers']
 
-    let permission = (await this.isAuthor(current)) && !current.submitted
+    let permission =
+      (await this.isAuthor(current)) && current.status !== 'submitted'
 
     permission = permission
       ? true
@@ -495,32 +474,32 @@ class XpubCollabraMode {
   }
 
   /**
-   * Checks if a user can update collection
+   * Checks if a user can update manuscript
    *
    * @returns {boolean}
    */
-  async canUpdateCollection() {
-    this.user = await this.context.models.User.find(this.userId)
-    const { current } = this.object
-    if (current) {
-      return this.checkTeamMembers(
-        ['isAuthor', 'isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-        current,
-      )
-    }
-    return false
-  }
+  // async canUpdateManuscript() {
+  //   this.user = await getUserAndTeams(this.userId, this.context)
+  //   const { current } = this.object
+  //   if (current) {
+  //     return this.checkTeamMembers(
+  //       ['isAuthor', 'isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
+  //       current,
+  //     )
+  //   }
+  //   return false
+  // }
 
   /**
-   * Checks if a user can delete fragment
+   * Checks if a user can delete Manuscript
    *
    * @returns {boolean}
    */
-  async canDeleteFragment() {
-    this.user = await this.context.models.User.find(this.userId)
-    const fragment = this.object
+  async canDeleteManuscript() {
+    this.user = await getUserAndTeams(this.userId, this.context)
+    const manuscript = this.object
 
-    return this.isAuthor(fragment) && !fragment.submitted
+    return this.isAuthor(manuscript) && manuscript.status !== 'submitted'
   }
 
   /**
@@ -529,7 +508,7 @@ class XpubCollabraMode {
    * @returns {boolean}
    */
   async canMakeInvitation() {
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
     const { current } = this.object
     if (current) {
       return this.checkTeamMembers(
@@ -540,22 +519,33 @@ class XpubCollabraMode {
     return false
   }
 
+  async isAllowedToReview(object) {
+    this.user = await getUserAndTeams(this.userId, this.context)
+    const permission = await this.isAssignedReviewerEditor({
+      id: object.manuscriptId,
+    })
+    return permission
+  }
+
   async canViewMySubmissionSection() {
-    this.user = await this.context.models.User.find(this.userId)
-    const collection = await Promise.all(
-      this.object.map(async collection => this.isAuthor(collection)),
+    this.user = await getUserAndTeams(this.userId, this.context)
+    const manuscripts = await Promise.all(
+      this.object.map(async manuscript => this.isAuthor(manuscript)),
     )
-    return collection.some(collection => collection)
+
+    return manuscripts.some(manuscript => manuscript)
   }
 
   async canViewReviewSection() {
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
+
     const collection = await Promise.all(
-      this.object.map(async collection => {
-        const permission = await this.canReadatLeastOneFragmentOfCollection(
-          collection,
+      this.object.map(async manuscript => {
+        const permission = await this.checkTeamMembers(
           ['isAssignedReviewerEditor'],
+          manuscript,
         )
+
         return permission
       }),
     )
@@ -563,46 +553,46 @@ class XpubCollabraMode {
   }
 
   async canViewManuscripts() {
-    this.user = await this.context.models.User.find(this.userId)
-    const collection = await Promise.all(
+    this.user = await getUserAndTeams(this.userId, this.context)
+    const manuscripts = await Promise.all(
       this.object.map(
-        async collection =>
+        async manuscript =>
           (await this.checkTeamMembers(
             ['isAdmin', 'isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-            collection,
+            manuscript,
           )) &&
-          (collection.status === 'revising' ||
-            collection.status === 'submitted'),
+          (manuscript.status === 'revising' ||
+            manuscript.status === 'submitted'),
       ),
     )
 
-    return collection.some(collection => collection)
+    return manuscripts.some(collection => collection)
   }
 
   async canViewPage() {
-    this.user = await this.context.models.User.find(this.userId)
+    this.user = await getUserAndTeams(this.userId, this.context)
     const { path, params } = this.object
 
     if (path === '/teams') {
       return !!this.isAdmin()
     }
 
-    if (path === '/projects/:project/versions/:version/submit') {
+    if (path === '/journals/:journal/versions/:version/submit') {
       return this.checkPageSubmit(params)
     }
 
-    if (path === '/projects/:project/versions/:version/reviews/:review') {
+    if (path === '/journals/:journal/versions/:version/reviews/:review') {
       return this.checkPageReviews(params)
     }
 
     if (
-      path === '/projects/:project/versions/:version/review' ||
-      path === '/projects/:project/versions/:version/reviewers'
+      path === '/journals/:journal/versions/:version/review' ||
+      path === '/journals/:journal/versions/:version/reviewers'
     ) {
       return this.checkPageReview(params)
     }
 
-    if (path === '/projects/:project/versions/:version/decisions/:decision') {
+    if (path === '/journals/:journal/versions/:version/decisions/:decision') {
       return this.checkPageDecision(params)
     }
 
@@ -613,16 +603,20 @@ class XpubCollabraMode {
     const collection = this.context.models.Collection.find(params.project)
     let permission = await this.isAuthor(collection)
 
-    permission = permission
-      ? true
-      : await !this.canReadatLeastOneFragmentOfCollection(collection, [
-          'isAssignedReviewerEditor',
-        ])
+    // permission = permission
+    //   ? true
+    //   : await !this.canReadatLeastOneFragmentOfCollection(collection, [
+    //       'isAssignedReviewerEditor',
+    //     ])
 
     permission = permission
       ? true
       : await this.checkTeamMembers(
-          ['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
+          [
+            'isAssignedSeniorEditor',
+            'isAssignedHandlingEditor',
+            'isAssignedReviewerEditor',
+          ],
           collection,
         )
 
@@ -670,109 +664,61 @@ class XpubCollabraMode {
   }
 }
 
+const getUserAndTeams = async (userId, context) => {
+  const user = await context.models.User.find(userId)
+  if (!user) return false
+  // If it runs on the client, it will have teams in there already.
+  // On the server, we need to add the team ids.
+  if (!user.teams && user.$relatedQuery) {
+    user.teams = (await user.$relatedQuery('teams')).map(team => team.id)
+  }
+
+  return user
+}
+
 module.exports = {
   // This runs before all other authorization queries and is used here
   // to allow admin to do everything
   before: async (userId, operation, object, context) => {
-    const user = await context.models.User.find(userId)
+    if (!userId) return false
+
+    const user = await getUserAndTeams(userId, context)
     if (!user) return false
 
     // we need to introduce a new Role Managing Editor
     // currently we take for granted that an admin is the Managing Editor
     // Temporally we need this if statement to prevent admin from seeing
     // review and submission section on dashboard (ME permissions)
-    if (
-      operation === 'can view review section' ||
-      operation === 'can view my submission section' ||
-      operation === 'can view my manuscripts section'
-    )
-      return false
-
+    // if (
+    //   operation === 'can view review section' ||
+    //   operation === 'can view my submission section' ||
+    //   operation === 'can view my manuscripts section'
+    // )
+    //   return false
     return user.admin
   },
-  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()
-    }
-
-    // GET /api/users
-    if (mode.object && mode.object.path === '/users') {
-      return mode.canListUsers()
-    }
-
-    // GET /api/fragments
-    if (mode.object && mode.object.path === '/fragments') {
-      return mode.canListFragments()
-    }
+  create: (userId, operation, object, context) => true,
+  update: async (userId, operation, object, context) => {
+    const mode = new SimpleJMode(userId, operation, object, context)
 
-    // GET /api/teams
-    if (mode.object && mode.object.path === '/teams') {
-      return mode.canListTeams()
-    }
-
-    // GET /api/collection
-    if (mode.object && mode.object.type === 'collection') {
-      return mode.canReadCollection()
-    }
-
-    // GET /api/fragment
-    if (mode.object && mode.object.type === 'fragment') {
-      return mode.canReadFragment()
-    }
-
-    // GET /api/team
-    if (object && object.type === 'team') {
-      return mode.canReadTeam()
-    }
-
-    // GET /api/user
-    if (mode.object && mode.object.type === 'user') {
-      return mode.canReadUser()
-    }
-
-    return false
-  },
-  POST: (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    // POST /api/collections
-    if (mode.object && mode.object.path === '/collections') {
-      return mode.canCreateCollection()
-    }
-
-    // POST /api/users
-    if (mode.object && mode.object.path === '/users') {
-      return mode.canCreateUser()
-    }
-
-    // POST /api/fragments
-    if (mode.object && mode.object.path === '/fragments') {
-      return mode.canCreateFragment()
-    }
-
-    // POST /api/collections/:collectionId/fragments
     if (
-      mode.object &&
-      mode.object.path === '/collections/:collectionId/fragments'
+      mode.object === 'Manuscript' ||
+      mode.object === 'Review' ||
+      mode.object === 'Team'
     ) {
-      return mode.canCreateFragmentInACollection()
+      return true
     }
 
-    // POST /api/teams
-    if (mode.object && mode.object.path === '/teams') {
-      return mode.canCreateTeam()
+    if (mode.object.current.type === 'team') {
+      return true
     }
 
-    return false
-  },
-  PATCH: (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
+    if (mode.object.current.type === 'Review') {
+      return mode.isAllowedToReview(mode.object.current)
+    }
 
-    // PATCH /api/collections/:id
-    if (mode.object.current && mode.object.current.type === 'collection') {
-      return mode.canUpdateCollection()
+    if (mode.object.current.type === 'Manuscript') {
+      return mode.canUpdateManuscript()
     }
 
     // PATCH /api/users/:id
@@ -780,94 +726,74 @@ module.exports = {
       return mode.canUpdateUser()
     }
 
-    // PATCH /api/fragments/:id
-    if (mode.object.current && mode.object.current.type === 'fragment') {
-      return mode.canUpdateFragment()
-    }
-
-    // PATCH /api/teams/:id
-    if (mode.object.current && mode.object.current.type === 'team') {
-      return mode.canUpdateTeam()
-    }
-
     return false
   },
-  DELETE: (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-
-    // DELETE /api/collections/:id
-    if (object && object.type === 'collection') {
-      return mode.canDeleteCollection()
-    }
+  delete: (userId, operation, object, context) => {
+    const mode = new SimpleJMode(userId, operation, object, context)
 
-    // DELETE /api/users/:id
     if (object && object.type === 'users') {
       return mode.canDeleteUser()
     }
 
-    // DELETE /api/fragments/:id
-    if (object && object.type === 'fragment') {
-      return mode.canDeleteFragment()
+    if (object === 'Manuscript' || object.type === 'Manuscript') {
+      return mode.isAuthor(object)
     }
 
-    // DELETE /api/teams/:id
-    if (object && object.type === 'teams') {
-      return mode.canDeleteTeam()
+    if (object === 'Team' || object.type === 'Team') {
+      return true
+      // return mode.canDeleteTeam()
     }
 
     return false
   },
-  // Example of a specific authorization query. Notice how easy it is to respond to this.
-  'list collections': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    return mode.canListCollections()
-  },
   'can view my submission section': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
+    const mode = new SimpleJMode(userId, operation, object, context)
     return mode.canViewMySubmissionSection()
   },
   'can view my manuscripts section': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
+    const mode = new SimpleJMode(userId, operation, object, context)
     return mode.canViewManuscripts()
   },
   'can view review section': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
+    const mode = new SimpleJMode(userId, operation, object, context)
     return mode.canViewReviewSection()
   },
-  'can delete collection': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    return mode.canDeleteCollection()
+  'can delete manuscript': (userId, operation, object, context) => {
+    const mode = new SimpleJMode(userId, operation, object, context)
+    return mode.canDeleteManuscript()
   },
   'can view page': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
+    const mode = new SimpleJMode(userId, operation, object, context)
     return mode.canViewPage()
   },
   'can view only admin': () => false,
-  create: (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
+  read: async (userId, operation, object, context) => {
+    const mode = new SimpleJMode(userId, operation, object, context)
 
-    if (object === 'collections' || object.type === 'collection') {
-      return mode.canCreateCollection()
+    if (object === 'Manuscript' || object === 'Review') {
+      return true
     }
 
-    return false
-  },
-  read: (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
+    if (object.type === 'Review') {
+      return mode.isAllowedToReview(object)
+    }
 
-    if (object === 'collections') {
-      return mode.canListCollections()
+    if (object.type === 'Manuscript') {
+      return mode.canReadManuscript()
+    }
+    if (object.type === 'team' || object === 'Team') {
+      return mode.canReadTeam()
     }
 
-    if (object.type === 'collection') {
-      return mode.canReadCollection()
+    if (object.constructor.name === 'TeamMember') {
+      return true
     }
 
     if (object === 'users') {
       return mode.canListUsers()
     }
 
-    if (object.type === 'user') {
+    if (object.type === 'user' || object === 'User') {
       return mode.canReadUser()
     }
 
diff --git a/config/authsomeGraphql.js b/config/authsomeGraphql.js
deleted file mode 100644
index e1ac0d4feb..0000000000
--- a/config/authsomeGraphql.js
+++ /dev/null
@@ -1,789 +0,0 @@
-const { pickBy } = require('lodash')
-
-class XpubCollabraMode {
-  /**
-   * Creates a new instance of XpubCollabraMode
-   *
-   * @param {string} userId A user's UUID
-   * @param {string} operation The operation you're authorizing for
-   * @param {any} object The object of authorization
-   * @param {any} context Context for authorization, e.g. database access
-   * @returns {string}
-   */
-  constructor(userId, operation, object, context) {
-    this.userId = userId
-    this.operation = XpubCollabraMode.mapOperation(operation)
-    this.object = object
-    this.context = context
-  }
-
-  /**
-   * Maps operations from HTTP verbs to semantic verbs
-   *
-   * @param {any} operation
-   * @returns {string}
-   */
-  static mapOperation(operation) {
-    const operationMap = {
-      GET: 'read',
-      POST: 'create',
-      PATCH: 'update',
-      DELETE: 'delete',
-    }
-
-    return operationMap[operation] ? operationMap[operation] : operation
-  }
-
-  /**
-   * Checks if user is a member of a team of a certain type for a certain object
-   *
-   * @param {any} role
-   * @param {any} object
-   * @returns {boolean}
-   */
-  async isTeamMember(role, object) {
-    if (!this.user || !Array.isArray(this.user.teams)) {
-      return false
-    }
-
-    let membershipCondition
-    if (object) {
-      // We're asking if a user is a member of a team for a specific object
-      membershipCondition = team => {
-        // TODO: This needs to be fixed...
-        const objectId = team.objectId || (team.object && team.object.objectId)
-        return team.role === role && objectId === object.id
-      }
-    } else {
-      // We're asking if a user is a member of a global team
-      membershipCondition = team => team.role === role && team.global
-    }
-
-    const memberships = await Promise.all(
-      this.user.teams.map(async teamId => {
-        const id = teamId.id ? teamId.id : teamId
-        const team = await this.context.models.Team.find(id)
-        if (!team) return [false]
-
-        return membershipCondition(team)
-      }),
-    )
-
-    return memberships.includes(true)
-  }
-
-  /**
-   * Returns permissions for unauthenticated users
-   *
-   * @param {any} operation
-   * @param {any} object
-   * @returns {boolean}
-   */
-  unauthenticatedUser(object) {
-    return this.operation === 'something public'
-  }
-
-  /**
-   * Checks if the user is an admin, as represented with the owners
-   * relationship
-   *
-   * @returns {boolean}
-   */
-  isAdmin() {
-    return this.user && this.user.admin
-  }
-
-  /**
-   * Checks if user is a author editor (member of a team of type author) for an object
-   *
-   * @returns {boolean}
-   */
-  isAuthor(object) {
-    return this.isTeamMember('author', object)
-  }
-
-  /**
-   * Checks if user is a handling editor (member of a team of type handling editor) for an object
-   *
-   * @returns {boolean}
-   */
-  isAssignedHandlingEditor(object) {
-    return this.isTeamMember('handlingEditor', object)
-  }
-
-  /**
-   * Checks if user is a senior editor (member of a team of type senior editor) for an object
-   *
-   * @returns {boolean}
-   */
-  isAssignedSeniorEditor(object) {
-    return this.isTeamMember('seniorEditor', object)
-  }
-
-  /**
-   * Checks if user is a senior editor (member of a team of type senior editor) for an object
-   *
-   * @returns {boolean}
-   */
-  isManagingEditor(object) {
-    return this.isTeamMember('managingEditor', object)
-  }
-
-  /**
-   * Checks if user is a reviewer editor (member of a team of type reviewer editor) for an object
-   *
-   * @returns {boolean}
-   */
-  isAssignedReviewerEditor(object) {
-    return this.isTeamMember('reviewerEditor', object)
-  }
-
-  /**
-   * Checks if userId is present, indicating an authenticated user
-   *
-   * @param {any} userId
-   * @returns {boolean}
-   */
-  isAuthenticated() {
-    return !!this.userId
-  }
-
-  /**
-   * Checks if a user can create a collection.
-   *
-   * @returns {boolean}
-   */
-  canCreateCollection() {
-    return this.isAuthenticated()
-  }
-
-  /**
-   * Checks if a user can read a specific collection
-   *
-   * @returns {boolean}
-   *
-   */
-  async canReadManuscript() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-
-    this.user = await this.context.models.User.find(this.userId)
-
-    const manuscript = this.object
-
-    // TODO: Enable more team types
-    // if (await this.isManagingEditor(manuscript)) {
-    //   return true
-    // }
-
-    let permission = await this.checkTeamMembers(
-      [
-        'isAssignedSeniorEditor',
-        'isAssignedHandlingEditor',
-        'isAssignedReviewerEditor',
-      ],
-      manuscript,
-    )
-
-    permission = permission ? true : await this.isAuthor(manuscript)
-
-    return permission
-  }
-
-  /**
-   * Checks if a user can list users
-   *
-   * @returns {boolean}
-   */
-  async canListUsers() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-
-    this.user = await this.context.models.User.find(this.userId)
-
-    return true
-  }
-
-  /**
-   * Checks if a user can read a specific user
-   *
-   * @returns {boolean}
-   */
-  async canReadUser() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-
-    this.user = await this.context.models.User.find(this.userId)
-
-    if (this.user.id === this.object.id) {
-      return true
-    }
-    return {
-      filter: user =>
-        pickBy(user, (_, key) => ['id', 'username', 'type'].includes(key)),
-    }
-  }
-
-  /**
-   * Checks if a user can read a fragment
-   *
-   * @returns {boolean}
-   */
-  async canReadFragment() {
-    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
-      : await this.isAssignedReviewerEditor(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
-    // link from a fragment back to a collection at this point. Something to keep in mind!
-    return permission
-  }
-
-  /**
-   * Checks if a user can list Manuscripts
-   *
-   * @returns {boolean}
-   */
-  // async canListManuscripts() {
-  //   if (!this.isAuthenticated()) {
-  //     return false
-  //   }
-
-  //   this.user = await this.context.models.User.find(this.userId)
-
-  //   return {
-  //     filter: async manuscripts => {
-  //       const filteredManuscripts = await Promise.all(
-  //         manuscripts.map(async manuscript => {
-  //           let condition = await this.checkTeamMembers(
-  //             [
-  //               'isAssignedSeniorEditor',
-  //               'isAssignedHandlingEditor',
-  //               'isManagingEditor',
-  //               'isAssignedReviewerEditor',
-  //             ],
-  //             manuscript,
-  //           )
-  //           // condition = condition
-  //           //   ? true
-  //           //   : await this.canReadatLeastOneFragmentOfCollection(collection, [
-  //           //       'isAssignedReviewerEditor',
-  //           //     ])
-
-  //           condition = condition ? true : await this.isAuthor(manuscript)
-  //           return condition ? manuscript : false
-  //         }),
-  //       )
-
-  //       return filteredManuscripts.filter(manuscript => manuscript)
-  //     },
-  //   }
-  // }
-
-  /**
-   * Checks if a user can create fragments
-   *
-   * @returns {boolean}
-   */
-  canCreateFragment() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-    return true
-  }
-
-  /**
-   * Checks if a user can create a fragment in a specific collection
-   *
-   * @returns {boolean}
-   */
-  async canCreateFragmentInACollection() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-
-    this.user = await this.context.models.User.find(this.userId)
-
-    const { collection } = this.object
-    if (collection) {
-      const permission = await this.checkTeamMembers(
-        ['isAuthor', 'isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-        collection,
-      )
-      return permission
-    }
-
-    return false
-  }
-
-  /**
-   * Checks if a user can create a fragment in a specific collection
-   *
-   * @returns {boolean}
-   */
-  async canUpdateFragmentInACollection() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-
-    this.user = await this.context.models.User.find(this.userId)
-
-    const { collection } = this.object
-    if (collection) {
-      const permission =
-        this.isAuthor(collection) ||
-        (await this.isAssignedHandlingEditor(collection)) ||
-        (await this.isAssignedSeniorEditor(collection)) ||
-        (await this.isAssignedReviewerEditor(collection))
-      return permission
-    }
-
-    return false
-  }
-
-  /**
-   * Checks if a user can be created
-   *
-   * @returns {boolean}
-   */
-  // eslint-disable-next-line
-  canCreateUser() {
-    return true
-  }
-
-  /**
-   * Checks if a user can create a team
-   *
-   * @returns {boolean}
-   * @memberof XpubCollabraMode
-   */
-  async canCreateTeam() {
-    if (!this.isAuthenticated()) {
-      return false
-    }
-    this.user = await this.context.models.User.find(this.userId)
-
-    const { role, object } = this.object.team
-    if (role === 'handlingEditor') {
-      return this.isAssignedSeniorEditor(object)
-    }
-
-    return false
-  }
-
-  /**
-   * Checks if a user can read a team
-   *
-   * @returns {boolean}
-   */
-  // eslint-disable-next-line
-  async canReadTeam() {
-    return true
-  }
-
-  /**
-   * Checks if a user can list a team
-   *
-   * @returns {boolean}
-   */
-  // eslint-disable-next-line
-  async canListTeam() {
-    return true
-  }
-
-  /**
-   * Checks if a user can lists team
-   *
-   * @returns {boolean}
-   */
-  // eslint-disable-next-line
-  async canListTeams() {
-    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 manuscript
-   *
-   * @returns {boolean}
-   */
-  async canUpdateManuscript() {
-    const { update, current } = this.object
-    this.user = await this.context.models.User.find(this.userId)
-    const collection = await this.context.models.Manuscript.find(current.id)
-
-    const schemaEditors = ['decision', 'id', 'reviewers']
-    const schemaReviewers = ['id', 'reviewers']
-
-    let permission =
-      (await this.isAuthor(current)) && current.status !== 'submitted'
-
-    permission = permission
-      ? true
-      : (await this.checkTeamMembers(
-          ['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-          collection,
-        )) &&
-        Object.keys(update).every(value => schemaEditors.indexOf(value) >= 0)
-
-    permission = permission
-      ? true
-      : (await this.isAssignedReviewerEditor(current)) &&
-        Object.keys(update).every(value => schemaReviewers.indexOf(value) >= 0)
-
-    return permission
-  }
-
-  /**
-   * Checks if a user can update manuscript
-   *
-   * @returns {boolean}
-   */
-  // async canUpdateManuscript() {
-  //   this.user = await this.context.models.User.find(this.userId)
-  //   const { current } = this.object
-  //   if (current) {
-  //     return this.checkTeamMembers(
-  //       ['isAuthor', 'isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-  //       current,
-  //     )
-  //   }
-  //   return false
-  // }
-
-  /**
-   * Checks if a user can delete Manuscript
-   *
-   * @returns {boolean}
-   */
-  async canDeleteManuscript() {
-    this.user = await this.context.models.User.find(this.userId)
-    const manuscript = this.object
-
-    return this.isAuthor(manuscript) && manuscript.status !== 'submitted'
-  }
-
-  /**
-   * Checks if editor can invite Reviewers
-   *
-   * @returns {boolean}
-   */
-  async canMakeInvitation() {
-    this.user = await this.context.models.User.find(this.userId)
-    const { current } = this.object
-    if (current) {
-      return this.checkTeamMembers(
-        ['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-        current,
-      )
-    }
-    return false
-  }
-
-  async isAllowedToReview(object) {
-    this.user = await this.context.models.User.query()
-      .findById(this.userId)
-      .eager('teams')
-    const permission = await this.isAssignedReviewerEditor({
-      id: object.manuscriptId,
-    })
-    return permission
-  }
-
-  async canViewMySubmissionSection() {
-    this.user = await this.context.models.User.find(this.userId)
-    const manuscripts = await Promise.all(
-      this.object.map(async manuscript => this.isAuthor(manuscript)),
-    )
-
-    return manuscripts.some(manuscript => manuscript)
-  }
-
-  async canViewReviewSection() {
-    this.user = await this.context.models.User.find(this.userId)
-
-    const collection = await Promise.all(
-      this.object.map(async manuscript => {
-        const permission = await this.checkTeamMembers(
-          ['isAssignedReviewerEditor'],
-          manuscript,
-        )
-
-        return permission
-      }),
-    )
-    return collection.some(collection => collection)
-  }
-
-  async canViewManuscripts() {
-    this.user = await this.context.models.User.find(this.userId)
-    const manuscripts = await Promise.all(
-      this.object.map(
-        async manuscript =>
-          (await this.checkTeamMembers(
-            ['isAdmin', 'isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-            manuscript,
-          )) &&
-          (manuscript.status === 'revising' ||
-            manuscript.status === 'submitted'),
-      ),
-    )
-
-    return manuscripts.some(collection => collection)
-  }
-
-  async canViewPage() {
-    this.user = await this.context.models.User.find(this.userId)
-    const { path, params } = this.object
-
-    if (path === '/teams') {
-      return !!this.isAdmin()
-    }
-
-    if (path === '/journals/:journal/versions/:version/submit') {
-      return this.checkPageSubmit(params)
-    }
-
-    if (path === '/journals/:journal/versions/:version/reviews/:review') {
-      return this.checkPageReviews(params)
-    }
-
-    if (
-      path === '/journals/:journal/versions/:version/review' ||
-      path === '/journals/:journal/versions/:version/reviewers'
-    ) {
-      return this.checkPageReview(params)
-    }
-
-    if (path === '/journals/:journal/versions/:version/decisions/:decision') {
-      return this.checkPageDecision(params)
-    }
-
-    return true
-  }
-
-  async checkPageSubmit(params) {
-    const collection = this.context.models.Collection.find(params.project)
-    let permission = await this.isAuthor(collection)
-
-    // permission = permission
-    //   ? true
-    //   : await !this.canReadatLeastOneFragmentOfCollection(collection, [
-    //       'isAssignedReviewerEditor',
-    //     ])
-
-    permission = permission
-      ? true
-      : await this.checkTeamMembers(
-          [
-            'isAssignedSeniorEditor',
-            'isAssignedHandlingEditor',
-            'isAssignedReviewerEditor',
-          ],
-          collection,
-        )
-
-    return permission
-  }
-
-  async checkPageDecision(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
-  }
-
-  async checkPageReviews(params) {
-    const fragment = this.context.models.Fragment.find(params.version)
-
-    const permission = await this.checkTeamMembers(
-      ['isAssignedReviewerEditor'],
-      fragment,
-    )
-
-    return permission
-  }
-
-  async checkPageReview(params) {
-    const collection = this.context.models.Collection.find(params.project)
-
-    const permission = await this.checkTeamMembers(
-      ['isAssignedSeniorEditor', 'isAssignedHandlingEditor'],
-      collection,
-    )
-
-    return permission
-  }
-
-  async checkTeamMembers(team, object) {
-    const permission = await Promise.all(team.map(t => this[t](object)))
-    return permission.includes(true)
-  }
-}
-
-module.exports = {
-  // This runs before all other authorization queries and is used here
-  // to allow admin to do everything
-  before: async (userId, operation, object, context) => {
-    if (!userId) return false
-
-    const user = await context.models.User.find(userId)
-    if (!user) return false
-
-    // we need to introduce a new Role Managing Editor
-    // currently we take for granted that an admin is the Managing Editor
-    // Temporally we need this if statement to prevent admin from seeing
-    // review and submission section on dashboard (ME permissions)
-    // if (
-    //   operation === 'can view review section' ||
-    //   operation === 'can view my submission section' ||
-    //   operation === 'can view my manuscripts section'
-    // )
-    //   return false
-    return user.admin
-  },
-  create: (userId, operation, object, context) => true,
-  update: async (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-
-    if (
-      mode.object === 'Manuscript' ||
-      mode.object === 'Review' ||
-      mode.object === 'Team'
-    ) {
-      return true
-    }
-
-    if (mode.object.current.type === 'team') {
-      return true
-    }
-
-    if (mode.object.current.type === 'Review') {
-      return mode.isAllowedToReview(mode.object.current)
-    }
-
-    if (mode.object.current.type === 'Manuscript') {
-      return mode.canUpdateManuscript()
-    }
-
-    // PATCH /api/users/:id
-    if (mode.object.current && mode.object.current.type === 'user') {
-      return mode.canUpdateUser()
-    }
-
-    return false
-  },
-  delete: (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-
-    if (object && object.type === 'users') {
-      return mode.canDeleteUser()
-    }
-
-    if (object === 'Manuscript' || object.type === 'Manuscript') {
-      return mode.isAuthor(object)
-    }
-
-    if (object === 'Team' || object.type === 'Team') {
-      return mode.canDeleteTeam()
-    }
-
-    return false
-  },
-  'can view my submission section': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    return mode.canViewMySubmissionSection()
-  },
-  'can view my manuscripts section': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    return mode.canViewManuscripts()
-  },
-  'can view review section': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    return mode.canViewReviewSection()
-  },
-  'can delete manuscript': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    return mode.canDeleteManuscript()
-  },
-  'can view page': (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-    return mode.canViewPage()
-  },
-  'can view only admin': () => false,
-  read: async (userId, operation, object, context) => {
-    const mode = new XpubCollabraMode(userId, operation, object, context)
-
-    if (object === 'Manuscript' || object === 'Review') {
-      return true
-    }
-
-    if (object.type === 'Review') {
-      return mode.isAllowedToReview(object)
-    }
-
-    if (object.type === 'Manuscript') {
-      return mode.canReadManuscript()
-    }
-    if (object.type === 'team' || object === 'Team') {
-      return mode.canReadTeam()
-    }
-
-    if (object.constructor.name === 'TeamMember') {
-      return true
-    }
-
-    if (object === 'users') {
-      return mode.canListUsers()
-    }
-
-    if (object.type === 'user' || object === 'User') {
-      return mode.canReadUser()
-    }
-
-    return false
-  },
-}
diff --git a/config/default.js b/config/default.js
index 13294c1dd1..5ba4fcd8fd 100644
--- a/config/default.js
+++ b/config/default.js
@@ -4,7 +4,7 @@ const logger = require('winston')
 
 module.exports = {
   authsome: {
-    mode: path.resolve(__dirname, 'authsomeGraphql.js'),
+    mode: path.resolve(__dirname, 'authsome.js'),
     teams: {
       seniorEditor: {
         name: 'Senior Editors',
diff --git a/cypress/integration/upload_spec.js b/cypress/integration/upload_spec.js
index 4db69798b1..4c04395442 100644
--- a/cypress/integration/upload_spec.js
+++ b/cypress/integration/upload_spec.js
@@ -1,14 +1,45 @@
+const login = (username, password = 'password') => {
+  cy.get('input[name="username"]').type(username)
+  cy.get('input[name="password"]').type(password)
+  cy.get('button[type="submit"]').click()
+}
+
+const doReview = (username, note, confidential, recommendation) => {
+  // 1. Login
+  login(username)
+
+  // 2. Accept and do the review
+  cy.get('[data-testid=accept-review]').click()
+  cy.contains('Do Review').click()
+
+  cy.get('[placeholder*="Enter your review"] div[contenteditable="true"]')
+    .focus()
+    .type(note)
+    .blur()
+  cy.wait(1000)
+  cy.get(
+    '[placeholder*="Enter a confidential note"] div[contenteditable="true"]',
+  )
+    .focus()
+    .type(confidential)
+    .blur()
+  cy.wait(1000)
+  // 0 == accept, 1 == revise, 2 == reject
+  cy.get(`[class*=Radio__Label]:nth(${recommendation})`).click()
+  cy.get('button[type=submit]').click()
+
+  // 3. Logout
+  cy.get('nav button').click()
+}
+
 describe('PDF submission test', () => {
   it('can upload and submit a PDF', () => {
     cy.visit('/dashboard')
 
-    const username = 'admin'
-    const password = 'password'
-
-    cy.get('input[name="username"]').type(username)
-    cy.get('input[name="password"]').type(password)
-    cy.get('button[type="submit"]').click()
+    // 1. Log in as author
+    login('author')
 
+    // 2. Submit a PDF
     cy.fixture('test-pdf.pdf', 'base64').then(fileContent => {
       cy.get('[data-testid="dropzone"]').upload(
         { fileContent, fileName: 'test-pdf.pdf', mimeType: 'application/pdf' },
@@ -18,14 +49,15 @@ describe('PDF submission test', () => {
 
     cy.get('body').contains('Submission information')
     cy.get('[data-testid="meta.title"]').contains('test pdf')
+    cy.get('[data-testid="meta.title"] div[contenteditable="true"]')
+      .click()
+      .type('{selectall}{del}A Manuscript For The Ages')
 
-    cy.get('[data-testid="meta.title"]').type(
-      '{selectall}{del}A Manuscript For The Ages',
-    )
-
-    cy.get('[data-testid="meta.abstract"]').type(`{selectall}{del}
-      Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem.
-    `)
+    cy.get('[data-testid="meta.abstract"] div[contenteditable="true"]')
+      .click()
+      .type(
+        `{selectall}{del}Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem.`,
+      )
 
     cy.get('[data-testid="meta.keywords"]').type('quantum, machines, nature')
 
@@ -58,17 +90,96 @@ describe('PDF submission test', () => {
     cy.get('[data-testid="suggestions.editors.suggested"]').type('John Ode')
     cy.get('[data-testid="suggestions.editors.opposed"]').type('Gina Ode')
 
-    cy.get('[name="meta.notes.0.content"] div[contenteditable="true"]').type(
-      'This work was supported by the Trust [grant numbers 393,295]; the Natural Environment Research Council [grant number 49493]; and the Economic and Social Research Council [grant number 30304]',
-    )
-    cy.get('[name="meta.notes.1.content"] div[contenteditable="true"]').type(
-      'This is extremely divisive work, choose reviewers with care.',
-    )
+    cy.get('[name="meta.notes.0.content"] div[contenteditable="true"]')
+      .click()
+      .type(
+        'This work was supported by the Trust [grant numbers 393,295]; the Natural Environment Research Council [grant number 49493].',
+      )
+    cy.get('[name="meta.notes.1.content"] div[contenteditable="true"]')
+      .click()
+      .type('This is extremely divisive work, choose reviewers with care.')
 
     cy.get('form button:last').click()
     cy.get('button[type="submit"]').click()
 
     cy.visit('/dashboard')
     cy.contains('A Manuscript For The Ages')
+
+    // 3. Logout
+    cy.get('nav button').click()
+
+    // 4. And login as admin
+    login('admin', 'password')
+
+    cy.get('[data-testid="control-panel"]').click()
+
+    // 5. Assign senior editor
+    // TODO: Find a way to not match by partial class
+    cy.get('[class*="AssignEditor"] [class*="Menu__Root"]:first').click()
+    cy.get(
+      '[class*="AssignEditor"] [class*="Menu__Root"]:first [role="option"]:nth(1)',
+    ).click()
+
+    // 6. Assign handling editor
+    cy.get('[class*="AssignEditor"] [class*="Menu__Root"]:nth(1)').click()
+    cy.get(
+      '[class*="AssignEditor"] [class*="Menu__Root"]:nth(1) [role="option"]:nth(2)',
+    ).click()
+
+    // 7. Logout
+    cy.get('nav button').click()
+
+    // 8. And login as handling editor
+    login('heditor')
+
+    cy.get('[data-testid="control-panel"]').click()
+
+    // 9. Assign reviewers
+    cy.get('[class*="AssignEditorsReviewers"] a').click()
+
+    cy.get('.Select-control').click()
+    cy.get('.Select-menu[role="listbox"] [role="option"]:nth(3)').click()
+    cy.get('button[type="submit"]').click()
+    cy.get('[class*="Reviewer__"]').should('have.length', 1)
+
+    cy.get('.Select-control').click()
+    cy.get('.Select-menu[role="listbox"] [role="option"]:nth(4)').click()
+    cy.get('button[type="submit"]').click()
+    cy.get('[class*="Reviewer__"]').should('have.length', 2)
+
+    cy.get('.Select-control').click()
+    cy.get('.Select-menu[role="listbox"] [role="option"]:nth(5)').click()
+    cy.get('button[type="submit"]').click()
+    cy.get('[class*="Reviewer__"]').should('have.length', 3)
+
+    // 10. Check that 3 reviewers are invited
+    cy.contains('SimpleJ').click()
+    cy.get('[data-testid="invited"]').contains('3')
+
+    // 11. Logout
+    cy.get('nav button').click()
+
+    doReview(
+      'reviewer1',
+      'Great research into CC bases in the ky289 variant are mutated to TC which results in the truncation of the SAD-1.',
+      'Not too bad.',
+      0,
+    )
+    doReview(
+      'reviewer2',
+      'Mediocre analysis of Iron-Sulfur ClUster assembly enzyme homolog.',
+      'It is so so.',
+      1,
+    )
+    doReview(
+      'reviewer3',
+      'mTOR-Is positively influence the occurrence and course of certain tumors after solid organ transplantation.',
+      'It is not good.',
+      2,
+    )
+
+    // 12. Log in as handling editor
+    login('heditor')
+    cy.get('[data-testid="control-panel"]').click()
   })
 })
diff --git a/scripts/clearAndSeed.js b/scripts/clearAndSeed.js
index 61f0379d98..b9e43a6e1b 100644
--- a/scripts/clearAndSeed.js
+++ b/scripts/clearAndSeed.js
@@ -18,6 +18,36 @@ const seed = async () => {
     password: 'password',
   }).save()
 
+  await new User({
+    username: 'seditor',
+    email: 'simone@example.com',
+    password: 'password',
+  }).save()
+
+  await new User({
+    username: 'heditor',
+    email: 'hector@example.com',
+    password: 'password',
+  }).save()
+
+  await new User({
+    username: 'reviewer1',
+    email: 'regina@example.com',
+    password: 'password',
+  }).save()
+
+  await new User({
+    username: 'reviewer2',
+    email: 'robert@example.com',
+    password: 'password',
+  }).save()
+
+  await new User({
+    username: 'reviewer3',
+    email: 'remionne@example.com',
+    password: 'password',
+  }).save()
+
   await new Journal({
     title: 'My Journal',
   }).save()
diff --git a/server/manuscript/src/resolvers.js b/server/manuscript/src/resolvers.js
index ba25fd8782..5a87fdbd28 100644
--- a/server/manuscript/src/resolvers.js
+++ b/server/manuscript/src/resolvers.js
@@ -123,8 +123,9 @@ const resolvers = {
     },
     async submitManuscript(_, { id, input }, ctx) {
       const data = JSON.parse(input)
-      const manuscript = await ctx.connectors.Manuscript.fetchOne(id, ctx)
 
+      const manuscript = await ctx.connectors.Manuscript.fetchOne(id, ctx)
+      console.log(manuscript, 'hello!')
       const update = merge({}, manuscript, data)
       // eslint-disable-next-line
       const previousVersion = await new ctx.connectors.Manuscript.model(
diff --git a/server/manuscript/src/typeDefs.js b/server/manuscript/src/typeDefs.js
index b620bfeb79..26c8cbdcc5 100644
--- a/server/manuscript/src/typeDefs.js
+++ b/server/manuscript/src/typeDefs.js
@@ -80,7 +80,7 @@ const typeDefs = `
 
   type ManuscriptMeta {
     title: String!
-    source: String!
+    source: String
     articleType: String
     declarations: Declarations
     articleSections: [String]
-- 
GitLab