Skip to content

Commit

Permalink
add more info to some errors #331; start documenting obs POST/PUT sch…
Browse files Browse the repository at this point in the history
…ema #332
  • Loading branch information
pleary committed Jul 19, 2022
1 parent 57d4839 commit a8624f4
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 40 deletions.
73 changes: 48 additions & 25 deletions lib/inaturalist_api_v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,18 @@ const InaturalistAPIV2 = class InaturalistAPIV2 {
from: "errorMiddleware"
}]
} );
} );
} ).catch( ( ) => InaturalistAPIV2.renderDefaultError( res, err, status ) );
return;
}
// console.log( "Error trace from errorMiddleware:" );
// if ( req ) {
// console.log( `[DEBUG] Error from request for ${req.path}` );
// }
// console.trace( err );
InaturalistAPIV2.renderDefaultError( res, err, status );
};

static renderDefaultError = ( res, err, status ) => {
res.status( status || 500 ).jsonp( err instanceof Error
? {
status: ( status || 500 ).toString( ),
Expand Down Expand Up @@ -488,7 +491,7 @@ const InaturalistAPIV2 = class InaturalistAPIV2 {
if ( req.userSession ) {
const defaults = await User.localeDefaults( req.userSession.user_id );
if ( defaults ) {
req.userSession = Object.assign( { }, req.userSession, defaults );
req.userSession = { ...req.userSession, ...defaults };
}
if ( req.userSession.isSuspended ) {
const error = new Error( "Unauthorized" );
Expand All @@ -497,7 +500,7 @@ const InaturalistAPIV2 = class InaturalistAPIV2 {
}
}
next( );
}
};

static userJwtValidate = ( req, required ) => {
if ( !req.headers.authorization ) {
Expand All @@ -507,15 +510,16 @@ const InaturalistAPIV2 = class InaturalistAPIV2 {
return Promise.resolve( true );
}
const token = _.last( req.headers.authorization.split( /\s+/ ) );
return jwt.verify( token, config.jwtSecret || "secret",
{ algorithms: ["HS512"] }, ( err, payload ) => {
if ( required === "required" && err ) throw jwtInvalidError;
if ( payload && payload.user_id ) {
req.userSession = payload;
}
return Promise.resolve( true );
} );
}
return jwt.verify( token, config.jwtSecret || "secret", {
algorithms: ["HS512"]
}, ( err, payload ) => {
if ( required === "required" && err ) throw jwtInvalidError;
if ( payload && payload.user_id ) {
req.userSession = payload;
}
return Promise.resolve( true );
} );
};

static applicationJwtValidate = ( req, required ) => {
if ( !req.headers.authorization ) {
Expand All @@ -525,15 +529,16 @@ const InaturalistAPIV2 = class InaturalistAPIV2 {
return Promise.resolve( true );
}
const token = _.last( req.headers.authorization.split( /\s+/ ) );
return jwt.verify( token, config.jwtApplicationSecret || "application_secret",
{ algorithms: ["HS512"] }, ( err, payload ) => {
if ( required === "required" && err ) throw jwtInvalidError;
if ( payload && payload.application ) {
req.applicationSession = payload;
}
return Promise.resolve( true );
} );
}
return jwt.verify( token, config.jwtApplicationSecret || "application_secret", {
algorithms: ["HS512"]
}, ( err, payload ) => {
if ( required === "required" && err ) throw jwtInvalidError;
if ( payload && payload.application ) {
req.applicationSession = payload;
}
return Promise.resolve( true );
} );
};

static initializeOpenapi = inaturalistAPIExpressApp => {
// method override middleware must be defined before initializing openapi
Expand Down Expand Up @@ -592,6 +597,22 @@ const InaturalistAPIV2 = class InaturalistAPIV2 {
// TODO: custom coercion for JSON bodies?
"multipart/form-data": InaturalistAPIV2.multipartMiddleware
},
errorTransformer: ( openapiError, ajvError ) => {
console.log( openapiError );
console.log( ajvError );
const returnedError = {
message: openapiError.message
};
if ( ajvError && ajvError ) {
if ( ajvError.instancePath ) {
returnedError.instancePath = ajvError.instancePath;
}
if ( ajvError.params ) {
returnedError.params = ajvError.params;
}
}
return returnedError;
},
errorMiddleware: InaturalistAPIV2.errorMiddleware
} );

Expand All @@ -613,19 +634,21 @@ const InaturalistAPIV2 = class InaturalistAPIV2 {
// "unsupported," or provide some kind of param that shows these private and
// unsupported endpoints to people who are interested, like developers on
// staff. ~~kueda 20200813
const swaggerApiDoc = Object.assign( {}, initializedOpenapi.apiDoc, {
const swaggerApiDoc = {
...initializedOpenapi.apiDoc,
paths: _.omitBy( initializedOpenapi.apiDoc.paths, ( pathConfig, path ) => path.match( /computervision/ ) ),
tags: _.sortBy(
_.omitBy( initializedOpenapi.apiDoc.tags, tag => tag.name.match( /Computer Vision/ ) ),
tag => tag.name
),
components: Object.assign( {}, initializedOpenapi.apiDoc.components, {
components: {
...initializedOpenapi.apiDoc.components,
schemas: _.omitBy(
initializedOpenapi.apiDoc.components.schemas,
( schema, schemaName ) => schemaName.match( /vision/i )
)
} )
} );
}
};
const swaggerUIMiddleware = swaggerUi.setup( swaggerApiDoc, swaggerOptions );
// temporary fix for swaggerUI loading issues
// See https://github.com/scottie1984/swagger-ui-express/issues/178
Expand Down
52 changes: 37 additions & 15 deletions openapi/schema/request/observations_create.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,40 @@ const Joi = require( "joi" );

module.exports = Joi.object( ).keys( {
fields: Joi.any( ),
observation: Joi.object( ).unknown( true )
// observation: Joi.object( ).keys( {
// species_guess: Joi.string( )
// .description( `
// The name of the organism observed. If the taxon ID is absent, iNat will
// try to choose a single taxon based on this string, but it may fail if
// there's some taxonomic amgiguity."
// ` ),
// taxon_uuid: Joi.string( ).guid( { version: "uuidv4" } )
// .description( `
// UUID of the taxon to associate with this observation. An identification
// for this taxon will automatically be added for the user.
// ` )
// } )
} );
observation: Joi.object( ).keys( {
captive_flag: Joi.boolean( ),
coordinate_system: Joi.string( ),
description: Joi.string( ),
geo_x: Joi.number( ),
geo_y: Joi.number( ),
geoprivacy: Joi.string( ),
latitude: Joi.number( ),
license: Joi.string( ),
location_is_exact: Joi.boolean( ),
longitude: Joi.number( ),
make_license_default: Joi.boolean( ),
make_licenses_same: Joi.boolean( ),
map_scale: Joi.number( ).integer( ),
observation_field_values_attributes: Joi.object( ).keys( {
observation_field_id: Joi.number( ).integer( ).required( ),
value: Joi.any( ).required( )
} ).unknown( false ),
observed_on_string: Joi.string( ),
owners_identification_from_vision: Joi.boolean( ),
place_guess: Joi.string( ),
positional_accuracy: Joi.number( ),
positioning_device: Joi.string( ),
positioning_method: Joi.string( ),
project_id: Joi.number( ).integer( ),
prefers_community_taxon: Joi.boolean( ),
site_id: Joi.number( ).integer( ),
species_guess: Joi.string( )
.description( "The name of the organism observed. If the taxon ID is absent, iNat will "
+ "try to choose a single taxon based on this string, but it may fail if "
+ "there's some taxonomic amgiguity." ),
tag_list: Joi.string( ),
taxon_id: Joi.number( ),
taxon_name: Joi.number( ),
time_zone: Joi.string( )
} ).unknown( false )
} ).unknown( false );

0 comments on commit a8624f4

Please sign in to comment.