mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-03 01:41:05 -05:00
Merge branch 'main' into notify-300b
This commit is contained in:
430
app/schemas.py
430
app/schemas.py
@@ -37,7 +37,9 @@ def _validate_positive_number(value, msg="Not a positive integer"):
|
||||
raise ValidationError(msg)
|
||||
|
||||
|
||||
def _validate_datetime_not_more_than_96_hours_in_future(dte, msg="Date cannot be more than 96hrs in the future"):
|
||||
def _validate_datetime_not_more_than_96_hours_in_future(
|
||||
dte, msg="Date cannot be more than 96hrs in the future"
|
||||
):
|
||||
if dte > datetime.utcnow() + timedelta(hours=96):
|
||||
raise ValidationError(msg)
|
||||
|
||||
@@ -53,33 +55,32 @@ class FlexibleDateTime(fields.DateTime):
|
||||
Outputs data using the output format that marshmallow version 2 used to use, OLD_MARSHMALLOW_FORMAT
|
||||
"""
|
||||
|
||||
DEFAULT_FORMAT = 'flexible'
|
||||
DEFAULT_FORMAT = "flexible"
|
||||
OLD_MARSHMALLOW_FORMAT = "%Y-%m-%dT%H:%M:%S+00:00"
|
||||
|
||||
def __init__(self, *args, allow_none=True, **kwargs):
|
||||
super().__init__(*args, allow_none=allow_none, **kwargs)
|
||||
self.DESERIALIZATION_FUNCS['flexible'] = parse
|
||||
self.SERIALIZATION_FUNCS['flexible'] = lambda x: x.strftime(self.OLD_MARSHMALLOW_FORMAT)
|
||||
self.DESERIALIZATION_FUNCS["flexible"] = parse
|
||||
self.SERIALIZATION_FUNCS["flexible"] = lambda x: x.strftime(
|
||||
self.OLD_MARSHMALLOW_FORMAT
|
||||
)
|
||||
|
||||
|
||||
class UUIDsAsStringsMixin:
|
||||
@post_dump()
|
||||
def __post_dump(self, data, **kwargs):
|
||||
for key, value in data.items():
|
||||
|
||||
if isinstance(value, UUID):
|
||||
data[key] = str(value)
|
||||
|
||||
if isinstance(value, list):
|
||||
data[key] = [
|
||||
(str(item) if isinstance(item, UUID) else item)
|
||||
for item in value
|
||||
(str(item) if isinstance(item, UUID) else item) for item in value
|
||||
]
|
||||
return data
|
||||
|
||||
|
||||
class BaseSchema(ma.SQLAlchemyAutoSchema):
|
||||
|
||||
class Meta:
|
||||
load_instance = True
|
||||
include_relationships = True
|
||||
@@ -102,13 +103,16 @@ class BaseSchema(ma.SQLAlchemyAutoSchema):
|
||||
|
||||
|
||||
class UserSchema(BaseSchema):
|
||||
|
||||
permissions = fields.Method("user_permissions", dump_only=True)
|
||||
password_changed_at = field_for(models.User, 'password_changed_at', format=DATETIME_FORMAT_NO_TIMEZONE)
|
||||
created_at = field_for(models.User, 'created_at', format=DATETIME_FORMAT_NO_TIMEZONE)
|
||||
password_changed_at = field_for(
|
||||
models.User, "password_changed_at", format=DATETIME_FORMAT_NO_TIMEZONE
|
||||
)
|
||||
created_at = field_for(
|
||||
models.User, "created_at", format=DATETIME_FORMAT_NO_TIMEZONE
|
||||
)
|
||||
updated_at = FlexibleDateTime()
|
||||
logged_in_at = FlexibleDateTime()
|
||||
auth_type = field_for(models.User, 'auth_type')
|
||||
auth_type = field_for(models.User, "auth_type")
|
||||
password = fields.String(required=True, load_only=True)
|
||||
|
||||
def user_permissions(self, usr):
|
||||
@@ -130,75 +134,74 @@ class UserSchema(BaseSchema):
|
||||
"verify_codes",
|
||||
)
|
||||
|
||||
@validates('name')
|
||||
@validates("name")
|
||||
def validate_name(self, value):
|
||||
if not value:
|
||||
raise ValidationError('Invalid name')
|
||||
raise ValidationError("Invalid name")
|
||||
|
||||
@validates('email_address')
|
||||
@validates("email_address")
|
||||
def validate_email_address(self, value):
|
||||
try:
|
||||
validate_email_address(value)
|
||||
except InvalidEmailError as e:
|
||||
raise ValidationError(str(e))
|
||||
|
||||
@validates('mobile_number')
|
||||
@validates("mobile_number")
|
||||
def validate_mobile_number(self, value):
|
||||
try:
|
||||
if value is not None:
|
||||
validate_phone_number(value, international=True)
|
||||
except InvalidPhoneError as error:
|
||||
raise ValidationError('Invalid phone number: {}'.format(error))
|
||||
raise ValidationError("Invalid phone number: {}".format(error))
|
||||
|
||||
|
||||
class UserUpdateAttributeSchema(BaseSchema):
|
||||
auth_type = field_for(models.User, 'auth_type')
|
||||
auth_type = field_for(models.User, "auth_type")
|
||||
email_access_validated_at = FlexibleDateTime()
|
||||
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.User
|
||||
exclude = (
|
||||
'_password',
|
||||
'created_at',
|
||||
'failed_login_count',
|
||||
'id',
|
||||
'logged_in_at',
|
||||
'password_changed_at',
|
||||
'platform_admin',
|
||||
'state',
|
||||
'updated_at',
|
||||
'verify_codes',
|
||||
"_password",
|
||||
"created_at",
|
||||
"failed_login_count",
|
||||
"id",
|
||||
"logged_in_at",
|
||||
"password_changed_at",
|
||||
"platform_admin",
|
||||
"state",
|
||||
"updated_at",
|
||||
"verify_codes",
|
||||
)
|
||||
|
||||
@validates('name')
|
||||
@validates("name")
|
||||
def validate_name(self, value):
|
||||
if not value:
|
||||
raise ValidationError('Invalid name')
|
||||
raise ValidationError("Invalid name")
|
||||
|
||||
@validates('email_address')
|
||||
@validates("email_address")
|
||||
def validate_email_address(self, value):
|
||||
try:
|
||||
validate_email_address(value)
|
||||
except InvalidEmailError as e:
|
||||
raise ValidationError(str(e))
|
||||
|
||||
@validates('mobile_number')
|
||||
@validates("mobile_number")
|
||||
def validate_mobile_number(self, value):
|
||||
try:
|
||||
if value is not None:
|
||||
validate_phone_number(value, international=True)
|
||||
except InvalidPhoneError as error:
|
||||
raise ValidationError('Invalid phone number: {}'.format(error))
|
||||
raise ValidationError("Invalid phone number: {}".format(error))
|
||||
|
||||
@validates_schema(pass_original=True)
|
||||
def check_unknown_fields(self, data, original_data, **kwargs):
|
||||
for key in original_data:
|
||||
if key not in self.fields:
|
||||
raise ValidationError('Unknown field name {}'.format(key))
|
||||
raise ValidationError("Unknown field name {}".format(key))
|
||||
|
||||
|
||||
class UserUpdatePasswordSchema(BaseSchema):
|
||||
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.User
|
||||
|
||||
@@ -206,11 +209,13 @@ class UserUpdatePasswordSchema(BaseSchema):
|
||||
def check_unknown_fields(self, data, original_data, **kwargs):
|
||||
for key in original_data:
|
||||
if key not in self.fields:
|
||||
raise ValidationError('Unknown field name {}'.format(key))
|
||||
raise ValidationError("Unknown field name {}".format(key))
|
||||
|
||||
|
||||
class ProviderDetailsSchema(BaseSchema):
|
||||
created_by = fields.Nested(UserSchema, only=['id', 'name', 'email_address'], dump_only=True)
|
||||
created_by = fields.Nested(
|
||||
UserSchema, only=["id", "name", "email_address"], dump_only=True
|
||||
)
|
||||
updated_at = FlexibleDateTime()
|
||||
|
||||
class Meta(BaseSchema.Meta):
|
||||
@@ -218,7 +223,9 @@ class ProviderDetailsSchema(BaseSchema):
|
||||
|
||||
|
||||
class ProviderDetailsHistorySchema(BaseSchema):
|
||||
created_by = fields.Nested(UserSchema, only=['id', 'name', 'email_address'], dump_only=True)
|
||||
created_by = fields.Nested(
|
||||
UserSchema, only=["id", "name", "email_address"], dump_only=True
|
||||
)
|
||||
updated_at = FlexibleDateTime()
|
||||
|
||||
class Meta(BaseSchema.Meta):
|
||||
@@ -226,51 +233,54 @@ class ProviderDetailsHistorySchema(BaseSchema):
|
||||
|
||||
|
||||
class ServiceSchema(BaseSchema, UUIDsAsStringsMixin):
|
||||
|
||||
created_by = field_for(models.Service, 'created_by', required=True)
|
||||
organisation_type = field_for(models.Service, 'organisation_type')
|
||||
permissions = fields.Method("serialize_service_permissions", "deserialize_service_permissions")
|
||||
email_branding = field_for(models.Service, 'email_branding')
|
||||
organisation = field_for(models.Service, 'organisation')
|
||||
go_live_at = field_for(models.Service, 'go_live_at', format=DATETIME_FORMAT_NO_TIMEZONE)
|
||||
created_by = field_for(models.Service, "created_by", required=True)
|
||||
organization_type = field_for(models.Service, "organization_type")
|
||||
permissions = fields.Method(
|
||||
"serialize_service_permissions", "deserialize_service_permissions"
|
||||
)
|
||||
email_branding = field_for(models.Service, "email_branding")
|
||||
organization = field_for(models.Service, "organization")
|
||||
go_live_at = field_for(
|
||||
models.Service, "go_live_at", format=DATETIME_FORMAT_NO_TIMEZONE
|
||||
)
|
||||
|
||||
def serialize_service_permissions(self, service):
|
||||
return [p.permission for p in service.permissions]
|
||||
|
||||
def deserialize_service_permissions(self, in_data):
|
||||
if isinstance(in_data, dict) and 'permissions' in in_data:
|
||||
str_permissions = in_data['permissions']
|
||||
if isinstance(in_data, dict) and "permissions" in in_data:
|
||||
str_permissions = in_data["permissions"]
|
||||
permissions = []
|
||||
for p in str_permissions:
|
||||
permission = ServicePermission(service_id=in_data["id"], permission=p)
|
||||
permissions.append(permission)
|
||||
|
||||
in_data['permissions'] = permissions
|
||||
in_data["permissions"] = permissions
|
||||
|
||||
return in_data
|
||||
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.Service
|
||||
exclude = (
|
||||
'all_template_folders',
|
||||
'annual_billing',
|
||||
'api_keys',
|
||||
'complaints',
|
||||
'created_at',
|
||||
'data_retention',
|
||||
'guest_list',
|
||||
'inbound_number',
|
||||
'inbound_sms',
|
||||
'jobs',
|
||||
'reply_to_email_addresses',
|
||||
'service_sms_senders',
|
||||
'templates',
|
||||
'updated_at',
|
||||
'users',
|
||||
'version',
|
||||
"all_template_folders",
|
||||
"annual_billing",
|
||||
"api_keys",
|
||||
"complaints",
|
||||
"created_at",
|
||||
"data_retention",
|
||||
"guest_list",
|
||||
"inbound_number",
|
||||
"inbound_sms",
|
||||
"jobs",
|
||||
"reply_to_email_addresses",
|
||||
"service_sms_senders",
|
||||
"templates",
|
||||
"updated_at",
|
||||
"users",
|
||||
"version",
|
||||
)
|
||||
|
||||
@validates('permissions')
|
||||
@validates("permissions")
|
||||
def validate_permissions(self, value):
|
||||
permissions = [v.permission for v in value]
|
||||
for p in permissions:
|
||||
@@ -279,25 +289,25 @@ class ServiceSchema(BaseSchema, UUIDsAsStringsMixin):
|
||||
|
||||
if len(set(permissions)) != len(permissions):
|
||||
duplicates = list(set([x for x in permissions if permissions.count(x) > 1]))
|
||||
raise ValidationError('Duplicate Service Permission: {}'.format(duplicates))
|
||||
raise ValidationError("Duplicate Service Permission: {}".format(duplicates))
|
||||
|
||||
@pre_load()
|
||||
def format_for_data_model(self, in_data, **kwargs):
|
||||
if isinstance(in_data, dict) and 'permissions' in in_data:
|
||||
str_permissions = in_data['permissions']
|
||||
if isinstance(in_data, dict) and "permissions" in in_data:
|
||||
str_permissions = in_data["permissions"]
|
||||
permissions = []
|
||||
for p in str_permissions:
|
||||
permission = ServicePermission(service_id=in_data["id"], permission=p)
|
||||
permissions.append(permission)
|
||||
|
||||
in_data['permissions'] = permissions
|
||||
in_data["permissions"] = permissions
|
||||
|
||||
return in_data
|
||||
|
||||
|
||||
class DetailedServiceSchema(BaseSchema):
|
||||
statistics = fields.Dict()
|
||||
organisation_type = field_for(models.Service, 'organisation_type')
|
||||
organization_type = field_for(models.Service, "organization_type")
|
||||
go_live_at = FlexibleDateTime()
|
||||
created_at = FlexibleDateTime()
|
||||
updated_at = FlexibleDateTime()
|
||||
@@ -305,33 +315,39 @@ class DetailedServiceSchema(BaseSchema):
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.Service
|
||||
exclude = (
|
||||
'all_template_folders',
|
||||
'annual_billing',
|
||||
'api_keys',
|
||||
'created_by',
|
||||
'email_branding',
|
||||
'email_from',
|
||||
'guest_list',
|
||||
'inbound_api',
|
||||
'inbound_number',
|
||||
'inbound_sms',
|
||||
'jobs',
|
||||
'message_limit',
|
||||
'total_message_limit',
|
||||
'permissions',
|
||||
'rate_limit',
|
||||
'reply_to_email_addresses',
|
||||
'service_sms_senders',
|
||||
'templates',
|
||||
'users',
|
||||
'version',
|
||||
"all_template_folders",
|
||||
"annual_billing",
|
||||
"api_keys",
|
||||
"created_by",
|
||||
"email_branding",
|
||||
"email_from",
|
||||
"guest_list",
|
||||
"inbound_api",
|
||||
"inbound_number",
|
||||
"inbound_sms",
|
||||
"jobs",
|
||||
"message_limit",
|
||||
"total_message_limit",
|
||||
"permissions",
|
||||
"rate_limit",
|
||||
"reply_to_email_addresses",
|
||||
"service_sms_senders",
|
||||
"templates",
|
||||
"users",
|
||||
"version",
|
||||
)
|
||||
|
||||
|
||||
class NotificationModelSchema(BaseSchema):
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.Notification
|
||||
exclude = ('_personalisation', 'job', 'service', 'template', 'api_key',)
|
||||
exclude = (
|
||||
"_personalisation",
|
||||
"job",
|
||||
"service",
|
||||
"template",
|
||||
"api_key",
|
||||
)
|
||||
|
||||
status = fields.String(required=False)
|
||||
created_at = FlexibleDateTime()
|
||||
@@ -355,9 +371,8 @@ class BaseTemplateSchema(BaseSchema):
|
||||
|
||||
|
||||
class TemplateSchema(BaseTemplateSchema, UUIDsAsStringsMixin):
|
||||
|
||||
created_by = field_for(models.Template, 'created_by', required=True)
|
||||
process_type = field_for(models.Template, 'process_type')
|
||||
created_by = field_for(models.Template, "created_by", required=True)
|
||||
process_type = field_for(models.Template, "process_type")
|
||||
redact_personalisation = fields.Method("redact")
|
||||
created_at = FlexibleDateTime()
|
||||
updated_at = FlexibleDateTime()
|
||||
@@ -367,29 +382,29 @@ class TemplateSchema(BaseTemplateSchema, UUIDsAsStringsMixin):
|
||||
|
||||
@validates_schema
|
||||
def validate_type(self, data, **kwargs):
|
||||
if data.get('template_type') == models.EMAIL_TYPE:
|
||||
subject = data.get('subject')
|
||||
if not subject or subject.strip() == '':
|
||||
raise ValidationError('Invalid template subject', 'subject')
|
||||
if data.get("template_type") == models.EMAIL_TYPE:
|
||||
subject = data.get("subject")
|
||||
if not subject or subject.strip() == "":
|
||||
raise ValidationError("Invalid template subject", "subject")
|
||||
|
||||
|
||||
class TemplateSchemaNoDetail(TemplateSchema):
|
||||
class Meta(TemplateSchema.Meta):
|
||||
exclude = TemplateSchema.Meta.exclude + (
|
||||
'archived',
|
||||
'created_at',
|
||||
'created_by',
|
||||
'created_by_id',
|
||||
'hidden',
|
||||
'process_type',
|
||||
'redact_personalisation',
|
||||
'reply_to',
|
||||
'reply_to_text',
|
||||
'service',
|
||||
'subject',
|
||||
'template_redacted',
|
||||
'updated_at',
|
||||
'version',
|
||||
"archived",
|
||||
"created_at",
|
||||
"created_by",
|
||||
"created_by_id",
|
||||
"hidden",
|
||||
"process_type",
|
||||
"redact_personalisation",
|
||||
"reply_to",
|
||||
"reply_to_text",
|
||||
"service",
|
||||
"subject",
|
||||
"template_redacted",
|
||||
"updated_at",
|
||||
"version",
|
||||
)
|
||||
|
||||
@pre_dump
|
||||
@@ -400,13 +415,16 @@ class TemplateSchemaNoDetail(TemplateSchema):
|
||||
|
||||
|
||||
class TemplateHistorySchema(BaseSchema):
|
||||
|
||||
reply_to = fields.Method("get_reply_to", allow_none=True)
|
||||
reply_to_text = fields.Method("get_reply_to_text", allow_none=True)
|
||||
process_type = field_for(models.Template, 'process_type')
|
||||
process_type = field_for(models.Template, "process_type")
|
||||
|
||||
created_by = fields.Nested(UserSchema, only=['id', 'name', 'email_address'], dump_only=True)
|
||||
created_at = field_for(models.Template, 'created_at', format=DATETIME_FORMAT_NO_TIMEZONE)
|
||||
created_by = fields.Nested(
|
||||
UserSchema, only=["id", "name", "email_address"], dump_only=True
|
||||
)
|
||||
created_at = field_for(
|
||||
models.Template, "created_at", format=DATETIME_FORMAT_NO_TIMEZONE
|
||||
)
|
||||
updated_at = FlexibleDateTime()
|
||||
|
||||
def get_reply_to(self, template):
|
||||
@@ -420,9 +438,8 @@ class TemplateHistorySchema(BaseSchema):
|
||||
|
||||
|
||||
class ApiKeySchema(BaseSchema):
|
||||
|
||||
created_by = field_for(models.ApiKey, 'created_by', required=True)
|
||||
key_type = field_for(models.ApiKey, 'key_type', required=True)
|
||||
created_by = field_for(models.ApiKey, "created_by", required=True)
|
||||
key_type = field_for(models.ApiKey, "key_type", required=True)
|
||||
expiry_date = FlexibleDateTime()
|
||||
created_at = FlexibleDateTime()
|
||||
updated_at = FlexibleDateTime()
|
||||
@@ -433,22 +450,32 @@ class ApiKeySchema(BaseSchema):
|
||||
|
||||
|
||||
class JobSchema(BaseSchema):
|
||||
created_by_user = fields.Nested(UserSchema, attribute="created_by",
|
||||
data_key="created_by", only=["id", "name"], dump_only=True)
|
||||
created_by = field_for(models.Job, 'created_by', required=True, load_only=True)
|
||||
created_by_user = fields.Nested(
|
||||
UserSchema,
|
||||
attribute="created_by",
|
||||
data_key="created_by",
|
||||
only=["id", "name"],
|
||||
dump_only=True,
|
||||
)
|
||||
created_by = field_for(models.Job, "created_by", required=True, load_only=True)
|
||||
created_at = FlexibleDateTime()
|
||||
updated_at = FlexibleDateTime()
|
||||
processing_started = FlexibleDateTime()
|
||||
processing_finished = FlexibleDateTime()
|
||||
|
||||
job_status = field_for(models.JobStatus, 'name', required=False)
|
||||
job_status = field_for(models.JobStatus, "name", required=False)
|
||||
|
||||
scheduled_for = FlexibleDateTime()
|
||||
service_name = fields.Nested(
|
||||
ServiceSchema, attribute="service", data_key="service_name", only=["name"], dump_only=True)
|
||||
ServiceSchema,
|
||||
attribute="service",
|
||||
data_key="service_name",
|
||||
only=["name"],
|
||||
dump_only=True,
|
||||
)
|
||||
|
||||
template_name = fields.Method('get_template_name', dump_only=True)
|
||||
template_type = fields.Method('get_template_type', dump_only=True)
|
||||
template_name = fields.Method("get_template_name", dump_only=True)
|
||||
template_type = fields.Method("get_template_type", dump_only=True)
|
||||
|
||||
def get_template_name(self, job):
|
||||
return job.template.name
|
||||
@@ -456,7 +483,7 @@ class JobSchema(BaseSchema):
|
||||
def get_template_type(self, job):
|
||||
return job.template.template_type
|
||||
|
||||
@validates('scheduled_for')
|
||||
@validates("scheduled_for")
|
||||
def validate_scheduled_for(self, value):
|
||||
_validate_datetime_not_in_past(value)
|
||||
_validate_datetime_not_more_than_96_hours_in_future(value)
|
||||
@@ -464,10 +491,10 @@ class JobSchema(BaseSchema):
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.Job
|
||||
exclude = (
|
||||
'notifications',
|
||||
'notifications_delivered',
|
||||
'notifications_failed',
|
||||
'notifications_sent',
|
||||
"notifications",
|
||||
"notifications_delivered",
|
||||
"notifications_failed",
|
||||
"notifications_sent",
|
||||
)
|
||||
|
||||
|
||||
@@ -482,16 +509,16 @@ class NotificationSchema(ma.Schema):
|
||||
class SmsNotificationSchema(NotificationSchema):
|
||||
to = fields.Str(required=True)
|
||||
|
||||
@validates('to')
|
||||
@validates("to")
|
||||
def validate_to(self, value):
|
||||
try:
|
||||
validate_phone_number(value, international=True)
|
||||
except InvalidPhoneError as error:
|
||||
raise ValidationError('Invalid phone number: {}'.format(error))
|
||||
raise ValidationError("Invalid phone number: {}".format(error))
|
||||
|
||||
@post_load
|
||||
def format_phone_number(self, item, **kwargs):
|
||||
item['to'] = validate_and_format_phone_number(item['to'], international=True)
|
||||
item["to"] = validate_and_format_phone_number(item["to"], international=True)
|
||||
return item
|
||||
|
||||
|
||||
@@ -499,7 +526,7 @@ class EmailNotificationSchema(NotificationSchema):
|
||||
to = fields.Str(required=True)
|
||||
template = fields.Str(required=True)
|
||||
|
||||
@validates('to')
|
||||
@validates("to")
|
||||
def validate_to(self, value):
|
||||
try:
|
||||
validate_email_address(value)
|
||||
@@ -515,26 +542,28 @@ class SmsTemplateNotificationSchema(SmsNotificationSchema):
|
||||
class NotificationWithTemplateSchema(BaseSchema):
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.Notification
|
||||
exclude = ('_personalisation',)
|
||||
exclude = ("_personalisation",)
|
||||
|
||||
template = fields.Nested(
|
||||
TemplateSchema,
|
||||
only=[
|
||||
'id',
|
||||
'version',
|
||||
'name',
|
||||
'template_type',
|
||||
'content',
|
||||
'subject',
|
||||
'redact_personalisation'
|
||||
"id",
|
||||
"version",
|
||||
"name",
|
||||
"template_type",
|
||||
"content",
|
||||
"subject",
|
||||
"redact_personalisation",
|
||||
],
|
||||
dump_only=True
|
||||
dump_only=True,
|
||||
)
|
||||
job = fields.Nested(JobSchema, only=["id", "original_file_name"], dump_only=True)
|
||||
created_by = fields.Nested(UserSchema, only=['id', 'name', 'email_address'], dump_only=True)
|
||||
created_by = fields.Nested(
|
||||
UserSchema, only=["id", "name", "email_address"], dump_only=True
|
||||
)
|
||||
status = fields.String(required=False)
|
||||
personalisation = fields.Dict(required=False)
|
||||
key_type = field_for(models.Notification, 'key_type', required=True)
|
||||
key_type = field_for(models.Notification, "key_type", required=True)
|
||||
key_name = fields.String()
|
||||
created_at = FlexibleDateTime()
|
||||
updated_at = FlexibleDateTime()
|
||||
@@ -550,9 +579,12 @@ class NotificationWithTemplateSchema(BaseSchema):
|
||||
|
||||
|
||||
class NotificationWithPersonalisationSchema(NotificationWithTemplateSchema):
|
||||
template_history = fields.Nested(TemplateHistorySchema, attribute="template",
|
||||
only=['id', 'name', 'template_type', 'content', 'subject', 'version'],
|
||||
dump_only=True)
|
||||
template_history = fields.Nested(
|
||||
TemplateHistorySchema,
|
||||
attribute="template",
|
||||
only=["id", "name", "template_type", "content", "subject", "version"],
|
||||
dump_only=True,
|
||||
)
|
||||
|
||||
class Meta(NotificationWithTemplateSchema.Meta):
|
||||
# mark as many fields as possible as required since this is a public api.
|
||||
@@ -560,25 +592,25 @@ class NotificationWithPersonalisationSchema(NotificationWithTemplateSchema):
|
||||
# 'body', 'subject' [for emails], and 'content_char_count'
|
||||
fields = (
|
||||
# db rows
|
||||
'billable_units',
|
||||
'created_at',
|
||||
'id',
|
||||
'job_row_number',
|
||||
'notification_type',
|
||||
'reference',
|
||||
'sent_at',
|
||||
'sent_by',
|
||||
'status',
|
||||
'template_version',
|
||||
'to',
|
||||
'updated_at',
|
||||
"billable_units",
|
||||
"created_at",
|
||||
"id",
|
||||
"job_row_number",
|
||||
"notification_type",
|
||||
"reference",
|
||||
"sent_at",
|
||||
"sent_by",
|
||||
"status",
|
||||
"template_version",
|
||||
"to",
|
||||
"updated_at",
|
||||
# computed fields
|
||||
'personalisation',
|
||||
"personalisation",
|
||||
# relationships
|
||||
'api_key',
|
||||
'job',
|
||||
'service',
|
||||
'template_history',
|
||||
"api_key",
|
||||
"job",
|
||||
"service",
|
||||
"template_history",
|
||||
)
|
||||
# Overwrite the `NotificationWithTemplateSchema` base class to not exclude `_personalisation`, which
|
||||
# isn't a defined field for this class
|
||||
@@ -591,29 +623,31 @@ class NotificationWithPersonalisationSchema(NotificationWithTemplateSchema):
|
||||
|
||||
@post_dump
|
||||
def handle_template_merge(self, in_data, **kwargs):
|
||||
in_data['template'] = in_data.pop('template_history')
|
||||
template = get_template_instance(in_data['template'], in_data['personalisation'])
|
||||
in_data['body'] = template.content_with_placeholders_filled_in
|
||||
if in_data['template']['template_type'] != models.SMS_TYPE:
|
||||
in_data['subject'] = template.subject
|
||||
in_data['content_char_count'] = None
|
||||
in_data["template"] = in_data.pop("template_history")
|
||||
template = get_template_instance(
|
||||
in_data["template"], in_data["personalisation"]
|
||||
)
|
||||
in_data["body"] = template.content_with_placeholders_filled_in
|
||||
if in_data["template"]["template_type"] != models.SMS_TYPE:
|
||||
in_data["subject"] = template.subject
|
||||
in_data["content_char_count"] = None
|
||||
else:
|
||||
in_data['content_char_count'] = template.content_count
|
||||
in_data["content_char_count"] = template.content_count
|
||||
|
||||
in_data.pop('personalisation', None)
|
||||
in_data['template'].pop('content', None)
|
||||
in_data['template'].pop('subject', None)
|
||||
in_data.pop("personalisation", None)
|
||||
in_data["template"].pop("content", None)
|
||||
in_data["template"].pop("subject", None)
|
||||
return in_data
|
||||
|
||||
|
||||
class InvitedUserSchema(BaseSchema):
|
||||
auth_type = field_for(models.InvitedUser, 'auth_type')
|
||||
auth_type = field_for(models.InvitedUser, "auth_type")
|
||||
created_at = FlexibleDateTime()
|
||||
|
||||
class Meta(BaseSchema.Meta):
|
||||
model = models.InvitedUser
|
||||
|
||||
@validates('email_address')
|
||||
@validates("email_address")
|
||||
def validate_to(self, value):
|
||||
try:
|
||||
validate_email_address(value)
|
||||
@@ -633,7 +667,7 @@ class EmailDataSchema(ma.Schema):
|
||||
super().__init__()
|
||||
self.partial_email = partial_email
|
||||
|
||||
@validates('email')
|
||||
@validates("email")
|
||||
def validate_email(self, value):
|
||||
if self.partial_email:
|
||||
return
|
||||
@@ -647,8 +681,8 @@ class NotificationsFilterSchema(ma.Schema):
|
||||
class Meta:
|
||||
unknown = EXCLUDE
|
||||
|
||||
template_type = fields.Nested(BaseTemplateSchema, only=['template_type'], many=True)
|
||||
status = fields.Nested(NotificationModelSchema, only=['status'], many=True)
|
||||
template_type = fields.Nested(BaseTemplateSchema, only=["template_type"], many=True)
|
||||
status = fields.Nested(NotificationModelSchema, only=["status"], many=True)
|
||||
page = fields.Int(required=False)
|
||||
page_size = fields.Int(required=False)
|
||||
limit_days = fields.Int(required=False)
|
||||
@@ -662,28 +696,32 @@ class NotificationsFilterSchema(ma.Schema):
|
||||
|
||||
@pre_load
|
||||
def handle_multidict(self, in_data, **kwargs):
|
||||
if isinstance(in_data, dict) and hasattr(in_data, 'getlist'):
|
||||
if isinstance(in_data, dict) and hasattr(in_data, "getlist"):
|
||||
out_data = dict([(k, in_data.get(k)) for k in in_data.keys()])
|
||||
if 'template_type' in in_data:
|
||||
out_data['template_type'] = [{'template_type': x} for x in in_data.getlist('template_type')]
|
||||
if 'status' in in_data:
|
||||
out_data['status'] = [{"status": x} for x in in_data.getlist('status')]
|
||||
if "template_type" in in_data:
|
||||
out_data["template_type"] = [
|
||||
{"template_type": x} for x in in_data.getlist("template_type")
|
||||
]
|
||||
if "status" in in_data:
|
||||
out_data["status"] = [{"status": x} for x in in_data.getlist("status")]
|
||||
|
||||
return out_data
|
||||
|
||||
@post_load
|
||||
def convert_schema_object_to_field(self, in_data, **kwargs):
|
||||
if 'template_type' in in_data:
|
||||
in_data['template_type'] = [x.template_type for x in in_data['template_type']]
|
||||
if 'status' in in_data:
|
||||
in_data['status'] = [x.status for x in in_data['status']]
|
||||
if "template_type" in in_data:
|
||||
in_data["template_type"] = [
|
||||
x.template_type for x in in_data["template_type"]
|
||||
]
|
||||
if "status" in in_data:
|
||||
in_data["status"] = [x.status for x in in_data["status"]]
|
||||
return in_data
|
||||
|
||||
@validates('page')
|
||||
@validates("page")
|
||||
def validate_page(self, value):
|
||||
_validate_positive_number(value)
|
||||
|
||||
@validates('page_size')
|
||||
@validates("page_size")
|
||||
def validate_page_size(self, value):
|
||||
_validate_positive_number(value)
|
||||
|
||||
@@ -730,14 +768,16 @@ class UnarchivedTemplateSchema(BaseSchema):
|
||||
|
||||
@validates_schema
|
||||
def validate_archived(self, data, **kwargs):
|
||||
if data['archived']:
|
||||
raise ValidationError('Template has been deleted', 'template')
|
||||
if data["archived"]:
|
||||
raise ValidationError("Template has been deleted", "template")
|
||||
|
||||
|
||||
# should not be used on its own for dumping - only for loading
|
||||
create_user_schema = UserSchema()
|
||||
user_update_schema_load_json = UserUpdateAttributeSchema(load_json=True, partial=True)
|
||||
user_update_password_schema_load_json = UserUpdatePasswordSchema(only=('_password',), load_json=True, partial=True)
|
||||
user_update_password_schema_load_json = UserUpdatePasswordSchema(
|
||||
only=("_password",), load_json=True, partial=True
|
||||
)
|
||||
service_schema = ServiceSchema()
|
||||
detailed_service_schema = DetailedServiceSchema()
|
||||
template_schema = TemplateSchema()
|
||||
|
||||
Reference in New Issue
Block a user