mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge remote-tracking branch 'origin/master' into dependabot/npm_and_yarn/@babel/core-7.3.4
This commit is contained in:
commit
cb78a30195
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,3 +8,6 @@ coverage.lcov
|
||||
.nyc_output/
|
||||
public/uploads/*
|
||||
!.gitkeep
|
||||
|
||||
# Apple macOS folder attribute file
|
||||
.DS_Store
|
||||
12
package.json
12
package.json
@ -34,10 +34,10 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"apollo-cache-inmemory": "~1.4.3",
|
||||
"apollo-client": "~2.4.13",
|
||||
"apollo-cache-inmemory": "~1.5.1",
|
||||
"apollo-client": "~2.5.1",
|
||||
"apollo-link-http": "~1.5.11",
|
||||
"apollo-server": "~2.4.2",
|
||||
"apollo-server": "~2.4.8",
|
||||
"bcryptjs": "~2.4.3",
|
||||
"cheerio": "~1.0.0-rc.2",
|
||||
"cross-env": "~5.2.0",
|
||||
@ -59,8 +59,6 @@
|
||||
"neo4j-graphql-js": "~2.3.1",
|
||||
"node-fetch": "~2.3.0",
|
||||
"npm-run-all": "~4.1.5",
|
||||
"passport": "~0.4.0",
|
||||
"passport-jwt": "~4.0.0",
|
||||
"sanitize-html": "~1.20.0",
|
||||
"slug": "~1.0.0",
|
||||
"trunc-html": "~1.1.2",
|
||||
@ -70,9 +68,9 @@
|
||||
"@babel/cli": "~7.2.3",
|
||||
"@babel/core": "~7.3.4",
|
||||
"@babel/node": "~7.2.2",
|
||||
"@babel/preset-env": "~7.3.1",
|
||||
"@babel/preset-env": "~7.3.4",
|
||||
"@babel/register": "~7.0.0",
|
||||
"apollo-server-testing": "~2.4.2",
|
||||
"apollo-server-testing": "~2.4.8",
|
||||
"babel-core": "~7.0.0-0",
|
||||
"babel-eslint": "~10.0.1",
|
||||
"babel-jest": "~24.1.0",
|
||||
|
||||
@ -1,182 +1,22 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import bcrypt from 'bcryptjs'
|
||||
import generateJwt from './jwt/generateToken'
|
||||
import uuid from 'uuid/v4'
|
||||
import { fixUrl } from './middleware/fixImageUrlsMiddleware'
|
||||
import { AuthenticationError } from 'apollo-server'
|
||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
import userManagement from './resolvers/user_management.js'
|
||||
import statistics from './resolvers/statistics.js'
|
||||
import reports from './resolvers/reports.js'
|
||||
import posts from './resolvers/posts.js'
|
||||
|
||||
export const typeDefs =
|
||||
fs.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql'))
|
||||
.toString('utf-8')
|
||||
|
||||
export const query = (cypher, session) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = []
|
||||
session
|
||||
.run(cypher)
|
||||
.subscribe({
|
||||
onNext: function (record) {
|
||||
let item = {}
|
||||
record.keys.forEach(key => {
|
||||
item[key] = record.get(key)
|
||||
})
|
||||
data.push(item)
|
||||
},
|
||||
onCompleted: function () {
|
||||
session.close()
|
||||
resolve(data)
|
||||
},
|
||||
onError: function (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const queryOne = (cypher, session) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
query(cypher, session)
|
||||
.then(res => {
|
||||
resolve(res.length ? res.pop() : {})
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
isLoggedIn: (parent, args, { driver, user }) => {
|
||||
return Boolean(user && user.id)
|
||||
},
|
||||
statistics: async (parent, args, { driver, user }) => {
|
||||
return new Promise(async (resolve) => {
|
||||
const session = driver.session()
|
||||
const queries = {
|
||||
countUsers: 'MATCH (r:User) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countUsers',
|
||||
countPosts: 'MATCH (r:Post) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countPosts',
|
||||
countComments: 'MATCH (r:Comment) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countComments',
|
||||
countNotifications: 'MATCH (r:Notification) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countNotifications',
|
||||
countOrganizations: 'MATCH (r:Organization) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countOrganizations',
|
||||
countProjects: 'MATCH (r:Project) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countProjects',
|
||||
countInvites: 'MATCH (r:Invite) WHERE r.wasUsed <> true OR NOT exists(r.wasUsed) RETURN COUNT(r) AS countInvites',
|
||||
countFollows: 'MATCH (:User)-[r:FOLLOWS]->(:User) RETURN COUNT(r) AS countFollows',
|
||||
countShouts: 'MATCH (:User)-[r:SHOUTED]->(:Post) RETURN COUNT(r) AS countShouts'
|
||||
}
|
||||
let data = {
|
||||
countUsers: (await queryOne(queries.countUsers, session)).countUsers.low,
|
||||
countPosts: (await queryOne(queries.countPosts, session)).countPosts.low,
|
||||
countComments: (await queryOne(queries.countComments, session)).countComments.low,
|
||||
countNotifications: (await queryOne(queries.countNotifications, session)).countNotifications.low,
|
||||
countOrganizations: (await queryOne(queries.countOrganizations, session)).countOrganizations.low,
|
||||
countProjects: (await queryOne(queries.countProjects, session)).countProjects.low,
|
||||
countInvites: (await queryOne(queries.countInvites, session)).countInvites.low,
|
||||
countFollows: (await queryOne(queries.countFollows, session)).countFollows.low,
|
||||
countShouts: (await queryOne(queries.countShouts, session)).countShouts.low
|
||||
}
|
||||
resolve(data)
|
||||
})
|
||||
}
|
||||
// usersBySubstring: neo4jgraphql
|
||||
...statistics.Query,
|
||||
...userManagement.Query
|
||||
},
|
||||
Mutation: {
|
||||
signup: async (parent, { email, password }, { req }) => {
|
||||
// if (data[email]) {
|
||||
// throw new Error('Another User with same email exists.')
|
||||
// }
|
||||
// data[email] = {
|
||||
// password: await bcrypt.hashSync(password, 10),
|
||||
// }
|
||||
|
||||
return true
|
||||
},
|
||||
login: async (parent, { email, password }, { driver, req, user }) => {
|
||||
// if (user && user.id) {
|
||||
// throw new Error('Already logged in.')
|
||||
// }
|
||||
const session = driver.session()
|
||||
return session.run(
|
||||
'MATCH (user:User {email: $userEmail}) ' +
|
||||
'RETURN user {.id, .slug, .name, .avatar, .locationName, .about, .email, .password, .role} as user LIMIT 1', {
|
||||
userEmail: email
|
||||
})
|
||||
.then(async (result) => {
|
||||
session.close()
|
||||
const [currentUser] = await result.records.map(function (record) {
|
||||
return record.get('user')
|
||||
})
|
||||
|
||||
if (currentUser && await bcrypt.compareSync(password, currentUser.password)) {
|
||||
delete currentUser.password
|
||||
currentUser.avatar = fixUrl(currentUser.avatar)
|
||||
return Object.assign(currentUser, {
|
||||
token: generateJwt(currentUser)
|
||||
})
|
||||
} else throw new AuthenticationError('Incorrect email address or password.')
|
||||
})
|
||||
},
|
||||
report: async (parent, { resource, description }, { driver, req, user }, resolveInfo) => {
|
||||
const contextId = uuid()
|
||||
const session = driver.session()
|
||||
const data = {
|
||||
id: contextId,
|
||||
type: resource.type,
|
||||
createdAt: (new Date()).toISOString(),
|
||||
description: resource.description
|
||||
}
|
||||
await session.run(
|
||||
'CREATE (r:Report $report) ' +
|
||||
'RETURN r.id, r.type, r.description', {
|
||||
report: data
|
||||
}
|
||||
)
|
||||
let contentType
|
||||
|
||||
switch (resource.type) {
|
||||
case 'post':
|
||||
case 'contribution':
|
||||
contentType = 'Post'
|
||||
break
|
||||
case 'comment':
|
||||
contentType = 'Comment'
|
||||
break
|
||||
case 'user':
|
||||
contentType = 'User'
|
||||
break
|
||||
}
|
||||
|
||||
await session.run(
|
||||
`MATCH (author:User {id: $userId}), (context:${contentType} {id: $resourceId}), (report:Report {id: $contextId}) ` +
|
||||
'MERGE (report)<-[:REPORTED]-(author) ' +
|
||||
'MERGE (context)<-[:REPORTED]-(report) ' +
|
||||
'RETURN context', {
|
||||
resourceId: resource.id,
|
||||
userId: user.id,
|
||||
contextId: contextId
|
||||
}
|
||||
)
|
||||
session.close()
|
||||
|
||||
// TODO: output Report compatible object
|
||||
return data
|
||||
},
|
||||
CreatePost: async (object, params, ctx, resolveInfo) => {
|
||||
const result = await neo4jgraphql(object, params, ctx, resolveInfo, false)
|
||||
|
||||
const session = ctx.driver.session()
|
||||
await session.run(
|
||||
'MATCH (author:User {id: $userId}), (post:Post {id: $postId}) ' +
|
||||
'MERGE (post)<-[:WROTE]-(author) ' +
|
||||
'RETURN author', {
|
||||
userId: ctx.user.id,
|
||||
postId: result.id
|
||||
})
|
||||
session.close()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
...userManagement.Mutation,
|
||||
...reports.Mutation,
|
||||
...posts.Mutation
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,184 +0,0 @@
|
||||
import Factory from './seed/factories'
|
||||
import { GraphQLClient, request } from 'graphql-request'
|
||||
import jwt from 'jsonwebtoken'
|
||||
import { host, login } from './jest/helpers'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', {
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('isLoggedIn', () => {
|
||||
describe('unauthenticated', () => {
|
||||
it('returns false', async () => {
|
||||
const query = '{ isLoggedIn }'
|
||||
await expect(request(host, query)).resolves.toEqual({ isLoggedIn: false })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('login', () => {
|
||||
const mutation = (params) => {
|
||||
const { email, password } = params
|
||||
return `
|
||||
mutation {
|
||||
login(email:"${email}", password:"${password}"){
|
||||
token
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
describe('ask for a `token`', () => {
|
||||
describe('with valid email/password combination', () => {
|
||||
it('responds with a JWT token', async () => {
|
||||
const data = await request(host, mutation({
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
}))
|
||||
const { token } = data.login
|
||||
jwt.verify(token, process.env.JWT_SECRET, (err, data) => {
|
||||
expect(data.email).toEqual('test@example.org')
|
||||
expect(err).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a valid email but incorrect password', () => {
|
||||
it('responds with "Incorrect email address or password."', async () => {
|
||||
await expect(
|
||||
request(host, mutation({
|
||||
email: 'test@example.org',
|
||||
password: 'wrong'
|
||||
}))
|
||||
).rejects.toThrow('Incorrect email address or password.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a non-existing email', () => {
|
||||
it('responds with "Incorrect email address or password."', async () => {
|
||||
await expect(
|
||||
request(host, mutation({
|
||||
email: 'non-existent@example.org',
|
||||
password: 'wrong'
|
||||
}))
|
||||
).rejects.toThrow('Incorrect email address or password.')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('CreatePost', () => {
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(client.request(`mutation {
|
||||
CreatePost(
|
||||
title: "I am a post",
|
||||
content: "Some content"
|
||||
) { slug }
|
||||
}`)).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
let headers
|
||||
let response
|
||||
beforeEach(async () => {
|
||||
headers = await login({ email: 'test@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
response = await client.request(`mutation {
|
||||
CreatePost(
|
||||
title: "A title",
|
||||
content: "Some content"
|
||||
) { title, content }
|
||||
}`, { headers })
|
||||
})
|
||||
|
||||
it('creates a post', () => {
|
||||
expect(response).toEqual({ CreatePost: { title: 'A title', content: 'Some content' } })
|
||||
})
|
||||
|
||||
it('assigns the authenticated user as author', async () => {
|
||||
const { User } = await client.request(`{
|
||||
User(email:"test@example.org") {
|
||||
contributions {
|
||||
title
|
||||
}
|
||||
}
|
||||
}`, { headers })
|
||||
expect(User).toEqual([ { contributions: [ { title: 'A title' } ] } ])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('report', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', {
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
})
|
||||
await factory.create('User', {
|
||||
id: 'u2',
|
||||
name: 'abusive-user',
|
||||
role: 'user',
|
||||
email: 'abusive-user@example.org'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(
|
||||
client.request(`mutation {
|
||||
report(
|
||||
description: "I don't like this user",
|
||||
resource: {
|
||||
id: "u2",
|
||||
type: user
|
||||
}
|
||||
) { id, createdAt }
|
||||
}`)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
let headers
|
||||
let response
|
||||
beforeEach(async () => {
|
||||
headers = await login({ email: 'test@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
response = await client.request(`mutation {
|
||||
report(
|
||||
description: "I don't like this user",
|
||||
resource: {
|
||||
id: "u2",
|
||||
type: user
|
||||
}
|
||||
) { id, createdAt }
|
||||
}`,
|
||||
{ headers }
|
||||
)
|
||||
})
|
||||
it('creates a report', () => {
|
||||
let { id, createdAt } = response.report
|
||||
expect(response).toEqual({
|
||||
report: { id, createdAt }
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -7,12 +7,10 @@ export const host = 'http://127.0.0.1:4123'
|
||||
export async function login ({ email, password }) {
|
||||
const mutation = `
|
||||
mutation {
|
||||
login(email:"${email}", password:"${password}"){
|
||||
token
|
||||
}
|
||||
login(email:"${email}", password:"${password}")
|
||||
}`
|
||||
const response = await request(host, mutation)
|
||||
return {
|
||||
authorization: `Bearer ${response.login.token}`
|
||||
authorization: `Bearer ${response.login}`
|
||||
}
|
||||
}
|
||||
|
||||
29
src/jwt/decode.js
Normal file
29
src/jwt/decode.js
Normal file
@ -0,0 +1,29 @@
|
||||
import jwt from 'jsonwebtoken'
|
||||
|
||||
export default async (driver, authorizationHeader) => {
|
||||
if (!authorizationHeader) return null
|
||||
const token = authorizationHeader.replace('Bearer ', '')
|
||||
let id = null
|
||||
try {
|
||||
const decoded = await jwt.verify(token, process.env.JWT_SECRET)
|
||||
id = decoded.sub
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
const session = driver.session()
|
||||
const query = `
|
||||
MATCH (user:User {id: {id} })
|
||||
RETURN user {.id, .slug, .name, .avatar, .email, .role} as user
|
||||
LIMIT 1
|
||||
`
|
||||
const result = await session.run(query, { id })
|
||||
session.close()
|
||||
const [currentUser] = await result.records.map((record) => {
|
||||
return record.get('user')
|
||||
})
|
||||
if (!currentUser) return null
|
||||
return {
|
||||
token,
|
||||
...currentUser
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ import jwt from 'jsonwebtoken'
|
||||
import ms from 'ms'
|
||||
|
||||
// Generate an Access Token for the given User ID
|
||||
export default function generateJwt (user) {
|
||||
export default function encode (user) {
|
||||
const token = jwt.sign(user, process.env.JWT_SECRET, {
|
||||
expiresIn: ms('1d'),
|
||||
issuer: process.env.GRAPHQL_URI,
|
||||
@ -1,42 +0,0 @@
|
||||
import { Strategy } from 'passport-jwt'
|
||||
import { fixUrl } from '../middleware/fixImageUrlsMiddleware'
|
||||
|
||||
const cookieExtractor = (req) => {
|
||||
var token = null
|
||||
if (req && req.cookies) {
|
||||
token = req.cookies['jwt']
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
export default (driver) => {
|
||||
const options = {
|
||||
jwtFromRequest: cookieExtractor,
|
||||
secretOrKey: process.env.JWT_SECRET,
|
||||
issuer: process.env.GRAPHQL_URI,
|
||||
audience: process.env.CLIENT_URI
|
||||
}
|
||||
|
||||
return new Strategy(options,
|
||||
async (JWTPayload, next) => {
|
||||
const session = driver.session()
|
||||
const result = await session.run(
|
||||
'MATCH (user:User {id: $userId}) ' +
|
||||
'RETURN user {.id, .slug, .name, .avatar, .email, .role} as user LIMIT 1',
|
||||
{
|
||||
userId: JWTPayload.id
|
||||
}
|
||||
)
|
||||
session.close()
|
||||
const [currentUser] = await result.records.map((record) => {
|
||||
return record.get('user')
|
||||
})
|
||||
|
||||
if (currentUser) {
|
||||
currentUser.avatar = fixUrl(currentUser.avatar)
|
||||
return next(null, currentUser)
|
||||
} else {
|
||||
return next(null, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -16,14 +16,19 @@ const isModerator = rule()(async (parent, args, ctx, info) => {
|
||||
})
|
||||
*/
|
||||
|
||||
const isMyOwn = rule({ cache: 'no_cache' })(async (parent, args, ctx, info) => {
|
||||
return ctx.user.id === parent.id
|
||||
const isAdmin = rule()(async (parent, args, { user }, info) => {
|
||||
return user && (user.role === 'admin')
|
||||
})
|
||||
|
||||
const isMyOwn = rule({ cache: 'no_cache' })(async (parent, args, context, info) => {
|
||||
return context.user.id === parent.id
|
||||
})
|
||||
|
||||
// Permissions
|
||||
const permissions = shield({
|
||||
Query: {
|
||||
statistics: allow
|
||||
statistics: allow,
|
||||
currentUser: allow
|
||||
// fruits: and(isAuthenticated, or(isAdmin, isModerator)),
|
||||
// customers: and(isAuthenticated, isAdmin)
|
||||
},
|
||||
@ -31,7 +36,10 @@ const permissions = shield({
|
||||
CreatePost: isAuthenticated,
|
||||
// TODO UpdatePost: isOwner,
|
||||
// TODO DeletePost: isOwner,
|
||||
report: isAuthenticated
|
||||
report: isAuthenticated,
|
||||
CreateBadge: isAdmin,
|
||||
UpdateBadge: isAdmin,
|
||||
DeleteBadge: isAdmin
|
||||
// addFruitToBasket: isAuthenticated
|
||||
// CreateUser: allow,
|
||||
},
|
||||
|
||||
223
src/resolvers/badges.spec.js
Normal file
223
src/resolvers/badges.spec.js
Normal file
@ -0,0 +1,223 @@
|
||||
import Factory from '../seed/factories'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import { host, login } from '../jest/helpers'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
describe('badges', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', {
|
||||
email: 'user@example.org',
|
||||
role: 'user',
|
||||
password: '1234'
|
||||
})
|
||||
await factory.create('User', {
|
||||
id: 'u2',
|
||||
role: 'moderator',
|
||||
email: 'moderator@example.org'
|
||||
})
|
||||
await factory.create('User', {
|
||||
id: 'u3',
|
||||
role: 'admin',
|
||||
email: 'admin@example.org'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('CreateBadge', () => {
|
||||
const variables = {
|
||||
id: 'b1',
|
||||
key: 'indiegogo_en_racoon',
|
||||
type: 'crowdfunding',
|
||||
status: 'permanent',
|
||||
icon: '/img/badges/indiegogo_en_racoon.svg'
|
||||
}
|
||||
|
||||
const mutation = `
|
||||
mutation(
|
||||
$id: ID
|
||||
$key: String!
|
||||
$type: BadgeTypeEnum!
|
||||
$status: BadgeStatusEnum!
|
||||
$icon: String!
|
||||
) {
|
||||
CreateBadge(id: $id, key: $key, type: $type, status: $status, icon: $icon) {
|
||||
id,
|
||||
key,
|
||||
type,
|
||||
status,
|
||||
icon
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(
|
||||
client.request(mutation, variables)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated admin', () => {
|
||||
let client
|
||||
beforeEach(async () => {
|
||||
const headers = await login({ email: 'admin@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
})
|
||||
it('creates a badge', async () => {
|
||||
const expected = {
|
||||
CreateBadge: {
|
||||
icon: '/img/badges/indiegogo_en_racoon.svg',
|
||||
id: 'b1',
|
||||
key: 'indiegogo_en_racoon',
|
||||
status: 'permanent',
|
||||
type: 'crowdfunding'
|
||||
}
|
||||
}
|
||||
await expect(client.request(mutation, variables)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated moderator', () => {
|
||||
let client
|
||||
beforeEach(async () => {
|
||||
const headers = await login({ email: 'moderator@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
})
|
||||
|
||||
it('throws authorization error', async () => {
|
||||
await expect(
|
||||
client.request(mutation, variables)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('UpdateBadge', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.authenticateAs({ email: 'admin@example.org', password: '1234' })
|
||||
await factory.create('Badge', { id: 'b1' })
|
||||
})
|
||||
const variables = {
|
||||
id: 'b1',
|
||||
key: 'whatever'
|
||||
}
|
||||
|
||||
const mutation = `
|
||||
mutation($id: ID!, $key: String!) {
|
||||
UpdateBadge(id: $id, key: $key) {
|
||||
id
|
||||
key
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(
|
||||
client.request(mutation, variables)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated moderator', () => {
|
||||
let client
|
||||
beforeEach(async () => {
|
||||
const headers = await login({ email: 'moderator@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
})
|
||||
|
||||
it('throws authorization error', async () => {
|
||||
await expect(
|
||||
client.request(mutation, variables)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated admin', () => {
|
||||
let client
|
||||
beforeEach(async () => {
|
||||
const headers = await login({ email: 'admin@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
})
|
||||
it('updates a badge', async () => {
|
||||
const expected = {
|
||||
UpdateBadge: {
|
||||
id: 'b1',
|
||||
key: 'whatever'
|
||||
}
|
||||
}
|
||||
await expect(client.request(mutation, variables)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('DeleteBadge', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.authenticateAs({ email: 'admin@example.org', password: '1234' })
|
||||
await factory.create('Badge', { id: 'b1' })
|
||||
})
|
||||
const variables = {
|
||||
id: 'b1'
|
||||
}
|
||||
|
||||
const mutation = `
|
||||
mutation($id: ID!) {
|
||||
DeleteBadge(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(
|
||||
client.request(mutation, variables)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated moderator', () => {
|
||||
let client
|
||||
beforeEach(async () => {
|
||||
const headers = await login({ email: 'moderator@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
})
|
||||
|
||||
it('throws authorization error', async () => {
|
||||
await expect(
|
||||
client.request(mutation, variables)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated admin', () => {
|
||||
let client
|
||||
beforeEach(async () => {
|
||||
const headers = await login({ email: 'admin@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
})
|
||||
it('deletes a badge', async () => {
|
||||
const expected = {
|
||||
DeleteBadge: {
|
||||
id: 'b1'
|
||||
}
|
||||
}
|
||||
await expect(client.request(mutation, variables)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
22
src/resolvers/posts.js
Normal file
22
src/resolvers/posts.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
|
||||
export default {
|
||||
Mutation: {
|
||||
CreatePost: async (object, params, ctx, resolveInfo) => {
|
||||
const result = await neo4jgraphql(object, params, ctx, resolveInfo, false)
|
||||
|
||||
const session = ctx.driver.session()
|
||||
await session.run(
|
||||
'MATCH (author:User {id: $userId}), (post:Post {id: $postId}) ' +
|
||||
'MERGE (post)<-[:WROTE]-(author) ' +
|
||||
'RETURN author', {
|
||||
userId: ctx.user.id,
|
||||
postId: result.id
|
||||
})
|
||||
session.close()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
61
src/resolvers/posts.spec.js
Normal file
61
src/resolvers/posts.spec.js
Normal file
@ -0,0 +1,61 @@
|
||||
import Factory from '../seed/factories'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import { host, login } from '../jest/helpers'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', {
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('CreatePost', () => {
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(client.request(`mutation {
|
||||
CreatePost(
|
||||
title: "I am a post",
|
||||
content: "Some content"
|
||||
) { slug }
|
||||
}`)).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
let headers
|
||||
let response
|
||||
beforeEach(async () => {
|
||||
headers = await login({ email: 'test@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
response = await client.request(`mutation {
|
||||
CreatePost(
|
||||
title: "A title",
|
||||
content: "Some content"
|
||||
) { title, content }
|
||||
}`, { headers })
|
||||
})
|
||||
|
||||
it('creates a post', () => {
|
||||
expect(response).toEqual({ CreatePost: { title: 'A title', content: 'Some content' } })
|
||||
})
|
||||
|
||||
it('assigns the authenticated user as author', async () => {
|
||||
const { User } = await client.request(`{
|
||||
User(email:"test@example.org") {
|
||||
contributions {
|
||||
title
|
||||
}
|
||||
}
|
||||
}`, { headers })
|
||||
expect(User).toEqual([ { contributions: [ { title: 'A title' } ] } ])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
51
src/resolvers/reports.js
Normal file
51
src/resolvers/reports.js
Normal file
@ -0,0 +1,51 @@
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default {
|
||||
Mutation: {
|
||||
report: async (parent, { resource, description }, { driver, req, user }, resolveInfo) => {
|
||||
const contextId = uuid()
|
||||
const session = driver.session()
|
||||
const data = {
|
||||
id: contextId,
|
||||
type: resource.type,
|
||||
createdAt: (new Date()).toISOString(),
|
||||
description: resource.description
|
||||
}
|
||||
await session.run(
|
||||
'CREATE (r:Report $report) ' +
|
||||
'RETURN r.id, r.type, r.description', {
|
||||
report: data
|
||||
}
|
||||
)
|
||||
let contentType
|
||||
|
||||
switch (resource.type) {
|
||||
case 'post':
|
||||
case 'contribution':
|
||||
contentType = 'Post'
|
||||
break
|
||||
case 'comment':
|
||||
contentType = 'Comment'
|
||||
break
|
||||
case 'user':
|
||||
contentType = 'User'
|
||||
break
|
||||
}
|
||||
|
||||
await session.run(
|
||||
`MATCH (author:User {id: $userId}), (context:${contentType} {id: $resourceId}), (report:Report {id: $contextId}) ` +
|
||||
'MERGE (report)<-[:REPORTED]-(author) ' +
|
||||
'MERGE (context)<-[:REPORTED]-(report) ' +
|
||||
'RETURN context', {
|
||||
resourceId: resource.id,
|
||||
userId: user.id,
|
||||
contextId: contextId
|
||||
}
|
||||
)
|
||||
session.close()
|
||||
|
||||
// TODO: output Report compatible object
|
||||
return data
|
||||
}
|
||||
}
|
||||
}
|
||||
68
src/resolvers/reports.spec.js
Normal file
68
src/resolvers/reports.spec.js
Normal file
@ -0,0 +1,68 @@
|
||||
import Factory from '../seed/factories'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import { host, login } from '../jest/helpers'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
describe('report', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', {
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
})
|
||||
await factory.create('User', {
|
||||
id: 'u2',
|
||||
name: 'abusive-user',
|
||||
role: 'user',
|
||||
email: 'abusive-user@example.org'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(
|
||||
client.request(`mutation {
|
||||
report(
|
||||
description: "I don't like this user",
|
||||
resource: {
|
||||
id: "u2",
|
||||
type: user
|
||||
}
|
||||
) { id, createdAt }
|
||||
}`)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
let headers
|
||||
let response
|
||||
beforeEach(async () => {
|
||||
headers = await login({ email: 'test@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
response = await client.request(`mutation {
|
||||
report(
|
||||
description: "I don't like this user",
|
||||
resource: {
|
||||
id: "u2",
|
||||
type: user
|
||||
}
|
||||
) { id, createdAt }
|
||||
}`,
|
||||
{ headers }
|
||||
)
|
||||
})
|
||||
it('creates a report', () => {
|
||||
let { id, createdAt } = response.report
|
||||
expect(response).toEqual({
|
||||
report: { id, createdAt }
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
67
src/resolvers/statistics.js
Normal file
67
src/resolvers/statistics.js
Normal file
@ -0,0 +1,67 @@
|
||||
export const query = (cypher, session) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = []
|
||||
session
|
||||
.run(cypher)
|
||||
.subscribe({
|
||||
onNext: function (record) {
|
||||
let item = {}
|
||||
record.keys.forEach(key => {
|
||||
item[key] = record.get(key)
|
||||
})
|
||||
data.push(item)
|
||||
},
|
||||
onCompleted: function () {
|
||||
session.close()
|
||||
resolve(data)
|
||||
},
|
||||
onError: function (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const queryOne = (cypher, session) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
query(cypher, session)
|
||||
.then(res => {
|
||||
resolve(res.length ? res.pop() : {})
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
statistics: async (parent, args, { driver, user }) => {
|
||||
return new Promise(async (resolve) => {
|
||||
const session = driver.session()
|
||||
const queries = {
|
||||
countUsers: 'MATCH (r:User) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countUsers',
|
||||
countPosts: 'MATCH (r:Post) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countPosts',
|
||||
countComments: 'MATCH (r:Comment) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countComments',
|
||||
countNotifications: 'MATCH (r:Notification) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countNotifications',
|
||||
countOrganizations: 'MATCH (r:Organization) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countOrganizations',
|
||||
countProjects: 'MATCH (r:Project) WHERE r.deleted <> true OR NOT exists(r.deleted) RETURN COUNT(r) AS countProjects',
|
||||
countInvites: 'MATCH (r:Invite) WHERE r.wasUsed <> true OR NOT exists(r.wasUsed) RETURN COUNT(r) AS countInvites',
|
||||
countFollows: 'MATCH (:User)-[r:FOLLOWS]->(:User) RETURN COUNT(r) AS countFollows',
|
||||
countShouts: 'MATCH (:User)-[r:SHOUTED]->(:Post) RETURN COUNT(r) AS countShouts'
|
||||
}
|
||||
let data = {
|
||||
countUsers: (await queryOne(queries.countUsers, session)).countUsers.low,
|
||||
countPosts: (await queryOne(queries.countPosts, session)).countPosts.low,
|
||||
countComments: (await queryOne(queries.countComments, session)).countComments.low,
|
||||
countNotifications: (await queryOne(queries.countNotifications, session)).countNotifications.low,
|
||||
countOrganizations: (await queryOne(queries.countOrganizations, session)).countOrganizations.low,
|
||||
countProjects: (await queryOne(queries.countProjects, session)).countProjects.low,
|
||||
countInvites: (await queryOne(queries.countInvites, session)).countInvites.low,
|
||||
countFollows: (await queryOne(queries.countFollows, session)).countFollows.low,
|
||||
countShouts: (await queryOne(queries.countShouts, session)).countShouts.low
|
||||
}
|
||||
resolve(data)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
51
src/resolvers/user_management.js
Normal file
51
src/resolvers/user_management.js
Normal file
@ -0,0 +1,51 @@
|
||||
import encode from '../jwt/encode'
|
||||
import bcrypt from 'bcryptjs'
|
||||
import { AuthenticationError } from 'apollo-server'
|
||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
isLoggedIn: (parent, args, { driver, user }) => {
|
||||
return Boolean(user && user.id)
|
||||
},
|
||||
currentUser: async (object, params, ctx, resolveInfo) => {
|
||||
const { user } = ctx
|
||||
if (!user) return null
|
||||
return neo4jgraphql(object, { id: user.id }, ctx, resolveInfo, false)
|
||||
}
|
||||
},
|
||||
Mutation: {
|
||||
signup: async (parent, { email, password }, { req }) => {
|
||||
// if (data[email]) {
|
||||
// throw new Error('Another User with same email exists.')
|
||||
// }
|
||||
// data[email] = {
|
||||
// password: await bcrypt.hashSync(password, 10),
|
||||
// }
|
||||
|
||||
return true
|
||||
},
|
||||
login: async (parent, { email, password }, { driver, req, user }) => {
|
||||
// if (user && user.id) {
|
||||
// throw new Error('Already logged in.')
|
||||
// }
|
||||
const session = driver.session()
|
||||
return session.run(
|
||||
'MATCH (user:User {email: $userEmail}) ' +
|
||||
'RETURN user {.id, .slug, .name, .avatar, .email, .password, .role} as user LIMIT 1', {
|
||||
userEmail: email
|
||||
})
|
||||
.then(async (result) => {
|
||||
session.close()
|
||||
const [currentUser] = await result.records.map(function (record) {
|
||||
return record.get('user')
|
||||
})
|
||||
|
||||
if (currentUser && await bcrypt.compareSync(password, currentUser.password)) {
|
||||
delete currentUser.password
|
||||
return encode(currentUser)
|
||||
} else throw new AuthenticationError('Incorrect email address or password.')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
179
src/resolvers/user_management.spec.js
Normal file
179
src/resolvers/user_management.spec.js
Normal file
@ -0,0 +1,179 @@
|
||||
import Factory from '../seed/factories'
|
||||
import { GraphQLClient, request } from 'graphql-request'
|
||||
import jwt from 'jsonwebtoken'
|
||||
import { host, login } from '../jest/helpers'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
// here is the decoded JWT token:
|
||||
// {
|
||||
// role: 'user',
|
||||
// locationName: null,
|
||||
// name: 'Jenny Rostock',
|
||||
// about: null,
|
||||
// avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/sasha_shestakov/128.jpg',
|
||||
// id: 'u3',
|
||||
// email: 'user@example.org',
|
||||
// slug: 'jenny-rostock',
|
||||
// iat: 1550846680,
|
||||
// exp: 1637246680,
|
||||
// aud: 'http://localhost:3000',
|
||||
// iss: 'http://localhost:4000',
|
||||
// sub: 'u3'
|
||||
// }
|
||||
const jennyRostocksHeaders = { authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoidXNlciIsImxvY2F0aW9uTmFtZSI6bnVsbCwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJhYm91dCI6bnVsbCwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9zYXNoYV9zaGVzdGFrb3YvMTI4LmpwZyIsImlkIjoidTMiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5vcmciLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTU1MDg0NjY4MCwiZXhwIjoxNjM3MjQ2NjgwLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.eZ_mVKas4Wzoc_JrQTEWXyRn7eY64cdIg4vqQ-F_7Jc' }
|
||||
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', {
|
||||
avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/seyedhossein1/128.jpg',
|
||||
id: 'acb2d923-f3af-479e-9f00-61b12e864666',
|
||||
name: 'Matilde Hermiston',
|
||||
slug: 'matilde-hermiston',
|
||||
role: 'user',
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('isLoggedIn', () => {
|
||||
const query = '{ isLoggedIn }'
|
||||
describe('unauthenticated', () => {
|
||||
it('returns false', async () => {
|
||||
await expect(request(host, query)).resolves.toEqual({ isLoggedIn: false })
|
||||
})
|
||||
})
|
||||
|
||||
describe('with malformed JWT Bearer token', () => {
|
||||
const headers = { authorization: 'blah' }
|
||||
const client = new GraphQLClient(host, { headers })
|
||||
|
||||
it('returns false', async () => {
|
||||
await expect(client.request(query)).resolves.toEqual({ isLoggedIn: false })
|
||||
})
|
||||
})
|
||||
|
||||
describe('with valid JWT Bearer token', () => {
|
||||
const client = new GraphQLClient(host, { headers: jennyRostocksHeaders })
|
||||
|
||||
it('returns false', async () => {
|
||||
await expect(client.request(query)).resolves.toEqual({ isLoggedIn: false })
|
||||
})
|
||||
|
||||
describe('and a corresponding user in the database', () => {
|
||||
it('returns true', async () => {
|
||||
// see the decoded token above
|
||||
await factory.create('User', { id: 'u3' })
|
||||
await expect(client.request(query)).resolves.toEqual({ isLoggedIn: true })
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('currentUser', () => {
|
||||
const query = `{
|
||||
currentUser {
|
||||
id
|
||||
slug
|
||||
name
|
||||
avatar
|
||||
email
|
||||
role
|
||||
}
|
||||
}`
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
it('returns null', async () => {
|
||||
const expected = { currentUser: null }
|
||||
await expect(request(host, query)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with valid JWT Bearer Token', () => {
|
||||
let client
|
||||
let headers
|
||||
|
||||
describe('but no corresponding user in the database', () => {
|
||||
beforeEach(async () => {
|
||||
client = new GraphQLClient(host, { headers: jennyRostocksHeaders })
|
||||
})
|
||||
|
||||
it('returns null', async () => {
|
||||
const expected = { currentUser: null }
|
||||
await expect(client.request(query)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('and corresponding user in the database', () => {
|
||||
beforeEach(async () => {
|
||||
headers = await login({ email: 'test@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
})
|
||||
|
||||
it('returns the whole user object', async () => {
|
||||
const expected = {
|
||||
currentUser: {
|
||||
avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/seyedhossein1/128.jpg',
|
||||
email: 'test@example.org',
|
||||
id: 'acb2d923-f3af-479e-9f00-61b12e864666',
|
||||
name: 'Matilde Hermiston',
|
||||
slug: 'matilde-hermiston',
|
||||
role: 'user'
|
||||
}
|
||||
}
|
||||
await expect(client.request(query)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('login', () => {
|
||||
const mutation = (params) => {
|
||||
const { email, password } = params
|
||||
return `
|
||||
mutation {
|
||||
login(email:"${email}", password:"${password}")
|
||||
}`
|
||||
}
|
||||
|
||||
describe('ask for a `token`', () => {
|
||||
describe('with valid email/password combination', () => {
|
||||
it('responds with a JWT token', async () => {
|
||||
const data = await request(host, mutation({
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
}))
|
||||
const token = data.login
|
||||
jwt.verify(token, process.env.JWT_SECRET, (err, data) => {
|
||||
expect(data.email).toEqual('test@example.org')
|
||||
expect(err).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a valid email but incorrect password', () => {
|
||||
it('responds with "Incorrect email address or password."', async () => {
|
||||
await expect(
|
||||
request(host, mutation({
|
||||
email: 'test@example.org',
|
||||
password: 'wrong'
|
||||
}))
|
||||
).rejects.toThrow('Incorrect email address or password.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a non-existing email', () => {
|
||||
it('responds with "Incorrect email address or password."', async () => {
|
||||
await expect(
|
||||
request(host, mutation({
|
||||
email: 'non-existent@example.org',
|
||||
password: 'wrong'
|
||||
}))
|
||||
).rejects.toThrow('Incorrect email address or password.')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,23 +1,13 @@
|
||||
type Query {
|
||||
isLoggedIn: Boolean!
|
||||
currentUser: User
|
||||
statistics: Statistics!
|
||||
}
|
||||
type Mutation {
|
||||
login(email: String!, password: String!): LoggedInUser
|
||||
login(email: String!, password: String!): String!
|
||||
signup(email: String!, password: String!): Boolean!
|
||||
report(resource: Resource!, description: String): Report
|
||||
}
|
||||
type LoggedInUser {
|
||||
id: ID!
|
||||
slug: String!
|
||||
name: String!
|
||||
avatar:String!
|
||||
email: String!
|
||||
role: String!
|
||||
locationName: String
|
||||
about: String
|
||||
token: String!
|
||||
}
|
||||
|
||||
type Statistics {
|
||||
countUsers: Int!
|
||||
|
||||
@ -10,14 +10,14 @@ export default function (params) {
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
CreateBadge(
|
||||
id: "${id}",
|
||||
key: "${key}",
|
||||
type: ${type},
|
||||
status: ${status},
|
||||
icon: "${icon}"
|
||||
) { id }
|
||||
}
|
||||
mutation {
|
||||
CreateBadge(
|
||||
id: "${id}",
|
||||
key: "${key}",
|
||||
type: ${type},
|
||||
status: ${status},
|
||||
icon: "${icon}"
|
||||
) { id }
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@ -15,13 +15,11 @@ export const seedServerHost = 'http://127.0.0.1:4001'
|
||||
const authenticatedHeaders = async ({ email, password }, host) => {
|
||||
const mutation = `
|
||||
mutation {
|
||||
login(email:"${email}", password:"${password}"){
|
||||
token
|
||||
}
|
||||
login(email:"${email}", password:"${password}")
|
||||
}`
|
||||
const response = await request(host, mutation)
|
||||
return {
|
||||
authorization: `Bearer ${response.login.token}`
|
||||
authorization: `Bearer ${response.login}`
|
||||
}
|
||||
}
|
||||
const factories = {
|
||||
|
||||
@ -8,10 +8,7 @@ import middleware from './middleware'
|
||||
import applyDirectives from './bootstrap/directives'
|
||||
import applyScalars from './bootstrap/scalars'
|
||||
import { getDriver } from './bootstrap/neo4j'
|
||||
|
||||
import passport from 'passport'
|
||||
import jwtStrategy from './jwt/strategy'
|
||||
import jwt from 'jsonwebtoken'
|
||||
import decode from './jwt/decode'
|
||||
|
||||
dotenv.config()
|
||||
// check env and warn
|
||||
@ -42,20 +39,14 @@ schema = applyScalars(applyDirectives(schema))
|
||||
|
||||
const createServer = (options) => {
|
||||
const defaults = {
|
||||
context: async (req) => {
|
||||
const payload = {
|
||||
context: async ({ request }) => {
|
||||
const authorizationHeader = request.headers.authorization || ''
|
||||
const user = await decode(driver, authorizationHeader)
|
||||
return {
|
||||
driver,
|
||||
user: null,
|
||||
req: req.request
|
||||
user,
|
||||
req: request
|
||||
}
|
||||
try {
|
||||
const token = payload.req.headers.authorization.replace('Bearer ', '')
|
||||
payload.user = await jwt.verify(token, process.env.JWT_SECRET)
|
||||
} catch (err) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
return payload
|
||||
},
|
||||
schema: schema,
|
||||
debug: debug,
|
||||
@ -65,11 +56,7 @@ const createServer = (options) => {
|
||||
}
|
||||
const server = new GraphQLServer(Object.assign({}, defaults, options))
|
||||
|
||||
passport.use('jwt', jwtStrategy(driver))
|
||||
server.express.use(passport.initialize())
|
||||
server.express.use(express.static('public'))
|
||||
|
||||
server.express.post('/graphql', passport.authenticate(['jwt'], { session: false }))
|
||||
return server
|
||||
}
|
||||
|
||||
|
||||
357
yarn.lock
357
yarn.lock
@ -38,7 +38,27 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.0.0"
|
||||
|
||||
"@babel/core@^7.1.0", "@babel/core@~7.3.4":
|
||||
"@babel/core@^7.1.0":
|
||||
version "7.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.3.tgz#d090d157b7c5060d05a05acaebc048bd2b037947"
|
||||
integrity sha512-w445QGI2qd0E0GlSnq6huRZWPMmQGCp5gd5ZWS4hagn0EiwzxD5QMFkpchyusAyVC1n27OKXzQ0/88aVU9n4xQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
"@babel/generator" "^7.3.3"
|
||||
"@babel/helpers" "^7.2.0"
|
||||
"@babel/parser" "^7.3.3"
|
||||
"@babel/template" "^7.2.2"
|
||||
"@babel/traverse" "^7.2.2"
|
||||
"@babel/types" "^7.3.3"
|
||||
convert-source-map "^1.1.0"
|
||||
debug "^4.1.0"
|
||||
json5 "^2.1.0"
|
||||
lodash "^4.17.11"
|
||||
resolve "^1.3.2"
|
||||
semver "^5.4.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/core@~7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b"
|
||||
integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==
|
||||
@ -58,7 +78,18 @@
|
||||
semver "^5.4.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/generator@^7.0.0", "@babel/generator@^7.3.4":
|
||||
"@babel/generator@^7.0.0", "@babel/generator@^7.2.2", "@babel/generator@^7.3.3":
|
||||
version "7.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.3.tgz#185962ade59a52e00ca2bdfcfd1d58e528d4e39e"
|
||||
integrity sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==
|
||||
dependencies:
|
||||
"@babel/types" "^7.3.3"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.17.11"
|
||||
source-map "^0.5.0"
|
||||
trim-right "^1.0.1"
|
||||
|
||||
"@babel/generator@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e"
|
||||
integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==
|
||||
@ -199,6 +230,16 @@
|
||||
"@babel/traverse" "^7.1.0"
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-replace-supers@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.3.4.tgz#a795208e9b911a6eeb08e5891faacf06e7013e13"
|
||||
integrity sha512-pvObL9WVf2ADs+ePg0jrqlhHoxRXlOa+SHRHzAXIz2xkYuOHfGl+fKxPMaS4Fq+uje8JQPobnertBBvyrWnQ1A==
|
||||
dependencies:
|
||||
"@babel/helper-member-expression-to-functions" "^7.0.0"
|
||||
"@babel/helper-optimise-call-expression" "^7.0.0"
|
||||
"@babel/traverse" "^7.3.4"
|
||||
"@babel/types" "^7.3.4"
|
||||
|
||||
"@babel/helper-simple-access@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c"
|
||||
@ -253,7 +294,12 @@
|
||||
lodash "^4.17.10"
|
||||
v8flags "^3.1.1"
|
||||
|
||||
"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4":
|
||||
"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.2.3", "@babel/parser@^7.3.3":
|
||||
version "7.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.3.tgz#092d450db02bdb6ccb1ca8ffd47d8774a91aef87"
|
||||
integrity sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==
|
||||
|
||||
"@babel/parser@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c"
|
||||
integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==
|
||||
@ -275,10 +321,10 @@
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/plugin-syntax-json-strings" "^7.2.0"
|
||||
|
||||
"@babel/plugin-proposal-object-rest-spread@^7.3.1":
|
||||
version "7.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.2.tgz#6d1859882d4d778578e41f82cc5d7bf3d5daf6c1"
|
||||
integrity sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA==
|
||||
"@babel/plugin-proposal-object-rest-spread@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.4.tgz#47f73cf7f2a721aad5c0261205405c642e424654"
|
||||
integrity sha512-j7VQmbbkA+qrzNqbKHrBsW3ddFnOeva6wzSe/zB7T+xaxGc+RCpwo44wCmRixAIGRoIpmVgvzFzNJqQcO3/9RA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/plugin-syntax-object-rest-spread" "^7.2.0"
|
||||
@ -335,10 +381,10 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-transform-async-to-generator@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz#68b8a438663e88519e65b776f8938f3445b1a2ff"
|
||||
integrity sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==
|
||||
"@babel/plugin-transform-async-to-generator@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.3.4.tgz#4e45408d3c3da231c0e7b823f407a53a7eb3048c"
|
||||
integrity sha512-Y7nCzv2fw/jEZ9f678MuKdMo99MFDJMT/PvD9LisrR5JDFcJH6vYeH6RnjVt3p5tceyGRvTtEN0VOlU+rgHZjA==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
@ -351,25 +397,25 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-transform-block-scoping@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz#f17c49d91eedbcdf5dd50597d16f5f2f770132d4"
|
||||
integrity sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==
|
||||
"@babel/plugin-transform-block-scoping@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.3.4.tgz#5c22c339de234076eee96c8783b2fed61202c5c4"
|
||||
integrity sha512-blRr2O8IOZLAOJklXLV4WhcEzpYafYQKSGT3+R26lWG41u/FODJuBggehtOwilVAcFu393v3OFj+HmaE6tVjhA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
lodash "^4.17.10"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@babel/plugin-transform-classes@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.0.tgz#374f8876075d7d21fea55aeb5c53561259163f96"
|
||||
integrity sha512-aPCEkrhJYebDXcGTAP+cdUENkH7zqOlgbKwLbghjjHpJRJBWM/FSlCjMoPGA8oUdiMfOrk3+8EFPLLb5r7zj2w==
|
||||
"@babel/plugin-transform-classes@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.4.tgz#dc173cb999c6c5297e0b5f2277fdaaec3739d0cc"
|
||||
integrity sha512-J9fAvCFBkXEvBimgYxCjvaVDzL6thk0j0dBvCeZmIUDBwyt+nv6HfbImsSrWsYXfDNDivyANgJlFXDUWRTZBuA==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.0.0"
|
||||
"@babel/helper-define-map" "^7.1.0"
|
||||
"@babel/helper-function-name" "^7.1.0"
|
||||
"@babel/helper-optimise-call-expression" "^7.0.0"
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/helper-replace-supers" "^7.1.0"
|
||||
"@babel/helper-replace-supers" "^7.3.4"
|
||||
"@babel/helper-split-export-declaration" "^7.0.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
@ -450,10 +496,10 @@
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/helper-simple-access" "^7.1.0"
|
||||
|
||||
"@babel/plugin-transform-modules-systemjs@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz#912bfe9e5ff982924c81d0937c92d24994bb9068"
|
||||
integrity sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==
|
||||
"@babel/plugin-transform-modules-systemjs@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.3.4.tgz#813b34cd9acb6ba70a84939f3680be0eb2e58861"
|
||||
integrity sha512-VZ4+jlGOF36S7TjKs8g4ojp4MEI+ebCQZdswWb/T9I4X84j8OtFAyjXjt/M16iIm5RIZn0UMQgg/VgIwo/87vw==
|
||||
dependencies:
|
||||
"@babel/helper-hoist-variables" "^7.0.0"
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
@ -497,12 +543,12 @@
|
||||
"@babel/helper-get-function-arity" "^7.0.0"
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-transform-regenerator@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz#5b41686b4ed40bef874d7ed6a84bdd849c13e0c1"
|
||||
integrity sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==
|
||||
"@babel/plugin-transform-regenerator@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.3.4.tgz#1601655c362f5b38eead6a52631f5106b29fa46a"
|
||||
integrity sha512-hvJg8EReQvXT6G9H2MvNPXkv9zK36Vxa1+csAVTpE1J3j0zlHplw76uudEbJxgvqZzAq9Yh45FLD4pk5mKRFQA==
|
||||
dependencies:
|
||||
regenerator-transform "^0.13.3"
|
||||
regenerator-transform "^0.13.4"
|
||||
|
||||
"@babel/plugin-transform-shorthand-properties@^7.2.0":
|
||||
version "7.2.0"
|
||||
@ -558,16 +604,16 @@
|
||||
core-js "^2.5.7"
|
||||
regenerator-runtime "^0.11.1"
|
||||
|
||||
"@babel/preset-env@~7.3.1":
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.1.tgz#389e8ca6b17ae67aaf9a2111665030be923515db"
|
||||
integrity sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==
|
||||
"@babel/preset-env@~7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.4.tgz#887cf38b6d23c82f19b5135298bdb160062e33e1"
|
||||
integrity sha512-2mwqfYMK8weA0g0uBKOt4FE3iEodiHy9/CW0b+nWXcbL+pGzLx8ESYc+j9IIxr6LTDHWKgPm71i9smo02bw+gA==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.2.0"
|
||||
"@babel/plugin-proposal-json-strings" "^7.2.0"
|
||||
"@babel/plugin-proposal-object-rest-spread" "^7.3.1"
|
||||
"@babel/plugin-proposal-object-rest-spread" "^7.3.4"
|
||||
"@babel/plugin-proposal-optional-catch-binding" "^7.2.0"
|
||||
"@babel/plugin-proposal-unicode-property-regex" "^7.2.0"
|
||||
"@babel/plugin-syntax-async-generators" "^7.2.0"
|
||||
@ -575,10 +621,10 @@
|
||||
"@babel/plugin-syntax-object-rest-spread" "^7.2.0"
|
||||
"@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
|
||||
"@babel/plugin-transform-arrow-functions" "^7.2.0"
|
||||
"@babel/plugin-transform-async-to-generator" "^7.2.0"
|
||||
"@babel/plugin-transform-async-to-generator" "^7.3.4"
|
||||
"@babel/plugin-transform-block-scoped-functions" "^7.2.0"
|
||||
"@babel/plugin-transform-block-scoping" "^7.2.0"
|
||||
"@babel/plugin-transform-classes" "^7.2.0"
|
||||
"@babel/plugin-transform-block-scoping" "^7.3.4"
|
||||
"@babel/plugin-transform-classes" "^7.3.4"
|
||||
"@babel/plugin-transform-computed-properties" "^7.2.0"
|
||||
"@babel/plugin-transform-destructuring" "^7.2.0"
|
||||
"@babel/plugin-transform-dotall-regex" "^7.2.0"
|
||||
@ -589,13 +635,13 @@
|
||||
"@babel/plugin-transform-literals" "^7.2.0"
|
||||
"@babel/plugin-transform-modules-amd" "^7.2.0"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.2.0"
|
||||
"@babel/plugin-transform-modules-systemjs" "^7.2.0"
|
||||
"@babel/plugin-transform-modules-systemjs" "^7.3.4"
|
||||
"@babel/plugin-transform-modules-umd" "^7.2.0"
|
||||
"@babel/plugin-transform-named-capturing-groups-regex" "^7.3.0"
|
||||
"@babel/plugin-transform-new-target" "^7.0.0"
|
||||
"@babel/plugin-transform-object-super" "^7.2.0"
|
||||
"@babel/plugin-transform-parameters" "^7.2.0"
|
||||
"@babel/plugin-transform-regenerator" "^7.0.0"
|
||||
"@babel/plugin-transform-regenerator" "^7.3.4"
|
||||
"@babel/plugin-transform-shorthand-properties" "^7.2.0"
|
||||
"@babel/plugin-transform-spread" "^7.2.0"
|
||||
"@babel/plugin-transform-sticky-regex" "^7.2.0"
|
||||
@ -636,7 +682,22 @@
|
||||
"@babel/parser" "^7.2.2"
|
||||
"@babel/types" "^7.2.2"
|
||||
|
||||
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.3.4":
|
||||
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.2":
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.2.3.tgz#7ff50cefa9c7c0bd2d81231fdac122f3957748d8"
|
||||
integrity sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
"@babel/generator" "^7.2.2"
|
||||
"@babel/helper-function-name" "^7.1.0"
|
||||
"@babel/helper-split-export-declaration" "^7.0.0"
|
||||
"@babel/parser" "^7.2.3"
|
||||
"@babel/types" "^7.2.2"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.10"
|
||||
|
||||
"@babel/traverse@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06"
|
||||
integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==
|
||||
@ -651,7 +712,16 @@
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.4":
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.3":
|
||||
version "7.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.3.tgz#6c44d1cdac2a7625b624216657d5bc6c107ab436"
|
||||
integrity sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.17.11"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.3.4":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed"
|
||||
integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==
|
||||
@ -938,13 +1008,13 @@ anymatch@^2.0.0:
|
||||
micromatch "^3.1.4"
|
||||
normalize-path "^2.1.1"
|
||||
|
||||
apollo-cache-control@0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.5.1.tgz#db7e86cd7ede6cad0a2e0ea97488d9fb5c33d913"
|
||||
integrity sha512-82hzX7/fFiu5dODLS8oGieEE4jLjMIhIkQ4JTsWj9drv8PZJltl0xqORtU2jA/FottjxfYab8+ebi3BgGPOaqw==
|
||||
apollo-cache-control@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.5.2.tgz#47931ede0b11c64d45429850c274b30d19322362"
|
||||
integrity sha512-uehXDUrd3Qim+nzxqqN7XT1YTbNSyumW3/FY5BxbKZTI8d4oPG4eyVQKqaggooSjswKQnOoIQVes3+qg9tGAkw==
|
||||
dependencies:
|
||||
apollo-server-env "2.2.0"
|
||||
graphql-extensions "0.5.2"
|
||||
graphql-extensions "0.5.4"
|
||||
|
||||
apollo-cache-control@^0.1.0:
|
||||
version "0.1.1"
|
||||
@ -953,35 +1023,37 @@ apollo-cache-control@^0.1.0:
|
||||
dependencies:
|
||||
graphql-extensions "^0.0.x"
|
||||
|
||||
apollo-cache-inmemory@~1.4.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.4.3.tgz#aded4fb8b3de9e2fb2573a6c03591b07ef98ed36"
|
||||
integrity sha512-p9KGtEZ9Mlb+FS0UEaxR8WvKOijYV0c+TXlhC/XZ3/ltYvP1zL3b1ozSOLGR9SawN2895Fc7QDV5nzPpihV0rA==
|
||||
apollo-cache-inmemory@~1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.5.1.tgz#265d1ee67b0bf0aca9c37629d410bfae44e62953"
|
||||
integrity sha512-D3bdpPmWfaKQkWy8lfwUg+K8OBITo3sx0BHLs1B/9vIdOIZ7JNCKq3EUcAgAfInomJUdN0QG1yOfi8M8hxkN1g==
|
||||
dependencies:
|
||||
apollo-cache "^1.1.26"
|
||||
apollo-utilities "^1.1.3"
|
||||
apollo-cache "^1.2.1"
|
||||
apollo-utilities "^1.2.1"
|
||||
optimism "^0.6.9"
|
||||
ts-invariant "^0.2.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
apollo-cache@1.1.26, apollo-cache@^1.1.26:
|
||||
version "1.1.26"
|
||||
resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.1.26.tgz#5afe023270effbc2063d90f51d8e56bce274ab37"
|
||||
integrity sha512-JKFHijwkhXpcQ3jOat+ctwiXyjDhQgy0p6GSaj7zG+or+ZSalPqUnPzFRgRwFLVbYxBKJgHCkWX+2VkxWTZzQQ==
|
||||
apollo-cache@1.2.1, apollo-cache@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.2.1.tgz#aae71eb4a11f1f7322adc343f84b1a39b0693644"
|
||||
integrity sha512-nzFmep/oKlbzUuDyz6fS6aYhRmfpcHWqNkkA9Bbxwk18RD6LXC4eZkuE0gXRX0IibVBHNjYVK+Szi0Yied4SpQ==
|
||||
dependencies:
|
||||
apollo-utilities "^1.1.3"
|
||||
apollo-utilities "^1.2.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
apollo-client@~2.4.13:
|
||||
version "2.4.13"
|
||||
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.4.13.tgz#09829fcbd68e069de9840d0a10764d7c6a3d0787"
|
||||
integrity sha512-7mBdW/CW1qHB8Mj4EFAG3MTtbRc6S8aUUntUdrKfRWV1rZdWa0NovxsgVD/R4HZWZjRQ2UOM4ENsHdM5g1uXOQ==
|
||||
apollo-client@~2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.5.1.tgz#36126ed1d32edd79c3713c6684546a3bea80e6d1"
|
||||
integrity sha512-MNcQKiqLHdGmNJ0rZ0NXaHrToXapJgS/5kPk0FygXt+/FmDCdzqcujI7OPxEC6e9Yw5S/8dIvOXcRNuOMElHkA==
|
||||
dependencies:
|
||||
"@types/zen-observable" "^0.8.0"
|
||||
apollo-cache "1.1.26"
|
||||
apollo-cache "1.2.1"
|
||||
apollo-link "^1.0.0"
|
||||
apollo-link-dedup "^1.0.0"
|
||||
apollo-utilities "1.1.3"
|
||||
apollo-utilities "1.2.1"
|
||||
symbol-observable "^1.0.2"
|
||||
ts-invariant "^0.2.1"
|
||||
tslib "^1.9.3"
|
||||
zen-observable "^0.8.0"
|
||||
|
||||
@ -1000,17 +1072,17 @@ apollo-engine-reporting-protobuf@0.2.1:
|
||||
dependencies:
|
||||
protobufjs "^6.8.6"
|
||||
|
||||
apollo-engine-reporting@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.0.2.tgz#5dd5411f17d76e6788a1166367a2ab7b52794224"
|
||||
integrity sha512-g6JkO5WaMuqXfn3WoZMQyyFzpxfHsw/f7P7XTHSEqTSd/M4uk7/uih/xcqmgBGt4ET30KbaGFz2l4FJzO06A5w==
|
||||
apollo-engine-reporting@1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.0.7.tgz#d326b51b12b1f71a40885b8189dbcd162171c953"
|
||||
integrity sha512-mFsXvd+1/o5jSa9tI2RoXYGcvCLcwwcfLwchjSTxqUd4ViB8RbqYKynzEZ+Omji7PBRM0azioBm43f7PSsQPqA==
|
||||
dependencies:
|
||||
apollo-engine-reporting-protobuf "0.2.1"
|
||||
apollo-graphql "^0.1.0"
|
||||
apollo-server-core "2.4.2"
|
||||
apollo-server-core "2.4.8"
|
||||
apollo-server-env "2.2.0"
|
||||
async-retry "^1.2.1"
|
||||
graphql-extensions "0.5.2"
|
||||
graphql-extensions "0.5.7"
|
||||
|
||||
apollo-env@0.3.3:
|
||||
version "0.3.3"
|
||||
@ -1063,24 +1135,24 @@ apollo-server-caching@0.3.1:
|
||||
dependencies:
|
||||
lru-cache "^5.0.0"
|
||||
|
||||
apollo-server-core@2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.4.2.tgz#916d98636b1bf576a84b4a469006c1c73741e03a"
|
||||
integrity sha512-IOWhqjjI1sH38sj7ycjke0dXXEgaqOkb2hDpLBTSiVWKBIqFfo4gchWK5wcWW9jReDpf/+G2wogH+UvONs2ejg==
|
||||
apollo-server-core@2.4.8:
|
||||
version "2.4.8"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.4.8.tgz#47e503a345e314222725597c889773e018d8c67a"
|
||||
integrity sha512-N+5UOzHhMOnHizEiArJtNvEe/cGhSHQyTn5tlU4RJ36FDBJ/WlYZfPbGDMLISSUCJ6t+aP8GLL4Mnudt9d2PDQ==
|
||||
dependencies:
|
||||
"@apollographql/apollo-tools" "^0.3.3"
|
||||
"@apollographql/graphql-playground-html" "^1.6.6"
|
||||
"@types/ws" "^6.0.0"
|
||||
apollo-cache-control "0.5.1"
|
||||
apollo-cache-control "0.5.2"
|
||||
apollo-datasource "0.3.1"
|
||||
apollo-engine-reporting "1.0.2"
|
||||
apollo-engine-reporting "1.0.7"
|
||||
apollo-server-caching "0.3.1"
|
||||
apollo-server-env "2.2.0"
|
||||
apollo-server-errors "2.2.0"
|
||||
apollo-server-plugin-base "0.3.2"
|
||||
apollo-tracing "0.5.1"
|
||||
apollo-server-errors "2.2.1"
|
||||
apollo-server-plugin-base "0.3.7"
|
||||
apollo-tracing "0.5.2"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
graphql-extensions "0.5.2"
|
||||
graphql-extensions "0.5.7"
|
||||
graphql-subscriptions "^1.0.0"
|
||||
graphql-tag "^2.9.2"
|
||||
graphql-tools "^4.0.0"
|
||||
@ -1106,15 +1178,15 @@ apollo-server-env@2.2.0:
|
||||
node-fetch "^2.1.2"
|
||||
util.promisify "^1.0.0"
|
||||
|
||||
apollo-server-errors@2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.2.0.tgz#5b452a1d6ff76440eb0f127511dc58031a8f3cb5"
|
||||
integrity sha512-gV9EZG2tovFtT1cLuCTavnJu2DaKxnXPRNGSTo+SDI6IAk6cdzyW0Gje5N2+3LybI0Wq5KAbW6VLei31S4MWmg==
|
||||
apollo-server-errors@2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.2.1.tgz#f68a3f845929768057da7e1c6d30517db5872205"
|
||||
integrity sha512-wY/YE3iJVMYC+WYIf8QODBjIP4jhI+oc7kiYo9mrz7LdYPKAgxr/he+NteGcqn/0Ea9K5/ZFTGJDbEstSMeP8g==
|
||||
|
||||
apollo-server-express@2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.4.2.tgz#870daf04fd9b727a54b1339cdb55066450b3e05a"
|
||||
integrity sha512-Q5/unCAi6a2dT39LQaIiLC1d8O4fmBDU2CrRhVhPWP8I344xPgNOcrs7MsNN7Ecb56UGbgDKxBoWowFG65ulKw==
|
||||
apollo-server-express@2.4.8:
|
||||
version "2.4.8"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.4.8.tgz#ec9eb61a87324555d49097e9fade3c7d142eb6cb"
|
||||
integrity sha512-i60l32mfVe33jnKDPNYgUKUKu4Al0xEm2HLOSMgtJ9Wbpe/MbOx5X8M5F27fnHYdM+G5XfAErsakAyRGnQJ48Q==
|
||||
dependencies:
|
||||
"@apollographql/graphql-playground-html" "^1.6.6"
|
||||
"@types/accepts" "^1.3.5"
|
||||
@ -1122,7 +1194,7 @@ apollo-server-express@2.4.2:
|
||||
"@types/cors" "^2.8.4"
|
||||
"@types/express" "4.16.1"
|
||||
accepts "^1.3.5"
|
||||
apollo-server-core "2.4.2"
|
||||
apollo-server-core "2.4.8"
|
||||
body-parser "^1.18.3"
|
||||
cors "^2.8.4"
|
||||
graphql-subscriptions "^1.0.0"
|
||||
@ -1150,36 +1222,36 @@ apollo-server-module-graphiql@^1.3.4, apollo-server-module-graphiql@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.4.0.tgz#c559efa285578820709f1769bb85d3b3eed3d8ec"
|
||||
integrity sha512-GmkOcb5he2x5gat+TuiTvabnBf1m4jzdecal3XbXBh/Jg+kx4hcvO3TTDFQ9CuTprtzdcVyA11iqG7iOMOt7vA==
|
||||
|
||||
apollo-server-plugin-base@0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.3.2.tgz#4609c9a9d154568401d84b7ac17d1e30e3529104"
|
||||
integrity sha512-yzXrkVSPBoux2uPgbTGROGh7W0axRWopMZM+KT9aF9H/+yMCwtt0EhGOGyNUDMOFA4rT3z+cLVvYuZr1rSQWcg==
|
||||
apollo-server-plugin-base@0.3.7:
|
||||
version "0.3.7"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.3.7.tgz#bfa4932fc9481bb36221545578d311db464af5a6"
|
||||
integrity sha512-hW1jaLKf9qNOxMTwRq2CSqz3eqXsZuEiCc8/mmEtOciiVBq1GMtxFf19oIYM9HQuPvQU2RWpns1VrYN59L3vbg==
|
||||
|
||||
apollo-server-testing@~2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.4.2.tgz#5c87b34b0b6a1a3e5a1784cadc16bc495dded2e1"
|
||||
integrity sha512-WZ901nh7uG75342lMukJvuxFF/w3W5JDyWElY8KDhXfaDLbMKqhRqaWRIiEEX4YvciO5ACSzqKt+957/y1yUUQ==
|
||||
apollo-server-testing@~2.4.8:
|
||||
version "2.4.8"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.4.8.tgz#eb929a431e059723c298919688355434d53e3ea8"
|
||||
integrity sha512-AmNn5pDn9FJ9AJbmc7gwsUFaUt4uf44IFHaCfZow/jkAeY2JZnIozt8LYC8Koidy+Lfb+i/HsjkgbBodElbGMQ==
|
||||
dependencies:
|
||||
apollo-server-core "2.4.2"
|
||||
apollo-server-core "2.4.8"
|
||||
|
||||
apollo-server@~2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.4.2.tgz#6ca42906664918c32d8be391db1178c6eaa8dc54"
|
||||
integrity sha512-oFwHUhJtJedIPCtZ2ftvRWrVA3KpmeWsgDBs4e5jW/7f5ozkUF22h7L3iy8rEljppiEa2X/GgSi11SVxIOL8gw==
|
||||
apollo-server@~2.4.8:
|
||||
version "2.4.8"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.4.8.tgz#b18ec24e6356dd2a191a6fa0f1429b07ef7c89e3"
|
||||
integrity sha512-IU6RekO2dqrDdC+5hU6aeVvGg/2t/f01inBMjDhAn1a7hoITUXEh8Sa57TgmYEZ5uAtDuWW7cdiZN2j0cMI3/w==
|
||||
dependencies:
|
||||
apollo-server-core "2.4.2"
|
||||
apollo-server-express "2.4.2"
|
||||
apollo-server-core "2.4.8"
|
||||
apollo-server-express "2.4.8"
|
||||
express "^4.0.0"
|
||||
graphql-subscriptions "^1.0.0"
|
||||
graphql-tools "^4.0.0"
|
||||
|
||||
apollo-tracing@0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.5.1.tgz#16be201bc276120f0f8b7aa180201ee89d57e3bd"
|
||||
integrity sha512-5gb8OWzkGaJFsmQdyMyZnOjcq6weMTkqJSGj0hfR7uX99X4SBFAzZV4nTeK4z0XkXO2I12xSTJoS4gxbFjgeaA==
|
||||
apollo-tracing@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.5.2.tgz#cc49936fb435fa98d19c841514cfe05237c85b33"
|
||||
integrity sha512-2FdwRvPIq9uuF6OzONroXep6VBGqzHOkP6LlcFQe7SdwxfRP+SD/ycHNSC1acVg2b8d+am9Kzqg2vV54UpOIKA==
|
||||
dependencies:
|
||||
apollo-server-env "2.2.0"
|
||||
graphql-extensions "0.5.2"
|
||||
graphql-extensions "0.5.4"
|
||||
|
||||
apollo-tracing@^0.1.0:
|
||||
version "0.1.4"
|
||||
@ -1198,12 +1270,13 @@ apollo-upload-server@^7.0.0:
|
||||
http-errors "^1.7.0"
|
||||
object-path "^0.11.4"
|
||||
|
||||
apollo-utilities@1.1.3, apollo-utilities@^1.0.1, apollo-utilities@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.1.3.tgz#a8883c0392f6b46eac0d366204ebf34be9307c87"
|
||||
integrity sha512-pF9abhiClX5gfj/WFWZh8DiI33nOLGxRhXH9ZMquaM1V8bhq1WLFPt2QjShWH3kGQVeIGUK+FQefnhe+ZaaAYg==
|
||||
apollo-utilities@1.2.1, apollo-utilities@^1.0.1, apollo-utilities@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.2.1.tgz#1c3a1ebf5607d7c8efe7636daaf58e7463b41b3c"
|
||||
integrity sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg==
|
||||
dependencies:
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
ts-invariant "^0.2.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
append-transform@^1.0.0:
|
||||
@ -3097,10 +3170,17 @@ graphql-deduplicator@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/graphql-deduplicator/-/graphql-deduplicator-2.0.2.tgz#d8608161cf6be97725e178df0c41f6a1f9f778f3"
|
||||
integrity sha512-0CGmTmQh4UvJfsaTPppJAcHwHln8Ayat7yXXxdnuWT+Mb1dBzkbErabCWzjXyKh/RefqlGTTA7EQOZHofMaKJA==
|
||||
|
||||
graphql-extensions@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.5.2.tgz#cdced94c1931c9983fffcc144e336d6cd4d8b02b"
|
||||
integrity sha512-D/FAvjYEZ8GM3vfALxRvItozy5iLUfzyoauE2lli+0OuUBCAZDLP0fgqeTFK93NnQX/XSjBVGhcuDWBB7JesEw==
|
||||
graphql-extensions@0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.5.4.tgz#18a9674f9adb11aa6c0737485887ea8877914cff"
|
||||
integrity sha512-qLThJGVMqcItE7GDf/xX/E40m/aeqFheEKiR5bfra4q5eHxQKGjnIc20P9CVqjOn9I0FkEiU9ypOobfmIf7t6g==
|
||||
dependencies:
|
||||
"@apollographql/apollo-tools" "^0.3.3"
|
||||
|
||||
graphql-extensions@0.5.7:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.5.7.tgz#2b647e4e36997dc85b7f58ebd64324a5250fb2cf"
|
||||
integrity sha512-HrU6APE1PiehZ46scMB3S5DezSeCATd8v+e4mmg2bqszMyCFkmAnmK6hR1b5VjHxhzt5/FX21x1WsXfqF4FwdQ==
|
||||
dependencies:
|
||||
"@apollographql/apollo-tools" "^0.3.3"
|
||||
|
||||
@ -4352,7 +4432,7 @@ jsonify@~0.0.0:
|
||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
|
||||
|
||||
jsonwebtoken@^8.2.0, jsonwebtoken@~8.5.0:
|
||||
jsonwebtoken@~8.5.0:
|
||||
version "8.5.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz#ebd0ca2a69797816e1c5af65b6c759787252947e"
|
||||
integrity sha512-IqEycp0znWHNA11TpYi77bVgyBO/pGESDh7Ajhas+u0ttkGkKYIIAjniL4Bw5+oVejVF+SYkaI7XKfwCCyeTuA==
|
||||
@ -5352,27 +5432,6 @@ pascalcase@^0.1.1:
|
||||
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
|
||||
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
|
||||
|
||||
passport-jwt@~4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-jwt/-/passport-jwt-4.0.0.tgz#7f0be7ba942e28b9f5d22c2ebbb8ce96ef7cf065"
|
||||
integrity sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==
|
||||
dependencies:
|
||||
jsonwebtoken "^8.2.0"
|
||||
passport-strategy "^1.0.0"
|
||||
|
||||
passport-strategy@1.x.x, passport-strategy@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
|
||||
integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=
|
||||
|
||||
passport@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.0.tgz#c5095691347bd5ad3b5e180238c3914d16f05811"
|
||||
integrity sha1-xQlWkTR71a07XhgCOMORTRbwWBE=
|
||||
dependencies:
|
||||
passport-strategy "1.x.x"
|
||||
pause "0.0.1"
|
||||
|
||||
path-dirname@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
|
||||
@ -5427,11 +5486,6 @@ pathval@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
|
||||
integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA=
|
||||
|
||||
pause@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
|
||||
integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=
|
||||
|
||||
performance-now@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
@ -5780,10 +5834,10 @@ regenerator-runtime@^0.12.0:
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
|
||||
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
|
||||
|
||||
regenerator-transform@^0.13.3:
|
||||
version "0.13.3"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb"
|
||||
integrity sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==
|
||||
regenerator-transform@^0.13.4:
|
||||
version "0.13.4"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb"
|
||||
integrity sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==
|
||||
dependencies:
|
||||
private "^0.1.6"
|
||||
|
||||
@ -6720,6 +6774,13 @@ trunc-text@1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/trunc-text/-/trunc-text-1.0.1.tgz#58f876d8ac59b224b79834bb478b8656e69622b5"
|
||||
integrity sha1-WPh22KxZsiS3mDS7R4uGVuaWIrU=
|
||||
|
||||
ts-invariant@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.2.1.tgz#3d587f9d6e3bded97bf9ec17951dd9814d5a9d3f"
|
||||
integrity sha512-Z/JSxzVmhTo50I+LKagEISFJW3pvPCqsMWLamCTX8Kr3N5aMrnGOqcflbe5hLUzwjvgPfnLzQtHZv0yWQ+FIHg==
|
||||
dependencies:
|
||||
tslib "^1.9.3"
|
||||
|
||||
tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user