From f1fe0510b183dc89c02e09d242dabf9e17de9bb3 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 1 Nov 2018 08:46:02 -0700 Subject: [PATCH 1/6] Update error handling --- api/package-lock.json | 37 +++++++++++++++++++++ api/package.json | 1 + api/src/directives/index.js | 3 +- api/src/errors/index.js | 18 ++++++++-- api/src/graphql/resolvers/Mutation/index.js | 34 +++++++++---------- api/src/graphql/resolvers/Query/Team.js | 9 +++-- api/src/logger/index.js | 4 ++- 7 files changed, 81 insertions(+), 25 deletions(-) diff --git a/api/package-lock.json b/api/package-lock.json index 8292250ea..3c93e902b 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -1648,6 +1648,15 @@ "protobufjs": "^6.8.6" } }, + "apollo-errors": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/apollo-errors/-/apollo-errors-1.9.0.tgz", + "integrity": "sha512-XVukHd0KLvgY6tNjsPS3/Re3U6RQlTKrTbIpqqeTMo2N34uQMr+H1UheV21o8hOZBAFosvBORVricJiP5vfmrw==", + "requires": { + "assert": "^1.4.1", + "extendable-error": "^0.1.5" + } + }, "apollo-link": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.2.tgz", @@ -1934,6 +1943,14 @@ "safer-buffer": "~2.1.0" } }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "requires": { + "util": "0.10.3" + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -3823,6 +3840,11 @@ } } }, + "extendable-error": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.5.tgz", + "integrity": "sha1-EiMIpwl7yJomOyxPvwiceBQOO20=" + }, "external-editor": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", @@ -10521,6 +10543,21 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + } + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/api/package.json b/api/package.json index f50720958..a4930bc5d 100644 --- a/api/package.json +++ b/api/package.json @@ -14,6 +14,7 @@ "@babel/polyfill": "^7.0.0", "@babel/preset-env": "^7.1.0", "@babel/register": "^7.0.0", + "apollo-errors": "^1.9.0", "apollo-server-express": "^2.1.0", "axios": "^0.18.0", "cors": "^2.8.4", diff --git a/api/src/directives/index.js b/api/src/directives/index.js index be47f90c1..03f2ae250 100644 --- a/api/src/directives/index.js +++ b/api/src/directives/index.js @@ -1,6 +1,6 @@ import { SchemaDirectiveVisitor } from 'apollo-server-express' import _get from 'lodash.get' -import { logger, AuthenticationError } from '../logger' +import { logger, AuthenticationError, DatabaseError } from '../logger' const memberLocationOnContext = 'request.user' const userIdOnContext = 'request.headers.userid' @@ -35,6 +35,7 @@ const isUserId = async ctx => { logger.info(member) if (!member) { throw new AuthenticationError() + return } else { return member } diff --git a/api/src/errors/index.js b/api/src/errors/index.js index e55a27cc7..d42bf2db7 100644 --- a/api/src/errors/index.js +++ b/api/src/errors/index.js @@ -10,12 +10,24 @@ export { ValidationError, } from 'apollo-server-express' -export function formatError(error) { +export const formatError = (error) => { // This can be used to send errors to third // party services like Sentry or Stackdriver - logger.error(error) + logger.info('formatError') + logger.error(JSON.stringify(error)) + const originalError = searchOriginalError(error) + logger.error(originalError) + return originalError +} - return error +const searchOriginalError = (error) => { + if (error.originalError) { + return searchOriginalError(error.originalError) + } + if (error.errors) { + return error.errors.map(searchOriginalError)[0] + } + return error; } // Define custom Apollo errors here diff --git a/api/src/graphql/resolvers/Mutation/index.js b/api/src/graphql/resolvers/Mutation/index.js index a56f0adeb..dd9605583 100644 --- a/api/src/graphql/resolvers/Mutation/index.js +++ b/api/src/graphql/resolvers/Mutation/index.js @@ -8,7 +8,7 @@ import TEAMS_CONNECTIONS_FRAGMENT from '../../fragments/TeamsConnectionsFragment import TEAMS_FRAGMENT from '../../fragments/TeamsFragment' import TEAM_FB_FRAGMENT from '../../fragments/TeamFBFragment' -import { logger, AuthenticationError, ServiceUnavailableError } from '../../../logger' +import { logger, AuthenticationError, ServiceUnavailableError, DatabaseError } from '../../../logger' export const resolvers = { Mutation: { @@ -36,7 +36,7 @@ export const resolvers = { logger.info('verifyTeamInvite.token: ', await verifiedToken) } catch (err) { logger.debug('verifyTeamInvite. err: ', err) - throw new Error(err.message) + throw new DatabaseError(err.message) } return team }, @@ -71,17 +71,17 @@ export const resolvers = { .then((result) => { console.log('createPlatformTeam result:', result.data) if(result.data.message === 'Team Name already taken'){ - return result.data.message + throw new DatabaseError(`${result.data.message} - Team already exists onAA Cloud`) } if(result.data.result === 'Fail'){ - return result.data.message + throw new DatabaseError(`${result.data.message} - Creating team on AA Cloud has failed`) } return result }) .catch(err =>{ logger.debug('createPlatformTeam err:') logger.debug(err) - throw new ServiceUnavailableError(err) + throw new DatabaseError(err) }) console.log('createPlatformTeam returned: ', await createPlatformTeam) if(await createPlatformTeam === 'Team Name already taken'){ @@ -91,11 +91,11 @@ export const resolvers = { const existingMember = await ctx.db.query.member({ where: { authId } }, `{id}`) .catch((err) => { logger.debug(err, 'existingMember error: ') - return err + throw new DatabaseError(err) }) - logger.info('existingMember:') - logger.info(await existingMember) + logger.debug('existingMember:') + logger.debug(await existingMember) let createTeam if(existingMember !== null && existingMember.id !== null){ @@ -103,14 +103,14 @@ export const resolvers = { createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {connect: {authId: authId}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Connected to Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'TRADER', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT) .catch((err) => { logger.debug(err, 'createTeamMutation error: ') - return err + throw new DatabaseError(err) }) } else { logger.info('createTeam without existingMember:') createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {create: {authId: authId, alias: alias, visible:'true', status: { create: { status: 'ACTIVE', reason: `Created team ${name}`}}}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Created with Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'TRADER', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT) .catch((err) => { logger.debug(err, 'createTeamMutation error: ') - return err + throw new DatabaseError(err) }) } @@ -120,21 +120,21 @@ export const resolvers = { }) .catch((err) => { logger.debug('createTeam error: ') - return err + throw new DatabaseError(`Team Creation Error: ${err}`) }) }, async updateTeamProfile(parent, { slug, owner, description, motto, avatar, banner }, ctx, info) { return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar, banner: banner}}}, where:{slug: slug}}, TEAMS_FRAGMENT) .catch((err) => { logger.debug('createTeam error: ', err) - return err + throw new DatabaseError(`Team Profile Update Error: ${err}`) }) }, async updateFB(parent, { fbId, avatar}, ctx, info) { return ctx.db.mutation.updateFinancialBeings({data:{avatar:avatar}, where:{id:fbId}}, info) .catch((err) => { logger.debug('createTeam error: ', err) - return err + throw new DatabaseError(`Update Financial Being Error: ${err}`) }) }, async deleteTeam(parent, { slug, botSlug }, ctx, info) { @@ -166,14 +166,14 @@ export const resolvers = { .then((result) => { console.log('deletePlatformTeam result:', result.data) if(result.data.result === 'Fail'){ - return result.data.message + throw new DatabaseError(result.data.message) } return result }) .catch(err =>{ logger.debug('deletePlatformTeam err:') logger.debug(err) - throw new Error(err) + throw new DatabaseError(err) }) console.log('deletePlatformTeam returned: ', await deletePlatformTeam) @@ -181,13 +181,13 @@ export const resolvers = { .catch((res) => { logger.info('deleteTeam error: ', res) const errors = res.graphQLErrors.map((error) => { - return error.message + throw new DatabaseError(error.message) }) }) }) .catch((err) => { logger.debug('deleteTeam error: ') - return err + throw new DatabaseError(err) }) } } diff --git a/api/src/graphql/resolvers/Query/Team.js b/api/src/graphql/resolvers/Query/Team.js index 4961888e5..001b6e7dc 100644 --- a/api/src/graphql/resolvers/Query/Team.js +++ b/api/src/graphql/resolvers/Query/Team.js @@ -1,4 +1,4 @@ -import { logger } from '../../../logger' +import { logger, AuthenticationError } from '../../../logger' import TEAMS_CONNECTIONS_FRAGMENT from '../../fragments/TeamsConnectionsFragment' import TEAMS_FRAGMENT from '../../fragments/TeamsFragment' @@ -9,8 +9,10 @@ export const teams = async (parent, args, ctx, info) => { return ctx.db.query.teamsConnection({}, TEAMS_CONNECTIONS_FRAGMENT) } -export const teamById = async (parent, { id }, ctx, info) => { - return ctx.db.query.team({ where: { id } }, info) +export const teamById = async (parent, { teamId }, ctx, info) => { + logger.info('teamById') + logger.info(teamId) + return ctx.db.query.team({ where: { id: teamId } }, info) } export const teamByName = async (parent, { name }, ctx, info) => { @@ -26,6 +28,7 @@ export const teamsByOwner = async (parent, args, ctx, info) => { const authId = ctx.request.headers.userid if (!authId) { throw new AuthenticationError() + return } return ctx.db.query.teams({where: { owner: authId }, orderBy:'updatedAt_DESC'}, TEAMS_FRAGMENT) } diff --git a/api/src/logger/index.js b/api/src/logger/index.js index 10d57fed8..4d3087ea9 100644 --- a/api/src/logger/index.js +++ b/api/src/logger/index.js @@ -1,6 +1,8 @@ import { createLogger, format, transports } from 'winston' import { inspect } from 'util' +import { AuthenticationError as ApolloAuthenticationError } from 'apollo-server-express' + import { AuthenticationError, DatabaseError, WrongArgumentsError, ServiceUnavailableError } from './errors' class LoggerService { @@ -30,4 +32,4 @@ class LoggerService { } export const logger = new LoggerService() // Default logger -export { LoggerService, AuthenticationError, DatabaseError, WrongArgumentsError, ServiceUnavailableError } +export { LoggerService, AuthenticationError, ApolloAuthenticationError, DatabaseError, WrongArgumentsError, ServiceUnavailableError } From edfa34ccbd2c4d794b9e55ac8b0544398008fe65 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 1 Nov 2018 08:49:19 -0700 Subject: [PATCH 2/6] Raise event to Canvas on team creation or deletion --- client/src/views/manage-teams/components/CreateTeamDialog.js | 1 + client/src/views/manage-teams/components/ManageTeamDelete.js | 1 + 2 files changed, 2 insertions(+) diff --git a/client/src/views/manage-teams/components/CreateTeamDialog.js b/client/src/views/manage-teams/components/CreateTeamDialog.js index 16f49bb29..a46652833 100644 --- a/client/src/views/manage-teams/components/CreateTeamDialog.js +++ b/client/src/views/manage-teams/components/CreateTeamDialog.js @@ -210,6 +210,7 @@ export class CreateTeamDialog extends Component { const slug = this.slugify(name) const botSlug = this.slugify(botName) await createTeam({ variables: { name, slug, botName, botSlug } }) + window.canvasApp.eventHandler.raiseEvent('User Profile Changed') this.setState({ name: '', open: false }) } diff --git a/client/src/views/manage-teams/components/ManageTeamDelete.js b/client/src/views/manage-teams/components/ManageTeamDelete.js index 7f56e9913..a480946dd 100644 --- a/client/src/views/manage-teams/components/ManageTeamDelete.js +++ b/client/src/views/manage-teams/components/ManageTeamDelete.js @@ -144,6 +144,7 @@ export class ManageTeamDelete extends Component { async handleSubmit (e, deleteTeam, slug, botSlug) { e.preventDefault() await deleteTeam({ variables: { slug, botSlug } }) + window.canvasApp.eventHandler.raiseEvent('User Profile Changed') this.setState({ open: false }) } } From fbd3903c8ba983eccfd48b65d43537d3fa139bc9 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 1 Nov 2018 08:50:56 -0700 Subject: [PATCH 3/6] Fix Team_FB Fragment --- api/src/graphql/resolvers/Query/Team.js | 7 +++---- api/src/graphql/resolvers/Query/TeamMember.js | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/api/src/graphql/resolvers/Query/Team.js b/api/src/graphql/resolvers/Query/Team.js index 001b6e7dc..d70de3cd4 100644 --- a/api/src/graphql/resolvers/Query/Team.js +++ b/api/src/graphql/resolvers/Query/Team.js @@ -1,4 +1,4 @@ -import { logger, AuthenticationError } from '../../../logger' +import { logger, AuthenticationError, DatabaseError } from '../../../logger' import TEAMS_CONNECTIONS_FRAGMENT from '../../fragments/TeamsConnectionsFragment' import TEAMS_FRAGMENT from '../../fragments/TeamsFragment' @@ -44,10 +44,9 @@ export const teamsByRole = async (parent, args, ctx, info) => { } catch (err) { logger.debug('teamsByRole error: ') logger.debug(err) - const errors = res.graphQLErrors.map((error) => { - return error.message + const errors = err.graphQLErrors.map((error) => { + throw new DatabaseError(error.message) }) - return errors } logger.info('teamsByRole teamAdmin: ', teamAdmin) return teamAdmin diff --git a/api/src/graphql/resolvers/Query/TeamMember.js b/api/src/graphql/resolvers/Query/TeamMember.js index 9126c9c5d..1a8416c1f 100644 --- a/api/src/graphql/resolvers/Query/TeamMember.js +++ b/api/src/graphql/resolvers/Query/TeamMember.js @@ -1,5 +1,7 @@ import { logger } from '../../../logger' +import TEAM_FB_FRAGMENT from '../../fragments/TeamFBFragment' + export const fbByTeamMember = async (parent, args, ctx, info) => { logger.info('fbByTeamMember: ', args, ctx.request, ctx.request.res.req.user) const authId = ctx.request.headers.userid From b87abdbb26cbde6ff15e210cd49a63347fc202d2 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 1 Nov 2018 08:52:56 -0700 Subject: [PATCH 4/6] Raise event to Canvas on profile image updates --- client/src/views/financial-beings/components/ManageFBEdit.js | 1 + client/src/views/manage-teams/components/ManageTeamEdit.js | 1 + 2 files changed, 2 insertions(+) diff --git a/client/src/views/financial-beings/components/ManageFBEdit.js b/client/src/views/financial-beings/components/ManageFBEdit.js index f74099d5c..ef4b2915a 100644 --- a/client/src/views/financial-beings/components/ManageFBEdit.js +++ b/client/src/views/financial-beings/components/ManageFBEdit.js @@ -190,6 +190,7 @@ export class ManageFBEdit extends Component { avatar: this.state.avatar } }) + window.canvasApp.eventHandler.raiseEvent('User Profile Changed') this.setState({ open: false }) } } diff --git a/client/src/views/manage-teams/components/ManageTeamEdit.js b/client/src/views/manage-teams/components/ManageTeamEdit.js index 4644f2e24..0c1692e07 100644 --- a/client/src/views/manage-teams/components/ManageTeamEdit.js +++ b/client/src/views/manage-teams/components/ManageTeamEdit.js @@ -266,6 +266,7 @@ export class ManageTeamEdit extends Component { banner: this.state.banner } }) + window.canvasApp.eventHandler.raiseEvent('User Profile Changed') this.setState({ description: '', motto: '', open: false }) } } From fab70311e9ba7af494febc3fd2e4c24fa8784f80 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 1 Nov 2018 08:54:55 -0700 Subject: [PATCH 5/6] Client: Hide settings --- client/src/views/common/components/TeamBar.js | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/client/src/views/common/components/TeamBar.js b/client/src/views/common/components/TeamBar.js index 324fc3d13..fb32b4d2f 100644 --- a/client/src/views/common/components/TeamBar.js +++ b/client/src/views/common/components/TeamBar.js @@ -12,19 +12,32 @@ import GroupIcon from '@material-ui/icons/Group' import UsersIcon from '@material-ui/icons/People' import SearchIcon from '@material-ui/icons/Search' import AdbIcon from '@material-ui/icons/Adb' -import SettingsApplicationsIcon from '@material-ui/icons/SettingsApplications' +// import SettingsApplicationsIcon from '@material-ui/icons/SettingsApplications' import BugReportIcon from '@material-ui/icons/BugReport' import { Link } from 'react-router-dom' import log from '../../../utils/log' -const SettingsLink = props => +// const SettingsLink = props => const FBLink = props => const MembersLink = props => const ManageLink = props => const ViewLink = props => +/* + +*/ + const styles = theme => ({ root: { flexGrow: 1 @@ -112,16 +125,6 @@ class TeamBar extends Component { Financial Beings -