better client error handling on API calls.

This commit is contained in:
fiatjaf 2018-09-02 14:40:50 +00:00
parent 203387074a
commit 5279698fee
5 changed files with 75 additions and 28 deletions

View File

@ -149,7 +149,6 @@ def delete(hashid):
# check that this request came from user dashboard to prevent XSS and CSRF
referrer = referrer_to_baseurl(request.referrer)
service = referrer_to_baseurl(settings.SERVICE_URL)
if referrer != service:
return jsonerror(400, {'error': 'Improper request.'})

View File

@ -5,6 +5,7 @@ const isValidUrl = require('valid-url').isWebUri
const isValidEmail = require('is-valid-email')
const React = require('react')
const toastr = window.toastr
const fetch = window.fetch
const modals = require('../modals')
@ -208,7 +209,7 @@ module.exports = class CreateForm extends React.Component {
e.preventDefault()
try {
let r = await (await fetch(`/api-int/forms/sitewide-check`, {
let resp = await fetch(`/api-int/forms/sitewide-check`, {
method: 'POST',
body: JSON.stringify({email: this.state.email, url: this.state.url}),
credentials: 'same-origin',
@ -216,9 +217,10 @@ module.exports = class CreateForm extends React.Component {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})).json()
})
let r = await resp.json()
if (!r.ok) {
if (!resp.ok || !r.ok) {
toastr.warning("The verification file wasn't found.")
this.setState({verified: false, disableVerification: true})
@ -232,7 +234,9 @@ module.exports = class CreateForm extends React.Component {
this.setState({verified: true})
} catch (e) {
console.error(e)
toastr.error(e.message)
toastr.error(
'Failed to call the sitewide verification API, see the console for more details.'
)
}
}
@ -240,7 +244,7 @@ module.exports = class CreateForm extends React.Component {
e.preventDefault()
try {
let r = await (await fetch('/api-int/forms', {
let resp = await fetch('/api-int/forms', {
method: 'POST',
body: JSON.stringify({
email: this.state.email,
@ -252,13 +256,23 @@ module.exports = class CreateForm extends React.Component {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})).json()
})
let r = await resp.json()
if (!r.ok || r.error) {
toastr.warning(
r.error
? `Error creating form: ${r.error}`
: 'Unexpected error creating form.'
)
return
}
toastr.success('Form created!')
this.props.history.push(`/forms/${r.hashid}`)
} catch (e) {
console.error(e)
toastr.error(e.message)
toastr.error('Failed to create form, see the console for more details.')
}
}
}

View File

@ -1,5 +1,7 @@
/** @format */
const toastr = window.toastr
const fetch = window.fetch
const React = require('react')
const cs = require('class-set')
const {Link} = require('react-router-dom')
@ -22,10 +24,15 @@ module.exports = class FormList extends React.Component {
async componentDidMount() {
try {
let r = await (await fetch('/api-int/forms', {
let resp = await fetch('/api-int/forms', {
credentials: 'same-origin',
headers: {Accept: 'application/json'}
})).json()
})
let r = await resp.json()
if (!resp.ok || r.error) {
throw new Error(r.error || '')
}
this.setState({
user: r.user,
@ -36,6 +43,9 @@ module.exports = class FormList extends React.Component {
} catch (e) {
console.error(e)
this.setState({error: e.message})
toastr.error(
'Failed to fetch your forms. See the console for more details.'
)
}
}
@ -174,7 +184,7 @@ class FormItem extends React.Component {
{form.email}
</td>
<td className="n-submissions" data-label="Submissions counter">
{form.counter == 0 ? (
{form.counter === 0 ? (
<Link
to={`/forms/${form.hashid}/integrations`}
className="no-underline"

View File

@ -1,6 +1,7 @@
/** @format */
const toastr = window.toastr
const fetch = window.fetch
const React = require('react')
const {Route, Link, NavLink, Redirect} = require('react-router-dom')
const CodeMirror = require('react-codemirror2')
@ -99,10 +100,18 @@ module.exports = class FormPage extends React.Component {
let hashid = this.props.match.params.hashid
try {
let r = await (await fetch(`/api-int/forms/${hashid}`, {
let resp = await fetch(`/api-int/forms/${hashid}`, {
credentials: 'same-origin',
headers: {Accept: 'application/json'}
})).json()
})
let r = await resp.json()
if (!resp.ok || r.error) {
toastr.warning(
r.error ? `Error fetching form: ${r.error}` : 'Error fetching form.'
)
return
}
this.setState({form: r})
} catch (e) {
@ -273,17 +282,22 @@ class FormSubmissions extends React.Component {
let subid = e.currentTarget.dataset.sub
try {
let r = await (await fetch(
let resp = await fetch(
`/api-int/forms/${this.props.form.hashid}/submissions/${subid}`,
{
method: 'DELETE',
credentials: 'same-origin',
headers: {Accept: 'application/json'}
}
)).json()
)
let r = await resp.json()
if (r.error) {
toastr.warning(`Failed to delete submission: ${r.error}`)
if (!resp.ok || r.error) {
toastr.warning(
r.error
? `Failed to delete submission: ${r.error}`
: `Failed to delete submission.`
)
return
}
@ -461,7 +475,7 @@ class FormSettings extends React.Component {
async update(e) {
try {
let res = await (await fetch(`/api-int/forms/${this.props.form.hashid}`, {
let resp = await fetch(`/api-int/forms/${this.props.form.hashid}`, {
method: 'PATCH',
body: JSON.stringify({
[e.currentTarget.name]: !e.currentTarget.checked
@ -471,10 +485,15 @@ class FormSettings extends React.Component {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})).json()
})
let r = await resp.json()
if (res.error) {
toastr.warning(`Failed to save settings: ${res.error}`)
if (!resp.ok || r.error) {
toastr.warning(
r.error
? `Failed to save settings: ${r.error}`
: 'Failed to save settings.'
)
return
}
@ -503,16 +522,21 @@ class FormSettings extends React.Component {
this.setState({deleting: false})
try {
let res = await (await fetch(`/api-int/forms/${this.props.form.hashid}`, {
let resp = await fetch(`/api-int/forms/${this.props.form.hashid}`, {
method: 'DELETE',
credentials: 'same-origin',
headers: {
Accept: 'application/json'
}
})).json()
})
let r = await resp.json()
if (res.error) {
toastr.warning(`Failed to delete form: ${res.error}`)
if (resp.error || r.error) {
toastr.warning(
r.error
? `failed to delete form: ${r.error}`
: 'failed to delete form.'
)
return
}

View File

@ -22,9 +22,9 @@
]
},
"devDependencies": {
"@babel/core": "^7.0.0-rc.1",
"@babel/preset-env": "^7.0.0-rc.1",
"@babel/preset-react": "^7.0.0-rc.1",
"@babel/core": "7.0.0-rc.1",
"@babel/preset-env": "7.0.0-rc.1",
"@babel/preset-react": "7.0.0-rc.1",
"babelify": "^9.0.0",
"browserify": "^16.2.2",
"envify": "^4.1.0",