Commit 9859187a authored by Juan's avatar Juan Committed by Yannis Barlas

refactor(auth): move client auth queries to models

parent 5cf8c183
......@@ -5,4 +5,20 @@ const REVIEWER_STATUSES = {
rejected: 'rejectedInvitation',
}
module.exports = { REVIEWER_STATUSES }
const TEAMS = Object.freeze({
EDITOR: 'editor',
AUTHOR: 'author',
REVIEWER: 'reviewer',
SCIENCE_OFFICER: 'scienceOfficer',
SECTION_EDITOR: 'sectionEditor',
CURATOR: 'curator',
})
const GLOBAL_TEAMS = Object.freeze({
EDITORS: 'editors',
SCIENCE_OFFICERS: 'scienceOfficers',
GLOBAL_SECTION_EDITOR: 'globalSectionEditor',
GLOBAL_CURATOR: 'globalCurator',
})
module.exports = { REVIEWER_STATUSES, TEAMS, GLOBAL_TEAMS }
const { TEAMS: ROLES, REVIEWER_STATUSES } = require('../../api/constants')
const {
Manuscript,
ManuscriptVersion,
Team,
TeamMember,
User,
} = require('@pubsweet/models')
const clearDb = require('./helpers/clearDb')
const expectManuscriptsToBeTiedToRole = async role => {
const { user, manuscript } = await insertNewUserWithRole(role)
const manuscriptIds = await TeamMember.manuscriptIdsWithRole(role, user.id)
expect(manuscriptIds).toContain(manuscript.id)
}
const insertNewUserWithRole = async role => {
const user = await User.query().insert({})
const manuscript = await Manuscript.query().insert({})
const manuscriptTeam = await Team.query().insert({
role,
objectId: manuscript.id,
objectType: 'article',
})
await Team.addMember(manuscriptTeam.id, user.id)
return { user, manuscript }
}
describe('Team Member Model', () => {
beforeAll(() => clearDb())
afterEach(() => clearDb())
afterAll(() => {
const knex = User.knex()
knex.destroy()
})
test('should return manuscript ids where user is author', async () => {
const role = ROLES.AUTHOR
const user = await User.query().insert({})
const manuscript = await Manuscript.query().insert({})
const manuscriptVersion = await ManuscriptVersion.query().insert({
manuscriptId: manuscript.id,
})
const manuscriptTeam = await Team.query().insert({
role,
objectId: manuscriptVersion.id,
objectType: 'manuscriptVersion',
})
await Team.addMember(manuscriptTeam.id, user.id)
const manuscriptIds = await TeamMember.manuscriptIdsWithRole(role, user.id)
expect(manuscriptIds).toContain(manuscript.id)
})
test('should return manuscript ids and manuscript version ids where user is reviewer', async () => {
const role = ROLES.REVIEWER
const user = await User.query().insert({})
const manuscript = await Manuscript.query().insert({})
const manuscriptVersion = await ManuscriptVersion.query().insert({
manuscriptId: manuscript.id,
})
const manuscriptTeam = await Team.query().insert({
role,
objectId: manuscriptVersion.id,
objectType: 'manuscriptVersion',
})
await Team.addMember(manuscriptTeam.id, user.id, {
status: REVIEWER_STATUSES.accepted,
})
const manuscriptVersionIds = await TeamMember.manuscriptVersionIdsWithRole(
role,
user.id,
REVIEWER_STATUSES.accepted,
)
const manuscriptIds = await TeamMember.manuscriptIdsWithRole(role, user.id)
expect(manuscriptIds).toContain(manuscript.id)
expect(manuscriptIds).toContain(manuscript.id)
expect(manuscriptVersionIds).toContain(manuscriptVersion.id)
})
/* eslint-disable-next-line jest/expect-expect */
test('should return manuscript ids where user is editor', async () => {
await expectManuscriptsToBeTiedToRole(ROLES.EDITOR)
})
/* eslint-disable-next-line jest/expect-expect */
test('should return manuscript ids where user is science officer', async () => {
await expectManuscriptsToBeTiedToRole(ROLES.SCIENCE_OFFICER)
})
/* eslint-disable-next-line jest/expect-expect */
test('should return manuscript ids where user is section editor', async () => {
await expectManuscriptsToBeTiedToRole(ROLES.SCIENCE_OFFICER)
})
/* eslint-disable-next-line jest/expect-expect */
test('should return manuscript ids where user is curator', async () => {
await expectManuscriptsToBeTiedToRole(ROLES.CURATOR)
})
test('should throw an error if no valid role is provided', async () => {
await expect(
TeamMember.manuscriptIdsWithRole('invalid-role', 1),
).rejects.toThrow(new Error('No valid role provided'))
})
})
const { TEAMS, GLOBAL_TEAMS } = require('../../api/constants')
const { ValidationError } = require('objection')
const union = require('lodash/union')
......@@ -8,22 +10,8 @@ const logger = require('@pubsweet/logger')
const { booleanDefaultFalse } = require('../_helpers/types')
const useTransaction = require('../_helpers/useTransaction')
const globalTeams = [
'editors',
'scienceOfficers',
'globalSectionEditor',
'globalCurator',
]
const nonGlobalTeams = [
'author',
'reviewer',
'editor',
'scienceOfficer',
'sectionEditor',
'curator',
]
const globalTeams = Object.values(GLOBAL_TEAMS)
const nonGlobalTeams = Object.values(TEAMS)
const allTeams = union(globalTeams, nonGlobalTeams)
class Team extends PubsweetTeam {
......
......@@ -2,6 +2,8 @@ const omit = require('lodash/omit')
const PubsweetTeamMember = require('@pubsweet/model-team/src/team_member')
const { REVIEWER_STATUSES, TEAMS } = require('../../api/constants')
class TeamMember extends PubsweetTeamMember {
static get schema() {
return {
......@@ -13,6 +15,102 @@ class TeamMember extends PubsweetTeamMember {
static get relationMappings() {
return omit(PubsweetTeamMember.relationMappings, 'alias')
}
static manuscriptFromMemberQuery(role, userId) {
return this.query()
.select('team_members.*', 'teams.role', 'manuscripts.id as manuscriptId')
.leftJoin('teams', 'team_members.team_id', 'teams.id')
.leftJoin('manuscripts', 'teams.object_id', 'manuscripts.id')
.where({
role,
userId,
})
}
static manuscriptVersionFromMemberQuery(role, userId, status) {
if (!role || !Object.values(TEAMS).includes(role)) {
throw new Error('No valid role provided')
}
let where = {
role,
userId,
}
if (status !== undefined) {
where = {
...where,
'team_members.status': status,
}
}
return this.query()
.select(
'team_members.*',
'teams.role',
'manuscripts.id as manuscriptId',
'manuscript_versions.id as manuscriptVersionId',
)
.leftJoin('teams', 'team_members.team_id', 'teams.id')
.leftJoin(
'manuscript_versions',
'teams.object_id',
'manuscript_versions.id',
)
.leftJoin(
'manuscripts',
'manuscript_versions.manuscript_id',
'manuscripts.id',
)
.where(where)
}
static teamFromMemberQuery() {
return this.query()
.select('team_members.*', 'teams.global', 'teams.role')
.leftJoin('teams', 'team_members.team_id', 'teams.id')
}
/**
* Will find manuscripts ids based on user's role
* @param role
* @param userId
* @returns {Promise<*>}
*/
static async manuscriptIdsWithRole(role, userId) {
if (!role || !Object.values(TEAMS).includes(role)) {
throw new Error('No valid role provided')
}
if (!userId) {
throw new Error('No user provided')
}
let manuscripts
switch (role) {
case TEAMS.AUTHOR:
manuscripts = await this.manuscriptVersionFromMemberQuery(role, userId)
break
case TEAMS.REVIEWER:
manuscripts = await this.manuscriptVersionFromMemberQuery(
role,
userId,
REVIEWER_STATUSES.accepted,
)
break
default: {
manuscripts = await this.manuscriptFromMemberQuery(role, userId)
}
}
return manuscripts.map(m => m.manuscriptId)
}
static async manuscriptVersionIdsWithRole(role, userId, status) {
const manuscripts = await this.manuscriptVersionFromMemberQuery(
role,
userId,
status,
)
return manuscripts.map(m => m.manuscriptVersionId)
}
}
module.exports = TeamMember
......@@ -24,7 +24,7 @@ class User extends PubsweetUser {
delete this.email
}
/*
/*
Given names & surname are not required, as pre-migration users might not
have them.
......
const { TeamMember, User } = require('@pubsweet/models')
const uniq = require('lodash/uniq')
const { REVIEWER_STATUSES } = require('../../api/constants')
/*
HELPERS
*/
const manuscriptVersionFromMemberQuery = () =>
TeamMember.query()
.select(
'team_members.*',
'teams.role',
'manuscripts.id as manuscriptId',
'manuscript_versions.id as manuscriptVersionId',
)
.leftJoin('teams', 'team_members.team_id', 'teams.id')
.leftJoin(
'manuscript_versions',
'teams.object_id',
'manuscript_versions.id',
)
.leftJoin(
'manuscripts',
'manuscript_versions.manuscript_id',
'manuscripts.id',
)
const manuscriptFromMemberQuery = () =>
TeamMember.query()
.select('team_members.*', 'teams.role', 'manuscripts.id as manuscriptId')
.leftJoin('teams', 'team_members.team_id', 'teams.id')
.leftJoin('manuscripts', 'teams.object_id', 'manuscripts.id')
const teamFromMemberQuery = () =>
TeamMember.query()
.select('team_members.*', 'teams.global', 'teams.role')
.leftJoin('teams', 'team_members.team_id', 'teams.id')
/*
END HELPERS
*/
const {
TEAMS: ROLES,
GLOBAL_TEAMS: TEAMS,
REVIEWER_STATUSES,
} = require('../../api/constants')
const createClientAuth = async userId => {
const user = await User.query().findById(userId)
......@@ -48,99 +13,77 @@ const createClientAuth = async userId => {
/*
Is user member of any global team
*/
const globalMembership = await teamFromMemberQuery().where({
const globalMembership = await TeamMember.teamFromMemberQuery().where({
global: true,
userId,
})
const isGlobal = globalMembership.length > 0 || user.admin
const isGlobalEditor = !!globalMembership.find(t => t.role === 'editors')
const isGlobalEditor = !!globalMembership.find(t => t.role === TEAMS.EDITORS)
const isGlobalScienceOfficer = !!globalMembership.find(
t => t.role === 'scienceOfficers',
t => t.role === TEAMS.SCIENCE_OFFICERS,
)
const isGlobalCurator = !!globalMembership.find(
t => t.role === 'globalCurator',
t => t.role === TEAMS.GLOBAL_CURATOR,
)
const isGlobalSectionEditor = !!globalMembership.find(
t => t.role === 'globalSectionEditor',
t => t.role === TEAMS.GLOBAL_SECTION_EDITOR,
)
/*
Manuscripts that the user is an author of
*/
const authorManuscripts = await manuscriptVersionFromMemberQuery().where({
role: 'author',
userId,
})
const isAuthor = authorManuscripts.map(m => m.manuscriptId)
const isAuthor = await TeamMember.manuscriptIdsWithRole(ROLES.AUTHOR, userId)
/*
Manuscripts that the user is assigned to as a science officer
*/
const scienceOfficerManuscripts = await manuscriptFromMemberQuery().where({
role: 'scienceOfficer',
const isAssignedScienceOfficer = await TeamMember.manuscriptIdsWithRole(
ROLES.SCIENCE_OFFICER,
userId,
})
const isAssignedScienceOfficer = scienceOfficerManuscripts.map(
m => m.manuscriptId,
)
/*
Manuscripts that the user is assigned to as a section editor
*/
const sectionEditorManuscripts = await manuscriptFromMemberQuery().where({
role: 'sectionEditor',
const isAssignedSectionEditor = await TeamMember.manuscriptIdsWithRole(
ROLES.SECTION_EDITOR,
userId,
})
const isAssignedSectionEditor = sectionEditorManuscripts.map(
m => m.manuscriptId,
)
/*
Manuscripts that the user is assigned to as an editor
*/
const editorManuscripts = await manuscriptFromMemberQuery().where({
role: 'editor',
const isAssignedEditor = await TeamMember.manuscriptIdsWithRole(
ROLES.EDITOR,
userId,
})
const isAssignedEditor = editorManuscripts.map(m => m.manuscriptId)
)
/*
Manuscripts that the user is assigned to as a curator
*/
const curatorManuscripts = await manuscriptFromMemberQuery().where({
role: 'curator',
const isAssignedCurator = await TeamMember.manuscriptIdsWithRole(
ROLES.CURATOR,
userId,
})
const isAssignedCurator = curatorManuscripts.map(m => m.manuscriptId)
)
/*
Manuscripts (not versions) that the user has accepted an invitation
to review
*/
const acceptedReviewInvitationManuscripts = await manuscriptVersionFromMemberQuery().where(
{
role: 'reviewer',
'team_members.status': REVIEWER_STATUSES.accepted,
userId,
},
const acceptedReviewInvitationManuscripts = await TeamMember.manuscriptIdsWithRole(
ROLES.REVIEWER,
userId,
)
const isAcceptedReviewerForManuscript = uniq(
acceptedReviewInvitationManuscripts.map(m => m.manuscriptId),
acceptedReviewInvitationManuscripts,
)
const isAcceptedReviewerForVersion = acceptedReviewInvitationManuscripts.map(
m => m.manuscriptVersionId,
const isAcceptedReviewerForVersion = await TeamMember.manuscriptVersionIdsWithRole(
ROLES.REVIEWER,
userId,
REVIEWER_STATUSES.accepted,
)
return {
......
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