Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
joybytes committed Dec 10, 2024
1 parent f16c4ba commit 60f38f3
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 26 deletions.
11 changes: 0 additions & 11 deletions app/dao/inbound_numbers_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,3 @@ def dao_allocate_number_for_service(service_id, inbound_number_id):
if not updated:
raise Exception(f"Inbound number: {inbound_number_id} is not available")
return InboundNumber.query.get(inbound_number_id)


@autocommit
def dao_archive_inbound_number(service_id: str):
# has the number been used?
# no:
# set active to false
return InboundNumber.filter_by(service_id=service_id, active=True).update(
{"service_id": None, "active": False},
synchronize_session="fetch",
)
48 changes: 48 additions & 0 deletions app/dao/inbound_sms_dao.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from datetime import datetime, timedelta
from uuid import UUID

from flask import current_app
from sqlalchemy import and_, desc
from sqlalchemy.dialects.postgresql import insert
Expand All @@ -9,6 +12,7 @@
from app.models import (
InboundSms,
InboundSmsHistory,
Notification,
Service,
ServiceDataRetention,
)
Expand Down Expand Up @@ -179,3 +183,47 @@ def dao_get_paginated_most_recent_inbound_sms_by_user_number_for_service(service
)

return q.paginate(page=page, per_page=current_app.config["PAGE_SIZE"])


def has_inbound_number_been_used_recently(service_id: UUID, inbound_number: str, days: int | None = 30) -> bool:
time_threshold = datetime.utcnow() - timedelta(days=days)

last_notification = (
Notification.query.filter(
Notification.reply_to_text == inbound_number,
Notification.service_id == service_id,
)
.order_by(Notification.created_at.desc())
.first()
)

last_inbound_sms = (
InboundSms.query.filter(
InboundSms.notify_number == inbound_number,
InboundSms.service_id == service_id,
)
.order_by(InboundSms.created_at.desc())
.first()
)

last_inbound_sms_history = (
InboundSmsHistory.query.filter(
InboundSmsHistory.notify_number == inbound_number,
InboundSmsHistory.service_id == service_id,
)
.order_by(InboundSmsHistory.created_at.desc())
.first()
)

most_recent_usage = max(
filter(
None,
[
last_notification.created_at if last_notification else None,
last_inbound_sms.created_at if last_inbound_sms else None,
last_inbound_sms_history.created_at if last_inbound_sms_history else None,
],
)
)

return most_recent_usage and most_recent_usage >= time_threshold
11 changes: 5 additions & 6 deletions app/dao/service_permissions_dao.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from uuid import UUID

from app import db
from app.dao.dao_utils import autocommit
from app.models import ServicePermission
Expand All @@ -15,8 +13,9 @@ def dao_add_service_permission(service_id, permission):
db.session.add(service_permission)


@autocommit
def dao_remove_service_permissions(service_id: UUID, permissions: list[str]):
return ServicePermission.query.filter(
ServicePermission.service_id == service_id, ServicePermission.permission.in_(permissions)
def dao_remove_service_permission(service_id, permission):
deleted = ServicePermission.query.filter(
ServicePermission.service_id == service_id, ServicePermission.permission == permission
).delete()
db.session.commit()
return deleted
7 changes: 3 additions & 4 deletions app/inbound_sms/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from notifications_utils.recipient_validation.phone_number import try_validate_and_format_phone_number

from app.constants import INBOUND_SMS_TYPE
from app.dao.inbound_numbers_dao import dao_archive_inbound_number
from app.dao.inbound_sms_dao import (
dao_count_inbound_sms_for_service,
dao_get_inbound_sms_by_id,
Expand All @@ -11,7 +10,7 @@
)
from app.dao.service_data_retention_dao import fetch_service_data_retention_by_notification_type
from app.dao.service_permissions_dao import (
dao_remove_service_permissions,
dao_remove_service_permission,
)
from app.dao.service_sms_sender_dao import dao_remove_inbound_sms_senders
from app.dao.services_dao import dao_fetch_service_by_id
Expand Down Expand Up @@ -76,9 +75,9 @@ def remove_inbound_sms_capability(service_id):
return jsonify({"message": "Service not found"}), 404

try:
dao_remove_service_permissions(service_id, [INBOUND_SMS_TYPE])
dao_remove_service_permission(service_id, [INBOUND_SMS_TYPE])
dao_remove_inbound_sms_senders(service_id)
dao_archive_inbound_number(service_id)
# dao_release_or_archive_inbound_number(service_id)

return jsonify({"message": "Inbound SMS capability removed successfully"}), 200

Expand Down
1 change: 1 addition & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,7 @@ class Notification(db.Model):
Index("ix_notifications_notification_type_composite", "notification_type", "status", "created_at"),
Index("ix_notifications_service_created_at", "service_id", "created_at"),
Index("ix_notifications_service_id_composite", "service_id", "notification_type", "status", "created_at"),
Index("ix_notifications_service_id_ntype_created_at", "service_id", "notification_type", "created_at"),
# unsubscribe_link value should be null for non-email notifications
CheckConstraint(
"notification_type = 'email' OR unsubscribe_link is null",
Expand Down
17 changes: 17 additions & 0 deletions tests/app/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from app.history_meta import create_history
from app.models import (
ApiKey,
InboundSmsHistory,
InvitedUser,
Job,
Notification,
Expand Down Expand Up @@ -1043,6 +1044,22 @@ def sample_inbound_numbers(sample_service):
return inbound_numbers


@pytest.fixture
def sample_inbound_sms_history(notify_db_session, sample_service):
inbound_sms = InboundSmsHistory(
id=uuid.uuid4(),
created_at=datetime.utcnow(),
service_id=sample_service.id,
notify_number="3",
provider_date=datetime.utcnow(),
provider_reference="reference-id",
provider="firetext",
)
notify_db_session.add(inbound_sms)
notify_db_session.commit()
return inbound_sms


@pytest.fixture
def sample_organisation(notify_db_session):
org = Organisation(name="sample organisation")
Expand Down
69 changes: 69 additions & 0 deletions tests/app/dao/test_inbound_sms_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@
from freezegun import freeze_time

from app import db
from app.constants import KEY_TYPE_NORMAL
from app.dao.inbound_numbers_dao import dao_get_inbound_number_for_service
from app.dao.inbound_sms_dao import (
dao_count_inbound_sms_for_service,
dao_get_inbound_sms_by_id,
dao_get_inbound_sms_for_service,
dao_get_paginated_inbound_sms_for_service_for_public_api,
dao_get_paginated_most_recent_inbound_sms_by_user_number_for_service,
delete_inbound_sms_older_than_retention,
has_inbound_number_been_used_recently,
)
from app.models import InboundSmsHistory
from tests.app.db import (
create_inbound_sms,
create_job,
create_notification,
create_service,
create_service_data_retention,
create_template,
)
from tests.conftest import set_config

Expand Down Expand Up @@ -353,3 +359,66 @@ def test_most_recent_inbound_sms_only_returns_values_within_7_days(sample_servic

assert len(res.items) == 1
assert res.items[0].content == "new"


def test_has_inbound_number_been_used_recently_notifications_table(sample_service, sample_inbound_numbers):
template = create_template(service=sample_service)
job = create_job(template=template)
inbound = dao_get_inbound_number_for_service(sample_service.id)

create_notification(
template=template,
job=job,
job_row_number=None,
to_field=None,
status="created",
reference=None,
created_at=None,
sent_at=None,
billable_units=1,
personalisation=None,
api_key=None,
key_type=KEY_TYPE_NORMAL,
reply_to_text=inbound.number,
)

assert has_inbound_number_been_used_recently(sample_service.id, inbound.number) is True


def test_has_inbound_number_been_used_recently_inbound_sms_table(sample_service, sample_inbound_numbers):
create_inbound_sms(sample_service)
inbound = dao_get_inbound_number_for_service(sample_service.id)

assert has_inbound_number_been_used_recently(sample_service.id, inbound.number) is True


def test_has_inbound_number_been_used_recently_inbound_sms_history_table(
sample_service, sample_inbound_numbers, sample_inbound_sms_history
):
inbound = dao_get_inbound_number_for_service(sample_service.id)

assert has_inbound_number_been_used_recently(sample_service.id, inbound.number) is True


def test_has_inbound_number_been_used_recently_no_recent_notifications(sample_service, sample_inbound_numbers):
template = create_template(service=sample_service)
job = create_job(template=template)
inbound = dao_get_inbound_number_for_service(sample_service.id)

create_notification(
template=template,
job=job,
job_row_number=None,
to_field=None,
status="created",
reference=None,
created_at=datetime(2017, 1, 3),
sent_at=None,
billable_units=1,
personalisation=None,
api_key=None,
key_type=KEY_TYPE_NORMAL,
reply_to_text=inbound.number,
)

assert has_inbound_number_been_used_recently(sample_service.id, inbound.number) is False
13 changes: 8 additions & 5 deletions tests/app/dao/test_service_permissions_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,13 @@ def test_fetch_service_permissions_gets_service_permissions(service_without_perm
assert all(sp.permission in [LETTER_TYPE, INTERNATIONAL_SMS_TYPE, SMS_TYPE] for sp in service_permissions)


def test_remove_service_permission():
service = create_service(service_permissions=[INBOUND_SMS_TYPE, EMAIL_TYPE])
dao_remove_service_permission(service.id, [INBOUND_SMS_TYPE])
permissions = dao_fetch_service_permissions(service.id)
def test_remove_service_permission(service_without_permissions):
create_service_permission(service_id=service_without_permissions.id, permission=EMAIL_TYPE)
create_service_permission(service_id=service_without_permissions.id, permission=INBOUND_SMS_TYPE)

dao_remove_service_permission(service_without_permissions.id, EMAIL_TYPE)

permissions = dao_fetch_service_permissions(service_without_permissions.id)
assert len(permissions) == 1
assert permissions[0].permission == EMAIL_TYPE
assert permissions[0].permission == INBOUND_SMS_TYPE
assert permissions[0].service_id == service_without_permissions.id

0 comments on commit 60f38f3

Please sign in to comment.