diff --git a/neon_users_service/databases/sqlite.py b/neon_users_service/databases/sqlite.py index ce6d28c..33074f3 100644 --- a/neon_users_service/databases/sqlite.py +++ b/neon_users_service/databases/sqlite.py @@ -15,7 +15,7 @@ class SQLiteUserDatabase(UserDatabase): def __init__(self, db_path: Optional[str] = None): db_path = expanduser(db_path or "~/.local/share/neon/user-db.sqlite") makedirs(dirname(db_path), exist_ok=True) - self.connection = connect(db_path) + self.connection = connect(db_path, check_same_thread=False) self._db_lock = Lock() self.connection.execute( '''CREATE TABLE IF NOT EXISTS users diff --git a/neon_users_service/models.py b/neon_users_service/models.py index d9e38ef..5e2a437 100644 --- a/neon_users_service/models.py +++ b/neon_users_service/models.py @@ -112,11 +112,16 @@ class PermissionsConfig(BaseModel): class TokenConfig(BaseModel): - description: str + username: str client_id: str - expiration_timestamp: int + permissions: dict refresh_token: str - last_used_timestamp: int + expiration: int + refresh_expiration: int + token_name: str + creation_timestamp: int + last_refresh_timestamp: int + access_token: Optional[str] = None class User(BaseModel): diff --git a/neon_users_service/mq_connector.py b/neon_users_service/mq_connector.py index 4fa8ca0..2a3e97f 100644 --- a/neon_users_service/mq_connector.py +++ b/neon_users_service/mq_connector.py @@ -5,6 +5,7 @@ from ovos_config.config import Configuration from neon_mq_connector.connector import MQConnector from neon_mq_connector.utils.network_utils import b64_to_dict, dict_to_b64 +from neon_users_service.exceptions import UserNotFoundError, AuthenticationError, UserNotMatchedError, UserExistsError from neon_users_service.models import MQRequest, User from neon_users_service.service import NeonUsersService @@ -27,45 +28,46 @@ def parse_mq_request(self, mq_req: dict) -> dict: "error": f"Supplied username ({mq_req.username}) " f"Does not match user object " f"({mq_req.user.username})"} - - if mq_req.operaion == "create": - if not mq_req.password: - return {"success": False, - "error": "Empty password provided"} - if not mq_req.user: - mq_req.user = User(username=mq_req.username, - password_hash=mq_req.password) - mq_req.user.password_hash = mq_req.password - try: + try: + if mq_req.operation == "create": + if not mq_req.password: + return {"success": False, + "error": "Empty password provided"} + if not mq_req.user: + mq_req.user = User(username=mq_req.username, + password_hash=mq_req.password) + mq_req.user.password_hash = mq_req.password user = self.service.create_user(mq_req.user) - except Exception as e: - return {"success": False, "error": repr(e)} - elif mq_req.operation == "read": - try: + elif mq_req.operation == "read": if mq_req.password: user = self.service.read_authenticated_user(mq_req.username, mq_req.password) else: user = self.service.read_unauthenticated_user( mq_req.username) - except Exception as e: - return {"success": False, "error": repr(e)} - elif mq_req.operation == "update": - try: + elif mq_req.operation == "update": if mq_req.password: mq_req.user.password_hash = mq_req.password user = self.service.update_user(mq_req.user) - except Exception as e: - return {"success": False, "error": repr(e)} - elif mq_req.operation == "delete": - try: + elif mq_req.operation == "delete": user = self.service.delete_user(mq_req.user) - except Exception as e: - return {"success": False, "error": repr(e)} - else: - raise RuntimeError(f"Invalid operation requested: " - f"{mq_req.operation}") - return {"success": True, "user": user.model_dump()} + else: + raise RuntimeError(f"Invalid operation requested: " + f"{mq_req.operation}") + return {"success": True, "user": user.model_dump()} + except UserExistsError: + return {"success": False, "error": "User already exists", + "code": 409} + except UserNotFoundError: + return {"success": False, "error": "User does not exist", + "code": 404} + except UserNotMatchedError: + return {"success": False, "error": "Invalid user", "code": 401} + except AuthenticationError: + return {"success": False, "error": "Invalid username or password", + "code": 401} + except Exception as e: + return {"success": False, "error": repr(e), "code": 500} def handle_request(self, channel: pika.channel.Channel, @@ -87,18 +89,20 @@ def handle_request(self, request = b64_to_dict(body) message_id = request.get("message_id") response = self.parse_mq_request(request) + response["message_id"] = message_id data = dict_to_b64(response) + routing_key = request.get('routing_key', 'neon_users_output') # queue declare is idempotent, just making sure queue exists - channel.queue_declare(queue='neon_users_output') + channel.queue_declare(queue=routing_key) channel.basic_publish( exchange='', - routing_key=request.get('routing_key', - 'neon_users_output'), + routing_key=routing_key, body=data, properties=pika.BasicProperties(expiration='1000') ) + LOG.info(f"Sent response to queue {routing_key}: {response}") channel.basic_ack(method.delivery_tag) except Exception as e: LOG.exception(f"message_id={message_id}: {e}")