diff --git a/app/components/component-manuscripts/src/Manuscript.jsx b/app/components/component-manuscripts/src/Manuscript.jsx index f1b4113583d0343a2eb256c35d382ab08d037740..4af2aaa9a542a3030eee4c4de53994498ba3ab97 100644 --- a/app/components/component-manuscripts/src/Manuscript.jsx +++ b/app/components/component-manuscripts/src/Manuscript.jsx @@ -27,7 +27,15 @@ const DELETE_MANUSCRIPT = gql` ` const User = ({ manuscript }) => { - const [deleteManuscript] = useMutation(DELETE_MANUSCRIPT) + const [deleteManuscript] = useMutation(DELETE_MANUSCRIPT, { + update(cache, { data: { deleteManuscript } }) { + const id = cache.identify({ + __typename: 'Manuscript', + id: deleteManuscript, + }) + cache.evict({ id }) + }, + }) return ( <Row> diff --git a/app/components/component-review/src/components/ReviewPage.js b/app/components/component-review/src/components/ReviewPage.js index 399c0a4ddcb60811387dd960e5265ce4450b9e68..9640ac9061164d67798b570ad815487aa3cbed16 100644 --- a/app/components/component-review/src/components/ReviewPage.js +++ b/app/components/component-review/src/components/ReviewPage.js @@ -161,6 +161,7 @@ export default ({ match, ...props }) => { variables: { id: match.params.version, }, + partialRefetch: true, }) const reviewOrInitial = manuscript => diff --git a/app/components/shared/FilesUpload.js b/app/components/shared/FilesUpload.js index 6fc7c38dbf316c77ad71feed744bbb2536d49760..b4405cd9a70853c50ed0c2d043e596b628742e11 100644 --- a/app/components/shared/FilesUpload.js +++ b/app/components/shared/FilesUpload.js @@ -7,6 +7,7 @@ import { useMutation, gql } from '@apollo/client' import UploadingFile from './UploadingFile' import { Dropzone } from './Dropzone' import { Icon } from './Icon' +import theme from '../../theme' const Root = styled.div` border: 1px dashed ${th('colorBorder')}; @@ -71,7 +72,7 @@ const DropzoneAndList = ({ <input {...getInputProps()} /> <Message> Drag and drop your files here - <Icon color={th('colorPrimary')} inline> + <Icon color={theme.colorPrimary} inline> file-plus </Icon> </Message> diff --git a/app/queries/index.js b/app/queries/index.js index 6f86f24089190cc2f054069b6b881f52872b5d02..cc18666edc9fd7860025b96e4ea0df4f623c2de6 100644 --- a/app/queries/index.js +++ b/app/queries/index.js @@ -20,6 +20,19 @@ export const GET_CURRENT_USER = gql` id roles } + teams { + id + manuscript { + id + status + } + members { + status + user { + id + } + } + } } } ` diff --git a/config/permissions.js b/config/permissions.js index 7a88852adb4ef7b1ef6d88c6c8f0669d6ed03760..583bf92a182cb1512c1e63731fc464d1a7461d60 100644 --- a/config/permissions.js +++ b/config/permissions.js @@ -1,42 +1,257 @@ // eslint-disable-next-line no-unused-vars const { rule, shield, and, or, not, allow, deny } = require('graphql-shield') -const isAdmin = rule({ cache: 'contextual' })( - async (parent, args, ctx, info) => ctx.user.admin, +const _userIsEditor = async (user, manuscriptId) => { + if (!user) { + return false + } + + let query = user + .$relatedQuery('teams') + .where(builder => + builder + .where({ role: 'seniorEditor' }) + .orWhere({ role: 'handlingEditor' }), + ) + + // Manuscript is optional... + if (manuscriptId) { + query = query.where({ manuscriptId }) + } + + const rows = await query.resultSize() + return !!rows +} + +const userIsEditor = rule({ + cache: 'contextual', +})(async (parent, args, ctx, info) => _userIsEditor(ctx.user)) + +const _userIsMemberOfTeamWithRole = async (user, manuscriptId, role) => { + if (!user) { + return false + } + + const query = user + .$relatedQuery('teams') + .where({ role }) + .andWhere({ manuscriptId }) + const rows = await query.resultSize() + return !!rows +} + +const userIsAdmin = rule({ cache: 'contextual' })( + async (parent, args, ctx, info) => ctx.user && ctx.user.admin, ) -const isEditor = rule({ cache: 'contextual' })( +const parent_manuscript_is_published = rule({ cache: 'contextual' })( async (parent, args, ctx, info) => { - const rows = ctx.user - .$relatedQuery('teams') - .where({ role: 'seniorEditor' }) - .orWhere({ role: 'handlingEditor' }) - .resultSize() - return rows !== 0 + const manuscript = await ctx.models.Manuscript.query().findById( + parent.manuscriptId, + ) + return !!manuscript.published }, ) +const review_is_by_current_user = rule({ cache: 'contextual' })( + async (parent, args, ctx, info) => { + const rows = + ctx.user && + ctx.user + .$relatedQuery('teams') + .where({ role: 'reviewer' }) + .resultSize() + + return !!rows + }, +) const isAuthenticated = rule({ cache: 'contextual' })( async (parent, args, ctx, info) => !!ctx.user, ) +// Who can send a message to a channel? +// Configured like so now: +// if the channel is for 'all', then all associated with the manuscript can create messages +// if the channel is for 'editorial', only editors and admins can chat there +const userIsAllowedToChat = rule({ cache: 'strict' })( + async (parent, args, ctx, info) => { + 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( + ctx.user, + manuscript.id, + 'author', + ) + const isReviewer = await _userIsMemberOfTeamWithRole( + ctx.user, + manuscript.id, + 'reviewer', + ) + const isEditor = await _userIsEditor(ctx.user, manuscript.id) + + if (channel.type === 'all') { + return isAuthor || isReviewer || isEditor + } else if (channel.type === 'editorial') { + return isReviewer || isEditor + } + }, +) + +const user_is_review_author_and_review_is_not_completed = rule({ + cache: 'strict', +})(async (parent, args, ctx, info) => { + const review = await ctx.models.Review.query().findById(args.id) + const manuscript = await ctx.models.Manuscript.query().findById( + review.manuscriptId, + ) + const team = await ctx.models.Team.query() + .where({ + manuscriptId: manuscript.id, + role: 'reviewer', + }) + .first() + const members = await team + .$relatedQuery('members') + .where('userId', ctx.user.id) + + if (members && members[0] && members[0].status !== 'completed') { + return true + } + + return false +}) + +const user_is_invited_reviewer = 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' }) + .first() + + return !!member + }, +) + +const user_is_author = rule({ cache: 'strict' })( + async (parent, args, ctx, info) => { + const team = await ctx.models.Team.query() + .where({ + manuscriptId: args.id, + role: 'author', + }) + .first() + const author = team + .$relatedQuery('members') + .where({ userId: ctx.user.id }) + .first() + + return !!author + }, +) + +// ¯\_(ツ)_/¯ +const current_user_is_the_reviewer_of_the_manuscript_of_the_file_and_review_not_complete = rule( + { + cache: 'strict', + }, +)(async (parent, args, ctx, info) => { + const manuscript = await ctx.models.File.relatedQuery('manuscript') + .for(parent.id) + .first() + + const team = await ctx.models.Team.query() + .where({ + manuscriptId: manuscript.id, + role: 'reviewer', + }) + .first() + + if (!team) { + return false + } + const members = await team + .$relatedQuery('members') + .where('userId', ctx.user.id) + + if (members && members[0] && members[0].status !== 'completed') { + return true + } + + return false +}) + const permissions = shield( { Query: { - paginatedManuscripts: isAdmin, + currentUser: isAuthenticated, + paginatedManuscripts: userIsAdmin, detailsForURL: allow, + publishedManuscripts: allow, + manuscripts: allow, + manuscript: allow, + messages: allow, + getFile: allow, // this is a query that gets the form }, Mutation: { createManuscript: isAuthenticated, + updateManuscript: user_is_author, + createMessage: userIsAllowedToChat, + updateReview: user_is_review_author_and_review_is_not_completed, + reviewerResponse: user_is_invited_reviewer, + completeReview: user_is_review_author_and_review_is_not_completed, + }, + Subscription: { + messageCreated: userIsAllowedToChat, }, + CurrentRole: allow, + Team: allow, + TeamMember: allow, URLMetadata: allow, - // Fruit: isAuthenticated, - // Customer: isAdmin, + User: allow, + PaginatedManuscripts: allow, + Manuscript: allow, + File: or( + parent_manuscript_is_published, + or( + current_user_is_the_reviewer_of_the_manuscript_of_the_file_and_review_not_complete, + userIsEditor, + userIsAdmin, + ), + ), + Review: or(parent_manuscript_is_published, review_is_by_current_user), + ReviewComment: allow, + Channel: allow, + Message: allow, + MessagesRelay: allow, + PageInfo: allow, + ManuscriptMeta: allow, + Note: allow, + Identity: allow, }, { - allowExternalErrors: true, - fallbackRule: or(isAdmin, isEditor), + allowExternalErrors: false, + debug: true, + fallbackRule: or(userIsAdmin, userIsEditor), }, ) module.exports = permissions + +// const userIsEditorOfManuscript = rule({ +// cache: 'strict', +// })(async (parent, args, ctx, info) => +// _userIsEditor(ctx.user, parent.manuscriptId), +// ) + +// const userIsAuthorOfManuscript = rule({ +// cache: 'strict', +// })(async (parent, args, ctx, info) => +// _userIsMemberOfTeamWithRole(ctx.user, parent.manuscriptId, 'author'), +// ) diff --git a/package.json b/package.json index e6dd3210b4fa32da53253da72b48e8504bc39ff7..daea59cdd85b085a9bcad249d1964cb429141d8d 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,10 @@ "@apollo/react-testing": "3.1.4", "@babel/core": "7.11.6", "@guardian/prosemirror-invisibles": "1.2.1", - "@pubsweet/base-model": "3.6.5", + "@pubsweet/base-model": "4.0.0", "@pubsweet/component-send-email": "0.4.3", "@pubsweet/job-xsweet": "2.1.11", - "@pubsweet/model-user": "5.1.12", + "@pubsweet/model-user": "6.0.3", "@pubsweet/ui": "12.6.0", "apollo-link-context": "1.0.20", "apollo-link-schema": "1.2.5", diff --git a/server/model-manuscript/src/graphql.js b/server/model-manuscript/src/graphql.js index 775e3f7ceddd69cbae17a66d941a4c87ae5317d2..c65b23affceefb6f9e7689b6a4efc0d080881074 100644 --- a/server/model-manuscript/src/graphql.js +++ b/server/model-manuscript/src/graphql.js @@ -87,13 +87,12 @@ const resolvers = { } return id }, - async reviewerResponse(_, { currentUserId, action, teamId }, context) { + async reviewerResponse(_, { action, teamId }, context) { const { Team, Review } = require('@pubsweet/models') if (action !== 'accepted' && action !== 'rejected') throw new Error( - `Invalid action provided to handleInvitation: - Must be either "accepted" or "rejected"`, + `Invalid action (revieweResponse): Must be either "accepted" or "rejected"`, ) const team = await Team.query() @@ -101,7 +100,7 @@ const resolvers = { .eager('members') team.members = team.members.map(m => { - if (m.userId === currentUserId) { + if (m.userId === context.user.id) { m.status = action } return m @@ -114,7 +113,7 @@ const resolvers = { const review = { recommendation: '', isDecision: false, - userId: currentUserId, + userId: context.user.id, manuscriptId: team.manuscriptId, } await new Review(review).save() diff --git a/server/model-review/src/resolvers.js b/server/model-review/src/graphql.js similarity index 62% rename from server/model-review/src/resolvers.js rename to server/model-review/src/graphql.js index 566b16eb3abcee690d095bdb239c07bb5bcceaa0..8132e4874c53852c0c53c34a780a482c15c671d7 100644 --- a/server/model-review/src/resolvers.js +++ b/server/model-review/src/graphql.js @@ -60,4 +60,48 @@ const resolvers = { }, } -module.exports = resolvers +const typeDefs = ` + extend type Mutation { + updateReview(id: ID, input: ReviewInput): Review! + completeReview(id: ID!): TeamMember + } + + type Review implements Object { + id: ID! + created: DateTime! + updated: DateTime + recommendation: String + isDecision: Boolean + open: Boolean + user: User + reviewComment: ReviewComment + confidentialComment: ReviewComment + decisionComment: ReviewComment + } + + input ReviewInput { + reviewComment: ReviewCommentInput + confidentialComment: ReviewCommentInput + decisionComment: ReviewCommentInput + recommendation: String + isDecision: Boolean + manuscriptId: ID! + } + + type ReviewComment implements Object { + id: ID! + created: DateTime! + updated: DateTime + commentType: String + content: String + files: [File] + } + + input ReviewCommentInput { + id: ID + commentType: String + content: String + } +` + +module.exports = { resolvers, typeDefs } diff --git a/server/model-review/src/index.js b/server/model-review/src/index.js index 92e1efbc087a696c0c6d9eb3cd9fe23701e00ff7..e1f1649b6d0f3fca4cb3f88484e7a0ff1e81069f 100644 --- a/server/model-review/src/index.js +++ b/server/model-review/src/index.js @@ -1,9 +1,7 @@ -const resolvers = require('./resolvers') -const typeDefs = require('./typeDefs') +const graphql = require('./graphql') module.exports = { - resolvers, - typeDefs, + ...graphql, models: [ { modelName: 'Review', model: require('./review') }, { modelName: 'ReviewComment', model: require('./review_comment') }, diff --git a/server/model-review/src/typeDefs.js b/server/model-review/src/typeDefs.js deleted file mode 100644 index 43b7dc62d4336c86761581bfad24dc4739061f1f..0000000000000000000000000000000000000000 --- a/server/model-review/src/typeDefs.js +++ /dev/null @@ -1,45 +0,0 @@ -const typeDefs = ` - extend type Mutation { - updateReview(id: ID, input: ReviewInput): Review! - completeReview(id: ID!): TeamMember - } - - type Review implements Object { - id: ID! - created: DateTime! - updated: DateTime - recommendation: String - isDecision: Boolean - open: Boolean - user: User - reviewComment: ReviewComment - confidentialComment: ReviewComment - decisionComment: ReviewComment - } - - input ReviewInput { - reviewComment: ReviewCommentInput - confidentialComment: ReviewCommentInput - decisionComment: ReviewCommentInput - recommendation: String - isDecision: Boolean - manuscriptId: ID! - } - - type ReviewComment implements Object { - id: ID! - created: DateTime! - updated: DateTime - commentType: String - content: String - files: [File] - } - - input ReviewCommentInput { - id: ID - commentType: String - content: String - } -` - -module.exports = typeDefs diff --git a/yarn.lock b/yarn.lock index 2b54d641083a1ac367b7a71e4fe387d647160ed8..261c5fa5551227561ef1b78fbd947a0f285869b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1059,14 +1059,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/polyfill@^7.4.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.10.4.tgz#915e5bfe61490ac0199008e35ca9d7d151a8e45a" - integrity sha512-8BYcnVqQ5kMD2HXoHInBH7H1b/uP3KdnwCYXOqFnXqguOyuu443WXusbIUbWEfY3Z0Txk0M1uG/8YuAMhNl6zg== - dependencies: - core-js "^2.6.5" - regenerator-runtime "^0.13.4" - "@babel/preset-env@7.11.5": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.5.tgz#18cb4b9379e3e92ffea92c07471a99a2914e4272" @@ -2040,18 +2032,18 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@pubsweet/base-model@3.6.5", "@pubsweet/base-model@^3.6.2": - version "3.6.5" - resolved "https://registry.yarnpkg.com/@pubsweet/base-model/-/base-model-3.6.5.tgz#a2a6dd9be999b8360abbb0a4a1a22cb9b6b7aa37" - integrity sha512-zhqh8cQL+0rE1U0PbeKUy+Vr7BvF4D/AoW57pI6JnGBZ8iaLtes49Vbzgj4aykQZKgzxraXyJssFHAn1E74TSQ== +"@pubsweet/base-model@4.0.0", "@pubsweet/base-model@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@pubsweet/base-model/-/base-model-4.0.0.tgz#ead8a0bfcbce9b77893f90afe5d1b8e109ef54a5" + integrity sha512-PUsBoGpHtJL8ZIRbGIBsGd+tso3wUuv2Ad09p3dmp6SK3nA15DuTn+nV48DRX0Qvxg6lXlfCjqOdrlI+OdFoGQ== dependencies: - "@pubsweet/db-manager" "^3.1.10" - "@pubsweet/errors" "^2.0.35" - "@pubsweet/logger" "^0.2.45" - knex "^0.16.3" + "@pubsweet/db-manager" "^3.1.11" + "@pubsweet/errors" "^2.0.36" + "@pubsweet/logger" "^0.2.46" + knex "^0.21.1" lodash "^4.17.11" - objection "^1.5.3" - uuid "^3.3.2" + objection "^2.1.6" + uuid "^7.0.3" "@pubsweet/component-send-email@0.4.3": version "0.4.3" @@ -2060,7 +2052,7 @@ dependencies: nodemailer "^4.4.2" -"@pubsweet/db-manager@^3.1.10", "@pubsweet/db-manager@^3.1.11": +"@pubsweet/db-manager@^3.1.11": version "3.1.11" resolved "https://registry.yarnpkg.com/@pubsweet/db-manager/-/db-manager-3.1.11.tgz#d11c3081de5e419edbb7b66546439c4cd24bf762" integrity sha512-/9DR2Hplt1EOu36lAisgGOk89O5IVRUTgggG06WJlHyuLardueTOMXF08YVVfzTRBEnvIlLd1kCwWXQbMNUyoA== @@ -2075,7 +2067,7 @@ tmp-promise "^2.0.0" umzug "^2.1.0" -"@pubsweet/errors@^2.0.32", "@pubsweet/errors@^2.0.35", "@pubsweet/errors@^2.0.36": +"@pubsweet/errors@^2.0.36": version "2.0.36" resolved "https://registry.yarnpkg.com/@pubsweet/errors/-/errors-2.0.36.tgz#afa254f26578468b6d1f8839ba6310e2fd7c6177" integrity sha512-7qKSBCywp2v9yyf118ZK5A8GPuhVNGugRiUaYw/mxx5I5cZAP8xvUSnaIQMY4g+aaty6eYa5XOLUxZwpwA9IFA== @@ -2095,7 +2087,7 @@ tmp-promise "^2.0.0" waait "^1.0.5" -"@pubsweet/logger@^0.2.42", "@pubsweet/logger@^0.2.45", "@pubsweet/logger@^0.2.46": +"@pubsweet/logger@^0.2.46": version "0.2.46" resolved "https://registry.yarnpkg.com/@pubsweet/logger/-/logger-0.2.46.tgz#46a7c7918b678982ac3f613664accbf6a515c608" integrity sha512-bBR0eAY2Cf1P+bL21561po8vDKhyqYnziHmGjW3M4LTOWW+AGaZsRGqZgymsemC814lJCnSTuxxJZ+tPa8TPjw== @@ -2103,18 +2095,18 @@ "@hapi/joi" "^14.5.0" config "^3.0.1" -"@pubsweet/model-user@5.1.12": - version "5.1.12" - resolved "https://registry.yarnpkg.com/@pubsweet/model-user/-/model-user-5.1.12.tgz#2c54102f6cb3a7dea2b11b98ed141a059abfbecd" - integrity sha512-NTzhj1XOBnK2MDJg1C/uazNo4q5aqHApkYDWZyGGrY8tsDhBOr3m5y0gAzTC2nRl8bUc6h5qLwtxt1ai75C+3g== +"@pubsweet/model-user@6.0.3": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@pubsweet/model-user/-/model-user-6.0.3.tgz#b0ad3e307e293d9794f20bcc3797164732eb221b" + integrity sha512-7i86E0kfUu+seeSJqnFETGNAM1/sc8EnitW1QZYuCI3AMawfV4/qlVtlVLV9HdcOl6oORRzjtuiSm1+TcLhgwQ== dependencies: - "@pubsweet/base-model" "^3.6.2" - "@pubsweet/errors" "^2.0.32" - "@pubsweet/logger" "^0.2.42" - "@pubsweet/models" "^0.3.7" + "@pubsweet/base-model" "^4.0.0" + "@pubsweet/errors" "^2.0.36" + "@pubsweet/logger" "^0.2.46" + "@pubsweet/models" "^0.3.11" bcrypt "^3.0.6" -"@pubsweet/models@^0.3.11", "@pubsweet/models@^0.3.7": +"@pubsweet/models@^0.3.11": version "0.3.11" resolved "https://registry.yarnpkg.com/@pubsweet/models/-/models-0.3.11.tgz#65658468d83360a1a0293f88941590c58b74ecf7" integrity sha512-9SvVItqghaFowmNrr0SVlm8ecgGMQlgu39gZbGgbqmPSZpNUJtGEyM0xXJK1qpfOYmfzQqlwnKrtjmAU+jaQjg== @@ -2193,11 +2185,6 @@ dependencies: "@types/node" "*" -"@types/bluebird@^3.5.26": - version "3.5.32" - resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.32.tgz#381e7b59e39f010d20bbf7e044e48f5caf1ab620" - integrity sha512-dIOxFfI0C+jz89g6lQ+TqhGgPQ0MxSnh/E4xuC0blhFtyW269+mPG5QeLgbdwst/LvdP8o1y0o/Gz5EHXLec/g== - "@types/body-parser@*", "@types/body-parser@1.19.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" @@ -2799,7 +2786,7 @@ ajv@^6.0.1, ajv@^6.12.2: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5: +ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5: version "6.12.3" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== @@ -4123,7 +4110,7 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bluebird@3.7.2, bluebird@^3.5.1, bluebird@^3.5.2, bluebird@^3.5.4, bluebird@^3.5.5, bluebird@^3.7.2: +bluebird@3.7.2, bluebird@^3.5.1, bluebird@^3.5.2, bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -5107,11 +5094,6 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -colorette@1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.0.7.tgz#7adf43c445ee63a541b4a4aef7d13f03df1e0cc0" - integrity sha512-KeK4klsvAgdODAjFPm6QLzvStizJqlxMBtVo4KQMCgk5tt/tf9rAzxmxLHNRynJg3tJjkKGKbHx3j4HLox27Lw== - colorette@1.2.1, colorette@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" @@ -5383,7 +5365,7 @@ core-js@^1.0.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= -core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: +core-js@^2.4.0, core-js@^2.5.0: version "2.6.11" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== @@ -7870,11 +7852,6 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= -getopts@2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.3.tgz#11d229775e2ec2067ed8be6fcc39d9b4bf39cf7d" - integrity sha512-viEcb8TpgeG05+Nqo5EzZ8QR0hxdyrYDp6ZSTZqe2M/h53Bk036NmqG38Vhf5RGirC/Of9Xql+v66B2gp256SQ== - getopts@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b" @@ -8899,7 +8876,7 @@ internal-slot@^1.0.2: has "^1.0.3" side-channel "^1.0.2" -interpret@^1.2.0, interpret@^1.4.0: +interpret@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== @@ -10194,29 +10171,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -knex@^0.16.3: - version "0.16.5" - resolved "https://registry.yarnpkg.com/knex/-/knex-0.16.5.tgz#8ba3806289a5d543dd42ed21420a31c578476993" - integrity sha512-1RVxMU8zGOBqgmXlAvs8vohg9MD14iiRZZPe0IeQXd554n4xxPmoMkbH4hlFeqfM6eOdFE3AVqVSncL3YuocqA== - dependencies: - "@babel/polyfill" "^7.4.3" - "@types/bluebird" "^3.5.26" - bluebird "^3.5.4" - colorette "1.0.7" - commander "^2.20.0" - debug "4.1.1" - getopts "2.2.3" - inherits "~2.0.3" - interpret "^1.2.0" - liftoff "3.1.0" - lodash "^4.17.11" - mkdirp "^0.5.1" - pg-connection-string "2.0.0" - tarn "^1.1.5" - tildify "1.2.0" - uuid "^3.3.2" - v8flags "^3.1.2" - knex@^0.21.1: version "0.21.2" resolved "https://registry.yarnpkg.com/knex/-/knex-0.21.2.tgz#716e2f515aa55575eb812b4c7f58e532a3de6a12" @@ -11990,15 +11944,6 @@ object.values@^1.1.1: function-bind "^1.1.1" has "^1.0.3" -objection@^1.5.3: - version "1.6.11" - resolved "https://registry.yarnpkg.com/objection/-/objection-1.6.11.tgz#6755c15300277eee76c44faf4295704d8e2e02e2" - integrity sha512-/W6iR6+YvFg1U4k5DyX1MrY+xqodDM8AAOU1J0b3HlptsNw8V3uDHjZgTi1cFPPe5+ZeTTMvhIFhNiUP6+nqYQ== - dependencies: - ajv "^6.10.0" - bluebird "^3.5.5" - lodash "^4.17.11" - objection@^2.1.3: version "2.2.1" resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.1.tgz#d0d4ae91bf97c89301d1390bf76c8bf4ab237e56" @@ -12007,6 +11952,14 @@ objection@^2.1.3: ajv "^6.12.0" db-errors "^0.2.3" +objection@^2.1.6: + version "2.2.3" + resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.3.tgz#7509620b75a6907227cfb6a3fc4135222bb2e749" + integrity sha512-uNya9GuHlNeix7H0URthVE3+CmAlXmxkU69LAcRnncLjujJ8l1YX8JCB2GVSErTYS3Oc2xneF1ZWaR/MS8r63g== + dependencies: + ajv "^6.12.0" + db-errors "^0.2.3" + obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -12609,11 +12562,6 @@ pg-connection-string@0.1.3: resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= -pg-connection-string@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.0.0.tgz#3eefe5997e06d94821e4d502e42b6a1c73f8df82" - integrity sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I= - pg-connection-string@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.3.0.tgz#c13fcb84c298d0bfa9ba12b40dd6c23d946f55d6" @@ -16084,11 +16032,6 @@ tar@^6.0.1: mkdirp "^1.0.3" yallist "^4.0.0" -tarn@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.5.tgz#7be88622e951738b9fa3fb77477309242cdddc2d" - integrity sha512-PMtJ3HCLAZeedWjJPgGnCvcphbCOMbtZpjKgLq3qM5Qq9aQud+XHrL0WlrlgnTyS8U+jrjGbEXprFcQrxPy52g== - tarn@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.0.tgz#a4082405216c0cce182b8b4cb2639c52c1e870d4" @@ -16171,13 +16114,6 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -tildify@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" - integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo= - dependencies: - os-homedir "^1.0.0" - tildify@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tildify/-/tildify-2.0.0.tgz#f205f3674d677ce698b7067a99e949ce03b4754a" @@ -16872,7 +16808,7 @@ v8-compile-cache@^2.1.1: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== -v8flags@^3.1.2, v8flags@^3.2.0: +v8flags@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==