Files
notifications-api/app/serialised_models.py
Carlo Costino 99edc88197 Localize notification_utils to the API
This changeset pulls in all of the notification_utils code directly into the API and removes it as an external dependency.  We are doing this to cut down on operational maintenance of the project and will begin removing parts of it no longer needed for the API.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2024-05-16 10:17:45 -04:00

135 lines
3.4 KiB
Python

from collections import defaultdict
from functools import partial
from threading import RLock
import cachetools
from flask import current_app
from werkzeug.utils import cached_property
from app import db, redis_store
from app.dao.api_key_dao import get_model_api_keys
from app.dao.services_dao import dao_fetch_service_by_id
from notifications_utils.clients.redis import RequestCache
from notifications_utils.serialised_model import (
SerialisedModel,
SerialisedModelCollection,
)
caches = defaultdict(partial(cachetools.TTLCache, maxsize=1024, ttl=2))
locks = defaultdict(RLock)
redis_cache = RequestCache(redis_store)
def memory_cache(func):
@cachetools.cached(
cache=caches[func.__qualname__],
lock=locks[func.__qualname__],
key=ignore_first_argument_cache_key,
)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def ignore_first_argument_cache_key(cls, *args, **kwargs):
return cachetools.keys.hashkey(*args, **kwargs)
class SerialisedTemplate(SerialisedModel):
ALLOWED_PROPERTIES = {
"archived",
"content",
"id",
"process_type",
"reply_to_text",
"subject",
"template_type",
"version",
}
@classmethod
@memory_cache
def from_id_and_service_id(cls, template_id, service_id, version=None):
return cls(cls.get_dict(template_id, service_id, version)["data"])
@staticmethod
@redis_cache.set("service-{service_id}-template-{template_id}-version-{version}")
def get_dict(template_id, service_id, version):
from app.dao import templates_dao
from app.schemas import template_schema
fetched_template = templates_dao.dao_get_template_by_id_and_service_id(
template_id=template_id,
service_id=service_id,
version=version,
)
template_dict = template_schema.dump(fetched_template)
db.session.commit()
return {"data": template_dict}
class SerialisedService(SerialisedModel):
ALLOWED_PROPERTIES = {
"id",
"name",
"active",
"contact_link",
"email_from",
"message_limit",
"total_message_limit",
"permissions",
"rate_limit",
"restricted",
"prefix_sms",
"email_branding",
}
@classmethod
@memory_cache
def from_id(cls, service_id):
return cls(cls.get_dict(service_id)["data"])
@staticmethod
@redis_cache.set("service-{service_id}")
def get_dict(service_id):
from app.schemas import service_schema
service_dict = service_schema.dump(dao_fetch_service_by_id(service_id))
db.session.commit()
return {"data": service_dict}
@cached_property
def api_keys(self):
return SerialisedAPIKeyCollection.from_service_id(self.id)
@property
def high_volume(self):
return self.id in current_app.config["HIGH_VOLUME_SERVICE"]
class SerialisedAPIKey(SerialisedModel):
ALLOWED_PROPERTIES = {
"id",
"secret",
"expiry_date",
"key_type",
}
class SerialisedAPIKeyCollection(SerialisedModelCollection):
model = SerialisedAPIKey
@classmethod
@memory_cache
def from_service_id(cls, service_id):
keys = [
{k: getattr(key, k) for k in SerialisedAPIKey.ALLOWED_PROPERTIES}
for key in get_model_api_keys(service_id)
]
db.session.commit()
return cls(keys)