From f789f9d1aa27c802f4cb55e282ea0f65ebb35ccd Mon Sep 17 00:00:00 2001 From: Louis Capitanchik <contact@louiscap.co> Date: Wed, 30 Mar 2022 20:37:12 +0100 Subject: [PATCH] Increase range of first party metric types supported --- helm/api/Chart.yaml | 4 +-- package.json | 2 +- src/core/errors/InputValidationError.js | 18 ++++++++++++ src/database/models/Metric.js | 12 ++++++++ src/domain/auth/AuthenticationService.js | 5 +++- src/domain/auth/oidc/DBAdapter.js | 5 +++- src/domain/auth/oidc/OIDCServer.js | 2 +- src/http/controllers/api/content.js | 37 ++++++++++-------------- src/http/middleware/DeviceProperties.js | 6 ++-- src/http/routers/routes_v2.js | 1 + 10 files changed, 61 insertions(+), 31 deletions(-) diff --git a/helm/api/Chart.yaml b/helm/api/Chart.yaml index a072fe4..cdf0ae7 100644 --- a/helm/api/Chart.yaml +++ b/helm/api/Chart.yaml @@ -15,10 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.3.2 +version: 0.3.3 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "2.3.0" +appVersion: "2.4.0" diff --git a/package.json b/package.json index a79e183..c6f5cd0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jetsam-api", - "version": "2.3.0", + "version": "2.4.0", "description": "The Jetsam App API Server", "main": "server.js", "scripts": { diff --git a/src/core/errors/InputValidationError.js b/src/core/errors/InputValidationError.js index 1a97aef..115cb4d 100644 --- a/src/core/errors/InputValidationError.js +++ b/src/core/errors/InputValidationError.js @@ -4,4 +4,22 @@ module.exports = class InputValidationError extends HttpError { constructor(fields) { super(422, 'The supplied input was not valid', { fields }) } + + toJSON() { + return { + status: this._status, + message: this._message, + ...this._payload, + } + } + + respondTo(ctx) { + ctx.status = this._status + ctx.body = { + errors: { + general: [this._message], + ...this._payload, + } + } + } } diff --git a/src/database/models/Metric.js b/src/database/models/Metric.js index a47f28a..d19aadd 100644 --- a/src/database/models/Metric.js +++ b/src/database/models/Metric.js @@ -4,6 +4,18 @@ const BaseModel = require('./BaseModel') const metricConversionMap = { trash: Number, numeric: Number, + 'pm2.5': Number, + co2_ppm: Number, + wind_mph: Number, + wind_kph: Number, + temp_c: Number, + temp_f: Number, + temp_k: Number, + pressure_pa: Number, + pressure_mbar: Number, + rain_mm: Number, + custom_string: String, + custom_number: Number, } class Metric extends BaseModel { diff --git a/src/domain/auth/AuthenticationService.js b/src/domain/auth/AuthenticationService.js index 6ad4ea3..57d17f8 100644 --- a/src/domain/auth/AuthenticationService.js +++ b/src/domain/auth/AuthenticationService.js @@ -77,8 +77,11 @@ module.exports = class AuthenticationService extends ContextualModule { } if (accessToken == null) { - console.log('oidc token', token) accessToken = await this.ctx.services['auth.oidc'].withProvider(provider => provider.AccessToken.find(token)) + if (accessToken) { + const user = await User.findByPk(accessToken.accountId) + accessToken.User = user + } } else { if (accessToken?.User) { this.authenticateAs(accessToken.User, 'oauth_token', accessToken) diff --git a/src/domain/auth/oidc/DBAdapter.js b/src/domain/auth/oidc/DBAdapter.js index baf2d70..797fa27 100644 --- a/src/domain/auth/oidc/DBAdapter.js +++ b/src/domain/auth/oidc/DBAdapter.js @@ -2,7 +2,9 @@ const moment = require('moment') const { OIDCEntity, User, OAuthClient, AccessToken, RefreshToken, sequelize, Sequelize } = require('database/models') const debug = require('debug')('server:auth:oidc:adapter') -const key = (id, name) => `urn:jetsam:resources:oidc:${name}/${id}` +const key = (id, name) => { + return `urn:jetsam:resources:oidc:${name}/${id}`; +} class DBAdapter { constructor(name, { model = OIDCEntity } = {}) { @@ -16,6 +18,7 @@ class DBAdapter { const oidc = await this.model.upsert({ id: key(id, this.name), grant_id: data.grantId ?? null, + related_user_id: data.accountId ?? null, user_code: data.user_code ?? null, uid: data.uid ?? null, data, diff --git a/src/domain/auth/oidc/OIDCServer.js b/src/domain/auth/oidc/OIDCServer.js index 0c59af7..1d5fe26 100644 --- a/src/domain/auth/oidc/OIDCServer.js +++ b/src/domain/auth/oidc/OIDCServer.js @@ -8,7 +8,7 @@ module.exports = async function createOIDCServer() { const {validScopes} = require("../OAuthFlow"); debug(`Creating OIDC Provider with base ${config('app.host.web')}`) - const provider = new Provider( /*config('app.host.web') + 'oidc/' */ 'http://trash.4l2.uk/oidc/', { + const provider = new Provider(config('app.host.web') + 'oidc/', { clients: [ { client_id: 'kbyuFDidLLm280LIwVFiazOqjO3ty8KH', diff --git a/src/http/controllers/api/content.js b/src/http/controllers/api/content.js index 0bf47a9..5db0f4c 100644 --- a/src/http/controllers/api/content.js +++ b/src/http/controllers/api/content.js @@ -2,6 +2,7 @@ const HttpError = require('core/errors/HttpError') const { Sequelize, sequelize, Metric } = require('database/models') const { Op } = Sequelize const moment = require('moment') +const InputValidationError = require("../../../core/errors/InputValidationError"); exports.postMetric = async ctx => { const allowedTypes = new Set(Metric.getSupportedMetricTypes()) @@ -20,19 +21,16 @@ exports.postMetric = async ctx => { transaction: t, ctx, }) - metrics.push(result) } }) } catch (e) { console.log(e) - - throw new HttpError({ - status: 400, - code: 'MTR-001', - title: 'Failed to save metric', - description: 'Something went wrong trying to save the metric', - }) + if (e instanceof HttpError) { + throw e + } else { + throw new HttpError(500, 'Failed to save metric') + } } ctx.body = { @@ -56,12 +54,7 @@ const save = async ( location.longitude == null || location.latitude == null ) { - throw new HttpError({ - status: 400, - code: 'MTR-001', - title: 'Invalid Metric', - description: 'A location must be provided for metrics', - }) + throw new HttpError(422, 'A location must be provided for metrics') } if (allowedTypes.has(type)) { @@ -73,12 +66,7 @@ const save = async ( transaction, ) } else { - throw new HttpError({ - status: 400, - code: 'MTR-002', - title: 'Invalid Metric', - description: `${type} is not a supported type`, - }) + throw new HttpError(422, `${type} is not a supported type`) } } @@ -134,7 +122,13 @@ exports.getWithin = async ctx => { format = 'full', } = ctx.request.query - const pointBufferData = within ? bufferFromPolygon(within) : bufferFromCorners(point_from, point_to) + let pointBufferData = null + + try { + pointBufferData = within ? bufferFromPolygon(within) : bufferFromCorners(point_from, point_to) + } catch (e) { + throw new InputValidationError(['within', 'point_from', 'point_to']) + } const pointBuffer = pointBufferData.map(pb => pb.map(Number).join(' ')).join(',') const fromDate = moment.utc(date_from) @@ -142,7 +136,6 @@ exports.getWithin = async ctx => { const metricTypes = splitString(types) - const query = format === 'marker' ? ctx.services['data.metrics'].queryAggregate diff --git a/src/http/middleware/DeviceProperties.js b/src/http/middleware/DeviceProperties.js index ae8f957..cbe1fee 100644 --- a/src/http/middleware/DeviceProperties.js +++ b/src/http/middleware/DeviceProperties.js @@ -1,7 +1,7 @@ exports.extractDevice = async (ctx, next) => { - const deviceId = ctx.get('x-request-device') - const platform = ctx.get('x-request-platform') - const rawSlug = ctx.get('x-request-slug') + const deviceId = ctx.get('x-request-device') || ctx.get('Request-Device') + const platform = ctx.get('x-request-platform') || ctx.get('Request-Platform') + const rawSlug = ctx.get('x-request-slug') || ctx.get('Request-Info') const slug = rawSlug ? Buffer.from(rawSlug, 'base64').toString('utf-8') : null diff --git a/src/http/routers/routes_v2.js b/src/http/routers/routes_v2.js index 7c4683d..5e1c911 100644 --- a/src/http/routers/routes_v2.js +++ b/src/http/routers/routes_v2.js @@ -22,6 +22,7 @@ router.get( ctx => (ctx.body = { name: 'Jetsam Data API', + version: require('../../../package.json').version, prefix: ctx.path, }), ) -- GitLab