mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-03 01:41:05 -05:00
Validate broadcast against schema
This commit adds a JSONSchema which can validate the fields in an API call to create a broadcast. It takes the CAP XML schema as a starting point.
This commit is contained in:
97
app/v2/broadcast/broadcast_schemas.py
Normal file
97
app/v2/broadcast/broadcast_schemas.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
post_broadcast_schema = {
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"reference",
|
||||||
|
"category",
|
||||||
|
"content",
|
||||||
|
"areas",
|
||||||
|
],
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {
|
||||||
|
"reference": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Geo",
|
||||||
|
"Met",
|
||||||
|
"Safety",
|
||||||
|
"Security",
|
||||||
|
"Rescue",
|
||||||
|
"Fire",
|
||||||
|
"Health",
|
||||||
|
"Env",
|
||||||
|
"Transport",
|
||||||
|
"Infra",
|
||||||
|
"CBRNE",
|
||||||
|
"Other",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"expires": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 1395,
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri",
|
||||||
|
},
|
||||||
|
"areas": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/area",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"area": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"polygons",
|
||||||
|
],
|
||||||
|
"additionalProperties": False,
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"polygons": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/polygon",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"polygon": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 4,
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/coordinatePair",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"coordinatePair": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"minItems": 2,
|
||||||
|
"maxItems": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
|
from itertools import chain
|
||||||
from flask import jsonify, request
|
from flask import jsonify, request
|
||||||
from app import authenticated_service, api_user
|
from app import authenticated_service, api_user
|
||||||
from app.dao.dao_utils import dao_save_object
|
from app.dao.dao_utils import dao_save_object
|
||||||
from app.notifications.validators import check_service_has_permission
|
from app.notifications.validators import check_service_has_permission
|
||||||
from app.models import BROADCAST_TYPE, BroadcastMessage, BroadcastStatusType
|
from app.models import BROADCAST_TYPE, BroadcastMessage, BroadcastStatusType
|
||||||
|
from app.schema_validation import validate
|
||||||
from app.v2.broadcast import v2_broadcast_blueprint
|
from app.v2.broadcast import v2_broadcast_blueprint
|
||||||
|
from app.v2.broadcast.broadcast_schemas import post_broadcast_schema
|
||||||
|
|
||||||
|
|
||||||
@v2_broadcast_blueprint.route("", methods=['POST'])
|
@v2_broadcast_blueprint.route("", methods=['POST'])
|
||||||
@@ -14,15 +17,19 @@ def create_broadcast():
|
|||||||
authenticated_service.permissions,
|
authenticated_service.permissions,
|
||||||
)
|
)
|
||||||
|
|
||||||
request_json = request.get_json()
|
broadcast_json = validate(request.get_json(), post_broadcast_schema)
|
||||||
|
|
||||||
broadcast_message = BroadcastMessage(
|
broadcast_message = BroadcastMessage(
|
||||||
service_id=authenticated_service.id,
|
service_id=authenticated_service.id,
|
||||||
content=request_json['content'],
|
content=broadcast_json['content'],
|
||||||
reference=request_json['reference'],
|
reference=broadcast_json['reference'],
|
||||||
areas={
|
areas={
|
||||||
"areas": [],
|
'areas': [
|
||||||
"simple_polygons": request_json['polygons'],
|
area['name'] for area in broadcast_json['areas']
|
||||||
|
],
|
||||||
|
'simple_polygons': list(chain.from_iterable((
|
||||||
|
area['polygons'] for area in broadcast_json['areas']
|
||||||
|
)))
|
||||||
},
|
},
|
||||||
status=BroadcastStatusType.PENDING_APPROVAL,
|
status=BroadcastStatusType.PENDING_APPROVAL,
|
||||||
api_key_id=api_user.id,
|
api_key_id=api_user.id,
|
||||||
|
|||||||
@@ -32,9 +32,15 @@ def test_valid_post_broadcast_returns_201(
|
|||||||
data=json.dumps({
|
data=json.dumps({
|
||||||
'content': 'This is a test',
|
'content': 'This is a test',
|
||||||
'reference': 'abc123',
|
'reference': 'abc123',
|
||||||
'polygons': [[
|
'category': 'Other',
|
||||||
[1, 2], [3, 4], [5, 6],
|
'areas': [
|
||||||
]],
|
{
|
||||||
|
'name': 'Borchester Downs',
|
||||||
|
'polygons': [[
|
||||||
|
[1, 2], [3, 4], [5, 6], [1, 2],
|
||||||
|
]],
|
||||||
|
},
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
headers=[('Content-Type', 'application/json'), auth_header],
|
headers=[('Content-Type', 'application/json'), auth_header],
|
||||||
)
|
)
|
||||||
@@ -45,7 +51,9 @@ def test_valid_post_broadcast_returns_201(
|
|||||||
|
|
||||||
assert response_json['approved_at'] is None
|
assert response_json['approved_at'] is None
|
||||||
assert response_json['approved_by_id'] == None
|
assert response_json['approved_by_id'] == None
|
||||||
assert response_json['areas'] == []
|
assert response_json['areas'] == [
|
||||||
|
'Borchester Downs'
|
||||||
|
]
|
||||||
assert response_json['cancelled_at'] == None
|
assert response_json['cancelled_at'] == None
|
||||||
assert response_json['cancelled_by_id'] == None
|
assert response_json['cancelled_by_id'] == None
|
||||||
assert response_json['content'] == 'This is a test'
|
assert response_json['content'] == 'This is a test'
|
||||||
@@ -56,7 +64,9 @@ def test_valid_post_broadcast_returns_201(
|
|||||||
assert response_json['id'] == ANY
|
assert response_json['id'] == ANY
|
||||||
assert response_json['personalisation'] is None
|
assert response_json['personalisation'] is None
|
||||||
assert response_json['service_id'] == str(sample_broadcast_service.id)
|
assert response_json['service_id'] == str(sample_broadcast_service.id)
|
||||||
assert response_json['simple_polygons'] == [[[1, 2], [3, 4], [5, 6]]]
|
assert response_json['simple_polygons'] == [
|
||||||
|
[[1, 2], [3, 4], [5, 6], [1, 2],]
|
||||||
|
]
|
||||||
assert response_json['starts_at'] is None
|
assert response_json['starts_at'] is None
|
||||||
assert response_json['status'] == 'pending-approval'
|
assert response_json['status'] == 'pending-approval'
|
||||||
assert response_json['template_id'] is None
|
assert response_json['template_id'] is None
|
||||||
|
|||||||
Reference in New Issue
Block a user