Exemple #1
0
    def _apply_filter_by_client(self):
        # If the current context is a Client, filter Patients by Client UID
        if IClient.providedBy(self.context):
            client_uid = api.get_uid(self.context)
            self.contentFilter['getPrimaryReferrerUID'] = client_uid
            return

        # If the current user is a Client contact, filter the Patients in
        # accordance. For the rest of users (LabContacts), the visibility of
        # the patients depend on their permissions
        user = api.get_current_user()
        roles = user.getRoles()
        if 'Client' not in roles:
            return

        # Are we sure this a ClientContact?
        # May happen that this is a Plone member, w/o having a ClientContact
        # assigned or having a LabContact assigned... weird
        contact = api.get_user_contact(user)
        if not contact or ILabContact.providedBy(contact):
            return

        # Is the parent from the Contact a Client?
        client = api.get_parent(contact)
        if not client or not IClient.providedBy(client):
            return
        client_uid = api.get_uid(client)
        self.contentFilter['getPrimaryReferrerUID'] = client_uid
Exemple #2
0
def changeWorkflowState(content, wf_id, state_id, **kw):
    """Change the workflow state of an object
    @param content: Content obj which state will be changed
    @param state_id: name of the state to put on content
    @param kw: change the values of same name of the state mapping
    @return: True if succeed. Otherwise, False
    """
    portal_workflow = api.get_tool("portal_workflow")
    workflow = portal_workflow.getWorkflowById(wf_id)
    if not workflow:
        logger.error("%s: Cannot find workflow id %s" % (content, wf_id))
        return False

    wf_state = {
        'action': kw.get("action", None),
        'actor': kw.get("actor",
                        api.get_current_user().id),
        'comments': "Setting state to %s" % state_id,
        'review_state': state_id,
        'time': DateTime()
    }

    # Change status and update permissions
    portal_workflow.setStatusOf(wf_id, content, wf_state)
    workflow.updateRoleMappingsFor(content)

    # Map changes to catalog
    indexes = ["allowedRolesAndUsers", "review_state", "is_active"]
    content.reindexObject(idxs=indexes)
    return True
Exemple #3
0
    def _post(self, endpoint, resource=None, payload=None, timeout=10):
        """Sends a POST request to SENAITE's Queue Server
        Raises an exception if the response status is not HTTP 2xx or timeout
        :param endpoint: the endpoint to POST against
        :param resource: (Optional) resource from the endpoint to POST against
        :param payload: (Optional) hashable payload for the POST
        """
        server_url = api.get_server_url()
        parts = "/".join(filter(None, [endpoint, resource]))
        url = "{}/@@API/senaite/v1/queue_server/{}".format(server_url, parts)
        logger.info("** POST: {}".format(url))

        # HTTP Queue Authentication to be added in the request
        auth = QueueAuth(capi.get_current_user().id)

        # Additional information to the payload
        request = capi.get_request()
        if payload is None:
            payload = {}
        payload.update({"__zeo": request.get("SERVER_URL")})

        # This might rise exceptions (e.g. TimeoutException)
        response = self._req.post(url,
                                  json=payload,
                                  auth=auth,
                                  timeout=timeout)

        # Check the request is successful. Raise exception otherwise
        response.raise_for_status()

        # Return the result
        return response.json()
Exemple #4
0
    def folderitems(self):
        """Custom folderitems

        :returns: listing items
        """

        # XXX: Should be done via the Worflow
        # Check edit permissions
        self.allow_edit = False
        member = api.get_current_user()
        roles = member.getRoles()
        if set(roles).intersection(ALLOW_EDIT):
            self.allow_edit = True

        # Analysis Services retrieval and custom item creation
        items = []

        services = self.get_services()
        for num, service in enumerate(services):
            item = self.folderitem(service, {}, num)
            if item:
                items.append(item)

        self.categories = self.get_sorted_categories(items)

        return items
Exemple #5
0
    def _apply_filter_by_client(self):
        """
        If the user has the role Client, the user can not see batches
        from client objects he/she does not belong to.
        """
        # If the current context is a Client, filter Batches by Client UID
        if IClient.providedBy(self.context):
            client_uid = api.get_uid(self.context)
            self.contentFilter['getClientUID'] = client_uid
            return

        # If the current user is a Client contact, filter the Batches in
        # accordance. For the rest of users (LabContacts), the visibility of
        # the Batches depend on their permissions
        user = api.get_current_user()
        roles = user.getRoles()
        if 'Client' not in roles:
            return

        # Are we sure this a ClientContact?
        # May happen that this is a Plone member, w/o having a ClientContact
        # assigned or having a LabContact assigned... weird
        contact = api.get_user_contact(user)
        if not contact or ILabContact.providedBy(contact):
            return

        # Is the parent from the Contact a Client?
        client = api.get_parent(contact)
        if not client or not IClient.providedBy(client):
            return
        client_uid = api.get_uid(client)
        self.contentFilter['getClientUID'] = client_uid
Exemple #6
0
def guard_deliver(context):
    """Guard for deliver transition. Returns true if a Courier has been 
    assigned to the Sample and the Sample (context) is active. Note we
    do not check for roles or client here because permissions for clients
    when the sample is in state `sample_shipped` are already defined in the
    workflow definition.
    """
    sample = get_sample(context)
    if not sample:
        return False

    # If sample is inactive, we cannot deliver the sample to the lab
    if not api.is_active(sample):
        return False

    # If sample does not have a courier assigned, we cannot deliver
    if not sample.Schema()['Courier'].get(sample):
        return False

    # If the current user is a Client contact, do not allow to deliver
    user = api.get_current_user()
    if "Client" in user.getRoles():
        return False

    return True
Exemple #7
0
def user_has_super_roles():
    """Return whether the current belongs to superuser roles
    """
    member = api.get_current_user()
    super_roles = ["LabManager", "Manager"]
    diff = filter(lambda role: role in super_roles, member.getRoles())
    return len(diff) > 0
Exemple #8
0
def before_sample(analysis_request):
    """Method triggered before "sample" transition for the Analysis Request
    passed in is performed
    """
    if not analysis_request.getDateSampled():
        analysis_request.setDateSampled(DateTime())
    if not analysis_request.getSampler():
        analysis_request.setSampler(api.get_current_user().id)
Exemple #9
0
    def __call__(self):
        url = api.get_url(api.get_portal())
        current_user = api.get_current_user()
        contact = api.get_user_contact(current_user)
        if contact:
            parent = api.get_parent(contact)
            url = api.get_url(parent)

        return self.request.response.redirect(url)
Exemple #10
0
    def _folder_item_analyst(self, obj, item):
        is_editable = self.is_analysis_edition_allowed(obj)
        if not is_editable:
            item['Analyst'] = obj.getAnalystName
            return

        # Analyst is editable
        item['Analyst'] = obj.getAnalyst or api.get_current_user().id
        item['choices']['Analyst'] = self.get_analysts()
Exemple #11
0
def guard_sample(analysis_request):
    """Returns whether 'sample' transition can be performed or not. Returns
    True only if the analysis request has the DateSampled and Sampler set or if
    the user belongs to the Samplers group
    """
    if analysis_request.getDateSampled() and analysis_request.getSampler():
        return True

    current_user = api.get_current_user()
    return "Sampler" in current_user.getRolesInContext(analysis_request)
Exemple #12
0
 def user_can_delete_attachments(self):
     """Checks if the current logged in user is allowed to delete attachments
     """
     context = self.context
     user = api.get_current_user()
     if not self.is_ar_editable():
         return False
     return (self.user_can_add_attachments() and
             not user.allowed(context, ["Client"])) or \
         self.user_can_update_attachments()
 def is_edit_allowed(self):
     """Check if edit is allowed
     """
     current_user = api.get_current_user()
     roles = current_user.getRoles()
     if "LabManager" in roles:
         return True
     if "Manager" in roles:
         return True
     return False
Exemple #14
0
    def _get_authenticated_user(self, request):
        authenticated_user = request.get("AUTHENTICATED_USER")
        if authenticated_user:
            if hasattr(authenticated_user, "getId"):
                return authenticated_user.getId()
            if isinstance(authenticated_user, six.string_types):
                return authenticated_user

        # Pick current user
        current_user = api.get_current_user()
        return current_user and current_user.id or ""
Exemple #15
0
def guard_send_to_pot(context):
    """Guard for sending the sample to the point of testing
    """
    if not api.is_active(context):
        return False

    # If the current user is a Client contact, do not allow to deliver
    user = api.get_current_user()
    if "Client" in user.getRoles():
        return False

    return True
Exemple #16
0
 def __call__(self):
     plone.protect.CheckAuthenticator(self.request)
     curr_user = api.get_current_user()
     contact = api.get_user_contact(curr_user, contact_types=['Contact'])
     parent = contact and contact.getParent() or None
     if parent and not IClient.providedBy(parent):
         parent = None
     ret = {'ClientTitle': parent and parent.Title() or '',
            'ClientID': parent and parent.getClientID() or '',
            'ClientSysID': parent and parent.id or '',
            'ClientUID': parent and parent.UID() or '',}
     return json.dumps(ret)
Exemple #17
0
 def __call__(self):
     plone.protect.CheckAuthenticator(self.request)
     curr_user = api.get_current_user()
     contact = api.get_user_contact(curr_user, contact_types=['Contact'])
     parent = contact and contact.getParent() or None
     if parent and not IClient.providedBy(parent):
         parent = None
     ret = {'ClientTitle': parent and parent.Title() or '',
            'ClientID': parent and parent.getClientID() or '',
            'ClientSysID': parent and parent.id or '',
            'ClientUID': parent and parent.UID() or '',}
     return json.dumps(ret)
 def folderitems(self):
     """Processed once for all analyses
     """
     # XXX: Should be done via the Worflow
     # Check edit permissions
     self.allow_edit = False
     member = api.get_current_user()
     roles = member.getRoles()
     if set(roles).intersection(ALLOW_EDIT):
         self.allow_edit = True
     items = super(AnalysisProfileAnalysesView, self).folderitems()
     self.categories.sort()
     return items
Exemple #19
0
 def current_user(self):
     user = api.get_current_user()
     # XXX: we're missing here LDAP properties!
     #      needs to be fixed in the API.
     properties = api.get_user_properties(user)
     properties.update({
         "userid": user.getId(),
         "username": user.getUserName(),
         "roles": user.getRoles(),
         "email": user.getProperty("email"),
         "fullname": user.getProperty("fullname"),
     })
     return properties
Exemple #20
0
 def to_history_record(self, value):
     """Transforms the value to an history record
     """
     user = api.get_current_user()
     contact = api.get_user_contact(user)
     fullname = contact and contact.getFullname() or ""
     if not contact:
         # get the fullname from the user properties
         props = api.get_user_properties(user)
         fullname = props.get("fullname", "")
     return RemarksHistoryRecord(user_id=user.id,
                                 user_name=fullname,
                                 content=value.strip())
Exemple #21
0
def process(context, request, task_uid=None):  # noqa
    """Processes the task passed-in
    """
    # disable CSRF
    req.disable_csrf_protection()

    # Maybe the task uid has been sent via POST
    task_uid = task_uid or req.get_json().get("task_uid")

    # Get the task
    task = get_task(task_uid)
    if task.username != capi.get_current_user().id:
        # 403 Authenticated, but user does not have access to the resource
        _fail(403)

    # Process
    t0 = time.time()
    task_context = task.get_context()
    if not task_context:
        _fail(500, "Task's context is not available")

    # Get the adapter able to process this specific type of task
    adapter = queryAdapter(task_context, IQueuedTaskAdapter, name=task.name)
    if not adapter:
        _fail(501, "No adapter found for {}".format(task.name))

    logger.info("Processing task {}: '{}' for '{}' ({}) ...".format(
        task.task_short_uid, task.name, capi.get_id(task_context),
        task.context_uid))

    # Inject the queue_consumer marker to the request so guards skip checks
    # against the queue
    request = capi.get_request()
    request.set("queue_tuid", task_uid)

    # If the task refers to a worksheet, inject (ws_id) in params to make
    # sure guards (assign, un-assign) return True
    if IWorksheet.providedBy(task_context):
        request.set("ws_uid", capi.get_uid(task_context))

    # Process the task
    adapter.process(task)

    # Sleep a bit for minimum effect against userland threads
    # Better to have a transaction conflict here than in userland
    min_seconds = task.get("min_seconds", 3)
    while time.time() - t0 < min_seconds:
        time.sleep(0.5)

    msg = "Processed: {}".format(task.task_short_uid)
    return get_message_summary(msg, "consumer.process")
    def isVisible(self, field, mode="view", default="visible"):
        edit_modes = ["sample_received", "to_be_verified"]
        if mode == "edit":
            if api.get_review_status(self.context) not in edit_modes:
                return "invisible"

            # Only Lab Manager can edit Assay Date!
            allowed_roles = ["LabManager", "Manager", "Analyst"]
            user = api.get_current_user()
            user_roles = user.getRolesInContext(self.context)
            allowed_roles = filter(lambda r: r in user_roles, allowed_roles)
            if not allowed_roles:
                return "invisible"

        return default
    def get_current_client(self, default=None):
        """Returns the client the current user belongs to
        """
        user = api.get_current_user()
        roles = user.getRoles()
        if 'Client' not in roles:
            return default

        contact = api.get_user_contact(user)
        if not contact or ILabContact.providedBy(contact):
            return default

        client = api.get_parent(contact)
        if not client or not IClient.providedBy(client):
            return default

        return client
Exemple #24
0
    def get_current_client(self, default=None):
        """Returns the client the current user belongs to
        """
        user = api.get_current_user()
        roles = user.getRoles()
        if 'Client' not in roles:
            return default

        contact = api.get_user_contact(user)
        if not contact or ILabContact.providedBy(contact):
            return default

        client = api.get_parent(contact)
        if not client or not IClient.providedBy(client):
            return default

        return client
Exemple #25
0
def after_reinstate(analysis_request):
    """Method triggered after a 'reinstate' transition for the Analysis Request
    passed in is performed. Sets its status to the last status before it was
    cancelled. Reinstates the descendant partitions and all the analyses
    associated to the analysis request as well.
    """
    do_action_to_descendants(analysis_request, "reinstate")
    do_action_to_analyses(analysis_request, "reinstate")

    # Force the transition to previous state before the request was cancelled
    prev_status = get_prev_status_from_history(analysis_request, "cancelled")
    changeWorkflowState(analysis_request,
                        AR_WORKFLOW_ID,
                        prev_status,
                        action="reinstate",
                        actor=api.get_current_user().getId())
    analysis_request.reindexObject()
Exemple #26
0
def changeWorkflowState(content, wf_id, state_id, **kw):
    """Change the workflow state of an object
    @param content: Content obj which state will be changed
    @param state_id: name of the state to put on content
    @param kw: change the values of same name of the state mapping
    @return: True if succeed. Otherwise, False
    """
    portal_workflow = api.get_tool("portal_workflow")
    workflow = portal_workflow.getWorkflowById(wf_id)
    if not workflow:
        logger.error("%s: Cannot find workflow id %s" % (content, wf_id))
        return False

    wf_state = {
        'action': kw.get("action", None),
        'actor': kw.get("actor",
                        api.get_current_user().id),
        'comments': "Setting state to %s" % state_id,
        'review_state': state_id,
        'time': DateTime()
    }

    # Get old and new state info
    old_state = workflow._getWorkflowStateOf(content)
    new_state = workflow.states.get(state_id, None)
    if new_state is None:
        raise WorkflowException(
            "Destination state undefined: {}".format(state_id))

    # Change status and update permissions
    portal_workflow.setStatusOf(wf_id, content, wf_state)
    workflow.updateRoleMappingsFor(content)

    # Notify the object has been transitioned
    notify(
        AfterTransitionEvent(content, workflow, old_state, new_state, None,
                             wf_state, None))

    # Map changes to catalog
    indexes = ["allowedRolesAndUsers", "review_state", "is_active"]
    content.reindexObject(idxs=indexes)
    return True
Exemple #27
0
def guard_submit(analysis):
    """Return whether the transition "submit" can be performed or not
    """
    # Cannot submit without a result
    if not analysis.getResult():
        return False

    # Cannot submit with interims without value
    for interim in analysis.getInterimFields():
        if not interim.get("value", ""):
            return False

    # Cannot submit if attachment not set, but is required
    if not analysis.getAttachment():
        if analysis.getAttachmentOption() == 'r':
            return False

    # Check if can submit based on the Analysis Request state
    if IRequestAnalysis.providedBy(analysis):
        point_of_capture = analysis.getPointOfCapture()
        # Cannot submit if the Sample has not been received
        if point_of_capture == "lab" and not analysis.isSampleReceived():
            return False
        # Cannot submit if the Sample has not been sampled
        if point_of_capture == "field" and not analysis.isSampleSampled():
            return False

    # Check if the current user can submit if is not assigned
    if not analysis.bika_setup.getAllowToSubmitNotAssigned():
        if not user_has_super_roles():
            # Cannot submit if unassigned
            if not analysis.getAnalyst():
                return False
            # Cannot submit if assigned analyst is not the current user
            if analysis.getAnalyst() != api.get_current_user().getId():
                return False

    # Cannot submit unless all dependencies are submitted or can be submitted
    for dependency in analysis.getDependencies():
        if not is_submitted_or_submittable(dependency):
            return False
    return True
Exemple #28
0
def guard_process(context):
    """Guard for process (partitioning) process
    Only Primary Analysis Requests can be partitioned
    """
    sample = get_sample(context)
    if not sample:
        return False

    if not api.is_active(sample):
        return False

    # If the sample is not a primary sample, do not allow processing
    if sample.Schema()['PrimarySample'].get(sample):
        return False

    # If the current user is a Client contact, do not allow to deliver
    user = api.get_current_user()
    if "Client" in user.getRoles():
        return False

    return True
Exemple #29
0
    def __call__(self):
        """Handle request parameters and render the form
        """
        logger.info(u"ListingView::__call__")

        self.portal = api.get_portal()
        self.mtool = api.get_tool("portal_membership")
        self.workflow = api.get_tool("portal_workflow")
        self.member = api.get_current_user()
        self.translate = self.context.translate

        # Call update hook
        self.update()

        # handle subpath calls
        if len(self.traverse_subpath) > 0:
            return self.handle_subpath()

        # Call before render hook
        self.before_render()

        return self.template(self.context)
Exemple #30
0
def guard_send_to_lab(context):
    """ Guard for send_to_lab transition. Returns true if the current user is
    a client contact, the Sample (context) is active and it belongs to the same
    client.
    """
    sample = get_sample(context)
    if not sample:
        return False

    # If Sample is inactive, we cannot send the sample to the lab
    if not api.is_active(sample):
        return False

    # Only users from role Client can send the sample to the lab
    user = api.get_current_user()
    user_roles = user.getRoles()
    # Only contacts from the client the Sample belongs to
    if "Client" in user_roles:
        client = sample.aq_parent
        if not client.getContactFromUsername(user.id):
            return False

    return True
def set_department_cookies(event):
    """
    Login event handler.
    When user logs in, departments must be selected if filtering by department
    is enabled in Bika Setup.
        - For (Lab)Managers and Client Contacts, all the departments from the
          system must be selected.
        - For regular Lab Contacts, default Department must be selected. If
          the Contact doesn't have any default department assigned, then first
          department in alphabetical order will be selected.
    """
    if not is_bika_installed():
        logger.warn(
            "Package 'bika.lims' is not installed, skipping event handler "
            "for IUserLoggedInEvent.")
        return

    # get the bika_setup object
    portal = api.get_portal()
    bika_setup = portal.get("bika_setup")

    # just to be sure...
    # This should go into the api.py module once it is in place
    if bika_setup is None:
        raise RuntimeError(
            "bika_setup not found in this Bika LIMS installation")

    # Getting request, response and username
    request = api.get_request()
    response = request.RESPONSE
    user = api.get_current_user()
    username = user and user.getUserName() or None
    is_manager = user and (user.has_role('Manager') or
                           user.has_role('LabManager'))
    portal_catalog = api.get_tool("portal_catalog")

    # If department filtering is disabled, disable the cookies
    if not bika_setup.getAllowDepartmentFiltering():
        response.setCookie(
            'filter_by_department_info', None,  path='/', max_age=0)
        response.setCookie(
            'dep_filter_disabled', None,  path='/', max_age=0)
        return

    selected_deps = []

    # Select all Departments for Lab Managers
    if is_manager:
        selected_deps = portal_catalog(
            portal_type='Department',
            sort_on='sortable_title',
            sort_order='ascending',
            inactive_state='active')

        response.setCookie(
            'dep_filter_disabled', 'true',  path='/',
            max_age=24 * 3600)

    else:
        brain = portal_catalog(getUsername=username)
        # It is possible that current user is created by Plone ZMI.
        # Just log it as a warning and go on
        if not brain:
            logger.warn(
                "No lab Contact found... Plone user or Client "
                "Contact logged in. " + username)
            response.setCookie(
                'filter_by_department_info', None, path='/', max_age=0)
            response.setCookie(
                'dep_filter_disabled', None, path='/', max_age=0)
            return

        # If it is a Client Contact, select all departments no need to filter.
        elif brain[0].portal_type == 'Contact':
            selected_deps = portal_catalog(
                portal_type='Department',
                sort_on='sortable_title',
                sort_order='ascending',
                inactive_state='active')

            response.setCookie(
                'dep_filter_disabled', None, path='/', max_age=24 * 3600)

        # It is a LabContact, select only one department. It must be Default
        # Department of the Lab Contact if possible
        elif brain[0].portal_type == 'LabContact':
            lab_con = brain[0].getObject()
            if lab_con.getDefaultDepartment():
                selected_deps = [lab_con.getDefaultDepartment()]
            else:
                departments = lab_con.getSortedDepartments()
                selected_deps = [departments[0]] if departments else []

            response.setCookie(
                'dep_filter_disabled', None, path='/', max_age=0)

    selected_dep_uids = ','.join([api.get_uid(dep) for dep in selected_deps])
    response.setCookie(
        'filter_by_department_info',
        selected_dep_uids,
        path='/',
        max_age=24 * 3600)

    return
Exemple #32
0
def current_user_was_last_verifier(analysis):
    """Returns whether the current user was the last verifier or not
    """
    verifiers = analysis.getVerificators()
    return verifiers and verifiers[:-1] == api.get_current_user().getId()