Skip to content

Commit 4d0f04c

Browse files
committed
add validator page and api route
1 parent 1d4f1dc commit 4d0f04c

File tree

8 files changed

+656
-53
lines changed

8 files changed

+656
-53
lines changed

app/api_schemas.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
from enum import Enum as PyEnum
2+
import os
3+
import json
24

35
from apiflask import Schema, validators
4-
from apiflask.fields import UUID, Boolean, DateTime, Dict, Enum, Integer, List, String
6+
from apiflask.fields import (
7+
UUID,
8+
Boolean,
9+
DateTime,
10+
Dict,
11+
Enum,
12+
Integer,
13+
List,
14+
String,
15+
URL,
16+
)
17+
import marshmallow
18+
from marshmallow import ValidationError, validate
519

620
from shared.constants import (
721
ACTION_VALUES,
@@ -14,6 +28,8 @@
1428
SOURCE_TYPE_VALUES,
1529
)
1630

31+
IS_PROD = os.getenv("FLASK_ENV") == "production"
32+
1733

1834
def _to_enum(name, values):
1935
"""Make an iterable of values into a Python enum.
@@ -117,3 +133,57 @@ class SourceInfo(Schema):
117133
source_type = Enum(SOURCE_TYPE_ENUM, required=True)
118134
notification_frequency = Enum(NOTIFICATION_FREQUENCY_ENUM, required=True)
119135
collection_parent_url = String()
136+
137+
138+
class ValidatorInfo(Schema):
139+
schema = String(
140+
required=True,
141+
validate=validators.OneOf(
142+
[
143+
"dcatus1.1: federal dataset",
144+
"dcatus1.1: non-federal dataset",
145+
]
146+
),
147+
)
148+
fetch_method = String(
149+
required=True,
150+
validate=validators.OneOf(
151+
[
152+
"url",
153+
"paste",
154+
]
155+
),
156+
)
157+
url = URL(require_tld=IS_PROD)
158+
159+
@marshmallow.validates_schema
160+
def validate_url(self, data, **kwargs):
161+
if data.get("fetch_method") == "url" and not data.get("url"):
162+
raise ValidationError("'url' field is required when fetch_method is 'url'")
163+
164+
json_text = String()
165+
166+
@marshmallow.validates_schema
167+
def validate_json_text(self, data, **kwargs):
168+
if data.get("fetch_method") == "paste" and not data.get("json_text"):
169+
raise ValidationError(
170+
"'json_text' field is required when fetch_method is 'paste'"
171+
)
172+
try:
173+
json.loads(data.get("json_text"))
174+
except json.JSONDecodeError:
175+
raise ValidationError("Invalid JSON")
176+
177+
178+
class ValidationResultSchema(Schema):
179+
validation_errors = List(
180+
List(
181+
String(),
182+
validate=validate.Length(equal=2),
183+
),
184+
required=True,
185+
)
186+
187+
188+
class ValidationErrorResponseSchema(Schema):
189+
error = String(required=True)

app/forms.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import ast
22
import os
33
import re
4+
import json
45

56
from flask_wtf import FlaskForm
67
from wtforms import BooleanField, SelectField, StringField, SubmitField, TextAreaField
@@ -18,6 +19,18 @@
1819
is_prod = os.getenv("FLASK_ENV") == "production"
1920

2021

22+
def validate_json_format(form, field):
23+
"""
24+
Custom validator to check if the field data is valid JSON.
25+
"""
26+
try:
27+
json.loads(field.data)
28+
except json.JSONDecodeError:
29+
raise ValidationError(
30+
"Invalid JSON format. Please ensure the data is a valid JSON string."
31+
)
32+
33+
2134
def validate_email_list(form, field):
2235
emails = field.data
2336
for email in emails:
@@ -165,3 +178,53 @@ class HarvestTriggerForm(FlaskForm):
165178
class OrganizationTriggerForm(FlaskForm):
166179
edit = SubmitField("Edit")
167180
delete = SubmitField("Delete")
181+
182+
183+
def url_paste_validate(form, field):
184+
if form.fetch_method.data == "url":
185+
if not form.url.data:
186+
raise ValidationError("URL is required.")
187+
elif form.fetch_method.data == "paste":
188+
if not form.json_text.data:
189+
raise ValidationError("JSON input is required.")
190+
else:
191+
validate_json_format(form, form.json_text)
192+
193+
return True
194+
195+
196+
class ValidatorForm(FlaskForm):
197+
schema = SelectField(
198+
"Schema",
199+
choices=[
200+
"dcatus1.1: federal dataset",
201+
"dcatus1.1: non-federal dataset",
202+
],
203+
validators=[DataRequired()],
204+
)
205+
fetch_method = SelectField(
206+
"Fetch Method",
207+
choices=[
208+
("url", "Fetch from URL"),
209+
("paste", "Paste JSON"),
210+
],
211+
validators=[DataRequired()],
212+
)
213+
url = StringField(
214+
"URL",
215+
validators=[url_paste_validate],
216+
filters=[strip_filter],
217+
)
218+
219+
def validate_url(self, field):
220+
if self.fetch_method.data == "url" and field.data:
221+
try:
222+
URL(require_tld=is_prod)(self, field)
223+
except ValidationError:
224+
raise ValidationError("Invalid URL")
225+
226+
json_text = TextAreaField(
227+
"DCATUS Catalog JSON Input",
228+
validators=[url_paste_validate],
229+
)
230+
submit = SubmitField("Validate")

0 commit comments

Comments
 (0)