Better error pages and fix checkout admin issue

main
Ashelyn Dawn 4 years ago
parent 249d520070
commit 475b88626e

@ -34,7 +34,14 @@ router.use((err, req, res, next)=> {
console.error(err.stack)
res.status(err.status || 500)
res.json({
error: err.message
})
const error = {
message: err.message,
name: err.name
}
if(process.env.SOS_ENV === 'development')
error.stack = err.stack
res.json({ error })
})

@ -3,6 +3,7 @@ const parseJSON = require('body-parser').json()
const db = require('../db')
const stripe = require('stripe')(process.env.STRIPE_PRIVATE_KEY);
const ensureAdmin = require('./middleware/ensureAdmin')
const ensureCart = require('./middleware/ensureCart')
const validate = require('./middleware/validators')
@ -19,24 +20,22 @@ router.get('/all', ensureAdmin, async (req, res) => {
res.json(orders)
})
router.get('/:uuid', ensureAdmin, async (req, res) => {
const order = await db.order.findByUUID(req.params.uuid)
router.put('/', ensureCart, async (req, res) => {
const order = await db.order.create(req.cart.uuid, req.sessionObj.uuid);
res.json(order)
})
router.use(require('./middleware/ensureCart'))
router.put('/', async (req, res) => {
const order = await db.order.create(req.cart.uuid, req.sessionObj.uuid);
router.get('/current', ensureCart, async (req, res) => {
const order = await db.order.findForCart(req.cart.uuid);
res.json(order)
})
router.get('/current', async (req, res) => {
const order = await db.order.findForCart(req.cart.uuid);
router.get('/:uuid', ensureAdmin, async (req, res) => {
const order = await db.order.findByUUID(req.params.uuid)
res.json(order)
})
router.post('/current/address', parseJSON, validate.address, validate.handleApiError, async (req, res) => {
router.post('/current/address', ensureCart, parseJSON, validate.address, validate.handleApiError, async (req, res) => {
const origOrder = await db.order.findForCart(req.cart.uuid);
if(!origOrder) throw new Error("Unable to find current order");
@ -54,7 +53,7 @@ router.post('/current/address', parseJSON, validate.address, validate.handleApiE
res.json(order)
})
router.post('/current/coupon', parseJSON, validate.coupon, validate.handleApiError, async (req, res) => {
router.post('/current/coupon', ensureCart, parseJSON, validate.coupon, validate.handleApiError, async (req, res) => {
const origOrder = await db.order.findForCart(req.cart.uuid);
if(!origOrder) throw new Error("Unable to find current order");
@ -69,7 +68,7 @@ router.post('/current/coupon', parseJSON, validate.coupon, validate.handleApiErr
res.json(order)
})
router.post('/current/checkout/stripe', async (req, res) => {
router.post('/current/checkout/stripe', ensureCart, async (req, res) => {
const order = await db.order.findForCart(req.cart.uuid);
if(!order) throw new Error("Unable to find current order");
@ -127,7 +126,7 @@ router.post('/current/checkout/stripe', async (req, res) => {
res.json(session.id)
})
router.post('/current/checkout/verify', parseJSON, async (req, res) => {
router.post('/current/checkout/verify', ensureCart, parseJSON, async (req, res) => {
const {session_id} = req.body
if(!session_id) throw new Error("No session id given")

@ -1,6 +1,6 @@
import React from 'react'
import ErrorDisplay from '~/components/errorDisplay'
import ErrorPage from '~/pages/_error'
export default class ErrorBoundary extends React.Component {
constructor(props) {
@ -9,12 +9,12 @@ export default class ErrorBoundary extends React.Component {
}
static getDerivedStateFromError(error){
return {error}
return {error: error || {name: 'Not found', message: 'This page could not be found'}}
}
render() {
if(this.state.error)
return <ErrorDisplay error={this.state.error} />
return <ErrorPage error={this.state.error} />
return this.props.children;
}

@ -1,20 +0,0 @@
const errorMessages = {
404: {title: 'Page not found', message: 'Unfortunately that page could not be found. If you followed a link to get here, please let the owner of the link know that they need to update it.'},
[undefined]: {title: 'Unknown error', message: "We're not exactly sure what happened"}
}
export default function ErrorDisplay({error}){
const defaults = errorMessages[error.status]
return (
<>
<h2>{error.name || defaults.title}</h2>
<p>{error.message || defaults.message}</p>
{process.env.NODE_ENV === 'development' && (
<pre>
{JSON.stringify(error, null, 2)}
</pre>
)}
</>
)
}

@ -22,7 +22,8 @@ class CustomResolver {
'styles',
'hooks',
'components',
'images'
'images',
'pages'
]
// If it's not the right pattern, or it's outside our list of directories
@ -68,7 +69,8 @@ module.exports = withImages({
return config
},
env: {
STRIPE_PUBLIC_KEY: process.env.STRIPE_PUBLIC_KEY
publicRuntimeConfig: {
STRIPE_PUBLIC_KEY: process.env.STRIPE_PUBLIC_KEY,
SOS_ENV: process.env.SOS_ENV
}
})

@ -4,7 +4,7 @@
"description": "",
"main": "index.js",
"scripts": {
"dev": "cross-env NODE_ENV=development node index.js",
"dev": "cross-env NODE_ENV=development SOS_ENV=development node index.js",
"build": "next build",
"start": "cross-env NODE_ENV=production node index.js"
},

@ -20,6 +20,19 @@ Layout.getInitialProps = async ({Component, ctx}) => {
: undefined
})
ctx.axios.interceptors.response.use(res => res,
err => {
if(!err.isAxiosError || !err.response || !err.response.data || !err.response.data.error)
throw err
// Unwrap API error, rethrow that
throw {
...err.response.data.error,
url: err.request.path
}
}
)
const promises = {
user: ctx.axios.get(`/api/auth`),
cart: ctx.axios.get(`/api/cart`)

@ -1,18 +1,49 @@
import React from 'react'
import ErrorDisplay from '~/components/errorDisplay'
import getConfig from 'next/config'
const ErrorPage = ({error}) => (
<ErrorDisplay error={error} />
)
const {publicRuntimeConfig} = getConfig()
ErrorPage.getInitialProps = ({ res, err }) => {
let error = err || {};
const ErrorPage = ({error}) => {
const env = publicRuntimeConfig.SOS_ENV
if (!error)
return (
<>
<h2>Not Found</h2>
<p>This page was not found</p>
</>
)
if(!error)
error = new Error('Server Error')
return (
<>
<h2>{error.name}</h2>
<p>{error.message}</p>
{env === 'development' && (
<>
{error.stack && (
<p>
<pre>
{error.stack}
</pre>
</p>
)}
<p>
<pre>
{JSON.stringify(error, null, 2)}
</pre>
</p>
</>
)}
</>
)
}
ErrorPage.getInitialProps = ({ctx: {err, req, res}}) => {
if(!err) return {error: null}
if(res)
err.status = res.statusCode
error.status = (err && err.status) || (res ? res.statusCode : (error.statusCode || 404))
return { error }
return { error: err }
}
export default ErrorPage

@ -1,13 +1,15 @@
import {useState, useRef} from 'react'
import Link from 'next/link'
import Router from 'next/router'
import getConfig from 'next/config'
import styles from './style.module.css'
import {Input, Button} from '~/components/form'
import useUser from '~/hooks/useUser'
import axios from 'axios'
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(process.env.STRIPE_PUBLIC_KEY);
const { publicRuntimeConfig: {STRIPE_PUBLIC_KEY} } = getConfig()
const stripePromise = loadStripe(STRIPE_PUBLIC_KEY);
import PaypalIcon from '../../../images/icons/paypal.svg'
// TODO: Load previous addresses

Loading…
Cancel
Save