mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-24 16:24:08 -04:00
Compare commits
9 Commits
1bf55e7fa3
...
28f09674df
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28f09674df | ||
|
|
34aff103a0 | ||
|
|
de3730f04a | ||
|
|
1b8975ec32 | ||
|
|
6ee84af8f6 | ||
|
|
594dca06ab | ||
|
|
56175bd7aa | ||
|
|
e2e5d54af5 | ||
|
|
e9f6b93d85 |
35
app/enums.py
35
app/enums.py
@@ -16,6 +16,41 @@ class NotificationStatus(StrEnum):
|
||||
VALIDATION_FAILED = "validation-failed"
|
||||
CANCELLED = "cancelled"
|
||||
|
||||
@classmethod
|
||||
def sending_statuses(cls):
|
||||
return [cls.CREATED, cls.PENDING, cls.SENDING]
|
||||
|
||||
@classmethod
|
||||
def delivered_statuses(cls):
|
||||
return [cls.DELIVERED, cls.SENT]
|
||||
|
||||
@classmethod
|
||||
def failure_statuses(cls):
|
||||
return [
|
||||
cls.FAILED,
|
||||
cls.TEMPORARY_FAILURE,
|
||||
cls.PERMANENT_FAILURE,
|
||||
cls.TECHNICAL_FAILURE,
|
||||
cls.VALIDATION_FAILED,
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def requested_statuses(cls):
|
||||
return (
|
||||
cls.sending_statuses() + cls.delivered_statuses() + cls.failure_statuses()
|
||||
)
|
||||
|
||||
|
||||
class NotificationType(StrEnum):
|
||||
EMAIL = "email"
|
||||
SMS = "sms"
|
||||
|
||||
|
||||
class OrganizationType(StrEnum):
|
||||
FEDERAL = "federal"
|
||||
STATE = "state"
|
||||
OTHER = "other"
|
||||
|
||||
|
||||
class ApiKeyType(StrEnum):
|
||||
NORMAL = "normal"
|
||||
|
||||
@@ -17,6 +17,7 @@ from flask import render_template_string, url_for
|
||||
from flask.helpers import get_root_path
|
||||
from markupsafe import Markup
|
||||
|
||||
from app.enums import AuthType, NotificationStatus
|
||||
from app.utils.csv import get_user_preferred_timezone
|
||||
from app.utils.time import parse_naive_dt
|
||||
from notifications_utils.field import Field
|
||||
@@ -276,46 +277,53 @@ def format_notification_type(notification_type):
|
||||
def format_notification_status(status, template_type):
|
||||
return {
|
||||
"email": {
|
||||
"failed": "Failed",
|
||||
"technical-failure": "Technical failure",
|
||||
"temporary-failure": "Inbox not accepting messages right now",
|
||||
"permanent-failure": "Email address does not exist",
|
||||
"delivered": "Delivered",
|
||||
"sending": "Sending",
|
||||
"created": "Sending",
|
||||
"sent": "Delivered",
|
||||
NotificationStatus.FAILED: "Failed",
|
||||
NotificationStatus.TECHNICAL_FAILURE: "Technical failure",
|
||||
NotificationStatus.TEMPORARY_FAILURE: "Inbox not accepting messages right now",
|
||||
NotificationStatus.PERMANENT_FAILURE: "Email address does not exist",
|
||||
NotificationStatus.DELIVERED: "Delivered",
|
||||
NotificationStatus.SENDING: "Sending",
|
||||
NotificationStatus.CREATED: "Sending",
|
||||
NotificationStatus.SENT: "Delivered",
|
||||
},
|
||||
"sms": {
|
||||
"failed": "Failed",
|
||||
"technical-failure": "Technical failure",
|
||||
"temporary-failure": "Phone not accepting messages right now",
|
||||
"permanent-failure": "Not delivered",
|
||||
"delivered": "Delivered",
|
||||
"sending": "Sending",
|
||||
"created": "Sending",
|
||||
"pending": "Sending",
|
||||
"sent": "Sent",
|
||||
NotificationStatus.FAILED: "Failed",
|
||||
NotificationStatus.TECHNICAL_FAILURE: "Technical failure",
|
||||
NotificationStatus.TEMPORARY_FAILURE: "Phone not accepting messages right now",
|
||||
NotificationStatus.PERMANENT_FAILURE: "Not delivered",
|
||||
NotificationStatus.DELIVERED: "Delivered",
|
||||
NotificationStatus.SENDING: "Sending",
|
||||
NotificationStatus.CREATED: "Sending",
|
||||
NotificationStatus.PENDING: "Sending",
|
||||
NotificationStatus.SENT: "Sent",
|
||||
},
|
||||
}[template_type].get(status, status)
|
||||
|
||||
|
||||
def format_notification_status_as_time(status, created, updated):
|
||||
return dict.fromkeys(
|
||||
{"created", "pending", "sending"}, " since {}".format(created)
|
||||
{
|
||||
NotificationStatus.CREATED,
|
||||
NotificationStatus.PENDING,
|
||||
NotificationStatus.SENDING,
|
||||
},
|
||||
" since {}".format(created),
|
||||
).get(status, updated)
|
||||
|
||||
|
||||
def format_notification_status_as_field_status(status, notification_type):
|
||||
return {
|
||||
"failed": "error",
|
||||
"technical-failure": "error",
|
||||
"temporary-failure": "error",
|
||||
"permanent-failure": "error",
|
||||
"delivered": None,
|
||||
"sent": "sent-international" if notification_type == "sms" else None,
|
||||
"sending": "default",
|
||||
"created": "default",
|
||||
"pending": "default",
|
||||
NotificationStatus.FAILED: "error",
|
||||
NotificationStatus.TECHNICAL_FAILURE: "error",
|
||||
NotificationStatus.TEMPORARY_FAILURE: "error",
|
||||
NotificationStatus.PERMANENT_FAILURE: "error",
|
||||
NotificationStatus.DELIVERED: None,
|
||||
NotificationStatus.SENT: (
|
||||
"sent-international" if notification_type == "sms" else None
|
||||
),
|
||||
NotificationStatus.SENDING: "default",
|
||||
NotificationStatus.CREATED: "default",
|
||||
NotificationStatus.PENDING: "default",
|
||||
}.get(status, "error")
|
||||
|
||||
|
||||
@@ -323,9 +331,9 @@ def format_notification_status_as_url(status, notification_type):
|
||||
url = partial(url_for, "main.message_status")
|
||||
|
||||
if status not in {
|
||||
"technical-failure",
|
||||
"temporary-failure",
|
||||
"permanent-failure",
|
||||
NotificationStatus.TECHNICAL_FAILURE,
|
||||
NotificationStatus.TEMPORARY_FAILURE,
|
||||
NotificationStatus.PERMANENT_FAILURE,
|
||||
}:
|
||||
return None
|
||||
|
||||
@@ -559,8 +567,8 @@ def square_metres_to_square_miles(area):
|
||||
|
||||
def format_auth_type(auth_type, with_indefinite_article=False):
|
||||
indefinite_article, auth_type = {
|
||||
"email_auth": ("an", "Email link"),
|
||||
"sms_auth": ("a", "Text message code"),
|
||||
AuthType.EMAIL_AUTH: ("an", "Email link"),
|
||||
AuthType.SMS_AUTH: ("a", "Text message code"),
|
||||
}[auth_type]
|
||||
|
||||
if with_indefinite_article:
|
||||
|
||||
@@ -2,6 +2,7 @@ from flask import current_app, redirect, render_template, session, url_for
|
||||
from flask_login import current_user
|
||||
|
||||
from app import service_api_client
|
||||
from app.enums import OrganizationType
|
||||
from app.formatters import email_safe
|
||||
from app.main import main
|
||||
from app.main.forms import CreateServiceForm
|
||||
@@ -46,7 +47,7 @@ def _create_example_template(service_id):
|
||||
def add_service():
|
||||
default_organization_type = current_user.default_organization_type
|
||||
if default_organization_type is None:
|
||||
default_organization_type = "federal"
|
||||
default_organization_type = OrganizationType.FEDERAL
|
||||
form = CreateServiceForm(
|
||||
# This value is currently not useful but if it is not set it will result in a bug
|
||||
organization_type=default_organization_type
|
||||
|
||||
@@ -15,6 +15,7 @@ from app import (
|
||||
template_statistics_client,
|
||||
)
|
||||
from app.enums import ServicePermission
|
||||
from app.enums import JobStatus, NotificationStatus
|
||||
from app.main import main
|
||||
from app.main.views.user_profile import set_timezone
|
||||
from app.statistics_utils import get_formatted_percentage
|
||||
@@ -43,7 +44,9 @@ def service_dashboard(service_id):
|
||||
job_response = job_api_client.get_jobs(service_id)["data"]
|
||||
service_data_retention_days = 7
|
||||
|
||||
active_jobs = [job for job in job_response if job["job_status"] != "cancelled"]
|
||||
active_jobs = [
|
||||
job for job in job_response if job["job_status"] != JobStatus.CANCELLED
|
||||
]
|
||||
job_lists = [
|
||||
{**job_dict, "finished_processing": job_is_finished(job_dict)}
|
||||
for job_dict in active_jobs
|
||||
@@ -70,7 +73,9 @@ def service_dashboard(service_id):
|
||||
|
||||
|
||||
def job_is_finished(job_dict):
|
||||
done_statuses = DELIVERED_STATUSES + FAILURE_STATUSES + ["cancelled"]
|
||||
done_statuses = (
|
||||
DELIVERED_STATUSES + FAILURE_STATUSES + [NotificationStatus.CANCELLED]
|
||||
)
|
||||
processed_count = sum(
|
||||
stat["count"]
|
||||
for stat in job_dict["statistics"]
|
||||
@@ -107,8 +112,18 @@ def get_local_daily_stats_for_last_x_days(stats_utc, user_timezone, days):
|
||||
]
|
||||
aggregator = {
|
||||
d: {
|
||||
"sms": {"delivered": 0, "failure": 0, "pending": 0, "requested": 0},
|
||||
"email": {"delivered": 0, "failure": 0, "pending": 0, "requested": 0},
|
||||
"sms": {
|
||||
NotificationStatus.DELIVERED: 0,
|
||||
"failure": 0,
|
||||
NotificationStatus.PENDING: 0,
|
||||
"requested": 0,
|
||||
},
|
||||
"email": {
|
||||
NotificationStatus.DELIVERED: 0,
|
||||
"failure": 0,
|
||||
NotificationStatus.PENDING: 0,
|
||||
"requested": 0,
|
||||
},
|
||||
}
|
||||
for d in days_list
|
||||
}
|
||||
@@ -122,7 +137,12 @@ def get_local_daily_stats_for_last_x_days(stats_utc, user_timezone, days):
|
||||
|
||||
if local_day in aggregator:
|
||||
for msg_type in ["sms", "email"]:
|
||||
for status in ["delivered", "failure", "pending", "requested"]:
|
||||
for status in [
|
||||
NotificationStatus.DELIVERED,
|
||||
"failure",
|
||||
NotificationStatus.PENDING,
|
||||
"requested",
|
||||
]:
|
||||
aggregator[local_day][msg_type][status] += data[msg_type][status]
|
||||
|
||||
return aggregator
|
||||
@@ -232,7 +252,9 @@ def usage(service_id):
|
||||
|
||||
|
||||
def filter_out_cancelled_stats(template_statistics):
|
||||
return [s for s in template_statistics if s["status"] != "cancelled"]
|
||||
return [
|
||||
s for s in template_statistics if s["status"] != NotificationStatus.CANCELLED
|
||||
]
|
||||
|
||||
|
||||
def aggregate_template_usage(template_statistics, sort_key="count"):
|
||||
@@ -266,7 +288,7 @@ def get_dashboard_totals(statistics):
|
||||
|
||||
for msg_type in statistics.values():
|
||||
msg_type["failed_percentage"] = get_formatted_percentage(
|
||||
msg_type["failed"], msg_type["requested"]
|
||||
msg_type[NotificationStatus.FAILED], msg_type["requested"]
|
||||
)
|
||||
msg_type["show_warning"] = float(msg_type["failed_percentage"]) > 3
|
||||
|
||||
@@ -315,7 +337,9 @@ def aggregate_status_types(counts_dict):
|
||||
return get_dashboard_totals(
|
||||
{
|
||||
"{}_counts".format(message_type): {
|
||||
"failed": sum(stats.get(status, 0) for status in FAILURE_STATUSES),
|
||||
NotificationStatus.FAILED: sum(
|
||||
stats.get(status, 0) for status in FAILURE_STATUSES
|
||||
),
|
||||
"requested": sum(stats.get(status, 0) for status in REQUESTED_STATUSES),
|
||||
}
|
||||
for message_type, stats in counts_dict.items()
|
||||
|
||||
@@ -23,7 +23,7 @@ from app import (
|
||||
notification_api_client,
|
||||
service_api_client,
|
||||
)
|
||||
from app.enums import JobStatus, ServicePermission
|
||||
from app.enums import JobStatus, NotificationStatus, ServicePermission
|
||||
from app.formatters import get_time_left, message_count_noun
|
||||
from app.main import main
|
||||
from app.main.forms import SearchNotificationsForm
|
||||
@@ -304,22 +304,30 @@ def get_status_filters(service, message_type, statistics):
|
||||
if message_type is None:
|
||||
stats = {
|
||||
key: sum(statistics[message_type][key] for message_type in {"email", "sms"})
|
||||
for key in {"requested", "delivered", "failed"}
|
||||
for key in {
|
||||
"requested",
|
||||
NotificationStatus.DELIVERED,
|
||||
NotificationStatus.FAILED,
|
||||
}
|
||||
}
|
||||
else:
|
||||
stats = statistics[message_type]
|
||||
|
||||
if stats.get("failure") is not None:
|
||||
stats["failed"] = stats["failure"]
|
||||
stats[NotificationStatus.FAILED] = stats["failure"]
|
||||
|
||||
stats["pending"] = stats["requested"] - stats["delivered"] - stats["failed"]
|
||||
stats[NotificationStatus.PENDING] = (
|
||||
stats["requested"]
|
||||
- stats[NotificationStatus.DELIVERED]
|
||||
- stats[NotificationStatus.FAILED]
|
||||
)
|
||||
|
||||
filters = [
|
||||
# key, label, option
|
||||
("requested", "total", "sending,delivered,failed"),
|
||||
("pending", "pending", "sending,pending"),
|
||||
("delivered", "delivered", "delivered"),
|
||||
("failed", "failed", "failed"),
|
||||
(NotificationStatus.PENDING, "pending", "sending,pending"),
|
||||
(NotificationStatus.DELIVERED, "delivered", "delivered"),
|
||||
(NotificationStatus.FAILED, "failed", "failed"),
|
||||
]
|
||||
return [
|
||||
# return list containing label, option, link, count
|
||||
|
||||
@@ -25,6 +25,7 @@ from app import (
|
||||
service_api_client,
|
||||
user_api_client,
|
||||
)
|
||||
from app.enums import NotificationStatus
|
||||
from app.extensions import redis_client
|
||||
from app.main import main
|
||||
from app.main.forms import (
|
||||
@@ -769,32 +770,41 @@ def filter_and_sort_services(services, trial_mode_services=False):
|
||||
|
||||
def create_global_stats(services):
|
||||
stats = {
|
||||
"email": {"delivered": 0, "failed": 0, "requested": 0},
|
||||
"sms": {"delivered": 0, "failed": 0, "requested": 0},
|
||||
"email": {
|
||||
NotificationStatus.DELIVERED: 0,
|
||||
NotificationStatus.FAILED: 0,
|
||||
"requested": 0,
|
||||
},
|
||||
"sms": {
|
||||
NotificationStatus.DELIVERED: 0,
|
||||
NotificationStatus.FAILED: 0,
|
||||
"requested": 0,
|
||||
},
|
||||
}
|
||||
# Issue #1323. The back end is now sending 'failure' instead of
|
||||
# 'failed'. Adjust it here, but keep it flexible in case
|
||||
# the backend reverts to 'failed'.
|
||||
for service in services:
|
||||
if service["statistics"]["sms"].get("failure") is not None:
|
||||
service["statistics"]["sms"]["failed"] = service["statistics"]["sms"][
|
||||
"failure"
|
||||
]
|
||||
service["statistics"]["sms"][NotificationStatus.FAILED] = service[
|
||||
"statistics"
|
||||
]["sms"]["failure"]
|
||||
if service["statistics"]["email"].get("failure") is not None:
|
||||
service["statistics"]["email"]["failed"] = service["statistics"]["email"][
|
||||
"failure"
|
||||
]
|
||||
service["statistics"]["email"][NotificationStatus.FAILED] = service[
|
||||
"statistics"
|
||||
]["email"]["failure"]
|
||||
|
||||
for service in services:
|
||||
|
||||
for msg_type, status in itertools.product(
|
||||
("sms", "email"), ("delivered", "failed", "requested")
|
||||
("sms", "email"),
|
||||
(NotificationStatus.DELIVERED, NotificationStatus.FAILED, "requested"),
|
||||
):
|
||||
stats[msg_type][status] += service["statistics"][msg_type][status]
|
||||
|
||||
for stat in stats.values():
|
||||
stat["failure_rate"] = get_formatted_percentage(
|
||||
stat["failed"], stat["requested"]
|
||||
stat[NotificationStatus.FAILED], stat["requested"]
|
||||
)
|
||||
return stats
|
||||
|
||||
|
||||
@@ -146,14 +146,14 @@ def check_invited_user_email_address_matches_expected(
|
||||
@hide_from_search_engines
|
||||
def set_up_your_profile():
|
||||
|
||||
debug_msg(f"Enter set_up_your_profile with request.args {request.args}")
|
||||
current_app.logger.info("#invites: Enter set_up_your_profile")
|
||||
code = request.args.get("code")
|
||||
state = request.args.get("state")
|
||||
|
||||
state_key = f"login-state-{unquote(state)}"
|
||||
stored_state = unquote(redis_client.get(state_key).decode("utf8"))
|
||||
if state != stored_state:
|
||||
current_app.logger.error(f"State Error: {state} != {stored_state}")
|
||||
current_app.logger.error(f"#invites State Error: {state} != {stored_state}")
|
||||
abort(403)
|
||||
|
||||
login_gov_error = request.args.get("error")
|
||||
@@ -164,26 +164,29 @@ def set_up_your_profile():
|
||||
new_user = user_email is None or user_uuid is None
|
||||
|
||||
if new_user: # invite path
|
||||
current_app.logger.info(
|
||||
f"#invites: we are processing a new user with login.gov user_uuid {user_uuid}"
|
||||
)
|
||||
access_token = sign_in._get_access_token(code)
|
||||
|
||||
debug_msg("Got the access token for login.gov")
|
||||
user_email, user_uuid = sign_in._get_user_email_and_uuid(access_token)
|
||||
debug_msg(
|
||||
f"Got the user_email {user_email} and user_uuid {user_uuid} from login.gov"
|
||||
current_app.logger.info(
|
||||
f"#invites: Got the user_email and user_uuid {user_uuid} from login.gov"
|
||||
)
|
||||
invite_data = redis_client.get(f"invitedata-{state}")
|
||||
invite_data = json.loads(invite_data)
|
||||
debug_msg(f"final state {invite_data}")
|
||||
invited_user_id = invite_data["invited_user_id"]
|
||||
invited_user_email_address = get_invited_user_email_address(invited_user_id)
|
||||
debug_msg(f"email address from the invite_date is {invited_user_email_address}")
|
||||
current_app.logger.info(
|
||||
f"#invites: does user email match expected? {user_email == invited_user_email_address}"
|
||||
)
|
||||
check_invited_user_email_address_matches_expected(
|
||||
user_email, invited_user_email_address
|
||||
)
|
||||
|
||||
invited_user_accept_invite(invited_user_id)
|
||||
debug_msg(
|
||||
f"accepted invite user {invited_user_email_address} to service {invite_data['service_id']}"
|
||||
current_app.logger.info(
|
||||
f"accepted invite user with invited_user_id {invited_user_id} to service {invite_data['service_id']}"
|
||||
)
|
||||
# We need to avoid taking a second trip through the login.gov code because we cannot pull the
|
||||
# access token twice. So once we retrieve these values, let's park them in redis for 15 minutes
|
||||
@@ -194,9 +197,11 @@ def set_up_your_profile():
|
||||
form = SetupUserProfileForm()
|
||||
|
||||
if form.validate_on_submit() and not new_user:
|
||||
current_app.logger.info("#invites: this is an invite for a pre-existing user")
|
||||
invite_data, user_email, user_uuid, invited_user_email_address = (
|
||||
get_invite_data_from_redis(state)
|
||||
)
|
||||
current_app.logger.info(f"#invites: login.gov user_uuid from redis {user_uuid}")
|
||||
|
||||
# create or update the user
|
||||
user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email)
|
||||
@@ -208,15 +213,20 @@ def set_up_your_profile():
|
||||
password=str(uuid.uuid4()),
|
||||
auth_type="sms_auth",
|
||||
)
|
||||
debug_msg(f"registered user {form.name.data} with email {user_email}")
|
||||
current_app.logger.info(
|
||||
f"#invites: registered the new user with login.gov user_uuid {user_uuid}"
|
||||
)
|
||||
else:
|
||||
user.update(mobile_number=form.mobile_number.data, name=form.name.data)
|
||||
debug_msg(f"updated user {form.name.data}")
|
||||
current_app.logger.info(
|
||||
f"#invites: updated the pre-existing user with login.gov user_uuid {user_uuid}"
|
||||
)
|
||||
|
||||
# activate the user
|
||||
user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email)
|
||||
current_app.logger.info("#invites: going to activate user")
|
||||
activate_user(user["id"])
|
||||
debug_msg("activated user")
|
||||
current_app.logger.info(f"#invites: activated user with user.id {user['id']}")
|
||||
usr = User.from_id(user["id"])
|
||||
|
||||
usr.add_to_service(
|
||||
@@ -225,18 +235,17 @@ def set_up_your_profile():
|
||||
invite_data["folder_permissions"],
|
||||
invite_data["from_user_id"],
|
||||
)
|
||||
debug_msg(
|
||||
f"Added user {usr.email_address} to service {invite_data['service_id']}"
|
||||
)
|
||||
|
||||
# notify-admin-1766
|
||||
# redirect new users to templates area of new service instead of dashboard
|
||||
service_id = invite_data["service_id"]
|
||||
url = url_for(".service_dashboard", service_id=service_id)
|
||||
url = f"{url}/templates"
|
||||
current_app.logger.info(f"#invites redirecting to {url}")
|
||||
return redirect(url)
|
||||
|
||||
elif login_gov_error:
|
||||
current_app.logger.error(f"login.gov error: {login_gov_error}")
|
||||
current_app.logger.error(f"#invites: login.gov error: {login_gov_error}")
|
||||
abort(403)
|
||||
|
||||
# we take two trips through this method, but should only hit this
|
||||
|
||||
@@ -2,14 +2,15 @@ from collections import OrderedDict
|
||||
|
||||
from werkzeug.utils import cached_property
|
||||
|
||||
from app.enums import OrganizationType
|
||||
from app.models import JSONModel, ModelList, SerialisedModelCollection, SortByNameMixin
|
||||
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 = OrganizationType.FEDERAL
|
||||
TYPE_STATE = OrganizationType.STATE
|
||||
TYPE_OTHER = OrganizationType.OTHER
|
||||
|
||||
TYPE_LABELS = OrderedDict(
|
||||
[
|
||||
|
||||
@@ -323,7 +323,7 @@ class Service(JSONModel, SortByNameMixin):
|
||||
|
||||
@property
|
||||
def shouldnt_use_govuk_as_sms_sender(self):
|
||||
return self.organization_type != Organization.TYPE_CENTRAL
|
||||
return self.organization_type != Organization.TYPE_FEDERAL
|
||||
|
||||
@cached_property
|
||||
def sms_senders(self):
|
||||
|
||||
@@ -7,25 +7,15 @@ from ordered_set import OrderedSet
|
||||
from werkzeug.datastructures import MultiDict
|
||||
from werkzeug.routing import RequestRedirect
|
||||
|
||||
from app.enums import NotificationStatus, ServicePermission
|
||||
from app.enums import NotificationStatus, NotificationType, ServicePermission
|
||||
from notifications_utils.field import Field
|
||||
|
||||
SENDING_STATUSES = [
|
||||
NotificationStatus.CREATED,
|
||||
NotificationStatus.PENDING,
|
||||
NotificationStatus.SENDING,
|
||||
]
|
||||
DELIVERED_STATUSES = [NotificationStatus.DELIVERED, NotificationStatus.SENT]
|
||||
FAILURE_STATUSES = [
|
||||
NotificationStatus.FAILED,
|
||||
NotificationStatus.TEMPORARY_FAILURE,
|
||||
NotificationStatus.PERMANENT_FAILURE,
|
||||
NotificationStatus.TECHNICAL_FAILURE,
|
||||
NotificationStatus.VALIDATION_FAILED,
|
||||
]
|
||||
REQUESTED_STATUSES = SENDING_STATUSES + DELIVERED_STATUSES + FAILURE_STATUSES
|
||||
SENDING_STATUSES = NotificationStatus.sending_statuses()
|
||||
DELIVERED_STATUSES = NotificationStatus.delivered_statuses()
|
||||
FAILURE_STATUSES = NotificationStatus.failure_statuses()
|
||||
REQUESTED_STATUSES = NotificationStatus.requested_statuses()
|
||||
|
||||
NOTIFICATION_TYPES = ["sms", "email"]
|
||||
NOTIFICATION_TYPES = [NotificationType.SMS, NotificationType.EMAIL]
|
||||
|
||||
|
||||
def service_has_permission(permission):
|
||||
|
||||
168
package-lock.json
generated
168
package-lock.json
generated
@@ -50,7 +50,7 @@
|
||||
"jest-environment-jsdom": "^30.0.4",
|
||||
"jshint": "2.13.6",
|
||||
"jshint-stylish": "2.2.1",
|
||||
"rollup": "^4.45.0",
|
||||
"rollup": "^4.45.1",
|
||||
"rollup-plugin-commonjs": "10.1.0",
|
||||
"rollup-plugin-node-resolve": "5.2.0"
|
||||
},
|
||||
@@ -2805,9 +2805,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.0.tgz",
|
||||
"integrity": "sha512-2o/FgACbji4tW1dzXOqAV15Eu7DdgbKsF2QKcxfG4xbh5iwU7yr5RRP5/U+0asQliSYv5M4o7BevlGIoSL0LXg==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz",
|
||||
"integrity": "sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -2818,9 +2818,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.0.tgz",
|
||||
"integrity": "sha512-PSZ0SvMOjEAxwZeTx32eI/j5xSYtDCRxGu5k9zvzoY77xUNssZM+WV6HYBLROpY5CkXsbQjvz40fBb7WPwDqtQ==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz",
|
||||
"integrity": "sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2831,9 +2831,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.0.tgz",
|
||||
"integrity": "sha512-BA4yPIPssPB2aRAWzmqzQ3y2/KotkLyZukVB7j3psK/U3nVJdceo6qr9pLM2xN6iRP/wKfxEbOb1yrlZH6sYZg==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz",
|
||||
"integrity": "sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2844,9 +2844,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.0.tgz",
|
||||
"integrity": "sha512-Pr2o0lvTwsiG4HCr43Zy9xXrHspyMvsvEw4FwKYqhli4FuLE5FjcZzuQ4cfPe0iUFCvSQG6lACI0xj74FDZKRA==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz",
|
||||
"integrity": "sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2857,9 +2857,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.0.tgz",
|
||||
"integrity": "sha512-lYE8LkE5h4a/+6VnnLiL14zWMPnx6wNbDG23GcYFpRW1V9hYWHAw9lBZ6ZUIrOaoK7NliF1sdwYGiVmziUF4vA==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz",
|
||||
"integrity": "sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2870,9 +2870,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.0.tgz",
|
||||
"integrity": "sha512-PVQWZK9sbzpvqC9Q0GlehNNSVHR+4m7+wET+7FgSnKG3ci5nAMgGmr9mGBXzAuE5SvguCKJ6mHL6vq1JaJ/gvw==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz",
|
||||
"integrity": "sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2883,9 +2883,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.0.tgz",
|
||||
"integrity": "sha512-hLrmRl53prCcD+YXTfNvXd776HTxNh8wPAMllusQ+amcQmtgo3V5i/nkhPN6FakW+QVLoUUr2AsbtIRPFU3xIA==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz",
|
||||
"integrity": "sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -2896,9 +2896,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.0.tgz",
|
||||
"integrity": "sha512-XBKGSYcrkdiRRjl+8XvrUR3AosXU0NvF7VuqMsm7s5nRy+nt58ZMB19Jdp1RdqewLcaYnpk8zeVs/4MlLZEJxw==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz",
|
||||
"integrity": "sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -2909,9 +2909,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.0.tgz",
|
||||
"integrity": "sha512-fRvZZPUiBz7NztBE/2QnCS5AtqLVhXmUOPj9IHlfGEXkapgImf4W9+FSkL8cWqoAjozyUzqFmSc4zh2ooaeF6g==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz",
|
||||
"integrity": "sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2922,9 +2922,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.0.tgz",
|
||||
"integrity": "sha512-Btv2WRZOcUGi8XU80XwIvzTg4U6+l6D0V6sZTrZx214nrwxw5nAi8hysaXj/mctyClWgesyuxbeLylCBNauimg==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz",
|
||||
"integrity": "sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2935,9 +2935,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.0.tgz",
|
||||
"integrity": "sha512-Li0emNnwtUZdLwHjQPBxn4VWztcrw/h7mgLyHiEI5Z0MhpeFGlzaiBHpSNVOMB/xucjXTTcO+dhv469Djr16KA==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz",
|
||||
"integrity": "sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
@@ -2948,9 +2948,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.0.tgz",
|
||||
"integrity": "sha512-sB8+pfkYx2kvpDCfd63d5ScYT0Fz1LO6jIb2zLZvmK9ob2D8DeVqrmBDE0iDK8KlBVmsTNzrjr3G1xV4eUZhSw==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz",
|
||||
"integrity": "sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -2961,9 +2961,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.0.tgz",
|
||||
"integrity": "sha512-5GQ6PFhh7E6jQm70p1aW05G2cap5zMOvO0se5JMecHeAdj5ZhWEHbJ4hiKpfi1nnnEdTauDXxPgXae/mqjow9w==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz",
|
||||
"integrity": "sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -2974,9 +2974,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.0.tgz",
|
||||
"integrity": "sha512-N/euLsBd1rekWcuduakTo/dJw6U6sBP3eUq+RXM9RNfPuWTvG2w/WObDkIvJ2KChy6oxZmOSC08Ak2OJA0UiAA==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz",
|
||||
"integrity": "sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -2987,9 +2987,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.0.tgz",
|
||||
"integrity": "sha512-2l9sA7d7QdikL0xQwNMO3xURBUNEWyHVHfAsHsUdq+E/pgLTUcCE+gih5PCdmyHmfTDeXUWVhqL0WZzg0nua3g==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz",
|
||||
"integrity": "sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -3000,9 +3000,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.0.tgz",
|
||||
"integrity": "sha512-XZdD3fEEQcwG2KrJDdEQu7NrHonPxxaV0/w2HpvINBdcqebz1aL+0vM2WFJq4DeiAVT6F5SUQas65HY5JDqoPw==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz",
|
||||
"integrity": "sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3013,9 +3013,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.0.tgz",
|
||||
"integrity": "sha512-7ayfgvtmmWgKWBkCGg5+xTQ0r5V1owVm67zTrsEY1008L5ro7mCyGYORomARt/OquB9KY7LpxVBZes+oSniAAQ==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz",
|
||||
"integrity": "sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3026,9 +3026,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.0.tgz",
|
||||
"integrity": "sha512-B+IJgcBnE2bm93jEW5kHisqvPITs4ddLOROAcOc/diBgrEiQJJ6Qcjby75rFSmH5eMGrqJryUgJDhrfj942apQ==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz",
|
||||
"integrity": "sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3039,9 +3039,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.0.tgz",
|
||||
"integrity": "sha512-+CXwwG66g0/FpWOnP/v1HnrGVSOygK/osUbu3wPRy8ECXjoYKjRAyfxYpDQOfghC5qPJYLPH0oN4MCOjwgdMug==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz",
|
||||
"integrity": "sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -3052,9 +3052,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.0.tgz",
|
||||
"integrity": "sha512-SRf1cytG7wqcHVLrBc9VtPK4pU5wxiB/lNIkNmW2ApKXIg+RpqwHfsaEK+e7eH4A1BpI6BX/aBWXxZCIrJg3uA==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz",
|
||||
"integrity": "sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -12450,9 +12450,9 @@
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.45.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.0.tgz",
|
||||
"integrity": "sha512-WLjEcJRIo7i3WDDgOIJqVI2d+lAC3EwvOGy+Xfq6hs+GQuAA4Di/H72xmXkOhrIWFg2PFYSKZYfH0f4vfKXN4A==",
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz",
|
||||
"integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
@@ -12465,26 +12465,26 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.45.0",
|
||||
"@rollup/rollup-android-arm64": "4.45.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.45.0",
|
||||
"@rollup/rollup-darwin-x64": "4.45.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.45.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.45.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.45.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.45.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.45.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.45.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.45.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.45.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.45.0",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.45.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.45.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.45.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.45.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.45.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.45.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.45.0",
|
||||
"@rollup/rollup-android-arm-eabi": "4.45.1",
|
||||
"@rollup/rollup-android-arm64": "4.45.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.45.1",
|
||||
"@rollup/rollup-darwin-x64": "4.45.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.45.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.45.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.45.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.45.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.45.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.45.1",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.45.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.45.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.45.1",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.45.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.45.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.45.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.45.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.45.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.45.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.45.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
"jest-environment-jsdom": "^30.0.4",
|
||||
"jshint": "2.13.6",
|
||||
"jshint-stylish": "2.2.1",
|
||||
"rollup": "^4.45.0",
|
||||
"rollup": "^4.45.1",
|
||||
"rollup-plugin-commonjs": "10.1.0",
|
||||
"rollup-plugin-node-resolve": "5.2.0"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user