Skip to content

Commit

Permalink
Merge pull request #2665 from artsy/staging
Browse files Browse the repository at this point in the history
Deploy
  • Loading branch information
joeyAghion authored Sep 4, 2020
2 parents 5eaa696 + 5506a3f commit 1d21b16
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ DIFFUSION_API_BASE=https://diffusion-staging.artsy.net/api
DIFFUSION_TOKEN=REPLACE
EMBEDLY_ENDPOINT=https://i.embed.ly/1/display
EMBEDLY_KEY=REPLACE
ENABLE_APOLLO=true
ENABLE_APOLLO=false
ENABLE_CONSIGNMENTS_STITCHING=true
ENABLE_QUERY_TRACING=false
ENABLE_REQUEST_LOGGING=true
Expand All @@ -37,6 +37,7 @@ GRAVITY_SECRET=REPLACE
HMAC_SECRET=https://www.youtube.com/watch?v=F5bAa6gFvLs
IMPULSE_API_BASE=https://impulse-staging.artsy.net/api
IMPULSE_APPLICATION_ID=REPLACE
INTROSPECT_TOKEN=REPLACE
KAWS_API_BASE=https://kaws-staging.artsy.net
MEMCACHED_URL=localhost:11211
NODE_ENV=development
Expand Down
9 changes: 8 additions & 1 deletion _schemaV2.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -6918,7 +6918,7 @@ type Me implements Node {
before: String
first: Int
last: Int
sort: ArtworkSorts
sort: MyCollectionArtworkSorts
): MyCollectionConnection
name: String
orders(
Expand Down Expand Up @@ -7296,6 +7296,13 @@ union MyCollectionArtworkMutationType =
| MyCollectionArtworkMutationFailure
| MyCollectionArtworkMutationSuccess

enum MyCollectionArtworkSorts {
CREATED_AT_ASC
CREATED_AT_DESC
POSITION_ASC
POSITION_DESC
}

# A connection to a list of items.
type MyCollectionConnection {
default: Boolean!
Expand Down
26 changes: 18 additions & 8 deletions scripts/push-schema-changes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
const { updateRepo } = require("@artsy/update-repo")
const { execSync } = require("child_process")
const path = require("path")
const { buildSchema, introspectionQuery, graphqlSync } = require("graphql")
const { readFileSync, writeFileSync } = require("fs")

/**
* @param {'eigen' | 'force'} repo
* @param {string} repo - Name of artsy repo to update
* @param {string} [dest=data/schema.graphql] - Path to schema file in target repo
*/
async function updateSchemaFile(repo) {
async function updateSchemaFile(repo, dest = "data/schema.graphql") {
await updateRepo({
repo: {
owner: "artsy",
Expand All @@ -18,16 +21,22 @@ async function updateSchemaFile(repo) {
targetBranch: "master",
commitMessage: "Update metaphysics schema",
body:
"Greetings human :robot: this PR was automatically created as part of metaphysics's deploy process",
"Greetings human :robot: this PR was automatically created as part of metaphysics' deploy process.",
assignees: ["artsyit"],
labels: ["Merge On Green"],
update: (repoDir) => {
execSync(
`cp _schemaV2.graphql '${path.join(repoDir, "data/schema.graphql")}'`
)
const repoDest = path.join(repoDir, dest)
execSync("yarn install --ignore-engines", { cwd: repoDir })
execSync("./node_modules/.bin/relay-compiler", { cwd: repoDir })
execSync("./node_modules/.bin/prettier --write data/schema.graphql", {
if (dest.endsWith(".json")) {
const sdl = readFileSync("_schemaV2.graphql", "utf8").toString()
const schema = buildSchema(sdl, { commentDescriptions: true })
const gql = graphqlSync(schema, introspectionQuery)
writeFileSync(repoDest, JSON.stringify(gql, null, 2))
} else {
execSync(`cp _schemaV2.graphql '${repoDest}'`)
execSync("./node_modules/.bin/relay-compiler", { cwd: repoDir })
}
execSync(`./node_modules/.bin/prettier --write ${dest}`, {
cwd: repoDir,
})
},
Expand All @@ -42,6 +51,7 @@ async function main() {

await updateSchemaFile("eigen")
await updateSchemaFile("force")
await updateSchemaFile("volt", "vendor/graphql/schema/metaphysics.json")
} catch (error) {
console.error(error)
process.exit(1)
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const {
HMAC_SECRET,
IMPULSE_API_BASE,
IMPULSE_APPLICATION_ID,
INTROSPECT_TOKEN,
IP_BLACKLIST,
LOG_QUERY_DETAILS_THRESHOLD,
MEMCACHED_MAX_POOL,
Expand Down Expand Up @@ -186,6 +187,7 @@ export default {
HMAC_SECRET: HMAC_SECRET as string,
IMPULSE_API_BASE,
IMPULSE_APPLICATION_ID,
INTROSPECT_TOKEN,
IP_BLACKLIST: IP_BLACKLIST || "",
LOG_QUERY_DETAILS_THRESHOLD,
MEMCACHED_MAX_POOL: Number(MEMCACHED_MAX_POOL) || 10,
Expand Down
10 changes: 9 additions & 1 deletion src/data/complete.queryMap.json

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { ErrorExtension } from "./extensions/errorExtension"
import { LoggingExtension } from "./extensions/loggingExtension"
import { principalFieldDirectiveExtension } from "./extensions/principalFieldDirectiveExtension"
import { principalFieldDirectiveValidation } from "validations/principalFieldDirectiveValidation"
import { NoSchemaIntrospectionCustomRule } from "validations/noSchemaIntrospectionCustomRule"
import * as Sentry from "@sentry/node"

const {
Expand All @@ -44,6 +45,7 @@ const {
RESOLVER_TIMEOUT_MS,
SENTRY_PRIVATE_DSN,
ENABLE_APOLLO,
INTROSPECT_TOKEN,
} = config

const enableSentry = !!SENTRY_PRIVATE_DSN
Expand Down Expand Up @@ -220,7 +222,17 @@ function startApp(appSchema, path: string) {
userAgent,
}

const validationRules = [principalFieldDirectiveValidation]
const validationRules = [
principalFieldDirectiveValidation,

// require Authorization header for introspection (in production if configured)
...(PRODUCTION_ENV &&
INTROSPECT_TOKEN &&
req.headers["authorization"] !== `Bearer ${INTROSPECT_TOKEN}`
? [NoSchemaIntrospectionCustomRule]
: []),
]

if (QUERY_DEPTH_LIMIT)
validationRules.push(depthLimit(QUERY_DEPTH_LIMIT))

Expand Down
22 changes: 20 additions & 2 deletions src/schema/v2/me/myCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import {
GraphQLBoolean,
GraphQLObjectType,
GraphQLUnionType,
GraphQLEnumType,
} from "graphql"
import { GravityMutationErrorType } from "lib/gravityErrorHandler"
import ArtworkSorts from "../sorts/artwork_sorts"

const MyCollectionConnection = connectionWithCursorInfo({
name: "MyCollection",
Expand Down Expand Up @@ -48,7 +48,25 @@ export const {
export const MyCollection: GraphQLFieldConfig<any, ResolverContext> = {
type: MyCollectionConnection.connectionType,
args: pageable({
sort: ArtworkSorts,
sort: {
type: new GraphQLEnumType({
name: "MyCollectionArtworkSorts",
values: {
CREATED_AT_ASC: {
value: "created_at",
},
CREATED_AT_DESC: {
value: "-created_at",
},
POSITION_ASC: {
value: "position",
},
POSITION_DESC: {
value: "-position",
},
},
}),
},
}),
resolve: ({ id: userId }, options, { myCollectionArtworksLoader }) => {
if (!myCollectionArtworksLoader) {
Expand Down
41 changes: 41 additions & 0 deletions src/validations/noSchemaIntrospectionCustomRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
ASTVisitor,
GraphQLError,
FieldNode,
ValidationContext,
getNamedType,
isIntrospectionType,
} from "graphql"

// Adapted from https://github.com/graphql/graphql-js/pull/2600.
// TODO: replace once using graphql >=15.2.0

/**
* Prohibit introspection queries
*
* A GraphQL document is only valid if all fields selected are not fields that
* return an introspection type.
*
* Note: This rule is optional and is not part of the Validation section of the
* GraphQL Specification. This rule effectively disables introspection, which
* does not reflect best practices and should only be done if absolutely necessary.
*/
export const NoSchemaIntrospectionCustomRule = (
context: ValidationContext
): ASTVisitor => {
return {
Field(node: FieldNode) {
const contextType = context.getType()
if (!contextType) return
const type = getNamedType(contextType)
if (type && isIntrospectionType(type)) {
context.reportError(
new GraphQLError(
`GraphQL introspection has been disabled, but the requested query contained the field "${node.name.value}".`,
node
)
)
}
},
}
}
4 changes: 2 additions & 2 deletions src/validations/principalFieldDirectiveValidation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLError, BREAK } from "graphql"
import { GraphQLError, BREAK, ASTVisitor } from "graphql"

export const principalFieldDirectiveValidation = (context) => {
export const principalFieldDirectiveValidation = (context): ASTVisitor => {
let directivesSeen = 0
return {
Directive(node) {
Expand Down

0 comments on commit 1d21b16

Please sign in to comment.