Exemple #1
0
def send_reorder_supply_reminder_email(consumable: Consumable):
	user_office_email = get_customization('user_office_email_address')
	message = get_media_file_contents('reorder_supplies_reminder_email.html')
	if user_office_email and message:
		subject = f"Time to order more {consumable.name}"
		rendered_message = Template(message).render(Context({'item': consumable}))
		send_mail(subject=subject, content=rendered_message, from_email=user_office_email, to=[consumable.reminder_email], email_category=EmailCategory.SYSTEM)
Exemple #2
0
def feedback(request):
    recipient = get_customization('feedback_email_address')
    email_contents = get_media_file_contents('feedback_email.html')
    if not recipient or not email_contents:
        return render(request, 'feedback.html',
                      {'customization_required': True})

    if request.method == 'GET':
        return render(request, 'feedback.html')
    contents = parse_parameter_string(request.POST, 'feedback',
                                      FEEDBACK_MAXIMUM_LENGTH)
    if contents == '':
        return render(request, 'feedback.html')
    dictionary = {
        'contents': contents,
        'user': request.user,
    }

    email = Template(email_contents).render(Context(dictionary))
    send_mail('Feedback from ' + str(request.user), email, request.user.email,
              [recipient])
    dictionary = {
        'title':
        'Feedback',
        'heading':
        'Thanks for your feedback!',
        'content':
        'Your feedback has been sent to the NanoFab staff. We will follow up with you as soon as we can.',
    }
    return render(request, 'acknowledgement.html', dictionary)
Exemple #3
0
def send_missed_reservation_notification(reservation):
	subject = "Missed reservation for the " + str(reservation.tool)
	message = get_media_file_contents('missed_reservation_email.html')
	message = Template(message).render(Context({'reservation': reservation}))
	user_office_email = get_customization('user_office_email_address')
	abuse_email = get_customization('abuse_email_address')
	send_mail(subject, message, user_office_email, [reservation.user.email, abuse_email, user_office_email])
Exemple #4
0
def send_new_task_emails(request, task: Task, task_images: List[TaskImages]):
	message = get_media_file_contents('new_task_email.html')
	attachments = None
	if task_images:
		attachments = [create_email_attachment(task_image.image, task_image.image.name) for task_image in task_images]
	if message:
		dictionary = {
			'template_color': bootstrap_primary_color('danger') if task.force_shutdown else bootstrap_primary_color('warning'),
			'user': request.user,
			'task': task,
			'tool': task.tool,
			'tool_control_absolute_url': request.build_absolute_uri(task.tool.get_absolute_url())
		}
		# Send an email to the appropriate staff that a new task has been created:
		subject = ('SAFETY HAZARD: ' if task.safety_hazard else '') + task.tool.name + (' shutdown' if task.force_shutdown else ' problem')
		message = Template(message).render(Context(dictionary))
		managers = []
		if hasattr(settings, 'LAB_MANAGERS'):
			managers = settings.LAB_MANAGERS
		recipients = tuple([r for r in [task.tool.primary_owner.email, *task.tool.backup_owners.all().values_list('email', flat=True), task.tool.notification_email_address, *managers] if r])
		send_mail(subject, message, request.user.email, recipients, attachments)

	# Send an email to any user (excluding staff) with a future reservation on the tool:
	user_office_email = get_customization('user_office_email_address')
	message = get_media_file_contents('new_task_email.html')
	if user_office_email and message:
		upcoming_reservations = Reservation.objects.filter(start__gt=timezone.now(), cancelled=False, tool=task.tool, user__is_staff=False)
		for reservation in upcoming_reservations:
			if not task.tool.operational:
				subject = reservation.tool.name + " reservation problem"
				rendered_message = Template(message).render(Context({'reservation': reservation, 'template_color': bootstrap_primary_color('danger'), 'fatal_error': True}))
			else:
				subject = reservation.tool.name + " reservation warning"
				rendered_message = Template(message).render(Context({'reservation': reservation, 'template_color': bootstrap_primary_color('warning'), 'fatal_error': False}))
			reservation.user.email_user(subject, rendered_message, user_office_email)
Exemple #5
0
def send_task_updated_email(task, url, task_images: List[TaskImages]):
    if not hasattr(settings, 'LAB_MANAGERS'):
        return
    attachments = None
    if task_images:
        attachments = [
            create_email_attachment(task_image.image, task_image.image.name)
            for task_image in task_images
        ]
    task.refresh_from_db()
    if task.resolved:
        task_user = task.resolver
        task_status = 'resolved'
    else:
        task_user = task.last_updated_by
        task_status = 'updated'
    message = f"""
A task for the {task.tool} was just modified by {task_user}.
<br/><br/>
The latest update is at the bottom of the description. The entirety of the task status follows: 
<br/><br/>
Task problem description:<br/>
{task.problem_description}
<br/><br/>
Task progress description:<br/>
{task.progress_description}
<br/><br/>
Task resolution description:<br/>
{task.resolution_description}
<br/><br/>
Visit {url} to view the tool control page for the task.<br/>
"""
    send_mail(f'{task.tool} task {task_status}', message,
              settings.SERVER_EMAIL, settings.LAB_MANAGERS, attachments)
Exemple #6
0
def reset_tool_counter(request, counter_id):
    counter = get_object_or_404(ToolUsageCounter, id=counter_id)
    counter.last_reset_value = counter.value
    counter.value = 0
    counter.last_reset = datetime.now()
    counter.last_reset_by = request.user
    counter.save()

    # Save a comment about the counter being reset.
    comment = Comment()
    comment.tool = counter.tool
    comment.content = f"The {counter.name} counter was reset to 0. Its last value was {counter.last_reset_value}."
    comment.author = request.user
    comment.expiration_date = datetime.now() + timedelta(weeks=1)
    comment.save()

    # Send an email to Lab Managers about the counter being reset.
    if hasattr(settings, "LAB_MANAGERS"):
        message = f"""The {counter.name} counter for the {counter.tool.name} was reset to 0 on {formats.localize(counter.last_reset)} by {counter.last_reset_by}.

Its last value was {counter.last_reset_value}."""
        send_mail(
            subject=f"{counter.tool.name} counter reset",
            content=message,
            from_email=settings.SERVER_EMAIL,
            to=settings.LAB_MANAGERS,
            email_category=EmailCategory.SYSTEM,
        )
    return redirect("tool_control")
Exemple #7
0
def send_email(request):
	try:
		recipient = request.POST['recipient']
		validate_email(recipient)
		recipient_list = [recipient]
	except:
		return HttpResponseBadRequest('The intended recipient was not a valid email address. The email was not sent.')
	sender = request.user.email
	subject = request.POST.get('subject')
	body = request.POST.get('body')
	if request.POST.get('copy_me'):
		recipient_list.append(sender)
	try:
		send_mail(subject=subject, content=body, from_email=sender, bcc=recipient_list, email_category=EmailCategory.DIRECT_CONTACT)
	except SMTPException as error:
		site_title = get_customization('site_title')
		error_message = f'{site_title} was unable to send the email through the email server. The error message that was received is: ' + str(error)
		logger.exception(error_message)
		dictionary = {
			'title': 'Email not sent',
			'heading': 'There was a problem sending your email',
			'content': error_message,
		}
		return render(request, 'acknowledgement.html', dictionary)
	dictionary = {
		'title': 'Email sent',
		'heading': 'Your email was sent',
	}
	return render(request, 'acknowledgement.html', dictionary)
Exemple #8
0
def facility_rules(request):
    if request.method == "GET" and (request.user.training_required
                                    or request.user.access_expiration <
                                    timezone.now().date() + timedelta(weeks=2)
                                    or request.user.is_staff):
        tutorial = get_media_file_contents("facility_rules_tutorial.html")
        if tutorial:
            dictionary = {
                "active_user_count":
                User.objects.filter(is_active=True).count(),
                "active_project_count":
                Project.objects.filter(active=True).count(),
            }
            tutorial = Template(tutorial).render(
                RequestContext(request, dictionary))
        return render(request, "facility_rules.html",
                      {"facility_rules_tutorial": tutorial})
    elif request.method == "POST":
        facility_name = get_customization("facility_name")
        summary = request.POST.get("making_reservations_summary",
                                   "").strip()[:3000]
        dictionary = {
            "user": request.user,
            "making_reservations_rule_summary": summary
        }
        abuse_email = get_customization("abuse_email_address")
        email_contents = get_media_file_contents(
            "facility_rules_tutorial_email.html")
        if abuse_email and email_contents:
            message = Template(email_contents,
                               dictionary).render(Context(dictionary))
            send_mail(
                subject=f"{facility_name} rules tutorial",
                content=message,
                from_email=abuse_email,
                to=[abuse_email],
                email_category=EmailCategory.SYSTEM,
            )
        dictionary = {
            "title":
            f"{facility_name} rules tutorial",
            "heading":
            "Tutorial complete!",
            "content":
            "Tool usage and reservation privileges have been enabled on your user account.",
        }
        request.user.training_required = False
        while request.user.access_expiration < timezone.now().date(
        ) + timedelta(weeks=2):
            try:
                request.user.access_expiration = request.user.access_expiration.replace(
                    year=request.user.access_expiration.year + 1)
            except ValueError:
                request.user.access_expiration = request.user.access_expiration.replace(
                    year=request.user.access_expiration.year + 1,
                    day=request.user.access_expiration.day - 1)
        request.user.save()
        return render(request, "acknowledgement.html", dictionary)
Exemple #9
0
def send_broadcast_email(request):
	content = get_media_file_contents('generic_email.html')
	if not content:
		return HttpResponseBadRequest('Generic email template not defined. Visit the customization page to upload a template.')
	form = EmailBroadcastForm(request.POST)
	if not form.is_valid():
		return render(request, 'email/compose_email.html', {'form': form})
	dictionary = {
		'title': form.cleaned_data['title'],
		'greeting': form.cleaned_data['greeting'],
		'contents': form.cleaned_data['contents'],
		'template_color': form.cleaned_data['color'],
	}
	content = Template(content).render(Context(dictionary))
	users = None
	audience = form.cleaned_data['audience']
	selection = form.cleaned_data['selection']
	active_choice = form.cleaned_data['only_active_users']
	try:
		if audience == 'tool':
			users = User.objects.filter(qualifications__id=selection)
		elif audience == 'project':
			users = User.objects.filter(projects__id=selection)
		elif audience == 'account':
			users = User.objects.filter(projects__account__id=selection)
		if active_choice:
			users = users.filter(is_active=True)
	except Exception as error:
		warning_message = 'Your email was not sent. There was a problem finding the users to send the email to.'
		dictionary = {'error': warning_message}
		logger.warning(warning_message + ' audience: {}, only_active: {}. The error message that was received is: {}'.format(audience, active_choice, str(error)))
		return render(request, 'email/compose_email.html', dictionary)
	if not users:
		dictionary = {'error': 'The audience you specified is empty. You must send the email to at least one person.'}
		return render(request, 'email/compose_email.html', dictionary)
	subject = form.cleaned_data['subject']
	users = [x.email for x in users]
	if form.cleaned_data['copy_me']:
		users += [request.user.email]
	try:
		send_mail(subject=subject, content=content, from_email=request.user.email, bcc=set(users), email_category=EmailCategory.BROADCAST_EMAIL)
	except SMTPException as error:
		site_title = get_customization('site_title')
		error_message = f"{site_title} was unable to send the email through the email server. The error message that was received is: " + str(error)
		logger.exception(error_message)
		dictionary = {
			'title': 'Email not sent',
			'heading': 'There was a problem sending your email',
			'content': error_message,
		}
		return render(request, 'acknowledgement.html', dictionary)
	dictionary = {
		'title': 'Email sent',
		'heading': 'Your email was sent',
	}
	return render(request, 'acknowledgement.html', dictionary)
Exemple #10
0
def send_missed_reservation_notification(reservation):
	subject = "Missed reservation for the " + str(reservation.reservation_item)
	message = get_media_file_contents('missed_reservation_email.html')
	user_office_email = get_customization('user_office_email_address')
	abuse_email = get_customization('abuse_email_address')
	if message and user_office_email:
		message = Template(message).render(Context({'reservation': reservation}))
		send_mail(subject, message, user_office_email, [reservation.user.email, abuse_email, user_office_email])
	else:
		calendar_logger.error("Missed reservation email couldn't be send because missed_reservation_email.html or user_office_email are not defined")
Exemple #11
0
def send_out_of_time_reservation_notification(reservation:Reservation):
	subject = "Out of time in the " + str(reservation.area.name)
	message = get_media_file_contents('out_of_time_reservation_email.html')
	user_office_email = get_customization('user_office_email_address')
	if message and user_office_email:
		message = Template(message).render(Context({'reservation': reservation}))
		recipients = [reservation.user.email]
		recipients.extend(reservation.area.abuse_email_list())
		send_mail(subject, message, user_office_email, recipients)
	else:
		calendar_logger.error("Out of time reservation email couldn't be send because out_of_time_reservation_email.html or user_office_email are not defined")
Exemple #12
0
def send_safety_email_notification(request, issue):
	recipient = get_customization('safety_email_address')
	message = get_media_file_contents('safety_issue_email.html')
	if recipient and message:
		subject = 'Safety issue'
		dictionary = {
			'issue': issue,
			'issue_absolute_url': request.build_absolute_uri(issue.get_absolute_url()),
		}
		rendered_message = Template(message).render(Context(dictionary))
		from_email = issue.reporter.email if issue.reporter else recipient
		send_mail(subject=subject, content=rendered_message, from_email=from_email, to=[recipient], email_category=EmailCategory.SAFETY)
Exemple #13
0
def email_usage_reminders(request):
    projects_to_exclude = request.GET.getlist("projects_to_exclude[]")
    busy_users = AreaAccessRecord.objects.filter(
        end=None,
        staff_charge=None).exclude(project__id__in=projects_to_exclude)
    busy_tools = UsageEvent.objects.filter(end=None).exclude(
        project__id__in=projects_to_exclude)

    # Make lists of all the things a user is logged in to.
    # We don't want to send 3 separate emails if a user is logged into three things.
    # Just send one email for all the things!
    aggregate = {}
    for access_record in busy_users:
        key = str(access_record.customer)
        aggregate[key] = {
            'email': access_record.customer.email,
            'first_name': access_record.customer.first_name,
            'resources_in_use': [str(access_record.area)],
        }
    for usage_event in busy_tools:
        key = str(usage_event.operator)
        if key in aggregate:
            aggregate[key]['resources_in_use'].append(usage_event.tool.name)
        else:
            aggregate[key] = {
                'email': usage_event.operator.email,
                'first_name': usage_event.operator.first_name,
                'resources_in_use': [usage_event.tool.name],
            }

    user_office_email = get_customization('user_office_email_address')

    message = get_media_file_contents('usage_reminder_email.html')
    if message:
        subject = "NanoFab usage"
        for user in aggregate.values():
            rendered_message = Template(message).render(Context({'user':
                                                                 user}))
            send_mail(subject, rendered_message, user_office_email,
                      [user['email']])

    message = get_media_file_contents('staff_charge_reminder_email.html')
    if message:
        busy_staff = StaffCharge.objects.filter(end=None)
        for staff_charge in busy_staff:
            subject = "Active staff charge since " + format_datetime(
                staff_charge.start)
            rendered_message = Template(message).render(
                Context({'staff_charge': staff_charge}))
            staff_charge.staff_member.email_user(subject, rendered_message,
                                                 user_office_email)

    return HttpResponse()
Exemple #14
0
def set_task_status(request, task, status_name, user):

    if not user.is_staff and status_name:
        raise ValueError("Only staff can set task status")

        #If no status is given, assign to default status. This will make sure all tasks have a proper Task History
    if not status_name:
        status_name = "default"

    status = TaskStatus.objects.get_or_create(name=status_name)
    TaskHistory.objects.create(task=task,
                               status=status_name,
                               user=user,
                               shutdown=task.force_shutdown)

    status_message = f'On {format_datetime(timezone.now())}, {user.get_full_name()} set the status of this task to "{status_name}".'
    task.progress_description = status_message if task.progress_description is None else task.progress_description + '\n\n' + status_message
    task.save()

    message = get_media_file_contents('task_status_notification.html')
    # Send an email to the appropriate staff that a task status has been updated:
    if message:
        dictionary = {
            'template_color':
            bootstrap_primary_color('success'),
            'title':
            f'{task.tool} task notification',
            'status_message':
            status_message,
            'notification_message':
            status.notification_message,
            'task':
            task,
            'tool_control_absolute_url':
            request.build_absolute_uri(task.tool.get_absolute_url())
        }
        subject = f'{task.tool} task notification'
        message = Template(message).render(Context(dictionary))
        recipients = [
            task.tool.primary_tool_owner.email
            if status.notify_primary_tool_owner else None,
            task.tool.notification_email_address
            if status.notify_tool_notification_email else None,
            status.custom_notification_email_address
        ]
        if status.notify_backup_tool_owners:
            recipients += task.tool.backup_tool_owners.values_list('email')
        recipients = filter(None, recipients)
        send_mail(subject=subject,
                  content=message,
                  from_email=user.email,
                  to=recipients,
                  email_category=EmailCategory.TASKS)
Exemple #15
0
def send_tool_usage_counter_email(counter: ToolUsageCounter):
    user_office_email = get_customization('user_office_email_address')
    message = get_media_file_contents('counter_threshold_reached_email.html')
    if user_office_email and message:
        subject = f"Warning threshold reached for {counter.tool.name} {counter.name} counter"
        rendered_message = Template(message).render(
            Context({'counter': counter}))
        send_mail(subject=subject,
                  content=rendered_message,
                  from_email=user_office_email,
                  to=counter.warning_email,
                  email_category=EmailCategory.SYSTEM)
Exemple #16
0
def send_safety_email_notification(request, issue):
    subject = 'Safety issue'
    dictionary = {
        'issue': issue,
        'issue_absolute_url':
        request.build_absolute_uri(issue.get_absolute_url()),
    }
    recipient = get_customization('safety_email_address')
    message = get_media_file_contents('safety_issue_email.html')
    if not recipient or not message:
        return
    rendered_message = Template(message).render(Context(dictionary))
    from_email = issue.reporter.email if issue.reporter else recipient
    send_mail(subject, rendered_message, from_email, [recipient])
Exemple #17
0
def send_task_updated_email(task, url, task_images: List[TaskImages] = None):
    try:
        if not hasattr(settings, 'LAB_MANAGERS'):
            return
        attachments = None
        if task_images:
            attachments = [
                create_email_attachment(task_image.image,
                                        task_image.image.name)
                for task_image in task_images
            ]
        task.refresh_from_db()
        if task.cancelled:
            task_user = task.resolver
            task_status = 'cancelled'
        elif task.resolved:
            task_user = task.resolver
            task_status = 'resolved'
        else:
            task_user = task.last_updated_by
            task_status = 'updated'
        message = f"""
A task for the {task.tool} was just modified by {task_user}.
<br/><br/>
The latest update is at the bottom of the description. The entirety of the task status follows: 
<br/><br/>
Task problem description:<br/>
{linebreaksbr(task.problem_description)}
<br/><br/>
Task progress description:<br/>
{linebreaksbr(task.progress_description)}
<br/><br/>
Task resolution description:<br/>
{linebreaksbr(task.resolution_description)}
<br/><br/>
Visit {url} to view the tool control page for the task.<br/>
"""
        send_mail(subject=f'{task.tool} task {task_status}',
                  content=message,
                  from_email=settings.SERVER_EMAIL,
                  to=settings.LAB_MANAGERS,
                  attachments=attachments,
                  email_category=EmailCategory.TASKS)
    except Exception as error:
        site_title = get_customization('site_title')
        error_message = f"{site_title} was unable to send the task updated email. The error message that was received is: " + str(
            error)
        tasks_logger.exception(error_message)
Exemple #18
0
def send_user_cancelled_reservation_notification(reservation: Reservation):
	site_title = get_customization('site_title')
	recipients = [reservation.user.email] if getattr(reservation.user.preferences, 'attach_cancelled_reservation', False) else []
	if reservation.area:
		recipients.extend(reservation.area.reservation_email_list())
	if recipients:
		subject = f"[{site_title}] Cancelled Reservation for the " + str(reservation.reservation_item)
		message = get_media_file_contents('reservation_cancelled_user_email.html')
		message = Template(message).render(Context({'reservation': reservation}))
		user_office_email = get_customization('user_office_email_address')
		# We don't need to check for existence of reservation_cancelled_user_email because we are attaching the ics reservation and sending the email regardless (message will be blank)
		if user_office_email:
			attachment = create_ics_for_reservation(reservation, cancelled=True)
			send_mail(subject, message, user_office_email, recipients, [attachment])
		else:
			calendar_logger.error("User cancelled reservation notification could not be send because user_office_email_address is not defined")
Exemple #19
0
def facility_rules(request):
    if request.method == 'GET':
        tutorial = get_media_file_contents('facility_rules_tutorial.html')
        if tutorial:
            dictionary = {
                'active_user_count':
                User.objects.filter(is_active=True).count(),
                'active_project_count':
                Project.objects.filter(active=True).count(),
            }
            tutorial = Template(tutorial).render(
                RequestContext(request, dictionary))
        return render(request, 'facility_rules.html',
                      {'facility_rules_tutorial': tutorial})
    elif request.method == 'POST':
        facility_name = get_customization('facility_name')
        summary = request.POST.get('making_reservations_summary',
                                   '').strip()[:3000]
        dictionary = {
            'user': request.user,
            'making_reservations_rule_summary': summary,
        }
        abuse_email = get_customization('abuse_email_address')
        email_contents = get_media_file_contents(
            'facility_rules_tutorial_email.html')
        if abuse_email and email_contents:
            message = Template(email_contents,
                               dictionary).render(Context(dictionary))
            send_mail(f"{facility_name} rules tutorial", message, abuse_email,
                      [abuse_email])
        dictionary = {
            'title':
            f"{facility_name} rules tutorial",
            'heading':
            'Tutorial complete!',
            'content':
            'Tool usage and reservation privileges have been enabled on your user account.',
        }
        request.user.training_required = False
        request.user.save()
        return render(request, 'acknowledgement.html', dictionary)
Exemple #20
0
def set_task_status(request, task, status_name, user):
	if not status_name:
		return

	if not user.is_staff:
		raise ValueError("Only staff can set task status")

	status = TaskStatus.objects.get(name=status_name)
	TaskHistory.objects.create(task=task, status=status_name, user=user)

	status_message = f'On {format_datetime(timezone.now())}, {user.get_full_name()} set the status of this task to "{status_name}".'
	task.progress_description = status_message if task.progress_description is None else task.progress_description + '\n\n' + status_message
	task.save()

	message = get_media_file_contents('task_status_notification.html')
	if not message:
		return

	dictionary = {
		'template_color': bootstrap_primary_color('success'),
		'title': f'{task.tool} task notification',
		'status_message': status_message,
		'notification_message': status.notification_message,
		'task': task,
		'tool_control_absolute_url': request.build_absolute_uri(task.tool.get_absolute_url())
	}
	# Send an email to the appropriate staff that a new task has been created:
	subject = f'{task.tool} task notification'
	message = Template(message).render(Context(dictionary))
	recipients = [
		task.tool.primary_tool_owner.email if status.notify_primary_tool_owner else None,
		task.tool.notification_email_address if status.notify_tool_notification_email else None,
		status.custom_notification_email_address
	]
	if status.notify_backup_tool_owners:
		recipients += task.tool.backup_tool_owners.values_list('email')
	recipients = filter(None, recipients)
	send_mail(subject, message, user.email, recipients)
Exemple #21
0
def email_managers_required_questions_disable_tool(
        tool_user: User, staff_member: User, tool: Tool,
        questions: List[PostUsageQuestion]):
    abuse_email_address = get_customization('abuse_email_address')
    managers = []
    if hasattr(settings, 'LAB_MANAGERS'):
        managers = settings.LAB_MANAGERS
    ccs = set(
        tuple([
            r for r in [
                staff_member.email, tool.primary_owner.email, *tool.
                backup_owners.all().values_list('email', flat=True), *managers
            ] if r
        ]))
    display_questions = "".join([
        linebreaksbr(mark_safe(question.render_as_text())) + "<br/><br/>"
        for question in questions
    ])
    message = f"""
Dear {tool_user.get_name()},<br/>
You have been logged off by staff from the {tool} that requires answers to the following post-usage questions:<br/>
<br/>
{display_questions}
<br/>
Regards,<br/>
<br/>
NanoFab Management<br/>
"""
    send_mail(
        subject=
        f"Unanswered post‑usage questions after logoff from the {tool.name}",
        content=message,
        from_email=abuse_email_address,
        to=[tool_user.email],
        cc=ccs,
        email_category=EmailCategory.ABUSE)
Exemple #22
0
def check_policy_to_enable_tool(tool: Tool, operator: User, user: User,
                                project: Project, staff_charge: bool):
    """
	Check that the user is allowed to enable the tool. Enable the tool if the policy checks pass.
	"""
    facility_name = get_customization('facility_name')

    # The tool must be visible (or the parent if it's a child tool) to users.
    visible = tool.parent_tool.visible if tool.is_child_tool(
    ) else tool.visible
    if not visible:
        return HttpResponseBadRequest(
            "This tool is currently hidden from users.")

    # The tool must be operational.
    # If the tool is non-operational then it may only be accessed by staff members.
    if not tool.operational and not operator.is_staff:
        return HttpResponseBadRequest(
            "This tool is currently non-operational.")

    # The tool must not be in use.
    current_usage_event = tool.get_current_usage_event()
    if current_usage_event:
        return HttpResponseBadRequest("The tool is currently being used by " +
                                      str(current_usage_event.user) + ".")

    # The user must be qualified to use the tool itself, or the parent tool in case of alternate tool.
    tool_to_check_qualifications = tool.parent_tool if tool.is_child_tool(
    ) else tool
    if tool_to_check_qualifications not in operator.qualifications.all(
    ) and not operator.is_staff:
        return HttpResponseBadRequest(
            "You are not qualified to use this tool.")

    # Only staff members can operate a tool on behalf of another user.
    if (user and operator.pk != user.pk) and not operator.is_staff:
        return HttpResponseBadRequest(
            "You must be a staff member to use a tool on another user's behalf."
        )

    # All required resources must be available to operate a tool except for staff.
    if tool.required_resource_set.filter(
            available=False).exists() and not operator.is_staff:
        return HttpResponseBadRequest(
            "A resource that is required to operate this tool is unavailable.")

    # The tool operator may not activate tools in a particular area unless they are logged in to the area.
    # Staff are exempt from this rule.
    if tool.requires_area_access and AreaAccessRecord.objects.filter(
            area=tool.requires_area_access,
            customer=operator,
            staff_charge=None,
            end=None).count() == 0 and not operator.is_staff:
        dictionary = {'operator': operator, 'tool': tool, 'type': 'access'}
        abuse_email_address = get_customization('abuse_email_address')
        message = get_media_file_contents(
            'unauthorized_tool_access_email.html')
        if abuse_email_address and message:
            rendered_message = Template(message).render(Context(dictionary))
            send_mail("Area access requirement", rendered_message,
                      abuse_email_address, [abuse_email_address])
        return HttpResponseBadRequest(
            "You must be logged in to the {} to operate this tool.".format(
                tool.requires_area_access.name))

    # The tool operator may not activate tools in a particular area unless they are still within that area reservation window
    if not operator.is_staff and tool.requires_area_reservation():
        if not tool.requires_area_access.get_current_reservation_for_user(
                operator):
            dictionary = {
                'operator': operator,
                'tool': tool,
                'type': 'reservation',
            }
            abuse_email_address = get_customization('abuse_email_address')
            message = get_media_file_contents(
                'unauthorized_tool_access_email.html')
            if abuse_email_address and message:
                rendered_message = Template(message).render(
                    Context(dictionary))
                send_mail("Area reservation requirement", rendered_message,
                          abuse_email_address, [abuse_email_address])
            return HttpResponseBadRequest(
                "You must have a current reservation for the {} to operate this tool."
                .format(tool.requires_area_access.name))

    # Staff may only charge staff time for one user at a time.
    if staff_charge and operator.charging_staff_time():
        return HttpResponseBadRequest(
            'You are already charging staff time. You must end the current staff charge before you being another.'
        )

    # Staff may not bill staff time to the themselves.
    if staff_charge and operator == user:
        return HttpResponseBadRequest(
            'You cannot charge staff time to yourself.')

    # Users may only charge to projects they are members of.
    if project not in user.active_projects():
        return HttpResponseBadRequest(
            'The designated user is not assigned to the selected project.')

    # The tool operator must not have a lock on usage
    if operator.training_required:
        return HttpResponseBadRequest(
            f"You are blocked from using all tools in the {facility_name}. Please complete the {facility_name} rules tutorial in order to use tools."
        )

    # Users may only use a tool when delayed logoff is not in effect. Staff are exempt from this rule.
    if tool.delayed_logoff_in_progress() and not operator.is_staff:
        return HttpResponseBadRequest(
            "Delayed tool logoff is in effect. You must wait for the delayed logoff to expire before you can use the tool."
        )

    # Users may not enable a tool during a scheduled outage. Staff are exempt from this rule.
    if tool.scheduled_outage_in_progress() and not operator.is_staff:
        return HttpResponseBadRequest(
            "A scheduled outage is in effect. You must wait for the outage to end before you can use the tool."
        )

    return HttpResponse()
Exemple #23
0
def check_policy_to_enable_tool(tool: Tool, operator: User, user: User, project: Project, staff_charge: bool):
	"""
	Check that the user is allowed to enable the tool. Enable the tool if the policy checks pass.
	"""
	facility_name = get_customization('facility_name')

	# The tool must be visible (or the parent if it's a child tool) to users.
	visible = tool.parent_tool.visible if tool.is_child_tool() else tool.visible
	if not visible:
		return HttpResponseBadRequest("This tool is currently hidden from users.")

	# The tool must be operational.
	# If the tool is non-operational then it may only be accessed by staff members or service personnel.
	if not tool.operational and not operator.is_staff and not operator.is_service_personnel:
		return HttpResponseBadRequest("This tool is currently non-operational.")

	# The tool must not be in use.
	current_usage_event = tool.get_current_usage_event()
	if current_usage_event:
		return HttpResponseBadRequest("The tool is currently being used by " + str(current_usage_event.user) + ".")

	# The user must be qualified to use the tool itself, or the parent tool in case of alternate tool.
	tool_to_check_qualifications = tool.parent_tool if tool.is_child_tool() else tool
	if tool_to_check_qualifications not in operator.qualifications.all() and not operator.is_staff:
		return HttpResponseBadRequest("You are not qualified to use this tool.")

	# Only staff members can operate a tool on behalf of another user.
	if (user and operator.pk != user.pk) and not operator.is_staff:
		return HttpResponseBadRequest("You must be a staff member to use a tool on another user's behalf.")

	# All required resources must be available to operate a tool except for staff or service personnel.
	if tool.required_resource_set.filter(available=False).exists() and not operator.is_staff and not operator.is_service_personnel:
		return HttpResponseBadRequest("A resource that is required to operate this tool is unavailable.")

	# The tool operator may not activate tools in a particular area unless they are logged in to the area.
	# Staff are exempt from this rule.
	if tool.requires_area_access and AreaAccessRecord.objects.filter(area=tool.requires_area_access, customer=operator, staff_charge=None, end=None).count() == 0 and not operator.is_staff:
		abuse_email_address = get_customization('abuse_email_address')
		message = get_media_file_contents('unauthorized_tool_access_email.html')
		if abuse_email_address and message:
			dictionary = {
				'operator': operator,
				'tool': tool,
				'type': 'access'
			}
			rendered_message = Template(message).render(Context(dictionary))
			send_mail(subject="Area access requirement", content=rendered_message, from_email=abuse_email_address, to=[abuse_email_address], email_category=EmailCategory.ABUSE)
		return HttpResponseBadRequest("You must be logged in to the {} to operate this tool.".format(tool.requires_area_access.name))

	# The tool operator may not activate tools in a particular area unless they are still within that area reservation window
	# Staff and service personnel are exempt from this rule.
	if not operator.is_staff and not operator.is_service_personnel and tool.requires_area_reservation():
		if not tool.requires_area_access.get_current_reservation_for_user(operator):
			abuse_email_address = get_customization('abuse_email_address')
			message = get_media_file_contents('unauthorized_tool_access_email.html')
			if abuse_email_address and message:
				dictionary = {
					'operator': operator,
					'tool': tool,
					'type': 'reservation',
				}
				rendered_message = Template(message).render(Context(dictionary))
				send_mail(subject="Area reservation requirement", content=rendered_message, from_email=abuse_email_address, to=[abuse_email_address], email_category=EmailCategory.ABUSE)
			return HttpResponseBadRequest("You must have a current reservation for the {} to operate this tool.".format(tool.requires_area_access.name))

	# Staff may only charge staff time for one user at a time.
	if staff_charge and operator.charging_staff_time():
		return HttpResponseBadRequest('You are already charging staff time. You must end the current staff charge before you being another.')

	# Staff may not bill staff time to themselves.
	if staff_charge and operator == user:
		return HttpResponseBadRequest('You cannot charge staff time to yourself.')

	# Users may only charge to projects they are members of.
	if project not in user.active_projects():
		return HttpResponseBadRequest('The designated user is not assigned to the selected project.')

	# The tool operator must not have a lock on usage
	if operator.training_required:
		return HttpResponseBadRequest(f"You are blocked from using all tools in the {facility_name}. Please complete the {facility_name} rules tutorial in order to use tools.")

	# Users may only use a tool when delayed logoff is not in effect. Staff and service personnel are exempt from this rule.
	if tool.delayed_logoff_in_progress() and not operator.is_staff and not operator.is_service_personnel:
		return HttpResponseBadRequest("Delayed tool logoff is in effect. You must wait for the delayed logoff to expire before you can use the tool.")

	# Users may not enable a tool during a scheduled outage. Staff and service personnel are exempt from this rule.
	if tool.scheduled_outage_in_progress() and not operator.is_staff and not operator.is_service_personnel:
		return HttpResponseBadRequest("A scheduled outage is in effect. You must wait for the outage to end before you can use the tool.")

	#Refuses all tool logins if user is logged in using an excluded project (i.e. one reserved for buddy system or observation)
	if not operator.is_staff:
		projects_to_exclude = []
		exclude=get_customization('exclude_from_usage')
		if exclude:
			projects_to_exclude = [int(s) for s in exclude.split() if s.isdigit()]
		try:
			if tool.requires_area_access:
				current_access = AreaAccessRecord.objects.filter(area=tool.requires_area_access, customer=operator, staff_charge=None, end=None)
				if current_access[0].project.id in projects_to_exclude:
					return HttpResponseBadRequest("You may not use tools while logged in with this project.")
		except:
			return HttpResponseBadRequest("There was a problem enabling this tool. Please see staff.")

	if tool.reservation_required and not operator.is_staff:
		td=timedelta(minutes=15)
		if not Reservation.objects.filter(start__lt=timezone.now()+td, end__gt=timezone.now(), cancelled=False, missed=False, shortened=False, user=operator, tool=tool).exists():
			return HttpResponseBadRequest("A reservation is required to enable this tool.")

	return HttpResponse()
Exemple #24
0
def send_new_task_emails(request, task: Task, task_images: List[TaskImages]):
    message = get_media_file_contents('new_task_email.html')
    attachments = None
    if task_images:
        attachments = [
            create_email_attachment(task_image.image, task_image.image.name)
            for task_image in task_images
        ]
    # Send an email to the appropriate staff that a new task has been created:
    if message:
        dictionary = {
            'template_color':
            bootstrap_primary_color('danger')
            if task.force_shutdown else bootstrap_primary_color('warning'),
            'user':
            request.user,
            'task':
            task,
            'tool':
            task.tool,
            'tool_control_absolute_url':
            request.build_absolute_uri(task.tool.get_absolute_url())
        }
        subject = ('SAFETY HAZARD: ' if task.safety_hazard else
                   '') + task.tool.name + (' shutdown' if task.force_shutdown
                                           else ' problem')
        message = Template(message).render(Context(dictionary))
        managers = []
        if hasattr(settings, 'LAB_MANAGERS'):
            managers = settings.LAB_MANAGERS
        recipients = tuple([
            r for r in [
                task.tool.primary_owner.email,
                *task.tool.backup_owners.all().values_list('email', flat=True),
                task.tool.notification_email_address, *managers
            ] if r
        ])
        send_mail(subject=subject,
                  content=message,
                  from_email=request.user.email,
                  to=recipients,
                  attachments=attachments,
                  email_category=EmailCategory.TASKS)

    # Send an email to all users (excluding staff) qualified on the tool:
    user_office_email = get_customization('user_office_email_address')
    message = get_media_file_contents('new_task_email.html')
    if user_office_email and message:
        users = User.objects.filter(qualifications__id=task.tool.id,
                                    is_staff=False,
                                    is_active=True)
        dictionary = {
            'template_color':
            bootstrap_primary_color('danger')
            if task.force_shutdown else bootstrap_primary_color('warning'),
            'user':
            request.user,
            'task':
            task,
            'tool':
            task.tool,
            'tool_control_absolute_url':
            request.build_absolute_uri(task.tool.get_absolute_url()),
            'labmember':
            True
        }
        subject = task.tool.name + (' shutdown'
                                    if task.force_shutdown else ' problem')
        users = [x.email for x in users]
        rendered_message = Template(message).render(Context(dictionary))
        #try:
        email = EmailMultiAlternatives(subject,
                                       from_email=user_office_email,
                                       bcc=set(users))
        email.attach_alternative(rendered_message, 'text/html')
        email.send()