Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send timezone country code on create site #591

Merged
merged 4 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 1.3.9 (2024-04-xx)
### Common
* **core**: `GET /detections` return `Total-items` in response headers
* **core**: Include `timezone` and `country_code` when create site on Arbimon

### Bug Fixes
* **core**: Fix update only stream name also set default to timezone and country code
Expand Down
2 changes: 1 addition & 1 deletion core/_services/arbimon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function updateProject (opts, idToken) {

function createSite (stream, idToken) {
const body = {};
['name', 'latitude', 'longitude', 'altitude', 'hidden'].forEach((attr) => { body[attr] = stream[attr] })
['name', 'latitude', 'longitude', 'altitude', 'hidden', 'timezone', 'country_code'].forEach((attr) => { body[attr] = stream[attr] })
body.external_id = stream.id
if (!body.altitude) {
body.altitude = 0
Expand Down
64 changes: 64 additions & 0 deletions core/streams/bl/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const arbimonService = require('../../_services/arbimon')
const { randomId } = require('../../../common/crypto/random')
const { ValidationError } = require('../../../common/error-handling/errors')
const dao = require('../dao')

/**
* Create Stream
* @param {Stream} stream
* @param {string} stream.id
* @param {string} stream.name
* @param {integer} stream.latitude
* @param {integer} stream.longitude
* @param {integer} stream.altitude
* @param {string} stream.description
* @param {boolean} stream.is_public
* @param {integer} stream.external_id
* @param {string} stream.project_id
* @param {boolean} stream.hidden
* @param {*} options
* @param {number} options.creatableBy Create only if site is creatable by the given user id
* @param {string} options.requestSource Whether the request was sent from the Arbimon or not
* @param {string} options.idToken user jwt token
*/
async function create (params, options = {}) {
const stream = {
...params
}

if (!params.id) {
stream.id = randomId()
}

if (params.latitude === 0) {
stream.latitude = null
}

if (params.longitude === 0) {
stream.longitude = null
}

if (params.projectId) {
const duplicateStreamInProject = await dao.query({ names: [params.name], projects: [params.projectId] }, { fields: 'id' })
if (duplicateStreamInProject.total > 0) {
throw new ValidationError('Duplicate stream name in the project')
}
}
// Get timezone and countryCode for Arbimon
const fullStream = { ...stream, ...(await dao.computedAdditions(stream)) }
if (arbimonService.isEnabled && options.requestSource !== 'arbimon') {
try {
const arbimonSite = { ...fullStream, country_code: fullStream.countryCode }
const externalSite = await arbimonService.createSite(arbimonSite, options.idToken)
fullStream.externalId = externalSite.site_id
} catch (error) {
console.error(`Error creating site in Arbimon (stream: ${fullStream.id})`)
throw new Error()
}
}
return await dao.create(fullStream, options)
}

module.exports = {
create
}
11 changes: 11 additions & 0 deletions core/streams/create.int.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ describe('POST /streams', () => {
latitude: 10.123,
longitude: 101.456
}
const mockCountry = jest.spyOn(googleMap, 'getCountry')
mockCountry.mockReturnValueOnce({
data: {
results: []
}
})
const mockTimezone = jest.spyOn(googleMap, 'getTimezone')
mockTimezone.mockReturnValueOnce({
data: {}
})

const response = await request(app).post('/').send(requestBody)

expect(response.statusCode).toBe(500)
Expand Down
52 changes: 8 additions & 44 deletions core/streams/create.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
const { httpErrorHandler } = require('../../common/error-handling/http')
const dao = require('./dao')
const { randomId } = require('../../common/crypto/random')
const Converter = require('../../common/converter')
const arbimonService = require('../_services/arbimon')
const { ValidationError } = require('../../common/error-handling/errors')
const { create } = require('./bl')

/**
* @swagger
Expand Down Expand Up @@ -36,6 +33,10 @@ const { ValidationError } = require('../../common/error-handling/errors')
*/
module.exports = (req, res) => {
const user = req.rfcx.auth_token_info
const creatableBy = user.is_super || user.has_system_role ? undefined : user.id
const requestSource = req.headers.source
const idToken = req.headers.authorization
const options = { creatableBy, requestSource, idToken }
const converter = new Converter(req.body, {}, true)
converter.convert('id').optional().toString().minLength(12).maxLength(12).isPassingRegExp(/[a-z0-9]{12}/, 'should have only lowercase characters and integers')
converter.convert('name').toString()
Expand All @@ -50,46 +51,9 @@ module.exports = (req, res) => {

return converter.validate()
.then(async (params) => {
const stream = {
...params,
createdById: user.id
}
if (!params.id) {
stream.id = randomId()
}

if (params.latitude === 0) {
stream.latitude = null
}

if (params.longitude === 0) {
stream.longitude = null
}

if (params.projectId) {
const duplicateStreamInProject = await dao.query({ names: [params.name], projects: [params.projectId] }, { fields: 'id' })
if (duplicateStreamInProject.total > 0) {
throw new ValidationError('Duplicate stream name in the project')
}
}

// TODO move - route handler should not contain business logic
if (arbimonService.isEnabled && req.headers.source !== 'arbimon') {
try {
const externalSite = await arbimonService.createSite(stream, req.headers.authorization)
stream.externalId = externalSite.site_id
} catch (error) {
console.error(`Error creating site in Arbimon (stream: ${stream.id})`)
throw new Error()
}
}

const options = {
creatableBy: (user.is_super || user.has_system_role) ? undefined : user.id
}
const createdStream = await dao.create(stream, options)

return res.location(`/streams/${createdStream.id}`).sendStatus(201)
params.createdById = user.id
return await create(params, options)
})
.then(stream => res.location(`/streams/${stream.id}`).sendStatus(201))
.catch(httpErrorHandler(req, res, 'Failed creating stream'))
}
7 changes: 6 additions & 1 deletion core/streams/dao/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ async function get (idOrWhere, options = {}) {
* @param {*} options
*/
async function create (stream, options = {}) {
const fullStream = { ...stream, ...(await computedAdditions(stream)) }
let additionals = {}
// If timezone and countryCode already existing in stream blob then no need to get them again
if (!stream.timezone && !stream.countryCode) {
additionals = await computedAdditions(stream)
}
const fullStream = { ...stream, ...additionals }
if (fullStream.projectId && options.creatableBy && !(await hasPermission(UPDATE, options.creatableBy, fullStream.projectId, PROJECT))) {
throw new ForbiddenError()
}
Expand Down
Loading