Ejemplo n.º 1
0
def get_max_seconds(default=120):
    """Returns the max number of seconds to wait for a task to finish
    """
    registry_id = "senaite.queue.max_seconds_unlock"
    max_seconds = api.get_registry_record(registry_id)
    max_seconds = api.to_int(max_seconds, default=default)
    return max_seconds >= 30 and max_seconds or default
Ejemplo n.º 2
0
def get_max_retries(default=3):
    """Returns the number of retries before considering a task as failed
    """
    registry_id = "senaite.queue.max_retries"
    max_retries = api.get_registry_record(registry_id)
    max_retries = api.to_int(max_retries, default=default)
    return max_retries >= 1 and max_retries or default
Ejemplo n.º 3
0
 def wrapper(*args, **kwargs):
     if is_installed():
         # Check if enabled
         from bika.lims import api
         reg_id = "senaite.sqlmultiplex.enabled"
         if api.get_registry_record(reg_id) is True:
             return func(*args, **kwargs)
Ejemplo n.º 4
0
def get_min_seconds(default=3):
    """Returns the minimum number of seconds to book per task
    """
    registry_id = "senaite.queue.min_seconds_task"
    min_seconds = api.get_registry_record(registry_id)
    min_seconds = api.to_int(min_seconds, default=default)
    return min_seconds >= 1 and min_seconds or default
Ejemplo n.º 5
0
def is_patient_required():
    """Checks if the patient is required
    """
    required = api.get_registry_record("senaite.patient.require_patient")
    if not required:
        return False
    return True
Ejemplo n.º 6
0
def get_registry_records_by_keyword(keyword=None):
    """Get all the registry records (names and values) whose name
     contains the specified keyword or, if keyword is None, return
     all registry items

    :param keyword: The keyword that has to be contained in the record name
    :type keyword: str or None
    :returns: Dictionary mapping the names of the found records to its values
    """
    portal_reg = ploneapi.portal.get_tool(name="portal_registry")
    found_registers = {}
    for record in portal_reg.records:
        if keyword is None:
            found_registers[record] = api.get_registry_record(record)
        elif keyword.lower() in record.lower():
            found_registers[record] = api.get_registry_record(record)
    return found_registers
Ejemplo n.º 7
0
def get_patient_name_entry_mode():
    """Returns the entry mode for patient name
    """
    entry_mode = api.get_registry_record("senaite.patient.patient_entry_mode")
    if not entry_mode:
        # Default to firstname + fullname
        entry_mode = "parts"
    return entry_mode
Ejemplo n.º 8
0
 def get_connection_configuration(self):
     """Returns a dict with the configuration for the SQL connection
     """
     config = {}
     params = ["host", "port", "database", "user", "password"]
     for param in params:
         reg_id = "senaite.sqlmultiplex.{}".format(param)
         config.update({param: api.get_registry_record(reg_id)})
     return config
Ejemplo n.º 9
0
    def guard_publish(self):
        """Returns whether the sample can be published
        """
        temp_mrn = self.context.isMedicalRecordTemporary()
        if temp_mrn:
            if not api.get_registry_record("senaite.patient.publish_temp_mrn"):
                return False

        return True
Ejemplo n.º 10
0
 def get_default_template(self, default="senaite.lims:Default.pt"):
     """Returns the configured default template from the registry
     """
     template = self.get_request_parameter("template")
     if self.template_exists(template):
         return template
     template = api.get_registry_record("senaite.impress.default_template")
     if template is None:
         return default
     return template
Ejemplo n.º 11
0
    def guard_verify(self):
        """Returns whether the sample can be verified
        """
        temp_mrn = self.context.isMedicalRecordTemporary()
        if temp_mrn:
            # Check whether users can verify samples with a temporary MRN
            if not api.get_registry_record("senaite.patient.verify_temp_mrn"):
                return False

        return True
Ejemplo n.º 12
0
 def max_email_size(self):
     """Return the max. allowed email size in KB
     """
     # check first if a registry record exists
     max_email_size = api.get_registry_record("senaite.core.max_email_size")
     if max_email_size is None:
         max_size = DEFAULT_MAX_EMAIL_SIZE
     if max_size < 0:
         max_email_size = 0
     return max_size * 1024
Ejemplo n.º 13
0
 def get_default_orientation(self, default="portrait"):
     """Returns the configured default orientation from the registry
     """
     orientation = self.get_request_parameter("orientation")
     if orientation in ["portrait", "landscape"]:
         return orientation
     orientation = api.get_registry_record(
         "senaite.impress.default_orientation")
     if orientation is None:
         return default
     return orientation
Ejemplo n.º 14
0
 def get_default_paperformat(self, default="A4"):
     """Returns the configured default paperformat from the registry
     """
     paperformat = self.get_request_parameter("paperformat")
     if paperformat in self.get_paperformats():
         return paperformat
     paperformat = api.get_registry_record(
         "senaite.impress.default_paperformat")
     if paperformat is None:
         return default
     return paperformat
Ejemplo n.º 15
0
 def subject(self):
     """Returns the subject of the email
     """
     email_subject = api.get_registry_record("senaite.panic.email_subject")
     client = self.sample.getClient()
     return self.context.translate(
         email_subject,
         mapping={
             "sample_id": api.get_id(self.sample),
             "client_id": client.getClientID(),
             "client_sample_id": self.sample.getClientSampleID(),
         })
Ejemplo n.º 16
0
    def __call__(self, r):
        # We want our key to be valid for 10 seconds only
        secs = time.time() + 10
        token = "{}:{}".format(secs, self.username)

        # Encrypt the token using our symmetric auth key
        if not self.key:
            self.key = api.get_registry_record("senaite.queue.auth_key")
        auth_token = Fernet(str(self.key)).encrypt(token)

        # Modify and return the request
        r.headers["X-Queue-Auth-Token"] = auth_token
        return r
Ejemplo n.º 17
0
def get_server_url():
    """Returns the url of the queue server if valid. None otherwise.
    """
    url = _api.get_registry_record("senaite.queue.server")
    try:
        result = parse.urlparse(url)
    except:  # noqa a convenient way to check if the url is valid
        return None

    # Validate the url is ok
    if not all([result.scheme, result.netloc, result.path]):
        return None

    url = "{}://{}{}".format(result.scheme, result.netloc, result.path)
    return url.strip("/")
Ejemplo n.º 18
0
def get_chunk_size(name_or_action=None):
    """Returns the number of items to process at once for the given task name
    :param name_or_action: task name or workflow action id
    :returns: the number of items from the task to process async at once
    :rtype: int
    """
    chunk_size = api.get_registry_record("senaite.queue.default")
    chunk_size = api.to_int(chunk_size, 0)
    if chunk_size <= 0:
        # Queue disabled
        return 0

    if name_or_action:
        # TODO Retrieve task-specific chunk-sizes via adapters
        pass

    if chunk_size < 0:
        chunk_size = 0

    return chunk_size
Ejemplo n.º 19
0
    def extractCredentials(self, request):  # noqa camelCase
        """IExtractionPlugin implementation. Extracts login name from the
        request's "X-Queue-Auth-Token" header. This header contains an
        encrypted token with it's expiration date, together with the user name.

        Returns a dict with {'login': <username>} if:
        - current layer is ISenaiteQueueLayer,
        - the token can be decrypted,
        - the decrypted token contains both expiration and username and
        - the the token has not expired (expiration date)

        Returns an empty dict otherwise
        :param request: the HTTPRequest object to extract credentials from
        :return: a dict {"login": <username>} or empty dict
        """
        # Check if request provides ISenaiteQueueLayer
        if not ISenaiteQueueLayer.providedBy(request):
            return {}

        # Read the magical header that contains the encrypted info
        auth_token = request.getHeader("X-Queue-Auth-Token")
        if not auth_token:
            return {}

        # Decrypt the auth_token
        key = api.get_registry_record("senaite.queue.auth_key")
        token = Fernet(str(key)).decrypt(auth_token)

        # Check if token is valid
        tokens = token.split(":")
        if len(tokens) < 2 or not api.is_floatable(tokens[0]):
            return {}

        # Check if token has expired
        expiration = api.to_float(tokens[0])
        if expiration < time.time():
            return {}

        user_id = "".join(tokens[1:])
        return {"login": user_id}
Ejemplo n.º 20
0
    def body(self):
        """Returns the body message of the email
        """
        setup = api.get_setup()
        laboratory = setup.laboratory
        lab_address = "\n".join(laboratory.getPrintAddress())
        analyses = map(self.to_str, self.get_analyses_in_panic(self.sample))
        analyses = "\n-".join(analyses)

        # TODO more mappings here (custom body)!
        email_body = api.get_registry_record("senaite.panic.email_body")
        client = self.sample.getClient()
        return self.context.translate(
            email_body,
            mapping={
                "sample_id": api.get_id(self.sample),
                "analyses": analyses,
                "lab_address": lab_address,
                "client_id": client.getClientID(),
                "client_sample_id": self.sample.getClientSampleID(),
                "sample_url": api.get_url(self.sample),
            })
Ejemplo n.º 21
0
 def get_multiplexed_types(self):
     """Returns the list of portal types to be multiplexed
     """
     reg_id = "senaite.sqlmultiplex.content_types"
     return api.get_registry_record(reg_id, [])
Ejemplo n.º 22
0
 def store_multireports_individually(self):
     """Returns the configured setting from the registry
     """
     store_individually = api.get_registry_record(
         "senaite.impress.store_multireports_individually")
     return store_individually
Ejemplo n.º 23
0
 def get_developer_mode(self):
     """Returns the configured setting from the registry
     """
     mode = api.get_registry_record("senaite.impress.developer_mode", False)
     return mode
Ejemplo n.º 24
0
 def get_footer_text(self, escape=True):
     """Returns the footer text from the setup
     """
     return api.get_registry_record("senaite.impress.footer")
Ejemplo n.º 25
0
def consume_task():
    """Consumes a task from the queue, if any
    """
    if not is_installed():
        return info("Queue is not installed")

    host = _api.get_request().get("SERVER_URL")
    if not is_valid_zeo_host(host):
        return error("zeo host not set or not valid: {} [SKIP]".format(host))

    consumer_thread = get_consumer_thread()
    if consumer_thread:
        # There is a consumer working already
        name = consumer_thread.getName()
        return info("Consumer running: {} [SKIP]".format(name))

    logger.info("Queue client: {}".format(host))

    # Server's queue URL
    server = api.get_server_url()

    # Check the status of the queue
    status = api.get_queue_status()
    if status not in ["resuming", "ready"]:
        return warn("Server is {} ({}) [SKIP]".format(status, server))

    if api.is_queue_server():
        message = [
            "Server = Consumer: {}".format(server),
            "*******************************************************",
            "Client configured as both queue server and consumer.",
            "This is not suitable for productive environments!",
            "Change the Queue Server URL in SENAITE's control panel",
            "or setup another zeo client as queue consumer.",
            "Current URL: {}".format(server),
            "*******************************************************"
        ]
        logger.warn("\n".join(message))

    # Pop next task to process
    consumer_id = host
    try:
        task = api.get_queue().pop(consumer_id)
        if not task:
            return info("Queue is empty or process undergoing [SKIP]")
    except Exception as e:
        return error("Cannot pop. {}: {}".format(type(e).__name__, str(e)))

    auth_key = _api.get_registry_record("senaite.queue.auth_key")
    kwargs = {
        "task_uid": task.task_uid,
        "task_username": task.username,
        "consumer_id": consumer_id,
        "base_url": _api.get_url(_api.get_portal()),
        "server_url": api.get_server_url(),
        "user_id": _api.get_current_user().id,
        "max_seconds": get_max_seconds(),
        "auth_key": auth_key,
    }
    name = "{}{}".format(CONSUMER_THREAD_PREFIX, int(time.time()))
    t = threading.Thread(name=name, target=process_task, kwargs=kwargs)
    t.start()

    return info("Consumer running: {} [SKIP]".format(CONSUMER_THREAD_PREFIX))