Skip to content
Snippets Groups Projects
Commit a357ae5f authored by Yannis Barlas's avatar Yannis Barlas
Browse files

Merge branch 'issue30' into 'main'

Issue30 : fixes error on published manuscript front page

Closes #30

See merge request kotahi/kotahi!165
parents 8c760230 5c8f8881
No related branches found
No related tags found
No related merge requests found
// eslint-disable-next-line no-unused-vars
const { rule, shield, and, or, not, allow, deny } = require('graphql-shield')
const _userIsEditor = async (user, manuscriptId) => {
const userIsEditorQuery = async (user, manuscriptId) => {
if (!user) {
return false
}
......@@ -25,9 +25,9 @@ const _userIsEditor = async (user, manuscriptId) => {
const userIsEditor = rule({
cache: 'contextual',
})(async (parent, args, ctx, info) => _userIsEditor(ctx.user))
})(async (parent, args, ctx, info) => userIsEditorQuery(ctx.user))
const _userIsMemberOfTeamWithRole = async (user, manuscriptId, role) => {
const userIsMemberOfTeamWithRoleQuery = async (user, manuscriptId, role) => {
if (!user) {
return false
}
......@@ -36,6 +36,7 @@ const _userIsMemberOfTeamWithRole = async (user, manuscriptId, role) => {
.$relatedQuery('teams')
.where({ role })
.andWhere({ manuscriptId })
const rows = await query.resultSize()
return !!rows
}
......@@ -44,27 +45,26 @@ const userIsAdmin = rule({ cache: 'contextual' })(
async (parent, args, ctx, info) => ctx.user && ctx.user.admin,
)
const parent_manuscript_is_published = rule({ cache: 'contextual' })(
const parentManuscriptIsPublished = rule({ cache: 'contextual' })(
async (parent, args, ctx, info) => {
const manuscript = await ctx.models.Manuscript.query().findById(
parent.manuscriptId,
)
return !!manuscript.published
},
)
const review_is_by_user = rule({ cache: 'contextual' })(
const reviewIsByUser = rule({ cache: 'contextual' })(
async (parent, args, ctx, info) => {
const rows =
ctx.user &&
ctx.user
.$relatedQuery('teams')
.where({ role: 'reviewer' })
.resultSize()
ctx.user.$relatedQuery('teams').where({ role: 'reviewer' }).resultSize()
return !!rows
},
)
const isAuthenticated = rule({ cache: 'contextual' })(
async (parent, args, ctx, info) => !!ctx.user,
)
......@@ -78,35 +78,44 @@ const userIsAllowedToChat = rule({ cache: 'strict' })(
if (ctx.user && ctx.user.admin) {
return true
}
const channel = await ctx.models.Channel.query().findById(args.channelId)
const manuscript = await ctx.models.Manuscript.query().findById(
channel.manuscriptId,
)
const isAuthor = await _userIsMemberOfTeamWithRole(
const isAuthor = await userIsMemberOfTeamWithRoleQuery(
ctx.user,
manuscript.id,
'author',
)
const isReviewer = await _userIsMemberOfTeamWithRole(
const isReviewer = await userIsMemberOfTeamWithRoleQuery(
ctx.user,
manuscript.id,
'reviewer',
)
const isEditor = await _userIsEditor(ctx.user, manuscript.id)
const isEditor = await userIsEditorQuery(ctx.user, manuscript.id)
if (channel.type === 'all') {
return isAuthor || isReviewer || isEditor
} else if (channel.type === 'editorial') {
}
if (channel.type === 'editorial') {
return isReviewer || isEditor
}
return false
},
)
const user_is_review_author_and_review_is_not_completed = rule({
const userIsReviewAuthorAndReviewIsNotCompleted = rule({
cache: 'strict',
})(async (parent, args, ctx, info) => {
let manuscriptId
if (args.id) {
;({ manuscriptId } = await ctx.models.Review.query().findById(args.id))
} else {
......@@ -114,12 +123,14 @@ const user_is_review_author_and_review_is_not_completed = rule({
}
const manuscript = await ctx.models.Manuscript.query().findById(manuscriptId)
const team = await ctx.models.Team.query()
.where({
manuscriptId: manuscript.id,
role: 'reviewer',
})
.first()
if (!team) return false
const members = await team
......@@ -133,22 +144,24 @@ const user_is_review_author_and_review_is_not_completed = rule({
return false
})
const user_is_editor_of_the_manuscript_of_the_review = rule({
const userIsEditorOfTheManuscriptOfTheReview = rule({
cache: 'strict',
})(async (parent, args, ctx, info) => {
let manuscriptId
if (args.id) {
;({ manuscriptId } = await ctx.models.Review.query().findById(args.id))
} else {
;({ manuscriptId } = args.input)
}
return _userIsEditor(ctx.user, manuscriptId)
return userIsEditorQuery(ctx.user, manuscriptId)
})
const user_is_invited_reviewer = rule({ cache: 'strict' })(
const userIsInvitedReviewer = rule({ cache: 'strict' })(
async (parent, args, ctx, info) => {
const team = await ctx.models.Team.query().findById(args.teamId)
const member = await team
.$relatedQuery('members')
.where({ userId: ctx.user.id, status: 'invited' })
......@@ -158,7 +171,7 @@ const user_is_invited_reviewer = rule({ cache: 'strict' })(
},
)
const user_is_author = rule({ cache: 'strict' })(
const userIsAuthor = rule({ cache: 'strict' })(
async (parent, args, ctx, info) => {
const team = await ctx.models.Team.query()
.where({
......@@ -166,6 +179,7 @@ const user_is_author = rule({ cache: 'strict' })(
role: 'author',
})
.first()
const author = team
.$relatedQuery('members')
.where({ userId: ctx.user.id })
......@@ -175,10 +189,11 @@ const user_is_author = rule({ cache: 'strict' })(
},
)
const user_is_author_of_files_associated_manuscript = rule({
const userIsAuthorOfFilesAssociatedManuscript = rule({
cache: 'no_cache',
})(async (parent, args, ctx, info) => {
let manuscriptId
if (args.meta && args.meta.manuscriptId) {
// Meta is supplied for createFile
// eslint-disable-next-line prefer-destructuring
......@@ -202,6 +217,7 @@ const user_is_author_of_files_associated_manuscript = rule({
if (!team) {
return false
}
const members = await team
.$relatedQuery('members')
.where('userId', ctx.user.id)
......@@ -212,8 +228,13 @@ const user_is_author_of_files_associated_manuscript = rule({
return false
})
const user_is_author_of_the_manuscript_of_the_file = rule({ cache: 'strict' })(
const userIsAuthorOfTheManuscriptOfTheFile = rule({ cache: 'strict' })(
async (parent, args, ctx, info) => {
if (!ctx.user) {
return false
}
const manuscript = await ctx.models.File.relatedQuery('manuscript')
.for(parent.id)
.first()
......@@ -228,6 +249,7 @@ const user_is_author_of_the_manuscript_of_the_file = rule({ cache: 'strict' })(
if (!team) {
return false
}
const members = await team
.$relatedQuery('members')
.where('userId', ctx.user.id)
......@@ -241,11 +263,13 @@ const user_is_author_of_the_manuscript_of_the_file = rule({ cache: 'strict' })(
)
// ¯\_(ツ)_/¯
const user_is_the_reviewer_of_the_manuscript_of_the_file_and_review_not_complete = rule(
{
cache: 'strict',
},
)(async (parent, args, ctx, info) => {
const userIsTheReviewerOfTheManuscriptOfTheFileAndReviewNotComplete = rule({
cache: 'strict',
})(async (parent, args, ctx, info) => {
if (!ctx.user) {
return false
}
const manuscript = await ctx.models.File.relatedQuery('manuscript')
.for(parent.id)
.first()
......@@ -260,6 +284,7 @@ const user_is_the_reviewer_of_the_manuscript_of_the_file_and_review_not_complete
if (!team) {
return false
}
const members = await team
.$relatedQuery('members')
.where('userId', ctx.user.id)
......@@ -286,21 +311,21 @@ const permissions = {
Mutation: {
upload: isAuthenticated,
createManuscript: isAuthenticated,
updateManuscript: user_is_author,
submitManuscript: user_is_author,
updateManuscript: userIsAuthor,
submitManuscript: userIsAuthor,
createMessage: userIsAllowedToChat,
updateReview: or(
user_is_review_author_and_review_is_not_completed,
user_is_editor_of_the_manuscript_of_the_review,
userIsReviewAuthorAndReviewIsNotCompleted,
userIsEditorOfTheManuscriptOfTheReview,
),
reviewerResponse: user_is_invited_reviewer,
reviewerResponse: userIsInvitedReviewer,
completeReview: or(
user_is_review_author_and_review_is_not_completed,
user_is_editor_of_the_manuscript_of_the_review,
userIsReviewAuthorAndReviewIsNotCompleted,
userIsEditorOfTheManuscriptOfTheReview,
),
createNewVersion: allow,
createFile: user_is_author_of_files_associated_manuscript,
deleteFile: user_is_author_of_files_associated_manuscript,
createFile: userIsAuthorOfFilesAssociatedManuscript,
deleteFile: userIsAuthorOfFilesAssociatedManuscript,
},
Subscription: {
messageCreated: userIsAllowedToChat,
......@@ -314,16 +339,16 @@ const permissions = {
Manuscript: allow,
ManuscriptVersion: allow,
File: or(
parent_manuscript_is_published,
parentManuscriptIsPublished,
or(
user_is_author_of_the_manuscript_of_the_file,
user_is_the_reviewer_of_the_manuscript_of_the_file_and_review_not_complete,
userIsAuthorOfTheManuscriptOfTheFile,
userIsTheReviewerOfTheManuscriptOfTheFileAndReviewNotComplete,
userIsEditor,
userIsAdmin,
),
),
UploadResult: allow,
Review: or(parent_manuscript_is_published, review_is_by_user),
Review: or(parentManuscriptIsPublished, reviewIsByUser),
ReviewComment: allow,
Channel: allow,
Message: allow,
......@@ -337,10 +362,11 @@ const permissions = {
const fallbackRule = or(userIsAdmin, userIsEditor)
// We only ever need to go two levels down, so no need for recursion
const addOverrideRule = permissions => {
const addOverrideRule = perms => {
const adaptedPermissions = {}
Object.keys(permissions).forEach(key1 => {
const value = permissions[key1]
Object.keys(perms).forEach(key1 => {
const value = perms[key1]
if (value.constructor.name !== 'Object') {
adaptedPermissions[key1] = or(fallbackRule, value)
} else {
......
......@@ -1365,10 +1365,10 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
 
"@coko/lint@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@coko/lint/-/lint-1.3.0.tgz#b51464ad04162a378a681a7ae22514e3ad18c2df"
integrity sha512-jBLcukH05btHV+EBZfwSou5FFAu6UrZKZPjP4wslLU7fGLFpOBl28mlLAKg8PpCcEISe0PK0TWZGtEJNQ1YDqA==
"@coko/lint@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@coko/lint/-/lint-1.4.0.tgz#476986325676607d89a23cca2566da31d1ebd5b3"
integrity sha512-ed9WswpDJoxB8VVja/CgFUGjD0NxoQDvD/BXJ5kM/X/AaFYeanY7nr1bI4nCcas/IHHDb9nnEPRulqfMCuMBLA==
dependencies:
"@commitlint/cli" "^8.3.5"
"@commitlint/config-conventional" "^8.3.4"
......@@ -2763,10 +2763,10 @@
dependencies:
"@types/node" "*"
 
"@types/yup@0.29.8":
version "0.29.8"
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.8.tgz#83db15735987db9fe5a38772a0fb9500e3c5bf39"
integrity sha512-MBSp62AjB1KrSOI3gX9GekddXU5YYQAVA93+aSl78biBqoSzxg876aQY2KJK5Gnfbpqq7O2cadVX5kPAtBqIXw==
"@types/yup@0.29.11":
version "0.29.11"
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.11.tgz#d654a112973f5e004bf8438122bd7e56a8e5cd7e"
integrity sha512-9cwk3c87qQKZrT251EDoibiYRILjCmxBvvcb4meofCmx1vdnNcR9gyildy5vOHASpOKMsn42CugxUvcwK5eu1g==
 
"@types/zen-observable@^0.8.0":
version "0.8.0"
......@@ -8240,11 +8240,6 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
 
fn-name@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c"
integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA==
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
......@@ -8868,14 +8863,14 @@ graphql-postgres-subscriptions@^1.0.4:
pg "^7.4.1"
pg-ipc "^1.0.4"
 
graphql-shield@7.3.7:
version "7.3.7"
resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.3.7.tgz#6bca6ed5e4c45669a0485a6c0a4e1c46b76c0c1c"
integrity sha512-/bf0l5+is8IOfdafjbzws8oIgZJx7jhvegC1Wa2lyTATLFq0kQLvHPMwkVWmqbnW+3m8tgBALlyZABAHSzVl0A==
graphql-shield@^7.5.0:
version "7.5.0"
resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.5.0.tgz#aa3af226946946dfadac33eccc6cbe7fec6e9000"
integrity sha512-T1A6OreOe/dHDk/1Qg3AHCrKLmTkDJ3fPFGYpSOmUbYXyDnjubK4J5ab5FjHdKHK5fWQRZNTvA0SrBObYsyfaw==
dependencies:
"@types/yup" "0.29.8"
"@types/yup" "0.29.11"
object-hash "^2.0.3"
yup "^0.29.3"
yup "^0.31.0"
 
graphql-subscriptions@^0.5.8:
version "0.5.8"
......@@ -14247,10 +14242,10 @@ prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8,
object-assign "^4.1.1"
react-is "^16.8.1"
 
property-expr@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.2.tgz#fff2a43919135553a3bc2fdd94bdb841965b2330"
integrity sha512-bc/5ggaYZxNkFKj374aLbEDqVADdYaLcFo8XBkishUWbaAdjlphaBFns9TvRA2pUseVL/wMFmui9X3IdNDU37g==
property-expr@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910"
integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==
 
prosemirror-commands@^1.0.1, prosemirror-commands@^1.1.3:
version "1.1.4"
......@@ -16916,11 +16911,6 @@ symbol-tree@^3.2.2:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
 
synchronous-promise@^2.0.13:
version "2.0.14"
resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.14.tgz#86b3b3284ad8567b69dc0b2d51c6fd446ddc2d91"
integrity sha512-XassJA855Rbhsggr5Yr1sms+iDDzkmwfhqPJzl7Lq544+7fjo9NmCpetrvQc33S/HE1JnoI2zA3CLDxTQTpWHA==
table@^5.2.3:
version "5.4.6"
resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
......@@ -18838,17 +18828,15 @@ yjs@13.3.0:
dependencies:
lib0 "^0.2.32"
 
yup@^0.29.3:
version "0.29.3"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.3.tgz#69a30fd3f1c19f5d9e31b1cf1c2b851ce8045fea"
integrity sha512-RNUGiZ/sQ37CkhzKFoedkeMfJM0vNQyaz+wRZJzxdKE7VfDeVKH8bb4rr7XhRLbHJz5hSjoDNwMEIaKhuMZ8gQ==
yup@^0.31.0:
version "0.31.1"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.31.1.tgz#0954cb181161f397b804346037a04f8a4b31599e"
integrity sha512-Lf6648jDYOWR75IlWkVfwesPyW6oj+50NpxlKvsQlpPsB8eI+ndI7b4S1VrwbmeV9hIZDu1MzrlIL4W+gK1jPw==
dependencies:
"@babel/runtime" "^7.10.5"
fn-name "~3.0.0"
lodash "^4.17.15"
lodash "^4.17.20"
lodash-es "^4.17.11"
property-expr "^2.0.2"
synchronous-promise "^2.0.13"
property-expr "^2.0.4"
toposort "^2.0.2"
 
zen-observable-ts@^0.8.21:
......
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