예제 #1
0
def do_disable_tool(request, tool_id):
    tool = Tool.objects.get(id=tool_id)
    customer = User.objects.get(id=request.POST["customer_id"])
    downtime = timedelta(minutes=quiet_int(request.POST.get("downtime")))
    bypass_interlock = request.POST.get("bypass", "False") == "True"
    response = check_policy_to_disable_tool(tool, customer, downtime)
    if response.status_code != HTTPStatus.OK:
        dictionary = {"message": response.content, "delay": 10}
        return render(request, "kiosk/acknowledgement.html", dictionary)

    # All policy checks passed so try to disable the tool for the user.
    if tool.interlock and not tool.interlock.lock():
        if bypass_interlock and interlock_bypass_allowed(customer):
            pass
        else:
            return interlock_error("Disable", customer)

    # Shorten the user's tool reservation since we are now done using the tool
    shorten_reservation(user=customer,
                        item=tool,
                        new_end=timezone.now() + downtime)

    # End the current usage event for the tool and save it.
    current_usage_event = tool.get_current_usage_event()
    current_usage_event.end = timezone.now() + downtime

    # Collect post-usage questions
    dynamic_form = DynamicForm(tool.post_usage_questions)

    try:
        current_usage_event.run_data = dynamic_form.extract(request)
    except RequiredUnansweredQuestionsException as e:
        if customer.is_staff and customer != current_usage_event.operator and current_usage_event.user != customer:
            # if a staff is forcing somebody off the tool and there are required questions, send an email and proceed
            current_usage_event.run_data = e.run_data
            email_managers_required_questions_disable_tool(
                current_usage_event.operator, customer, tool, e.questions)
        else:
            dictionary = {"message": str(e), "delay": 10}
            return render(request, "kiosk/acknowledgement.html", dictionary)

    dynamic_form.charge_for_consumables(
        current_usage_event.user,
        current_usage_event.operator,
        current_usage_event.project,
        current_usage_event.run_data,
        request,
    )
    dynamic_form.update_tool_counters(current_usage_event.run_data, tool.id)

    current_usage_event.save()
    dictionary = {
        "message": "You are no longer using the {}".format(tool),
        "badge_number": customer.badge_number
    }
    return render(request, "kiosk/acknowledgement.html", dictionary)
예제 #2
0
def interlock_error(action: str = None,
                    user: User = None,
                    bypass_allowed: bool = None):
    error_message = get_customization('door_interlock_failure_message')
    bypass_allowed = interlock_bypass_allowed(
        user) if bypass_allowed is None else bypass_allowed
    dictionary = {
        "message": linebreaksbr(error_message),
        "bypass_allowed": bypass_allowed,
        "action": action
    }
    return JsonResponse(dictionary, status=501)
예제 #3
0
def do_enable_tool(request, tool_id):
    tool = Tool.objects.get(id=tool_id)
    customer = User.objects.get(id=request.POST["customer_id"])
    project = Project.objects.get(id=request.POST["project_id"])
    bypass_interlock = request.POST.get("bypass", 'False') == 'True'

    response = check_policy_to_enable_tool(tool,
                                           operator=customer,
                                           user=customer,
                                           project=project,
                                           staff_charge=False)
    if response.status_code != HTTPStatus.OK:
        dictionary = {
            "message":
            "You are not authorized to enable this tool. {}".format(
                response.content.decode()),
            "delay":
            10,
        }
        return render(request, "kiosk/acknowledgement.html", dictionary)

    # All policy checks passed so enable the tool for the user.
    if tool.interlock and not tool.interlock.unlock():
        if bypass_interlock and interlock_bypass_allowed(customer):
            pass
        else:
            return interlock_error("Enable", customer)

    # Create a new usage event to track how long the user uses the tool.
    new_usage_event = UsageEvent()
    new_usage_event.operator = customer
    new_usage_event.user = customer
    new_usage_event.project = project
    new_usage_event.tool = tool
    new_usage_event.save()

    dictionary = {
        "message": "You can now use the {}".format(tool),
        "badge_number": customer.badge_number
    }
    return render(request, "kiosk/acknowledgement.html", dictionary)
예제 #4
0
def login_to_area(request, door_id):
    door = get_object_or_404(Door, id=door_id)

    badge_number = request.POST.get("badge_number", "")
    bypass_interlock = request.POST.get("bypass", 'False') == 'True'
    if badge_number == "":
        return render(request, "area_access/badge_not_found.html")
    try:
        badge_number = int(badge_number)
        user = User.objects.get(badge_number=badge_number)
    except (User.DoesNotExist, ValueError):
        return render(request, "area_access/badge_not_found.html")

    log = PhysicalAccessLog()
    log.user = user
    log.door = door
    log.time = timezone.now()
    log.result = PhysicalAccessType.DENY  # Assume the user does not have access

    facility_name = get_customization("facility_name")

    # Check policy for entering an area
    try:
        check_policy_to_enter_any_area(user=user)
    except InactiveUserError:
        log.details = "This user is not active, preventing them from entering any access controlled areas."
        log.save()
        return render(request, "area_access/inactive.html")

    except NoActiveProjectsForUserError:
        log.details = "The user has no active projects, preventing them from entering an access controlled area."
        log.save()
        return render(request, "area_access/no_active_projects.html")

    except PhysicalAccessExpiredUserError:
        log.details = "This user was blocked from this physical access level because their physical access has expired."
        log.save()
        message = f"Your physical access to the {facility_name} has expired. Have you completed your safety training within the last year? Please visit the User Office to renew your access."
        return render(request, "area_access/physical_access_denied.html",
                      {"message": message})

    except NoPhysicalAccessUserError:
        log.details = "This user does not belong to ANY physical access levels."
        log.save()
        message = f"You have not been granted physical access to any {facility_name} area. Please visit the User Office if you believe this is an error."
        return render(request, "area_access/physical_access_denied.html",
                      {"message": message})

    max_capacity_reached = False
    reservation_requirement_failed = False
    scheduled_outage_in_progress = False
    # Check policy to enter this area
    try:
        check_policy_to_enter_this_area(area=door.area, user=user)
    except NoAccessiblePhysicalAccessUserError as error:
        if error.access_exception:
            log.details = (
                f"The user was blocked from entering this area because of an exception: {error.access_exception.name}."
            )
            message = f"You do not have access to this area of the {facility_name} due to the following exception: {error.access_exception}. The exception ends on {localize(error.access_exception.end_time.astimezone(timezone.get_current_timezone()))}"
        else:
            log.details = (
                "This user is not assigned to a physical access level that allows access to this door at this time."
            )
            message = f"You do not have access to this area of the {facility_name} at this time. Please visit the User Office if you believe this is an error."
        log.save()
        return render(request, "area_access/physical_access_denied.html",
                      {"message": message})

    except UnavailableResourcesUserError as error:
        log.details = f"The user was blocked from entering this area because a required resource was unavailable [{', '.join(str(resource) for resource in error.resources)}]."
        log.save()
        return render(request, "area_access/resource_unavailable.html",
                      {"unavailable_resources": error.resources})

    except MaximumCapacityReachedError as error:
        # deal with this error after checking if the user is already logged in
        max_capacity_reached = error

    except ScheduledOutageInProgressError as error:
        # deal with this error after checking if the user is already logged in
        scheduled_outage_in_progress = error

    except ReservationRequiredUserError:
        # deal with this error after checking if the user is already logged in
        reservation_requirement_failed = True

    current_area_access_record = user.area_access_record()
    if current_area_access_record and current_area_access_record.area == door.area:
        # No log entry necessary here because all validation checks passed.
        # The log entry is captured when the subsequent choice is made by the user.
        return render(
            request,
            "area_access/already_logged_in.html",
            {
                "area": door.area,
                "project": current_area_access_record.project,
                "badge_number": user.badge_number,
                "reservation_requirement_failed":
                reservation_requirement_failed,
                "max_capacity_reached": max_capacity_reached,
                "scheduled_outage_in_progress": scheduled_outage_in_progress,
            },
        )

    if scheduled_outage_in_progress:
        log.details = f"The user was blocked from entering this area because the {scheduled_outage_in_progress.area.name} has a scheduled outage in progress."
        log.save()
        message = (
            f"The {scheduled_outage_in_progress.area.name} is inaccessible because a scheduled outage is in progress."
        )
        return render(request, "area_access/physical_access_denied.html",
                      {"message": message})

    if max_capacity_reached:
        log.details = f"The user was blocked from entering this area because the {max_capacity_reached.area.name} has reached its maximum capacity of {max_capacity_reached.area.maximum_capacity} people at a time."
        log.save()
        message = f"The {max_capacity_reached.area.name} has reached its maximum capacity. Please wait for somebody to leave and try again."
        return render(request, "area_access/physical_access_denied.html",
                      {"message": message})

    if reservation_requirement_failed:
        log.details = f"The user was blocked from entering this area because the user does not have a current reservation for the {door.area}."
        log.save()
        message = "You do not have a current reservation for this area. Please make a reservation before trying to access this area."
        return render(request, "area_access/physical_access_denied.html",
                      {"message": message})

    if user.active_project_count() >= 1:
        if user.active_project_count() == 1:
            project = user.active_projects()[0]
        else:
            project_id = request.POST.get("project_id")
            if not project_id:
                # No log entry necessary here because all validation checks passed, and the user must indicate which project
                # the wish to login under. The log entry is captured when the subsequent choice is made by the user.
                return render(request, "area_access/choose_project.html", {
                    "area": door.area,
                    "user": user
                })
            else:
                project = get_object_or_404(Project, id=project_id)
                if project not in user.active_projects():
                    log.details = "The user attempted to bill the project named {}, but they are not a member of that project.".format(
                        project.name)
                    log.save()
                    message = "You are not authorized to bill this project."
                    return render(request,
                                  "area_access/physical_access_denied.html",
                                  {"message": message})

        log.result = PhysicalAccessType.ALLOW
        log.save()

        # Automatically log the user out of any previous area before logging them in to the new area.
        previous_area = None
        if user.in_area():
            previous_area = user.area_access_record().area
            log_out_user(user)

        # All policy checks passed so open the door for the user.
        if not door.interlock.unlock():
            if bypass_interlock and interlock_bypass_allowed(user):
                pass
            else:
                return interlock_error("Login", user)

        delay_lock_door(door.id)

        log_in_user_to_area(door.area, user, project)
        occupants = AreaAccessRecord.objects.filter(area__name=door.area,
                                                    end=None,
                                                    staff_charge=None).count()
        if door.area.buddy_required():
            if occupants == 1:
                return render(
                    request,
                    'area_access/buddy_login_warning.html',
                    {
                        'area': door.area,
                        'name': user.first_name,
                        'project': project,
                        'previous_area': previous_area
                    },
                )
            elif occupants <= 3:
                return render(
                    request,
                    'area_access/buddy_login_reminder.html',
                    {
                        'area': door.area,
                        'name': user.first_name,
                        'project': project,
                        'previous_area': previous_area,
                        'occupants': occupants
                    },
                )
        return render(
            request,
            'area_access/login_success.html',
            {
                'area': door.area,
                'name': user.first_name,
                'project': project,
                'previous_area': previous_area
            },
        )