diff --git a/apiserver/apimodels/queues.py b/apiserver/apimodels/queues.py index 3915379..e03b517 100644 --- a/apiserver/apimodels/queues.py +++ b/apiserver/apimodels/queues.py @@ -38,6 +38,7 @@ class GetAllRequest(Base): class GetNextTaskRequest(QueueRequest): queue = StringField(required=True) get_task_info = BoolField(default=False) + task = StringField() class DeleteRequest(QueueRequest): diff --git a/apiserver/bll/user/__init__.py b/apiserver/bll/user/__init__.py index ceb3b71..f47221b 100644 --- a/apiserver/bll/user/__init__.py +++ b/apiserver/bll/user/__init__.py @@ -1,3 +1,5 @@ +from datetime import datetime + from apiserver.apierrors import errors from apiserver.apimodels.users import CreateRequest from apiserver.database.errors import translate_errors_context @@ -12,7 +14,7 @@ class UserBLL: if user_id and User.objects(id=user_id).only("id"): raise errors.bad_request.UserIdExists(id=user_id) - user = User(**request.to_struct()) + user = User(**request.to_struct(), created=datetime.utcnow()) user.save(force_insert=True) @staticmethod diff --git a/apiserver/database/model/user.py b/apiserver/database/model/user.py index 18329c1..9281908 100644 --- a/apiserver/database/model/user.py +++ b/apiserver/database/model/user.py @@ -1,4 +1,4 @@ -from mongoengine import Document, StringField, DynamicField +from mongoengine import Document, StringField, DynamicField, DateTimeField from apiserver.database import Database, strict from apiserver.database.model import DbModelMixin @@ -20,3 +20,4 @@ class User(DbModelMixin, Document): given_name = StringField(user_set_allowed=True) avatar = StringField() preferences = DynamicField(default="", exclude_by_default=True) + created = DateTimeField() diff --git a/apiserver/mongo/initialize/migration.py b/apiserver/mongo/initialize/migration.py index 541b766..daa58b0 100644 --- a/apiserver/mongo/initialize/migration.py +++ b/apiserver/mongo/initialize/migration.py @@ -1,8 +1,10 @@ import importlib.util from datetime import datetime +from inspect import signature from logging import Logger from pathlib import Path +import pymongo.database from mongoengine.connection import get_db from packaging.version import Version, parse @@ -80,8 +82,15 @@ def _apply_migrations(log: Logger): if not func: continue try: + sig = signature(func) + kwargs = {} + if len(sig.parameters) == 2: + name, param = list(sig.parameters.items())[-1] + key = name.replace("_", "-") + if issubclass(param.annotation, pymongo.database.Database) and key in dbs: + kwargs[name] = get_db(key) log.info(f"Applying {script.stem}/{func_name}()") - func(get_db(alias)) + func(get_db(alias), **kwargs) except Exception: log.exception(f"Failed applying {script}:{func_name}()") raise ValueError( diff --git a/apiserver/mongo/initialize/user.py b/apiserver/mongo/initialize/user.py index adfd375..6682fe0 100644 --- a/apiserver/mongo/initialize/user.py +++ b/apiserver/mongo/initialize/user.py @@ -53,6 +53,7 @@ def _ensure_backend_user(user_id: str, company_id: str, user_name: str): name=user_name, given_name=given_name, family_name=family_name, + created=datetime.utcnow(), ).save() return user_id diff --git a/apiserver/mongo/migrations/1_7_0.py b/apiserver/mongo/migrations/1_7_0.py new file mode 100644 index 0000000..c8afd6b --- /dev/null +++ b/apiserver/mongo/migrations/1_7_0.py @@ -0,0 +1,15 @@ +from pymongo.collection import Collection +from pymongo.database import Database + + +def migrate_backend(db: Database, auth_db: Database): + users: Collection = db["user"] + auth_users: Collection = auth_db["user"] + created_field = "created" + for doc in users.find({created_field: {"$exists": False}}): + auth_user = auth_users.find_one({"_id": doc["_id"]}, projection=[created_field]) + if not auth_user or created_field not in auth_user: + continue + users.update_one( + {"_id": doc["_id"]}, {"$set": {created_field: auth_user[created_field]}} + ) diff --git a/apiserver/schema/services/queues.conf b/apiserver/schema/services/queues.conf index e9c1d5c..373dd78 100644 --- a/apiserver/schema/services/queues.conf +++ b/apiserver/schema/services/queues.conf @@ -463,6 +463,33 @@ get_next_task { } } } + "2.14": ${get_next_task."2.4"} { + request.properties.get_task_info { + description: "If set then additional task info is returned" + type: boolean + default: false + } + response.properties.task_info { + description: "Info about the returned task. Returned only if get_task_info is set to True" + type: object + properties { + company { + description: Task company ID + type: string + } + user { + description: ID of the user who created the task + type: string + } + } + } + } + "999.0": ${get_next_task."2.14"} { + request.properties.task { + description: Task company ID + type: string + } + } } remove_task { "2.4" { diff --git a/apiserver/services/queues.py b/apiserver/services/queues.py index 69227a3..a78a634 100644 --- a/apiserver/services/queues.py +++ b/apiserver/services/queues.py @@ -157,11 +157,13 @@ def add_task(call: APICall, company_id, req_model: TaskRequest): @endpoint("queues.get_next_task", request_data_model=GetNextTaskRequest) -def get_next_task(call: APICall, company_id, req_model: GetNextTaskRequest): - entry = queue_bll.get_next_task(company_id=company_id, queue_id=req_model.queue) +def get_next_task(call: APICall, company_id, request: GetNextTaskRequest): + entry = queue_bll.get_next_task( + company_id=company_id, queue_id=request.queue, task_id=request.task + ) if entry: data = {"entry": entry.to_proper_dict()} - if req_model.get_task_info: + if request.get_task_info: task = Task.objects(id=entry.task).first() if task: data["task_info"] = {"company": task.company, "user": task.user} diff --git a/apiserver/services/users.py b/apiserver/services/users.py index ef33bc5..70f1f93 100644 --- a/apiserver/services/users.py +++ b/apiserver/services/users.py @@ -12,7 +12,7 @@ from apiserver.bll.project import ProjectBLL from apiserver.bll.user import UserBLL from apiserver.config_repo import config from apiserver.database.errors import translate_errors_context -from apiserver.database.model.auth import Role, User as AuthUser +from apiserver.database.model.auth import Role from apiserver.database.model.company import Company from apiserver.database.model.user import User from apiserver.database.utils import parse_from_call @@ -114,12 +114,6 @@ def get_current_user(call: APICall, company_id, _): user = res[0] user["role"] = call.identity.role - auth_user: AuthUser = AuthUser.objects(id=user_id, company=company_id).first() - if not auth_user: - raise errors.bad_request.InvalidUser("failed loading user") - - user["created"] = auth_user.created - resp = { "user": user, "getting_started": config.get("apiserver.getting_started_info", None), diff --git a/apiserver/tests/automated/test_queues.py b/apiserver/tests/automated/test_queues.py index 1605ad2..f24857f 100644 --- a/apiserver/tests/automated/test_queues.py +++ b/apiserver/tests/automated/test_queues.py @@ -91,7 +91,6 @@ class TestQueues(TestService): self.assertEqual(res.task.status, "queued") self.api.queues.delete(queue=queue, force=True) - self.api.tasks.dequeue(task=task) res = self.api.tasks.get_by_id(task=task) self.assertEqual(res.task.status, "created")