Adds basic authentication logic.

+ Users need to be registered in order to send appointments (free registration for now)
+ The tower gives them a number of appointments to work with
+ Non-registered users and users with no enough appoitnemnts slots return the same error (to avoid proving)

- Authentication does not cover get_* requests yet
- No tests
- No docs
This commit is contained in:
Sergi Delgado Segura
2020-03-25 17:13:35 +01:00
parent 519caec29a
commit 83b3913cb5
6 changed files with 133 additions and 74 deletions

View File

@@ -1,8 +1,13 @@
import re
SUBSCRIPTION_SLOTS = 100
import teos.errors as errors
# TODO: UNITTEST
from common.appointment import Appointment
from common.cryptographer import Cryptographer
SUBSCRIPTION_SLOTS = 1
# TODO: UNITTEST, DOCS
class Gatekeeper:
def __init__(self):
self.registered_users = {}
@@ -30,3 +35,63 @@ class Gatekeeper:
self.registered_users[user_pk] += SUBSCRIPTION_SLOTS
return self.registered_users[user_pk]
def fill_subscription_slots(self, user_pk, n):
slots = self.registered_users.get(user_pk)
# FIXME: This looks pretty dangerous. I'm guessing race conditions can happen here.
if slots == n:
self.registered_users.pop(user_pk)
else:
self.registered_users[user_pk] -= n
def identify_user(self, appointment_data, signature):
"""
Checks if the provided user signature is comes from a registered user with available appointment slots.
Args:
appointment_data (:obj:`dict`): the appointment that was signed by the user.
signature (:obj:`str`): the user's signature (hex encoded).
Returns:
:obj:`tuple`: A tuple (return code, message) as follows:
- ``(0, None)`` if the user can be identified (recovered pk belongs to a registered user) and the user has
available slots.
- ``!= (0, None)`` otherwise.
The possible return errors are: ``APPOINTMENT_EMPTY_FIELD`` and ``APPOINTMENT_INVALID_SIGNATURE``.
"""
if signature is None:
rcode = errors.APPOINTMENT_EMPTY_FIELD
message = "empty signature received"
else:
appointment = Appointment.from_dict(appointment_data)
rpk = Cryptographer.recover_pk(appointment.serialize(), signature)
compressed_user_pk = Cryptographer.get_compressed_pk(rpk)
if compressed_user_pk and compressed_user_pk in self.registered_users:
rcode = 0
message = compressed_user_pk
else:
rcode = errors.APPOINTMENT_INVALID_SIGNATURE_OR_INSUFFICIENT_SLOTS
message = "invalid signature or the user does not have enough slots available"
return rcode, message
def get_slots(self, user_pk):
"""
Returns the number os available slots for a given user.
Args:
user_pk(:mod:`str`): the public key that identifies the user (33-bytes hex str)
Returns:
:obj:`int`: the number of available slots.
"""
slots = self.registered_users.get(user_pk)
return slots if slots is not None else 0