feat: add endpoints for sending and polling messages
This commit is contained in:
@@ -25,6 +25,7 @@ app.logger.addHandler(file_handler)
|
|||||||
app.logger.setLevel(logging.INFO)
|
app.logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
msg_403_not_primary = "Only a PRIMARY device can perform this action"
|
msg_403_not_primary = "Only a PRIMARY device can perform this action"
|
||||||
|
msg_403_not_secondary = "Only a SECONDARY device can perform this action"
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/v1/login", methods=["POST"])
|
@app.route("/api/v1/login", methods=["POST"])
|
||||||
@@ -95,5 +96,40 @@ def get_sms_messages_by_local_phone_number():
|
|||||||
return make_response(jsonify([n.to_dict() for n in db.get_sms_messages_by_local_phone_number(cur, local_phone_number)]), 200)
|
return make_response(jsonify([n.to_dict() for n in db.get_sms_messages_by_local_phone_number(cur, local_phone_number)]), 200)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/v1/send-message", methods=["POST"])
|
||||||
|
@jwt_required()
|
||||||
|
def send_sms_message():
|
||||||
|
if not is_primary(get_jwt()):
|
||||||
|
return make_response(jsonify(msg=msg_403_not_primary), 403)
|
||||||
|
|
||||||
|
content = request.json.get("content", None)
|
||||||
|
access_key = get_jwt_identity()
|
||||||
|
local_phone_number = request.json.get("local_phone_number", None)
|
||||||
|
remote_phone_number = request.json.get("remote_phone_number", None)
|
||||||
|
|
||||||
|
app.logger.debug(f"sending msg: content='{content}', access_key='{access_key}', local_num='{local_phone_number}', remote_num='{remote_phone_number}'")
|
||||||
|
|
||||||
|
if db.send_sms_message(cur, content, access_key, local_phone_number, remote_phone_number):
|
||||||
|
return make_response(jsonify(msg="Message successfully sent"), 200)
|
||||||
|
else:
|
||||||
|
return make_response(jsonify(msg="Failed to send message"), 400)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/v1/get-queued-sms-messages", methods=["GET"])
|
||||||
|
@jwt_required()
|
||||||
|
def get_queued_sms_messages():
|
||||||
|
if not is_secondary(get_jwt()):
|
||||||
|
return make_response(jsonify(msg=msg_403_not_secondary), 403)
|
||||||
|
|
||||||
|
access_key = get_jwt_identity()
|
||||||
|
local_phone_number = request.json.get("local_phone_number", None)
|
||||||
|
|
||||||
|
return make_response(jsonify([m.to_dict() for m in db.get_queued_sms_messages(cur, local_phone_number)]), 200)
|
||||||
|
|
||||||
|
|
||||||
def is_primary(jwt):
|
def is_primary(jwt):
|
||||||
return jwt["typ"] == "PRIMARY"
|
return jwt["typ"] == "PRIMARY"
|
||||||
|
|
||||||
|
|
||||||
|
def is_secondary(jwt):
|
||||||
|
return jwt["typ"] == "SECONDARY"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from dto import Device, SimCard, SmsMessage
|
from dto import Device, SimCard, SmsMessage, QueuedSmsMessage
|
||||||
|
|
||||||
|
|
||||||
def get_all_devices(cur) -> list[Device]:
|
def get_all_devices(cur) -> list[Device]:
|
||||||
@@ -31,3 +31,28 @@ def get_sms_messages_by_local_phone_number(cur, local_phone_number: str) -> list
|
|||||||
for item in msgs_from_db:
|
for item in msgs_from_db:
|
||||||
msgs.append(SmsMessage.convert(item))
|
msgs.append(SmsMessage.convert(item))
|
||||||
return msgs
|
return msgs
|
||||||
|
|
||||||
|
|
||||||
|
def send_sms_message(cur, content: str, sender_access_key: str, local_phone_number: str, remote_phone_number: str) -> bool:
|
||||||
|
if content is None or not content \
|
||||||
|
or sender_access_key is None or not sender_access_key \
|
||||||
|
or local_phone_number is None or not local_phone_number \
|
||||||
|
or remote_phone_number is None or not remote_phone_number:
|
||||||
|
return False
|
||||||
|
|
||||||
|
cur.execute("INSERT INTO message_queue VALUES (?, ?, ?, ?)", \
|
||||||
|
(content, sender_access_key, local_phone_number, remote_phone_number))
|
||||||
|
cur.commit()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_queued_sms_messages(cur, local_phone_number) -> list[QueuedSmsMessage]:
|
||||||
|
if local_phone_number is None or not local_phone_number:
|
||||||
|
return []
|
||||||
|
|
||||||
|
msgs_from_db = cur.execute("DELETE FROM message_queue WHERE local_phone_number = ? RETURNING *", (local_phone_number,)).fetchall()
|
||||||
|
cur.commit()
|
||||||
|
msgs = []
|
||||||
|
for item in msgs_from_db:
|
||||||
|
msgs.append(QueuedSmsMessage.convert(item))
|
||||||
|
return msgs
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class Device:
|
|||||||
def convert(device_from_db) -> Device:
|
def convert(device_from_db) -> Device:
|
||||||
return Device(*device_from_db)
|
return Device(*device_from_db)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SimCard:
|
class SimCard:
|
||||||
phone_number: str
|
phone_number: str
|
||||||
@@ -34,6 +35,7 @@ class SimCard:
|
|||||||
def convert(sim_from_db) -> SimCard:
|
def convert(sim_from_db) -> SimCard:
|
||||||
return SimCard(*sim_from_db)
|
return SimCard(*sim_from_db)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SmsMessage:
|
class SmsMessage:
|
||||||
content: str
|
content: str
|
||||||
@@ -56,3 +58,23 @@ class SmsMessage:
|
|||||||
|
|
||||||
def convert(sms_from_db) -> SmsMessage:
|
def convert(sms_from_db) -> SmsMessage:
|
||||||
return SmsMessage(*sms_from_db)
|
return SmsMessage(*sms_from_db)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class QueuedSmsMessage:
|
||||||
|
content: str
|
||||||
|
sender_access_key: str
|
||||||
|
local_phone_number: str
|
||||||
|
remote_phone_number: str
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
'content': self.content,
|
||||||
|
'sender_access_key': self.sender_access_key,
|
||||||
|
'local_phone_number': self.local_phone_number,
|
||||||
|
'remote_phone_number': self.remote_phone_number
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def convert(sms_from_db) -> QueuedSmsMessage:
|
||||||
|
return QueuedSmsMessage(*sms_from_db)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ cur.execute("CREATE TABLE devices(access_key, secret_key_hash, type, name)")
|
|||||||
cur.execute("CREATE TABLE messages(content, ts_received, ts_sent, type, local_phone_number, remote_phone_number)")
|
cur.execute("CREATE TABLE messages(content, ts_received, ts_sent, type, local_phone_number, remote_phone_number)")
|
||||||
cur.execute("CREATE TABLE sim_events(sim_id, ts, note, cost, currency)")
|
cur.execute("CREATE TABLE sim_events(sim_id, ts, note, cost, currency)")
|
||||||
cur.execute("CREATE TABLE sim_cards(phone_number, device_access_key)")
|
cur.execute("CREATE TABLE sim_cards(phone_number, device_access_key)")
|
||||||
|
cur.execute("CREATE TABLE message_queue(content, sender_access_key, local_phone_number, remote_phone_number)")
|
||||||
|
|
||||||
pw1_hash = flask_bcrypt.generate_password_hash('pw1').decode('utf-8')
|
pw1_hash = flask_bcrypt.generate_password_hash('pw1').decode('utf-8')
|
||||||
pw2_hash = flask_bcrypt.generate_password_hash('pw2').decode('utf-8')
|
pw2_hash = flask_bcrypt.generate_password_hash('pw2').decode('utf-8')
|
||||||
|
|||||||
Reference in New Issue
Block a user