diff --git a/app/api/__init__.py b/app/api/__init__.py index 00f5f78a..0f7932f0 100644 --- a/app/api/__init__.py +++ b/app/api/__init__.py @@ -12,4 +12,5 @@ from .views import ( notification, setting, export, + phone, ) diff --git a/app/api/views/phone.py b/app/api/views/phone.py new file mode 100644 index 00000000..9af3fd1e --- /dev/null +++ b/app/api/views/phone.py @@ -0,0 +1,51 @@ +import arrow +from flask import g +from flask import jsonify + +from app.api.base import api_bp, require_api_auth +from app.models import ( + PhoneReservation, + PhoneMessage, +) + + +@api_bp.route("/phone/reservations/", methods=["GET", "POST"]) +@require_api_auth +def phone_messages(reservation_id): + """ + Return messages during this reservation + Output: + - messages: list of alias: + - id + - from_number + - body + - created_at: e.g. 5 minutes ago + + """ + user = g.user + reservation: PhoneReservation = PhoneReservation.get(reservation_id) + if not reservation or reservation.user_id != user.id: + return jsonify(error="Invalid reservation"), 400 + + phone_number = reservation.number + messages = PhoneMessage.filter( + PhoneMessage.number_id == phone_number.id, + PhoneMessage.created_at > reservation.start, + PhoneMessage.created_at < reservation.end, + ).all() + + return ( + jsonify( + messages=[ + { + "id": message.id, + "from_number": message.from_number, + "body": message.body, + "created_at": message.created_at.humanize(), + } + for message in messages + ], + ended=reservation.end < arrow.now(), + ), + 200, + ) diff --git a/docs/api.md b/docs/api.md index 0b18b632..a78b1c0f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -18,6 +18,8 @@ [MISC endpoints](#misc-endpoints) +[Phone endpoints](#phone-endpoints) + --- SimpleLogin current API clients are Chrome/Firefox/Safari extension and mobile (iOS/Android) app. These clients rely @@ -944,4 +946,32 @@ Input: not iOS app. Output: -200 if user is upgraded successfully 4** if any error. \ No newline at end of file +200 if user is upgraded successfully 4** if any error. + +### Phone endpoints + +#### GET /api/phone/reservations/:reservation_id + +Get messages received during a reservation. + +Input: + +- `Authentication` in header: the api key +- `reservation_id` + +Output: +List of messages for this reservation and whether the reservation is ended. + +```json +{ + "ended": false, + "messages": [ + { + "body": "body", + "created_at": "just now", + "from_number": "from_number", + "id": 7 + } + ] +} +``` \ No newline at end of file diff --git a/tests/api/test_phone.py b/tests/api/test_phone.py new file mode 100644 index 00000000..b9a2bf77 --- /dev/null +++ b/tests/api/test_phone.py @@ -0,0 +1,64 @@ +import arrow + +from app.models import ( + PhoneReservation, + PhoneNumber, + PhoneCountry, + PhoneMessage, +) +from tests.utils import login + + +def test_phone_messages(flask_client): + user = login(flask_client) + + country = PhoneCountry.create(name="FR", commit=True) + number = PhoneNumber.create( + country_id=country.id, number="+331234567890", active=True, commit=True + ) + reservation = PhoneReservation.create( + number_id=number.id, + user_id=user.id, + start=arrow.now().shift(hours=-1), + end=arrow.now().shift(hours=1), + commit=True, + ) + + # no messages yet + r = flask_client.post(f"/api/phone/reservations/{reservation.id}") + assert r.status_code == 200 + assert r.json == {"ended": False, "messages": []} + + # a message arrives + PhoneMessage.create( + number_id=number.id, from_number="from_number", body="body", commit=True + ) + r = flask_client.post(f"/api/phone/reservations/{reservation.id}") + assert len(r.json["messages"]) == 1 + msg = r.json["messages"][0] + assert msg["body"] == "body" + assert msg["from_number"] == "from_number" + assert "created_at" in msg + assert "id" in msg + + # print(json.dumps(r.json, indent=2)) + + +def test_phone_messages_ended_reservation(flask_client): + user = login(flask_client) + + country = PhoneCountry.create(name="FR", commit=True) + number = PhoneNumber.create( + country_id=country.id, number="+331234567890", active=True, commit=True + ) + reservation = PhoneReservation.create( + number_id=number.id, + user_id=user.id, + start=arrow.now().shift(hours=-2), + end=arrow.now().shift(hours=-1), # reservation is ended + commit=True, + ) + + r = flask_client.post(f"/api/phone/reservations/{reservation.id}") + assert r.status_code == 200 + assert r.json == {"ended": True, "messages": []}