Skip to content

Commit

Permalink
Moving read-only geo points out of geo author, leaving metadata endpo…
Browse files Browse the repository at this point in the history
…ints. (#321)
  • Loading branch information
janedotx authored May 15, 2020
1 parent 0b37ca8 commit 3da8ad0
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 536 deletions.
106 changes: 21 additions & 85 deletions packages/mds-geography-author/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ import {
import { geographyValidationDetails } from '@mds-core/mds-schema-validators'
import logger from '@mds-core/mds-logger'

import { checkAccess, AccessTokenScopeValidator } from '@mds-core/mds-api-server'
import { checkAccess, AccessTokenScopeValidator, ApiResponse, ApiRequest } from '@mds-core/mds-api-server'
import { GeographyAuthorApiVersionMiddleware } from './middleware'
import {
GeographyAuthorApiRequest,
GeographyAuthorApiAccessTokenScopes,
GetGeographyMetadataResponse,
GetGeographyResponse,
GetGeographiesResponse,
DeleteGeographyResponse,
PostGeographyResponse,
PutGeographyResponse,
Expand All @@ -40,7 +38,7 @@ function api(app: express.Express): express.Express {
checkGeographyAuthorApiAccess(scopes => {
return scopes.includes('geographies:read:published') || scopes.includes('geographies:read:unpublished')
}),
async (req: GeographyAuthorApiRequest, res: GetGeographyMetadataResponse) => {
async (req: GeographyAuthorApiRequest, res: GetGeographyMetadataResponse, next: express.NextFunction) => {
const { scopes } = res.locals
const { get_published, get_unpublished } = req.query
const params = {
Expand Down Expand Up @@ -85,82 +83,15 @@ function api(app: express.Express): express.Express {
if (error instanceof InsufficientPermissionsError) {
return res.status(403).send({ error })
}
return res.status(500).send({ error })
}
}
)

app.get(
pathsFor('/geographies/:geography_id'),
checkGeographyAuthorApiAccess(scopes => {
return scopes.includes('geographies:read:published') || scopes.includes('geographies:read:unpublished')
}),
async (req: GeographyAuthorApiRequest, res: GetGeographyResponse) => {
const { geography_id } = req.params
try {
const geography = await db.readSingleGeography(geography_id)
if (!geography.publish_date && !res.locals.scopes.includes('geographies:read:unpublished')) {
throw new InsufficientPermissionsError('permission to read unpublished geographies missing')
}
return res.status(200).send({ version: res.locals.version, geography })
} catch (err) {
logger.error('failed to read geography', err.stack)
if (err instanceof NotFoundError) {
return res.status(404).send({ error: err })
}

if (err instanceof InsufficientPermissionsError) {
return res.status(403).send({ error: err })
}

return res.status(500).send({ error: new ServerError() })
}
}
)

app.get(
pathsFor('/geographies'),
checkGeographyAuthorApiAccess(scopes => {
return scopes.includes('geographies:read:published') || scopes.includes('geographies:read:unpublished')
}),
async (req: GeographyAuthorApiRequest, res: GetGeographiesResponse) => {
const summary = req.query.summary === 'true'
const { get_published, get_unpublished } = req.query
const params = {
get_published: get_published ? get_published === 'true' : null,
get_unpublished: get_unpublished ? get_unpublished === 'true' : null
}

try {
if (!res.locals.scopes.includes('geographies:read:unpublished') && params.get_unpublished) {
throw new InsufficientPermissionsError(
'Cannot require unpublished geos without geography:read:unpublished scope'
)
}

const geographies = summary ? await db.readGeographySummaries(params) : await db.readGeographies(params)
if (!res.locals.scopes.includes('geographies:read:unpublished')) {
const filteredGeos = geographies.filter(geo => !!geo.publish_date)
return res.status(200).send({ version: res.locals.version, geographies: filteredGeos })
}
return res.status(200).send({ version: res.locals.version, geographies })
} catch (error) {
/* We don't throw a NotFoundError if the number of results is zero, so the error handling
* doesn't need to consider it here.
*/
if (error instanceof InsufficientPermissionsError) {
return res.status(403).send({ error })
}
logger.error('failed to read geographies', error.stack)
return res.status(500).send({ error: new ServerError() })
return next(new ServerError())
}
}
)

app.post(
pathsFor('/geographies/'),
checkGeographyAuthorApiAccess(scopes => scopes.includes('geographies:write')),
async (req: GeographyAuthorApiRequest, res: PostGeographyResponse) => {
async (req: GeographyAuthorApiRequest, res: PostGeographyResponse, next: express.NextFunction) => {
const geography = req.body

try {
Expand All @@ -183,15 +114,15 @@ function api(app: express.Express): express.Express {
}
/* istanbul ignore next */
/* istanbul ignore next */
return res.status(500).send({ error: err })
return next(new ServerError(err))
}
}
)

app.put(
pathsFor('/geographies/:geography_id'),
checkGeographyAuthorApiAccess(scopes => scopes.includes('geographies:write')),
async (req: GeographyAuthorApiRequest, res: PutGeographyResponse) => {
async (req: GeographyAuthorApiRequest, res: PutGeographyResponse, next: express.NextFunction) => {
const geography = req.body
try {
const details = geographyValidationDetails(geography)
Expand All @@ -208,15 +139,15 @@ function api(app: express.Express): express.Express {
if (error instanceof ValidationError) {
return res.status(400).send({ error })
}
return res.status(500).send({ error })
return next(new ServerError())
}
}
)

app.delete(
pathsFor('/geographies/:geography_id'),
checkGeographyAuthorApiAccess(scopes => scopes.includes('geographies:write')),
async (req: GeographyAuthorApiRequest, res: DeleteGeographyResponse) => {
async (req: GeographyAuthorApiRequest, res: DeleteGeographyResponse, next: express.NextFunction) => {
const { geography_id } = req.params
try {
const isPublished = await db.isGeographyPublished(geography_id)
Expand Down Expand Up @@ -245,7 +176,7 @@ function api(app: express.Express): express.Express {
if (err instanceof AlreadyPublishedError) {
return res.status(405).send({ error: err })
}
return res.status(500).send({ error: err })
return next(new ServerError())
}
}
)
Expand All @@ -255,7 +186,7 @@ function api(app: express.Express): express.Express {
checkGeographyAuthorApiAccess(scopes => {
return scopes.includes('geographies:read:published') || scopes.includes('geographies:read:unpublished')
}),
async (req: GeographyAuthorApiRequest, res: GetGeographyMetadatumResponse) => {
async (req: GeographyAuthorApiRequest, res: GetGeographyMetadatumResponse, next: express.NextFunction) => {
const { geography_id } = req.params
try {
const geography_metadata = await db.readSingleGeographyMetadata(geography_id)
Expand All @@ -272,15 +203,15 @@ function api(app: express.Express): express.Express {
if (err instanceof InsufficientPermissionsError) {
return res.status(403).send({ error: err })
}
return res.status(500).send({ error: new ServerError() })
return next(new ServerError())
}
}
)

app.put(
pathsFor('/geographies/:geography_id/meta'),
checkGeographyAuthorApiAccess(scopes => scopes.includes('geographies:write')),
async (req: GeographyAuthorApiRequest, res: PutGeographyMetadataResponse) => {
async (req: GeographyAuthorApiRequest, res: PutGeographyMetadataResponse, next: express.NextFunction) => {
const geography_metadata = req.body
try {
await db.updateGeographyMetadata(geography_metadata)
Expand All @@ -295,10 +226,10 @@ function api(app: express.Express): express.Express {
if (writeErr instanceof DependencyMissingError) {
return res.status(404).send({ error: writeErr })
}
return res.status(500).send({ error: new ServerError() })
return next(new ServerError())
}
} else {
return res.status(500).send({ error: new ServerError() })
return next(new ServerError(updateErr))
}
}
}
Expand All @@ -307,7 +238,7 @@ function api(app: express.Express): express.Express {
app.put(
pathsFor('/geographies/:geography_id/publish'),
checkGeographyAuthorApiAccess(scopes => scopes.includes('geographies:publish')),
async (req: GeographyAuthorApiRequest, res: PutGeographyResponse) => {
async (req: GeographyAuthorApiRequest, res: PutGeographyResponse, next: express.NextFunction) => {
const { geography_id } = req.params
try {
await db.publishGeography({ geography_id })
Expand All @@ -317,11 +248,16 @@ function api(app: express.Express): express.Express {
if (updateErr instanceof NotFoundError) {
return res.status(404).send({ error: `unable to find geography of ${geography_id}` })
}
return res.status(500).send({ error: new ServerError() })
return next(new ServerError(updateErr))
}
}
)

app.use(async (error: Error, req: ApiRequest, res: ApiResponse) => {
await logger.error(req.method, req.originalUrl, error)
return res.status(500).send({ error })
})

return app
}

Expand Down
Loading

0 comments on commit 3da8ad0

Please sign in to comment.