mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-20 22:40:31 -04:00
notify-api-412 use black to enforce python coding style
This commit is contained in:
@@ -8,7 +8,6 @@ from notifications_utils.serialised_model import (
|
||||
|
||||
|
||||
class JSONModel(SerialisedModel):
|
||||
|
||||
def __init__(self, _dict):
|
||||
# in the case of a bad request _dict may be `None`
|
||||
self._dict = _dict or {}
|
||||
@@ -27,13 +26,12 @@ class JSONModel(SerialisedModel):
|
||||
|
||||
def _get_by_id(self, things, id):
|
||||
try:
|
||||
return next(thing for thing in things if thing['id'] == str(id))
|
||||
return next(thing for thing in things if thing["id"] == str(id))
|
||||
except StopIteration:
|
||||
abort(404)
|
||||
|
||||
|
||||
class ModelList(SerialisedModelCollection):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def client_method(self):
|
||||
@@ -44,8 +42,7 @@ class ModelList(SerialisedModelCollection):
|
||||
|
||||
|
||||
class PaginatedModelList(ModelList):
|
||||
|
||||
response_key = 'data'
|
||||
response_key = "data"
|
||||
|
||||
def __init__(self, *args, page=None, **kwargs):
|
||||
try:
|
||||
@@ -58,11 +55,10 @@ class PaginatedModelList(ModelList):
|
||||
page=self.current_page,
|
||||
)
|
||||
self.items = response[self.response_key]
|
||||
self.prev_page = response.get('links', {}).get('prev', None)
|
||||
self.next_page = response.get('links', {}).get('next', None)
|
||||
self.prev_page = response.get("links", {}).get("prev", None)
|
||||
self.next_page = response.get("links", {}).get("next", None)
|
||||
|
||||
|
||||
class SortByNameMixin():
|
||||
|
||||
class SortByNameMixin:
|
||||
def __lt__(self, other):
|
||||
return self.name.lower() < other.name.lower()
|
||||
|
||||
@@ -8,7 +8,6 @@ from app.notify_client.service_api_client import service_api_client
|
||||
|
||||
|
||||
class Event(ABC):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
item,
|
||||
@@ -17,8 +16,8 @@ class Event(ABC):
|
||||
value_to=None,
|
||||
):
|
||||
self.item = item
|
||||
self.time = item['updated_at'] or item['created_at']
|
||||
self.user_id = item['created_by_id']
|
||||
self.time = item["updated_at"] or item["created_at"]
|
||||
self.user_id = item["created_by_id"]
|
||||
self.key = key
|
||||
self.value_from = value_from
|
||||
self.value_to = value_to
|
||||
@@ -34,17 +33,13 @@ class Event(ABC):
|
||||
|
||||
|
||||
class ServiceCreationEvent(Event):
|
||||
|
||||
relevant = True
|
||||
|
||||
def __str__(self):
|
||||
return 'Created this service and called it ‘{}’'.format(
|
||||
self.item['name']
|
||||
)
|
||||
return "Created this service and called it ‘{}’".format(self.item["name"])
|
||||
|
||||
|
||||
class ServiceEvent(Event):
|
||||
|
||||
@property
|
||||
def relevant(self):
|
||||
return self.value_from != self.value_to and bool(self._formatter)
|
||||
@@ -54,44 +49,38 @@ class ServiceEvent(Event):
|
||||
|
||||
@property
|
||||
def _formatter(self):
|
||||
return getattr(self, 'format_{}'.format(self.key), None)
|
||||
return getattr(self, "format_{}".format(self.key), None)
|
||||
|
||||
def format_restricted(self):
|
||||
if self.value_to is False:
|
||||
return 'Made this service live'
|
||||
return "Made this service live"
|
||||
if self.value_to is True:
|
||||
return 'Put this service back into trial mode'
|
||||
return "Put this service back into trial mode"
|
||||
|
||||
def format_active(self):
|
||||
if self.value_to is False:
|
||||
return 'Deleted this service'
|
||||
return "Deleted this service"
|
||||
if self.value_to is True:
|
||||
return 'Unsuspended this service'
|
||||
return "Unsuspended this service"
|
||||
|
||||
def format_contact_link(self):
|
||||
return 'Set the contact details for this service to ‘{}’'.format(
|
||||
self.value_to
|
||||
)
|
||||
return "Set the contact details for this service to ‘{}’".format(self.value_to)
|
||||
|
||||
def format_email_branding(self):
|
||||
return 'Updated this service’s email branding'
|
||||
return "Updated this service’s email branding"
|
||||
|
||||
def format_inbound_api(self):
|
||||
return 'Updated the callback for received text messages'
|
||||
return "Updated the callback for received text messages"
|
||||
|
||||
def format_message_limit(self):
|
||||
return (
|
||||
'{} this service’s daily message limit from {} to {}'
|
||||
).format(
|
||||
'Reduced' if self.value_from > self.value_to else 'Increased',
|
||||
return ("{} this service’s daily message limit from {} to {}").format(
|
||||
"Reduced" if self.value_from > self.value_to else "Increased",
|
||||
format_thousands(self.value_from),
|
||||
format_thousands(self.value_to),
|
||||
)
|
||||
|
||||
def format_name(self):
|
||||
return (
|
||||
'Renamed this service from ‘{}’ to ‘{}’'
|
||||
).format(
|
||||
return ("Renamed this service from ‘{}’ to ‘{}’").format(
|
||||
self.value_from, self.value_to
|
||||
)
|
||||
|
||||
@@ -99,61 +88,54 @@ class ServiceEvent(Event):
|
||||
added = list(sorted(set(self.value_to) - set(self.value_from)))
|
||||
removed = list(sorted(set(self.value_from) - set(self.value_to)))
|
||||
if removed and added:
|
||||
return 'Removed {} from this service’s permissions, added {}'.format(
|
||||
return "Removed {} from this service’s permissions, added {}".format(
|
||||
formatted_list(removed),
|
||||
formatted_list(added),
|
||||
)
|
||||
if added:
|
||||
return 'Added {} to this service’s permissions'.format(
|
||||
return "Added {} to this service’s permissions".format(
|
||||
formatted_list(added)
|
||||
)
|
||||
if removed:
|
||||
return 'Removed {} from this service’s permissions'.format(
|
||||
return "Removed {} from this service’s permissions".format(
|
||||
formatted_list(removed)
|
||||
)
|
||||
|
||||
def format_prefix_sms(self):
|
||||
if self.value_to is True:
|
||||
return 'Set text messages to start with the name of this service'
|
||||
return "Set text messages to start with the name of this service"
|
||||
else:
|
||||
return 'Set text messages to not start with the name of this service'
|
||||
return "Set text messages to not start with the name of this service"
|
||||
|
||||
def format_research_mode(self):
|
||||
if self.value_to is True:
|
||||
return 'Put this service into research mode'
|
||||
return "Put this service into research mode"
|
||||
else:
|
||||
return 'Took this service out of research mode'
|
||||
return "Took this service out of research mode"
|
||||
|
||||
def format_service_callback_api(self):
|
||||
return 'Updated the callback for delivery receipts'
|
||||
return "Updated the callback for delivery receipts"
|
||||
|
||||
def format_go_live_user(self):
|
||||
return 'Requested for this service to go live'
|
||||
return "Requested for this service to go live"
|
||||
|
||||
|
||||
class APIKeyEvent(Event):
|
||||
|
||||
relevant = True
|
||||
|
||||
def __str__(self):
|
||||
if self.item['updated_at']:
|
||||
return (
|
||||
'Revoked the ‘{}’ API key'
|
||||
).format(self.item['name'])
|
||||
if self.item["updated_at"]:
|
||||
return ("Revoked the ‘{}’ API key").format(self.item["name"])
|
||||
else:
|
||||
return (
|
||||
'Created an API key called ‘{}’'
|
||||
).format(self.item['name'])
|
||||
return ("Created an API key called ‘{}’").format(self.item["name"])
|
||||
|
||||
|
||||
class APIKeyEvents(ModelList):
|
||||
|
||||
model = APIKeyEvent
|
||||
client_method = service_api_client.get_service_api_key_history
|
||||
|
||||
|
||||
class ServiceEvents(ModelList):
|
||||
|
||||
client_method = service_api_client.get_service_service_history
|
||||
|
||||
@property
|
||||
@@ -162,10 +144,9 @@ class ServiceEvents(ModelList):
|
||||
|
||||
@staticmethod
|
||||
def splat(events):
|
||||
for index, item in enumerate(sorted(
|
||||
events,
|
||||
key=lambda event: event['updated_at'] or event['created_at']
|
||||
)):
|
||||
for index, item in enumerate(
|
||||
sorted(events, key=lambda event: event["updated_at"] or event["created_at"])
|
||||
):
|
||||
if index == 0:
|
||||
yield ServiceCreationEvent(item)
|
||||
else:
|
||||
@@ -179,5 +160,7 @@ class ServiceEvents(ModelList):
|
||||
|
||||
def __init__(self, service_id):
|
||||
self.items = [
|
||||
event for event in self.splat(self.client_method(service_id)) if event.relevant
|
||||
event
|
||||
for event in self.splat(self.client_method(service_id))
|
||||
if event.relevant
|
||||
]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
QUESTION_TICKET_TYPE = 'ask-question-give-feedback'
|
||||
PROBLEM_TICKET_TYPE = 'report-problem'
|
||||
GENERAL_TICKET_TYPE = 'general'
|
||||
QUESTION_TICKET_TYPE = "ask-question-give-feedback"
|
||||
PROBLEM_TICKET_TYPE = "report-problem"
|
||||
GENERAL_TICKET_TYPE = "general"
|
||||
|
||||
@@ -9,65 +9,68 @@ from app.utils.time import is_less_than_days_ago
|
||||
|
||||
|
||||
class Job(JSONModel):
|
||||
|
||||
ALLOWED_PROPERTIES = {
|
||||
'id',
|
||||
'service',
|
||||
'template_name',
|
||||
'template_version',
|
||||
'original_file_name',
|
||||
'created_at',
|
||||
'notification_count',
|
||||
'created_by',
|
||||
'template_type',
|
||||
'recipient',
|
||||
"id",
|
||||
"service",
|
||||
"template_name",
|
||||
"template_version",
|
||||
"original_file_name",
|
||||
"created_at",
|
||||
"notification_count",
|
||||
"created_by",
|
||||
"template_type",
|
||||
"recipient",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_id(cls, job_id, service_id):
|
||||
return cls(job_api_client.get_job(service_id, job_id)['data'])
|
||||
return cls(job_api_client.get_job(service_id, job_id)["data"])
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
return self._dict.get('job_status')
|
||||
return self._dict.get("job_status")
|
||||
|
||||
@property
|
||||
def cancelled(self):
|
||||
return self.status == 'cancelled'
|
||||
return self.status == "cancelled"
|
||||
|
||||
@property
|
||||
def scheduled(self):
|
||||
return self.status == 'scheduled'
|
||||
return self.status == "scheduled"
|
||||
|
||||
@property
|
||||
def scheduled_for(self):
|
||||
return self._dict.get('scheduled_for')
|
||||
return self._dict.get("scheduled_for")
|
||||
|
||||
@property
|
||||
def upload_type(self):
|
||||
return self._dict.get('upload_type')
|
||||
return self._dict.get("upload_type")
|
||||
|
||||
@property
|
||||
def processing_started(self):
|
||||
if not self._dict.get('processing_started'):
|
||||
if not self._dict.get("processing_started"):
|
||||
return None
|
||||
return self._dict['processing_started']
|
||||
return self._dict["processing_started"]
|
||||
|
||||
def _aggregate_statistics(self, *statuses):
|
||||
return sum(
|
||||
outcome['count'] for outcome in self._dict['statistics']
|
||||
if not statuses or outcome['status'] in statuses
|
||||
outcome["count"]
|
||||
for outcome in self._dict["statistics"]
|
||||
if not statuses or outcome["status"] in statuses
|
||||
)
|
||||
|
||||
@property
|
||||
def notifications_delivered(self):
|
||||
return self._aggregate_statistics('delivered', 'sent')
|
||||
return self._aggregate_statistics("delivered", "sent")
|
||||
|
||||
@property
|
||||
def notifications_failed(self):
|
||||
return self._aggregate_statistics(
|
||||
'failed', 'technical-failure', 'temporary-failure',
|
||||
'permanent-failure', 'cancelled',
|
||||
"failed",
|
||||
"technical-failure",
|
||||
"temporary-failure",
|
||||
"permanent-failure",
|
||||
"cancelled",
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -92,9 +95,7 @@ class Job(JSONModel):
|
||||
|
||||
@property
|
||||
def still_processing(self):
|
||||
return (
|
||||
self.status != 'finished' or self.percentage_complete < 100
|
||||
)
|
||||
return self.status != "finished" or self.percentage_complete < 100
|
||||
|
||||
@cached_property
|
||||
def finished_processing(self):
|
||||
@@ -111,7 +112,7 @@ class Job(JSONModel):
|
||||
|
||||
@property
|
||||
def template_id(self):
|
||||
return self._dict['template']
|
||||
return self._dict["template"]
|
||||
|
||||
@cached_property
|
||||
def template(self):
|
||||
@@ -119,7 +120,7 @@ class Job(JSONModel):
|
||||
service_id=self.service,
|
||||
template_id=self.template_id,
|
||||
version=self.template_version,
|
||||
)['data']
|
||||
)["data"]
|
||||
|
||||
@property
|
||||
def percentage_complete(self):
|
||||
@@ -127,23 +128,21 @@ class Job(JSONModel):
|
||||
|
||||
@cached_property
|
||||
def all_notifications(self):
|
||||
return self.get_notifications(set_status_filters({}))['notifications']
|
||||
return self.get_notifications(set_status_filters({}))["notifications"]
|
||||
|
||||
@property
|
||||
def uncancellable_notifications(self):
|
||||
# TODO: this is redundant now
|
||||
return (
|
||||
n for n in self.all_notifications
|
||||
)
|
||||
return (n for n in self.all_notifications)
|
||||
|
||||
@property
|
||||
def failure_rate(self):
|
||||
if not self.notifications_delivered:
|
||||
return 100 if self.notifications_failed else 0
|
||||
return (
|
||||
self.notifications_failed / (
|
||||
self.notifications_failed + self.notifications_delivered
|
||||
) * 100
|
||||
self.notifications_failed
|
||||
/ (self.notifications_failed + self.notifications_delivered)
|
||||
* 100
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -152,7 +151,9 @@ class Job(JSONModel):
|
||||
|
||||
def get_notifications(self, status):
|
||||
return notification_api_client.get_notifications_for_service(
|
||||
self.service, self.id, status=status,
|
||||
self.service,
|
||||
self.id,
|
||||
status=status,
|
||||
)
|
||||
|
||||
def cancel(self):
|
||||
|
||||
@@ -8,31 +8,32 @@ from app.notify_client.organizations_api_client import organizations_client
|
||||
|
||||
|
||||
class Organization(JSONModel, SortByNameMixin):
|
||||
TYPE_FEDERAL = "federal"
|
||||
TYPE_STATE = "state"
|
||||
TYPE_OTHER = "other"
|
||||
|
||||
TYPE_FEDERAL = 'federal'
|
||||
TYPE_STATE = 'state'
|
||||
TYPE_OTHER = 'other'
|
||||
|
||||
TYPE_LABELS = OrderedDict([
|
||||
(TYPE_FEDERAL, 'Federal government'),
|
||||
(TYPE_STATE, 'State government'),
|
||||
(TYPE_OTHER, 'Other'),
|
||||
])
|
||||
TYPE_LABELS = OrderedDict(
|
||||
[
|
||||
(TYPE_FEDERAL, "Federal government"),
|
||||
(TYPE_STATE, "State government"),
|
||||
(TYPE_OTHER, "Other"),
|
||||
]
|
||||
)
|
||||
|
||||
ALLOWED_PROPERTIES = {
|
||||
'id',
|
||||
'name',
|
||||
'active',
|
||||
'organization_type',
|
||||
'email_branding_id',
|
||||
'domains',
|
||||
'request_to_go_live_notes',
|
||||
'count_of_live_services',
|
||||
'billing_contact_email_addresses',
|
||||
'billing_contact_names',
|
||||
'billing_reference',
|
||||
'purchase_order_number',
|
||||
'notes',
|
||||
"id",
|
||||
"name",
|
||||
"active",
|
||||
"organization_type",
|
||||
"email_branding_id",
|
||||
"domains",
|
||||
"request_to_go_live_notes",
|
||||
"count_of_live_services",
|
||||
"billing_contact_email_addresses",
|
||||
"billing_contact_names",
|
||||
"billing_reference",
|
||||
"purchase_order_number",
|
||||
"notes",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@@ -58,13 +59,14 @@ class Organization(JSONModel, SortByNameMixin):
|
||||
|
||||
@classmethod
|
||||
def create(cls, name, organization_type):
|
||||
return cls(organizations_client.create_organization(
|
||||
name=name,
|
||||
organization_type=organization_type,
|
||||
))
|
||||
return cls(
|
||||
organizations_client.create_organization(
|
||||
name=name,
|
||||
organization_type=organization_type,
|
||||
)
|
||||
)
|
||||
|
||||
def __init__(self, _dict):
|
||||
|
||||
super().__init__(_dict)
|
||||
|
||||
if self._dict == {}:
|
||||
@@ -84,7 +86,7 @@ class Organization(JSONModel, SortByNameMixin):
|
||||
self.billing_contact_email_addresses,
|
||||
self.billing_contact_names,
|
||||
self.billing_reference,
|
||||
self.purchase_order_number
|
||||
self.purchase_order_number,
|
||||
]
|
||||
if any(billing_details):
|
||||
return billing_details
|
||||
@@ -97,24 +99,26 @@ class Organization(JSONModel, SortByNameMixin):
|
||||
|
||||
@cached_property
|
||||
def service_ids(self):
|
||||
return [s['id'] for s in self.services]
|
||||
return [s["id"] for s in self.services]
|
||||
|
||||
@property
|
||||
def live_services(self):
|
||||
return [s for s in self.services if s['active'] and not s['restricted']]
|
||||
return [s for s in self.services if s["active"] and not s["restricted"]]
|
||||
|
||||
@property
|
||||
def trial_services(self):
|
||||
return [s for s in self.services if not s['active'] or s['restricted']]
|
||||
return [s for s in self.services if not s["active"] or s["restricted"]]
|
||||
|
||||
@cached_property
|
||||
def invited_users(self):
|
||||
from app.models.user import OrganizationInvitedUsers
|
||||
|
||||
return OrganizationInvitedUsers(self.id)
|
||||
|
||||
@cached_property
|
||||
def active_users(self):
|
||||
from app.models.user import OrganizationUsers
|
||||
|
||||
return OrganizationUsers(self.id)
|
||||
|
||||
@cached_property
|
||||
@@ -127,15 +131,15 @@ class Organization(JSONModel, SortByNameMixin):
|
||||
@cached_property
|
||||
def email_branding(self):
|
||||
if self.email_branding_id:
|
||||
return email_branding_client.get_email_branding(
|
||||
self.email_branding_id
|
||||
)['email_branding']
|
||||
return email_branding_client.get_email_branding(self.email_branding_id)[
|
||||
"email_branding"
|
||||
]
|
||||
|
||||
@property
|
||||
def email_branding_name(self):
|
||||
if self.email_branding_id:
|
||||
return self.email_branding['name']
|
||||
return 'GOV.UK'
|
||||
return self.email_branding["name"]
|
||||
return "GOV.UK"
|
||||
|
||||
def update(self, delete_services_cache=False, **kwargs):
|
||||
response = organizations_client.update_organization(
|
||||
@@ -146,10 +150,7 @@ class Organization(JSONModel, SortByNameMixin):
|
||||
self.__init__(response)
|
||||
|
||||
def associate_service(self, service_id):
|
||||
organizations_client.update_service_organization(
|
||||
service_id,
|
||||
self.id
|
||||
)
|
||||
organizations_client.update_service_organization(service_id, self.id)
|
||||
|
||||
def services_and_usage(self, financial_year):
|
||||
return organizations_client.get_services_and_usage(self.id, financial_year)
|
||||
|
||||
@@ -19,52 +19,51 @@ from app.utils import get_default_sms_sender
|
||||
|
||||
|
||||
class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
ALLOWED_PROPERTIES = {
|
||||
'active',
|
||||
'billing_contact_email_addresses',
|
||||
'billing_contact_names',
|
||||
'billing_reference',
|
||||
'consent_to_research',
|
||||
'contact_link',
|
||||
'count_as_live',
|
||||
'email_from',
|
||||
'go_live_at',
|
||||
'go_live_user',
|
||||
'id',
|
||||
'inbound_api',
|
||||
'message_limit',
|
||||
'rate_limit',
|
||||
'name',
|
||||
'notes',
|
||||
'prefix_sms',
|
||||
'purchase_order_number',
|
||||
'research_mode',
|
||||
'service_callback_api',
|
||||
'volume_email',
|
||||
'volume_sms',
|
||||
"active",
|
||||
"billing_contact_email_addresses",
|
||||
"billing_contact_names",
|
||||
"billing_reference",
|
||||
"consent_to_research",
|
||||
"contact_link",
|
||||
"count_as_live",
|
||||
"email_from",
|
||||
"go_live_at",
|
||||
"go_live_user",
|
||||
"id",
|
||||
"inbound_api",
|
||||
"message_limit",
|
||||
"rate_limit",
|
||||
"name",
|
||||
"notes",
|
||||
"prefix_sms",
|
||||
"purchase_order_number",
|
||||
"research_mode",
|
||||
"service_callback_api",
|
||||
"volume_email",
|
||||
"volume_sms",
|
||||
}
|
||||
|
||||
TEMPLATE_TYPES = (
|
||||
'email',
|
||||
'sms',
|
||||
"email",
|
||||
"sms",
|
||||
)
|
||||
|
||||
ALL_PERMISSIONS = TEMPLATE_TYPES + (
|
||||
'edit_folder_permissions',
|
||||
'email_auth',
|
||||
'inbound_sms',
|
||||
'international_sms',
|
||||
'upload_document',
|
||||
"edit_folder_permissions",
|
||||
"email_auth",
|
||||
"inbound_sms",
|
||||
"international_sms",
|
||||
"upload_document",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_id(cls, service_id):
|
||||
return cls(service_api_client.get_service(service_id)['data'])
|
||||
return cls(service_api_client.get_service(service_id)["data"])
|
||||
|
||||
@property
|
||||
def permissions(self):
|
||||
return self._dict.get('permissions', self.TEMPLATE_TYPES)
|
||||
return self._dict.get("permissions", self.TEMPLATE_TYPES)
|
||||
|
||||
@property
|
||||
def billing_details(self):
|
||||
@@ -72,7 +71,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
self.billing_contact_email_addresses,
|
||||
self.billing_contact_names,
|
||||
self.billing_reference,
|
||||
self.purchase_order_number
|
||||
self.purchase_order_number,
|
||||
]
|
||||
if any(billing_details):
|
||||
return billing_details
|
||||
@@ -83,7 +82,9 @@ class Service(JSONModel, SortByNameMixin):
|
||||
return service_api_client.update_service(self.id, **kwargs)
|
||||
|
||||
def update_count_as_live(self, count_as_live):
|
||||
return service_api_client.update_count_as_live(self.id, count_as_live=count_as_live)
|
||||
return service_api_client.update_count_as_live(
|
||||
self.id, count_as_live=count_as_live
|
||||
)
|
||||
|
||||
def update_status(self, live):
|
||||
return service_api_client.update_status(self.id, live=live)
|
||||
@@ -95,7 +96,6 @@ class Service(JSONModel, SortByNameMixin):
|
||||
)
|
||||
|
||||
def force_permission(self, permission, on=False):
|
||||
|
||||
permissions, permission = set(self.permissions), {permission}
|
||||
|
||||
return self.update_permissions(
|
||||
@@ -110,7 +110,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@property
|
||||
def trial_mode(self):
|
||||
return self._dict['restricted']
|
||||
return self._dict["restricted"]
|
||||
|
||||
@property
|
||||
def live(self):
|
||||
@@ -118,7 +118,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
def has_permission(self, permission):
|
||||
if permission not in self.ALL_PERMISSIONS:
|
||||
raise KeyError(f'{permission} is not a service permission')
|
||||
raise KeyError(f"{permission} is not a service permission")
|
||||
return permission in self.permissions
|
||||
|
||||
def get_page_of_jobs(self, page):
|
||||
@@ -146,7 +146,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
@cached_property
|
||||
def scheduled_job_stats(self):
|
||||
if not self.has_jobs:
|
||||
return {'count': 0}
|
||||
return {"count": 0}
|
||||
return job_api_client.get_scheduled_job_stats(self.id)
|
||||
|
||||
@cached_property
|
||||
@@ -155,8 +155,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
def invite_pending_for(self, email_address):
|
||||
return email_address.lower() in (
|
||||
invited_user.email_address.lower()
|
||||
for invited_user in self.invited_users
|
||||
invited_user.email_address.lower() for invited_user in self.invited_users
|
||||
)
|
||||
|
||||
@cached_property
|
||||
@@ -172,10 +171,16 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@cached_property
|
||||
def has_team_members(self):
|
||||
return len([
|
||||
user for user in self.team_members
|
||||
if user.has_permission_for_service(self.id, 'manage_service')
|
||||
]) > 1
|
||||
return (
|
||||
len(
|
||||
[
|
||||
user
|
||||
for user in self.team_members
|
||||
if user.has_permission_for_service(self.id, "manage_service")
|
||||
]
|
||||
)
|
||||
> 1
|
||||
)
|
||||
|
||||
def cancel_invite(self, invited_user_id):
|
||||
if str(invited_user_id) not in {user.id for user in self.invited_users}:
|
||||
@@ -187,7 +192,6 @@ class Service(JSONModel, SortByNameMixin):
|
||||
)
|
||||
|
||||
def get_team_member(self, user_id):
|
||||
|
||||
if str(user_id) not in {user.id for user in self.active_users}:
|
||||
abort(404)
|
||||
|
||||
@@ -195,20 +199,22 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@cached_property
|
||||
def all_templates(self):
|
||||
|
||||
templates = service_api_client.get_service_templates(self.id)['data']
|
||||
templates = service_api_client.get_service_templates(self.id)["data"]
|
||||
|
||||
return [
|
||||
template for template in templates
|
||||
if template['template_type'] in self.available_template_types
|
||||
template
|
||||
for template in templates
|
||||
if template["template_type"] in self.available_template_types
|
||||
]
|
||||
|
||||
@cached_property
|
||||
def all_template_ids(self):
|
||||
return {template['id'] for template in self.all_templates}
|
||||
return {template["id"] for template in self.all_templates}
|
||||
|
||||
def get_template(self, template_id, version=None):
|
||||
return service_api_client.get_service_template(self.id, template_id, version)['data']
|
||||
return service_api_client.get_service_template(self.id, template_id, version)[
|
||||
"data"
|
||||
]
|
||||
|
||||
def get_template_folder_with_user_permission_or_403(self, folder_id, user):
|
||||
template_folder = self.get_template_folder(folder_id)
|
||||
@@ -221,7 +227,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
def get_template_with_user_permission_or_403(self, template_id, user):
|
||||
template = self.get_template(template_id)
|
||||
|
||||
self.get_template_folder_with_user_permission_or_403(template['folder'], user)
|
||||
self.get_template_folder_with_user_permission_or_403(template["folder"], user)
|
||||
|
||||
return template
|
||||
|
||||
@@ -238,32 +244,31 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@property
|
||||
def has_multiple_template_types(self):
|
||||
return len({
|
||||
template['template_type'] for template in self.all_templates
|
||||
}) > 1
|
||||
return len({template["template_type"] for template in self.all_templates}) > 1
|
||||
|
||||
@property
|
||||
def has_estimated_usage(self):
|
||||
return (
|
||||
self.consent_to_research is not None and any((
|
||||
return self.consent_to_research is not None and any(
|
||||
(
|
||||
self.volume_email,
|
||||
self.volume_sms,
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
def has_templates_of_type(self, template_type):
|
||||
return any(
|
||||
template for template in self.all_templates
|
||||
if template['template_type'] == template_type
|
||||
template
|
||||
for template in self.all_templates
|
||||
if template["template_type"] == template_type
|
||||
)
|
||||
|
||||
@property
|
||||
def has_email_templates(self):
|
||||
return self.has_templates_of_type('email')
|
||||
return self.has_templates_of_type("email")
|
||||
|
||||
@property
|
||||
def has_sms_templates(self):
|
||||
return self.has_templates_of_type('sms')
|
||||
return self.has_templates_of_type("sms")
|
||||
|
||||
@property
|
||||
def intending_to_send_email(self):
|
||||
@@ -293,9 +298,11 @@ class Service(JSONModel, SortByNameMixin):
|
||||
def default_email_reply_to_address(self):
|
||||
return next(
|
||||
(
|
||||
x['email_address']
|
||||
for x in self.email_reply_to_addresses if x['is_default']
|
||||
), None
|
||||
x["email_address"]
|
||||
for x in self.email_reply_to_addresses
|
||||
if x["is_default"]
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
def get_email_reply_to_address(self, id):
|
||||
@@ -315,15 +322,14 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@property
|
||||
def sms_senders_with_hints(self):
|
||||
|
||||
def attach_hint(sender):
|
||||
hints = []
|
||||
if sender['is_default']:
|
||||
if sender["is_default"]:
|
||||
hints += ["default"]
|
||||
if sender['inbound_number_id']:
|
||||
if sender["inbound_number_id"]:
|
||||
hints += ["receives replies"]
|
||||
if hints:
|
||||
sender['hint'] = "(" + " and ".join(hints) + ")"
|
||||
sender["hint"] = "(" + " and ".join(hints) + ")"
|
||||
return sender
|
||||
|
||||
return [attach_hint(sender) for sender in self.sms_senders]
|
||||
@@ -338,39 +344,48 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@property
|
||||
def sms_sender_is_govuk(self):
|
||||
return self.default_sms_sender in {'GOVUK', 'None'}
|
||||
return self.default_sms_sender in {"GOVUK", "None"}
|
||||
|
||||
def get_sms_sender(self, id):
|
||||
return service_api_client.get_sms_sender(self.id, id)
|
||||
|
||||
@property
|
||||
def needs_to_change_sms_sender(self):
|
||||
return all((
|
||||
self.intending_to_send_sms,
|
||||
self.shouldnt_use_govuk_as_sms_sender,
|
||||
self.sms_sender_is_govuk,
|
||||
))
|
||||
return all(
|
||||
(
|
||||
self.intending_to_send_sms,
|
||||
self.shouldnt_use_govuk_as_sms_sender,
|
||||
self.sms_sender_is_govuk,
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def volumes(self):
|
||||
return sum(filter(None, (
|
||||
self.volume_email,
|
||||
self.volume_sms,
|
||||
)))
|
||||
return sum(
|
||||
filter(
|
||||
None,
|
||||
(
|
||||
self.volume_email,
|
||||
self.volume_sms,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def go_live_checklist_completed(self):
|
||||
return all((
|
||||
bool(self.volumes),
|
||||
self.has_team_members,
|
||||
self.has_templates,
|
||||
not self.needs_to_add_email_reply_to_address,
|
||||
not self.needs_to_change_sms_sender,
|
||||
))
|
||||
return all(
|
||||
(
|
||||
bool(self.volumes),
|
||||
self.has_team_members,
|
||||
self.has_templates,
|
||||
not self.needs_to_add_email_reply_to_address,
|
||||
not self.needs_to_change_sms_sender,
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def go_live_checklist_completed_as_yes_no(self):
|
||||
return 'Yes' if self.go_live_checklist_completed else 'No'
|
||||
return "Yes" if self.go_live_checklist_completed else "No"
|
||||
|
||||
@cached_property
|
||||
def free_sms_fragment_limit(self):
|
||||
@@ -381,36 +396,42 @@ class Service(JSONModel, SortByNameMixin):
|
||||
return service_api_client.get_service_data_retention(self.id)
|
||||
|
||||
def get_data_retention_item(self, id):
|
||||
return next(
|
||||
(dr for dr in self.data_retention if dr['id'] == id),
|
||||
None
|
||||
)
|
||||
return next((dr for dr in self.data_retention if dr["id"] == id), None)
|
||||
|
||||
def get_days_of_retention(self, notification_type):
|
||||
return next(
|
||||
(dr for dr in self.data_retention if dr['notification_type'] == notification_type),
|
||||
{}
|
||||
).get('days_of_retention', current_app.config['ACTIVITY_STATS_LIMIT_DAYS'])
|
||||
(
|
||||
dr
|
||||
for dr in self.data_retention
|
||||
if dr["notification_type"] == notification_type
|
||||
),
|
||||
{},
|
||||
).get("days_of_retention", current_app.config["ACTIVITY_STATS_LIMIT_DAYS"])
|
||||
|
||||
@property
|
||||
def email_branding_id(self):
|
||||
return self._dict['email_branding']
|
||||
return self._dict["email_branding"]
|
||||
|
||||
@cached_property
|
||||
def email_branding(self):
|
||||
if self.email_branding_id:
|
||||
return email_branding_client.get_email_branding(self.email_branding_id)['email_branding']
|
||||
return email_branding_client.get_email_branding(self.email_branding_id)[
|
||||
"email_branding"
|
||||
]
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def email_branding_name(self):
|
||||
if self.email_branding is None:
|
||||
return 'GOV.UK'
|
||||
return self.email_branding['name']
|
||||
return "GOV.UK"
|
||||
return self.email_branding["name"]
|
||||
|
||||
@property
|
||||
def needs_to_change_email_branding(self):
|
||||
return self.email_branding_id is None and self.organization_type != Organization.TYPE_CENTRAL
|
||||
return (
|
||||
self.email_branding_id is None
|
||||
and self.organization_type != Organization.TYPE_CENTRAL
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def organization(self):
|
||||
@@ -418,11 +439,11 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@property
|
||||
def organization_id(self):
|
||||
return self._dict['organization']
|
||||
return self._dict["organization"]
|
||||
|
||||
@property
|
||||
def organization_type(self):
|
||||
return self.organization.organization_type or self._dict['organization_type']
|
||||
return self.organization.organization_type or self._dict["organization_type"]
|
||||
|
||||
@property
|
||||
def organization_name(self):
|
||||
@@ -436,7 +457,9 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@cached_property
|
||||
def inbound_number(self):
|
||||
return inbound_number_client.get_inbound_sms_number_for_service(self.id)['data'].get('number', '')
|
||||
return inbound_number_client.get_inbound_sms_number_for_service(self.id)[
|
||||
"data"
|
||||
].get("number", "")
|
||||
|
||||
@property
|
||||
def has_inbound_number(self):
|
||||
@@ -444,7 +467,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@cached_property
|
||||
def inbound_sms_summary(self):
|
||||
if not self.has_permission('inbound_sms'):
|
||||
if not self.has_permission("inbound_sms"):
|
||||
return None
|
||||
return service_api_client.get_inbound_sms_summary(self.id)
|
||||
|
||||
@@ -452,35 +475,34 @@ class Service(JSONModel, SortByNameMixin):
|
||||
def all_template_folders(self):
|
||||
return sorted(
|
||||
template_folder_api_client.get_template_folders(self.id),
|
||||
key=lambda folder: folder['name'].lower(),
|
||||
key=lambda folder: folder["name"].lower(),
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def all_template_folder_ids(self):
|
||||
return {folder['id'] for folder in self.all_template_folders}
|
||||
return {folder["id"] for folder in self.all_template_folders}
|
||||
|
||||
def get_template_folder(self, folder_id):
|
||||
if folder_id is None:
|
||||
return {
|
||||
'id': None,
|
||||
'name': 'Templates',
|
||||
'parent_id': None,
|
||||
"id": None,
|
||||
"name": "Templates",
|
||||
"parent_id": None,
|
||||
}
|
||||
return self._get_by_id(self.all_template_folders, folder_id)
|
||||
|
||||
def get_template_folder_path(self, template_folder_id):
|
||||
|
||||
folder = self.get_template_folder(template_folder_id)
|
||||
|
||||
if folder['id'] is None:
|
||||
if folder["id"] is None:
|
||||
return [folder]
|
||||
|
||||
return self.get_template_folder_path(folder['parent_id']) + [
|
||||
self.get_template_folder(folder['id'])
|
||||
return self.get_template_folder_path(folder["parent_id"]) + [
|
||||
self.get_template_folder(folder["id"])
|
||||
]
|
||||
|
||||
def get_template_path(self, template):
|
||||
return self.get_template_folder_path(template['folder']) + [
|
||||
return self.get_template_folder_path(template["folder"]) + [
|
||||
template,
|
||||
]
|
||||
|
||||
@@ -489,7 +511,6 @@ class Service(JSONModel, SortByNameMixin):
|
||||
return len(self.all_templates + self.all_template_folders)
|
||||
|
||||
def move_to_folder(self, ids_to_move, move_to):
|
||||
|
||||
ids_to_move = set(ids_to_move)
|
||||
|
||||
template_folder_api_client.move_to_folder(
|
||||
@@ -502,8 +523,8 @@ class Service(JSONModel, SortByNameMixin):
|
||||
@cached_property
|
||||
def api_keys(self):
|
||||
return sorted(
|
||||
api_key_api_client.get_api_keys(self.id)['apiKeys'],
|
||||
key=lambda key: key['name'].lower(),
|
||||
api_key_api_client.get_api_keys(self.id)["apiKeys"],
|
||||
key=lambda key: key["name"].lower(),
|
||||
)
|
||||
|
||||
def get_api_key(self, id):
|
||||
|
||||
@@ -6,26 +6,21 @@ import pyexcel
|
||||
import pyexcel_xlsx
|
||||
|
||||
|
||||
class Spreadsheet():
|
||||
|
||||
ALLOWED_FILE_EXTENSIONS = ('csv', 'xlsx', 'xls', 'ods', 'xlsm', 'tsv')
|
||||
|
||||
def __init__(self, csv_data=None, rows=None, filename=''):
|
||||
class Spreadsheet:
|
||||
ALLOWED_FILE_EXTENSIONS = ("csv", "xlsx", "xls", "ods", "xlsm", "tsv")
|
||||
|
||||
def __init__(self, csv_data=None, rows=None, filename=""):
|
||||
self.filename = filename
|
||||
|
||||
if csv_data and rows:
|
||||
raise TypeError('Spreadsheet must be created from either rows or CSV data')
|
||||
raise TypeError("Spreadsheet must be created from either rows or CSV data")
|
||||
|
||||
self._csv_data = csv_data or ''
|
||||
self._csv_data = csv_data or ""
|
||||
self._rows = rows or []
|
||||
|
||||
@property
|
||||
def as_dict(self):
|
||||
return {
|
||||
'file_name': self.filename,
|
||||
'data': self.as_csv_data
|
||||
}
|
||||
return {"file_name": self.filename, "data": self.as_csv_data}
|
||||
|
||||
@property
|
||||
def as_csv_data(self):
|
||||
@@ -43,37 +38,36 @@ class Spreadsheet():
|
||||
|
||||
@staticmethod
|
||||
def get_extension(filename):
|
||||
return path.splitext(filename)[1].lower().lstrip('.')
|
||||
return path.splitext(filename)[1].lower().lstrip(".")
|
||||
|
||||
@staticmethod
|
||||
def normalise_newlines(file_content):
|
||||
return '\r\n'.join(file_content.read().decode('utf-8').splitlines())
|
||||
return "\r\n".join(file_content.read().decode("utf-8").splitlines())
|
||||
|
||||
@classmethod
|
||||
def from_rows(cls, rows, filename=''):
|
||||
def from_rows(cls, rows, filename=""):
|
||||
return cls(rows=rows, filename=filename)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, dictionary, filename=''):
|
||||
def from_dict(cls, dictionary, filename=""):
|
||||
return cls.from_rows(
|
||||
zip(
|
||||
*sorted(dictionary.items(), key=lambda pair: pair[0])
|
||||
),
|
||||
zip(*sorted(dictionary.items(), key=lambda pair: pair[0])),
|
||||
filename=filename,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_file(cls, file_content, filename=''):
|
||||
def from_file(cls, file_content, filename=""):
|
||||
extension = cls.get_extension(filename)
|
||||
|
||||
if extension == 'csv':
|
||||
return cls(csv_data=Spreadsheet.normalise_newlines(file_content), filename=filename)
|
||||
if extension == "csv":
|
||||
return cls(
|
||||
csv_data=Spreadsheet.normalise_newlines(file_content), filename=filename
|
||||
)
|
||||
|
||||
if extension == 'tsv':
|
||||
file_content = StringIO(
|
||||
Spreadsheet.normalise_newlines(file_content))
|
||||
if extension == "tsv":
|
||||
file_content = StringIO(Spreadsheet.normalise_newlines(file_content))
|
||||
|
||||
if extension == 'xlsm':
|
||||
if extension == "xlsm":
|
||||
file_data = pyexcel_xlsx.get_data(file_content)
|
||||
instance = cls.from_rows(
|
||||
# Get the first sheet from the workbook
|
||||
@@ -83,10 +77,8 @@ class Spreadsheet():
|
||||
return instance
|
||||
|
||||
instance = cls.from_rows(
|
||||
pyexcel.iget_array(
|
||||
file_type=extension,
|
||||
file_stream=file_content),
|
||||
filename)
|
||||
pyexcel.iget_array(file_type=extension, file_stream=file_content), filename
|
||||
)
|
||||
pyexcel.free_resources()
|
||||
return instance
|
||||
|
||||
|
||||
@@ -3,12 +3,11 @@ from werkzeug.utils import cached_property
|
||||
from app import format_notification_type
|
||||
|
||||
|
||||
class TemplateList():
|
||||
|
||||
class TemplateList:
|
||||
def __init__(
|
||||
self,
|
||||
service,
|
||||
template_type='all',
|
||||
template_type="all",
|
||||
template_folder_id=None,
|
||||
user=None,
|
||||
):
|
||||
@@ -22,33 +21,35 @@ class TemplateList():
|
||||
|
||||
@cached_property
|
||||
def items(self):
|
||||
return list(self.get_templates_and_folders(
|
||||
self.template_type, self.template_folder_id, ancestors=[]
|
||||
))
|
||||
return list(
|
||||
self.get_templates_and_folders(
|
||||
self.template_type, self.template_folder_id, ancestors=[]
|
||||
)
|
||||
)
|
||||
|
||||
def get_templates_and_folders(self, template_type, template_folder_id, ancestors):
|
||||
|
||||
for item in self.get_template_folders(
|
||||
template_type, template_folder_id,
|
||||
template_type,
|
||||
template_folder_id,
|
||||
):
|
||||
yield TemplateListFolder(
|
||||
item,
|
||||
folders=self.get_template_folders(
|
||||
template_type, item['id'],
|
||||
),
|
||||
templates=self.get_templates(
|
||||
template_type, item['id']
|
||||
template_type,
|
||||
item["id"],
|
||||
),
|
||||
templates=self.get_templates(template_type, item["id"]),
|
||||
ancestors=ancestors,
|
||||
service_id=self.service.id,
|
||||
)
|
||||
for sub_item in self.get_templates_and_folders(
|
||||
template_type, item['id'], ancestors + [item]
|
||||
template_type, item["id"], ancestors + [item]
|
||||
):
|
||||
yield sub_item
|
||||
|
||||
for item in self.get_templates(
|
||||
template_type, template_folder_id,
|
||||
template_type,
|
||||
template_folder_id,
|
||||
):
|
||||
yield TemplateListTemplate(
|
||||
item,
|
||||
@@ -56,7 +57,7 @@ class TemplateList():
|
||||
service_id=self.service.id,
|
||||
)
|
||||
|
||||
def get_templates(self, template_type='all', template_folder_id=None):
|
||||
def get_templates(self, template_type="all", template_folder_id=None):
|
||||
if self.user and template_folder_id:
|
||||
folder = self.service.get_template_folder(template_folder_id)
|
||||
if not self.user.has_template_folder_permission(folder):
|
||||
@@ -67,9 +68,10 @@ class TemplateList():
|
||||
if template_folder_id:
|
||||
template_folder_id = str(template_folder_id)
|
||||
return [
|
||||
template for template in self.service.all_templates
|
||||
if (set(template_type) & {'all', template['template_type']})
|
||||
and template.get('folder') == template_folder_id
|
||||
template
|
||||
for template in self.service.all_templates
|
||||
if (set(template_type) & {"all", template["template_type"]})
|
||||
and template.get("folder") == template_folder_id
|
||||
]
|
||||
|
||||
@cached_property
|
||||
@@ -89,15 +91,19 @@ class TemplateList():
|
||||
"""
|
||||
user_folders = []
|
||||
for folder in self.service.all_template_folders:
|
||||
if not self.user.has_template_folder_permission(folder, service=self.service):
|
||||
if not self.user.has_template_folder_permission(
|
||||
folder, service=self.service
|
||||
):
|
||||
continue
|
||||
parent = self.service.get_template_folder(folder["parent_id"])
|
||||
if self.user.has_template_folder_permission(parent, service=self.service):
|
||||
user_folders.append(folder)
|
||||
else:
|
||||
folder_attrs = {
|
||||
"id": folder["id"], "name": folder["name"], "parent_id": folder["parent_id"],
|
||||
"users_with_permission": folder["users_with_permission"]
|
||||
"id": folder["id"],
|
||||
"name": folder["name"],
|
||||
"parent_id": folder["parent_id"],
|
||||
"users_with_permission": folder["users_with_permission"],
|
||||
}
|
||||
while folder_attrs["parent_id"] is not None:
|
||||
folder_attrs["name"] = [
|
||||
@@ -109,12 +115,14 @@ class TemplateList():
|
||||
else:
|
||||
parent = self.service.get_template_folder(parent["parent_id"])
|
||||
folder_attrs["parent_id"] = parent.get("id", None)
|
||||
if self.user.has_template_folder_permission(parent, service=self.service):
|
||||
if self.user.has_template_folder_permission(
|
||||
parent, service=self.service
|
||||
):
|
||||
break
|
||||
user_folders.append(folder_attrs)
|
||||
return user_folders
|
||||
|
||||
def get_template_folders(self, template_type='all', parent_folder_id=None):
|
||||
def get_template_folders(self, template_type="all", parent_folder_id=None):
|
||||
if self.user:
|
||||
folders = self.user_template_folders
|
||||
else:
|
||||
@@ -123,24 +131,26 @@ class TemplateList():
|
||||
parent_folder_id = str(parent_folder_id)
|
||||
|
||||
return [
|
||||
folder for folder in folders
|
||||
folder
|
||||
for folder in folders
|
||||
if (
|
||||
folder['parent_id'] == parent_folder_id
|
||||
and self.is_folder_visible(folder['id'], template_type)
|
||||
folder["parent_id"] == parent_folder_id
|
||||
and self.is_folder_visible(folder["id"], template_type)
|
||||
)
|
||||
]
|
||||
|
||||
def is_folder_visible(self, template_folder_id, template_type='all'):
|
||||
|
||||
if template_type == 'all':
|
||||
def is_folder_visible(self, template_folder_id, template_type="all"):
|
||||
if template_type == "all":
|
||||
return True
|
||||
|
||||
if self.get_templates(template_type, template_folder_id):
|
||||
return True
|
||||
|
||||
if any(
|
||||
self.is_folder_visible(child_folder['id'], template_type)
|
||||
for child_folder in self.get_template_folders(template_type, template_folder_id)
|
||||
self.is_folder_visible(child_folder["id"], template_type)
|
||||
for child_folder in self.get_template_folders(
|
||||
template_type, template_folder_id
|
||||
)
|
||||
):
|
||||
return True
|
||||
|
||||
@@ -156,9 +166,9 @@ class TemplateList():
|
||||
|
||||
@property
|
||||
def folder_is_empty(self):
|
||||
return not any(self.get_templates_and_folders(
|
||||
'all', self.template_folder_id, []
|
||||
))
|
||||
return not any(
|
||||
self.get_templates_and_folders("all", self.template_folder_id, [])
|
||||
)
|
||||
|
||||
|
||||
class ServiceTemplateList(TemplateList):
|
||||
@@ -178,12 +188,11 @@ class ServiceTemplateList(TemplateList):
|
||||
yield from self.get_templates_and_folders(
|
||||
self.template_type,
|
||||
self.template_folder_id,
|
||||
ancestors=[template_list_service]
|
||||
ancestors=[template_list_service],
|
||||
)
|
||||
|
||||
|
||||
class TemplateLists():
|
||||
|
||||
class TemplateLists:
|
||||
def __init__(self, user):
|
||||
self.services = sorted(
|
||||
user.services,
|
||||
@@ -210,8 +219,7 @@ class TemplateLists():
|
||||
return bool(self.services)
|
||||
|
||||
|
||||
class TemplateListItem():
|
||||
|
||||
class TemplateListItem:
|
||||
is_service = False
|
||||
|
||||
def __init__(
|
||||
@@ -219,13 +227,12 @@ class TemplateListItem():
|
||||
template_or_folder,
|
||||
ancestors,
|
||||
):
|
||||
self.id = template_or_folder['id']
|
||||
self.name = template_or_folder['name']
|
||||
self.id = template_or_folder["id"]
|
||||
self.name = template_or_folder["name"]
|
||||
self.ancestors = ancestors
|
||||
|
||||
|
||||
class TemplateListTemplate(TemplateListItem):
|
||||
|
||||
is_folder = False
|
||||
|
||||
def __init__(
|
||||
@@ -236,16 +243,15 @@ class TemplateListTemplate(TemplateListItem):
|
||||
):
|
||||
super().__init__(template, ancestors)
|
||||
self.service_id = service_id
|
||||
self.template_type = template['template_type']
|
||||
self.content = template.get('content')
|
||||
self.template_type = template["template_type"]
|
||||
self.content = template.get("content")
|
||||
|
||||
@property
|
||||
def hint(self):
|
||||
return format_notification_type(self.template_type) + ' template'
|
||||
return format_notification_type(self.template_type) + " template"
|
||||
|
||||
|
||||
class TemplateListFolder(TemplateListItem):
|
||||
|
||||
is_folder = True
|
||||
|
||||
def __init__(
|
||||
@@ -264,23 +270,22 @@ class TemplateListFolder(TemplateListItem):
|
||||
|
||||
@property
|
||||
def _hint_parts(self):
|
||||
|
||||
if self.number_of_folders == self.number_of_templates == 0:
|
||||
yield 'Empty'
|
||||
yield "Empty"
|
||||
|
||||
if self.number_of_templates == 1:
|
||||
yield '1 template'
|
||||
yield "1 template"
|
||||
elif self.number_of_templates > 1:
|
||||
yield '{} templates'.format(self.number_of_templates)
|
||||
yield "{} templates".format(self.number_of_templates)
|
||||
|
||||
if self.number_of_folders == 1:
|
||||
yield '1 folder'
|
||||
yield "1 folder"
|
||||
elif self.number_of_folders > 1:
|
||||
yield '{} folders'.format(self.number_of_folders)
|
||||
yield "{} folders".format(self.number_of_folders)
|
||||
|
||||
@property
|
||||
def hint(self):
|
||||
return ', '.join(self._hint_parts)
|
||||
return ", ".join(self._hint_parts)
|
||||
|
||||
|
||||
class TemplateListService(TemplateListFolder):
|
||||
|
||||
@@ -24,36 +24,35 @@ from app.utils.user_permissions import (
|
||||
|
||||
|
||||
def _get_service_id_from_view_args():
|
||||
return str(request.view_args.get('service_id', '')) or None
|
||||
return str(request.view_args.get("service_id", "")) or None
|
||||
|
||||
|
||||
def _get_org_id_from_view_args():
|
||||
return str(request.view_args.get('org_id', '')) or None
|
||||
return str(request.view_args.get("org_id", "")) or None
|
||||
|
||||
|
||||
class User(JSONModel, UserMixin):
|
||||
|
||||
MAX_FAILED_LOGIN_COUNT = 10
|
||||
|
||||
ALLOWED_PROPERTIES = {
|
||||
'id',
|
||||
'name',
|
||||
'email_address',
|
||||
'auth_type',
|
||||
'current_session_id',
|
||||
'failed_login_count',
|
||||
'email_access_validated_at',
|
||||
'logged_in_at',
|
||||
'mobile_number',
|
||||
'password_changed_at',
|
||||
'permissions',
|
||||
'state',
|
||||
"id",
|
||||
"name",
|
||||
"email_address",
|
||||
"auth_type",
|
||||
"current_session_id",
|
||||
"failed_login_count",
|
||||
"email_access_validated_at",
|
||||
"logged_in_at",
|
||||
"mobile_number",
|
||||
"password_changed_at",
|
||||
"permissions",
|
||||
"state",
|
||||
}
|
||||
|
||||
def __init__(self, _dict):
|
||||
super().__init__(_dict)
|
||||
self.permissions = _dict.get('permissions', {})
|
||||
self._platform_admin = _dict['platform_admin']
|
||||
self.permissions = _dict.get("permissions", {})
|
||||
self._platform_admin = _dict["platform_admin"]
|
||||
|
||||
@classmethod
|
||||
def from_id(cls, user_id):
|
||||
@@ -104,8 +103,7 @@ class User(JSONModel, UserMixin):
|
||||
"""
|
||||
self._permissions = {
|
||||
service: translate_permissions_from_db_to_ui(permissions)
|
||||
for service, permissions
|
||||
in permissions_by_service.items()
|
||||
for service, permissions in permissions_by_service.items()
|
||||
}
|
||||
|
||||
def update(self, **kwargs):
|
||||
@@ -117,9 +115,7 @@ class User(JSONModel, UserMixin):
|
||||
self.__init__(response)
|
||||
|
||||
def update_email_access_validated_at(self):
|
||||
self.update(
|
||||
email_access_validated_at=datetime.utcnow().isoformat()
|
||||
)
|
||||
self.update(email_access_validated_at=datetime.utcnow().isoformat())
|
||||
|
||||
def password_changed_more_recently_than(self, datetime_string):
|
||||
if not self.password_changed_at:
|
||||
@@ -144,24 +140,26 @@ class User(JSONModel, UserMixin):
|
||||
)
|
||||
|
||||
def logged_in_elsewhere(self):
|
||||
return session.get('current_session_id') != self.current_session_id
|
||||
return session.get("current_session_id") != self.current_session_id
|
||||
|
||||
def activate(self):
|
||||
if self.is_pending:
|
||||
user_data = user_api_client.activate_user(self.id)
|
||||
return self.__class__(user_data['data'])
|
||||
return self.__class__(user_data["data"])
|
||||
else:
|
||||
return self
|
||||
|
||||
def login(self):
|
||||
login_user(self)
|
||||
session['user_id'] = self.id
|
||||
session["user_id"] = self.id
|
||||
|
||||
def send_login_code(self):
|
||||
if self.email_auth:
|
||||
user_api_client.send_verify_code(self.id, 'email', None, request.args.get('next'))
|
||||
user_api_client.send_verify_code(
|
||||
self.id, "email", None, request.args.get("next")
|
||||
)
|
||||
if self.sms_auth:
|
||||
user_api_client.send_verify_code(self.id, 'sms', self.mobile_number)
|
||||
user_api_client.send_verify_code(self.id, "sms", self.mobile_number)
|
||||
|
||||
def sign_out(self):
|
||||
session.clear()
|
||||
@@ -172,22 +170,22 @@ class User(JSONModel, UserMixin):
|
||||
|
||||
@property
|
||||
def sms_auth(self):
|
||||
return self.auth_type == 'sms_auth'
|
||||
return self.auth_type == "sms_auth"
|
||||
|
||||
@property
|
||||
def email_auth(self):
|
||||
return self.auth_type == 'email_auth'
|
||||
return self.auth_type == "email_auth"
|
||||
|
||||
def reset_failed_login_count(self):
|
||||
user_api_client.reset_failed_login_count(self.id)
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
return self.state == 'active'
|
||||
return self.state == "active"
|
||||
|
||||
@property
|
||||
def is_pending(self):
|
||||
return self.state == 'pending'
|
||||
return self.state == "pending"
|
||||
|
||||
@property
|
||||
def is_gov_user(self):
|
||||
@@ -197,20 +195,25 @@ class User(JSONModel, UserMixin):
|
||||
|
||||
@property
|
||||
def is_authenticated(self):
|
||||
return (
|
||||
not self.logged_in_elsewhere() and
|
||||
super(User, self).is_authenticated
|
||||
)
|
||||
return not self.logged_in_elsewhere() and super(User, self).is_authenticated
|
||||
|
||||
@property
|
||||
def platform_admin(self):
|
||||
current_app.logger.warn(f"Checking User {self.id} for platform admin: {self._platform_admin}")
|
||||
return self._platform_admin and not session.get('disable_platform_admin_view', False)
|
||||
current_app.logger.warn(
|
||||
f"Checking User {self.id} for platform admin: {self._platform_admin}"
|
||||
)
|
||||
return self._platform_admin and not session.get(
|
||||
"disable_platform_admin_view", False
|
||||
)
|
||||
|
||||
def has_permissions(self, *permissions, restrict_admin_usage=False, allow_org_user=False):
|
||||
def has_permissions(
|
||||
self, *permissions, restrict_admin_usage=False, allow_org_user=False
|
||||
):
|
||||
unknown_permissions = set(permissions) - all_ui_permissions
|
||||
if unknown_permissions:
|
||||
raise TypeError('{} are not valid permissions'.format(list(unknown_permissions)))
|
||||
raise TypeError(
|
||||
"{} are not valid permissions".format(list(unknown_permissions))
|
||||
)
|
||||
|
||||
# Service id is always set on the request for service specific views.
|
||||
service_id = _get_service_id_from_view_args()
|
||||
@@ -236,9 +239,7 @@ class User(JSONModel, UserMixin):
|
||||
current_app.logger.warn(f"{log_msg} True because belongs_to_service")
|
||||
return True
|
||||
|
||||
if any(
|
||||
self.permissions_for_service(service_id) & set(permissions)
|
||||
):
|
||||
if any(self.permissions_for_service(service_id) & set(permissions)):
|
||||
current_app.logger.warn(f"{log_msg} permissions valid")
|
||||
return True
|
||||
|
||||
@@ -266,7 +267,7 @@ class User(JSONModel, UserMixin):
|
||||
return True
|
||||
|
||||
# Top-level templates are always visible
|
||||
if template_folder is None or template_folder['id'] is None:
|
||||
if template_folder is None or template_folder["id"] is None:
|
||||
return True
|
||||
|
||||
return self.id in template_folder.get("users_with_permission", [])
|
||||
@@ -297,7 +298,7 @@ class User(JSONModel, UserMixin):
|
||||
|
||||
@property
|
||||
def email_domain(self):
|
||||
return self.email_address.split('@')[-1]
|
||||
return self.email_address.split("@")[-1]
|
||||
|
||||
@cached_property
|
||||
def orgs_and_services(self):
|
||||
@@ -306,38 +307,36 @@ class User(JSONModel, UserMixin):
|
||||
@property
|
||||
def services(self):
|
||||
from app.models.service import Services
|
||||
return Services(self.orgs_and_services['services'])
|
||||
|
||||
return Services(self.orgs_and_services["services"])
|
||||
|
||||
@property
|
||||
def services_with_organization(self):
|
||||
return [
|
||||
service for service in self.services
|
||||
service
|
||||
for service in self.services
|
||||
if self.belongs_to_organization(service.organization_id)
|
||||
]
|
||||
|
||||
@property
|
||||
def service_ids(self):
|
||||
return self._dict['services']
|
||||
return self._dict["services"]
|
||||
|
||||
@property
|
||||
def trial_mode_services(self):
|
||||
return [
|
||||
service for service in self.services if service.trial_mode
|
||||
]
|
||||
return [service for service in self.services if service.trial_mode]
|
||||
|
||||
@property
|
||||
def live_services(self):
|
||||
return [
|
||||
service for service in self.services if service.live
|
||||
]
|
||||
return [service for service in self.services if service.live]
|
||||
|
||||
@property
|
||||
def organizations(self):
|
||||
return Organizations(self.orgs_and_services['organizations'])
|
||||
return Organizations(self.orgs_and_services["organizations"])
|
||||
|
||||
@property
|
||||
def organization_ids(self):
|
||||
return self._dict['organizations']
|
||||
return self._dict["organizations"]
|
||||
|
||||
@cached_property
|
||||
def default_organization(self):
|
||||
@@ -351,11 +350,7 @@ class User(JSONModel, UserMixin):
|
||||
|
||||
@property
|
||||
def has_access_to_live_and_trial_mode_services(self):
|
||||
return (
|
||||
self.organizations or self.live_services
|
||||
) and (
|
||||
self.trial_mode_services
|
||||
)
|
||||
return (self.organizations or self.live_services) and (self.trial_mode_services)
|
||||
|
||||
def serialize(self):
|
||||
dct = {
|
||||
@@ -368,10 +363,10 @@ class User(JSONModel, UserMixin):
|
||||
"failed_login_count": self.failed_login_count,
|
||||
"permissions": [x for x in self._permissions],
|
||||
"organizations": self.organization_ids,
|
||||
"current_session_id": self.current_session_id
|
||||
"current_session_id": self.current_session_id,
|
||||
}
|
||||
if hasattr(self, '_password'):
|
||||
dct['password'] = self._password
|
||||
if hasattr(self, "_password"):
|
||||
dct["password"] = self._password
|
||||
return dct
|
||||
|
||||
@classmethod
|
||||
@@ -383,13 +378,15 @@ class User(JSONModel, UserMixin):
|
||||
password,
|
||||
auth_type,
|
||||
):
|
||||
return cls(user_api_client.register_user(
|
||||
name,
|
||||
email_address,
|
||||
mobile_number or None,
|
||||
password,
|
||||
auth_type,
|
||||
))
|
||||
return cls(
|
||||
user_api_client.register_user(
|
||||
name,
|
||||
email_address,
|
||||
mobile_number or None,
|
||||
password,
|
||||
auth_type,
|
||||
)
|
||||
)
|
||||
|
||||
def set_password(self, pwd):
|
||||
self._password = pwd
|
||||
@@ -398,16 +395,20 @@ class User(JSONModel, UserMixin):
|
||||
user_api_client.send_verify_email(self.id, self.email_address)
|
||||
|
||||
def send_verify_code(self, to=None):
|
||||
user_api_client.send_verify_code(self.id, 'sms', to or self.mobile_number)
|
||||
user_api_client.send_verify_code(self.id, "sms", to or self.mobile_number)
|
||||
|
||||
def send_already_registered_email(self):
|
||||
user_api_client.send_already_registered_email(self.id, self.email_address)
|
||||
|
||||
def refresh_session_id(self):
|
||||
self.current_session_id = user_api_client.get_user(self.id).get('current_session_id')
|
||||
session['current_session_id'] = self.current_session_id
|
||||
self.current_session_id = user_api_client.get_user(self.id).get(
|
||||
"current_session_id"
|
||||
)
|
||||
session["current_session_id"] = self.current_session_id
|
||||
|
||||
def add_to_service(self, service_id, permissions, folder_permissions, invited_by_id):
|
||||
def add_to_service(
|
||||
self, service_id, permissions, folder_permissions, invited_by_id
|
||||
):
|
||||
try:
|
||||
user_api_client.add_user_to_service(
|
||||
service_id,
|
||||
@@ -422,7 +423,10 @@ class User(JSONModel, UserMixin):
|
||||
ui_permissions=permissions,
|
||||
)
|
||||
except HTTPError as exception:
|
||||
if exception.status_code == 400 and 'already part of service' in exception.message:
|
||||
if (
|
||||
exception.status_code == 400
|
||||
and "already part of service" in exception.message
|
||||
):
|
||||
pass
|
||||
else:
|
||||
raise exception
|
||||
@@ -442,22 +446,21 @@ class User(JSONModel, UserMixin):
|
||||
|
||||
|
||||
class InvitedUser(JSONModel):
|
||||
|
||||
ALLOWED_PROPERTIES = {
|
||||
'id',
|
||||
'service',
|
||||
'email_address',
|
||||
'permissions',
|
||||
'status',
|
||||
'created_at',
|
||||
'auth_type',
|
||||
'folder_permissions',
|
||||
"id",
|
||||
"service",
|
||||
"email_address",
|
||||
"permissions",
|
||||
"status",
|
||||
"created_at",
|
||||
"auth_type",
|
||||
"folder_permissions",
|
||||
}
|
||||
|
||||
def __init__(self, _dict):
|
||||
super().__init__(_dict)
|
||||
self.permissions = _dict.get('permissions') or []
|
||||
self._from_user = _dict['from_user']
|
||||
self.permissions = _dict.get("permissions") or []
|
||||
self._from_user = _dict["from_user"]
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
@@ -469,14 +472,16 @@ class InvitedUser(JSONModel):
|
||||
auth_type,
|
||||
folder_permissions,
|
||||
):
|
||||
return cls(invite_api_client.create_invite(
|
||||
invite_from_id,
|
||||
service_id,
|
||||
email_address,
|
||||
permissions,
|
||||
auth_type,
|
||||
folder_permissions,
|
||||
))
|
||||
return cls(
|
||||
invite_api_client.create_invite(
|
||||
invite_from_id,
|
||||
service_id,
|
||||
email_address,
|
||||
permissions,
|
||||
auth_type,
|
||||
folder_permissions,
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def by_id_and_service_id(cls, service_id, invited_user_id):
|
||||
@@ -486,9 +491,7 @@ class InvitedUser(JSONModel):
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, invited_user_id):
|
||||
return cls(
|
||||
invite_api_client.get_invited_user(invited_user_id)
|
||||
)
|
||||
return cls(invite_api_client.get_invited_user(invited_user_id))
|
||||
|
||||
def accept_invite(self):
|
||||
invite_api_client.accept_invite(self.service, self.id)
|
||||
@@ -502,7 +505,7 @@ class InvitedUser(JSONModel):
|
||||
if isinstance(permissions, list):
|
||||
self._permissions = permissions
|
||||
else:
|
||||
self._permissions = permissions.split(',')
|
||||
self._permissions = permissions.split(",")
|
||||
self._permissions = translate_permissions_from_db_to_ui(self.permissions)
|
||||
|
||||
@property
|
||||
@@ -511,110 +514,122 @@ class InvitedUser(JSONModel):
|
||||
|
||||
@property
|
||||
def sms_auth(self):
|
||||
return self.auth_type == 'sms_auth'
|
||||
return self.auth_type == "sms_auth"
|
||||
|
||||
@property
|
||||
def email_auth(self):
|
||||
return self.auth_type == 'email_auth'
|
||||
return self.auth_type == "email_auth"
|
||||
|
||||
@classmethod
|
||||
def from_token(cls, token):
|
||||
try:
|
||||
return cls(invite_api_client.check_token(token))
|
||||
except HTTPError as exception:
|
||||
if exception.status_code == 400 and 'invitation' in exception.message:
|
||||
raise InviteTokenError(exception.message['invitation'])
|
||||
if exception.status_code == 400 and "invitation" in exception.message:
|
||||
raise InviteTokenError(exception.message["invitation"])
|
||||
else:
|
||||
raise exception
|
||||
|
||||
@classmethod
|
||||
def from_session(cls):
|
||||
invited_user_id = session.get('invited_user_id')
|
||||
invited_user_id = session.get("invited_user_id")
|
||||
return cls.by_id(invited_user_id) if invited_user_id else None
|
||||
|
||||
def has_permissions(self, *permissions):
|
||||
current_app.logger.warn(f"Checking invited user {self.id} for permissions: {permissions}")
|
||||
if self.status == 'cancelled':
|
||||
current_app.logger.warn(
|
||||
f"Checking invited user {self.id} for permissions: {permissions}"
|
||||
)
|
||||
if self.status == "cancelled":
|
||||
return False
|
||||
return set(self.permissions) > set(permissions)
|
||||
|
||||
def has_permission_for_service(self, service_id, permission):
|
||||
current_app.logger.warn(f"Checking invited user {self.id} for permission: {permission} on service {service_id}")
|
||||
if self.status == 'cancelled':
|
||||
current_app.logger.warn(
|
||||
f"Checking invited user {self.id} for permission: {permission} on service {service_id}"
|
||||
)
|
||||
if self.status == "cancelled":
|
||||
return False
|
||||
return self.service == service_id and permission in self.permissions
|
||||
|
||||
def __eq__(self, other):
|
||||
return ((self.id,
|
||||
self.service,
|
||||
self._from_user,
|
||||
self.email_address,
|
||||
self.auth_type,
|
||||
self.status) == (other.id,
|
||||
other.service,
|
||||
other._from_user,
|
||||
other.email_address,
|
||||
other.auth_type,
|
||||
other.status))
|
||||
return (
|
||||
self.id,
|
||||
self.service,
|
||||
self._from_user,
|
||||
self.email_address,
|
||||
self.auth_type,
|
||||
self.status,
|
||||
) == (
|
||||
other.id,
|
||||
other.service,
|
||||
other._from_user,
|
||||
other.email_address,
|
||||
other.auth_type,
|
||||
other.status,
|
||||
)
|
||||
|
||||
def serialize(self, permissions_as_string=False):
|
||||
data = {'id': self.id,
|
||||
'service': self.service,
|
||||
'from_user': self._from_user,
|
||||
'email_address': self.email_address,
|
||||
'status': self.status,
|
||||
'created_at': str(self.created_at),
|
||||
'auth_type': self.auth_type,
|
||||
'folder_permissions': self.folder_permissions
|
||||
}
|
||||
data = {
|
||||
"id": self.id,
|
||||
"service": self.service,
|
||||
"from_user": self._from_user,
|
||||
"email_address": self.email_address,
|
||||
"status": self.status,
|
||||
"created_at": str(self.created_at),
|
||||
"auth_type": self.auth_type,
|
||||
"folder_permissions": self.folder_permissions,
|
||||
}
|
||||
if permissions_as_string:
|
||||
data['permissions'] = ','.join(self.permissions)
|
||||
data["permissions"] = ",".join(self.permissions)
|
||||
else:
|
||||
data['permissions'] = sorted(self.permissions)
|
||||
data["permissions"] = sorted(self.permissions)
|
||||
return data
|
||||
|
||||
def template_folders_for_service(self, service=None):
|
||||
# only used on the manage users page to display the count, so okay to not be fully fledged for now
|
||||
return [{'id': x} for x in self.folder_permissions]
|
||||
return [{"id": x} for x in self.folder_permissions]
|
||||
|
||||
def is_editable_by(self, other):
|
||||
return False
|
||||
|
||||
|
||||
class InvitedOrgUser(JSONModel):
|
||||
|
||||
ALLOWED_PROPERTIES = {
|
||||
'id',
|
||||
'organization',
|
||||
'email_address',
|
||||
'status',
|
||||
'created_at',
|
||||
"id",
|
||||
"organization",
|
||||
"email_address",
|
||||
"status",
|
||||
"created_at",
|
||||
}
|
||||
|
||||
def __init__(self, _dict):
|
||||
super().__init__(_dict)
|
||||
self._invited_by = _dict['invited_by']
|
||||
self._invited_by = _dict["invited_by"]
|
||||
|
||||
def __eq__(self, other):
|
||||
return ((self.id,
|
||||
self.organization,
|
||||
self._invited_by,
|
||||
self.email_address,
|
||||
self.status) == (other.id,
|
||||
other.organization,
|
||||
other._invited_by,
|
||||
other.email_address,
|
||||
other.status))
|
||||
return (
|
||||
self.id,
|
||||
self.organization,
|
||||
self._invited_by,
|
||||
self.email_address,
|
||||
self.status,
|
||||
) == (
|
||||
other.id,
|
||||
other.organization,
|
||||
other._invited_by,
|
||||
other.email_address,
|
||||
other.status,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def create(cls, invite_from_id, org_id, email_address):
|
||||
return cls(org_invite_api_client.create_invite(
|
||||
invite_from_id, org_id, email_address
|
||||
))
|
||||
return cls(
|
||||
org_invite_api_client.create_invite(invite_from_id, org_id, email_address)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_session(cls):
|
||||
invited_org_user_id = session.get('invited_org_user_id')
|
||||
invited_org_user_id = session.get("invited_org_user_id")
|
||||
return cls.by_id(invited_org_user_id) if invited_org_user_id else None
|
||||
|
||||
@classmethod
|
||||
@@ -625,18 +640,17 @@ class InvitedOrgUser(JSONModel):
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, invited_user_id):
|
||||
return cls(
|
||||
org_invite_api_client.get_invited_user(invited_user_id)
|
||||
)
|
||||
return cls(org_invite_api_client.get_invited_user(invited_user_id))
|
||||
|
||||
def serialize(self, permissions_as_string=False):
|
||||
data = {'id': self.id,
|
||||
'organization': self.organization,
|
||||
'invited_by': self._invited_by,
|
||||
'email_address': self.email_address,
|
||||
'status': self.status,
|
||||
'created_at': str(self.created_at)
|
||||
}
|
||||
data = {
|
||||
"id": self.id,
|
||||
"organization": self.organization,
|
||||
"invited_by": self._invited_by,
|
||||
"email_address": self.email_address,
|
||||
"status": self.status,
|
||||
"created_at": str(self.created_at),
|
||||
}
|
||||
return data
|
||||
|
||||
@property
|
||||
@@ -648,8 +662,8 @@ class InvitedOrgUser(JSONModel):
|
||||
try:
|
||||
return cls(org_invite_api_client.check_token(token))
|
||||
except HTTPError as exception:
|
||||
if exception.status_code == 400 and 'invitation' in exception.message:
|
||||
raise InviteTokenError(exception.message['invitation'])
|
||||
if exception.status_code == 400 and "invitation" in exception.message:
|
||||
raise InviteTokenError(exception.message["invitation"])
|
||||
else:
|
||||
raise exception
|
||||
|
||||
@@ -669,7 +683,6 @@ class AnonymousUser(AnonymousUserMixin):
|
||||
|
||||
|
||||
class Users(ModelList):
|
||||
|
||||
client_method = user_api_client.get_users_for_service
|
||||
model = User
|
||||
|
||||
@@ -683,7 +696,7 @@ class Users(ModelList):
|
||||
user = User.from_id(id)
|
||||
if user and user.name:
|
||||
return user.name
|
||||
return 'Unknown'
|
||||
return "Unknown"
|
||||
|
||||
|
||||
class OrganizationUsers(Users):
|
||||
@@ -691,14 +704,14 @@ class OrganizationUsers(Users):
|
||||
|
||||
|
||||
class InvitedUsers(Users):
|
||||
|
||||
client_method = invite_api_client.get_invites_for_service
|
||||
model = InvitedUser
|
||||
|
||||
def __init__(self, service_id):
|
||||
self.items = [
|
||||
user for user in self.client_method(service_id)
|
||||
if user['status'] != 'accepted'
|
||||
user
|
||||
for user in self.client_method(service_id)
|
||||
if user["status"] != "accepted"
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user