Ejemplo n.º 1
0
def add_publications(request, project_id):
    mapper = ProjectAllocationMapper(request)
    try:
        project = mapper.get_project(project_id)
        if project.source != "Chameleon" or not can_add_publications(
            request.user, project
        ):
            raise Http404("The requested project does not exist!")
    except Exception as e:
        logger.error(e)
        raise Http404("The requested project does not exist!")
    if request.POST:
        pubs_form = AddBibtexPublicationForm(request.POST)
        if pubs_form.is_valid():
            bib_database = bibtexparser.loads(pubs_form.cleaned_data["bibtex_string"])
            for entry in bib_database.entries:
                Publication.objects.create_from_bibtex(
                    entry, project, request.user.username
                )
            messages.success(request, "Publication added successfully")
        else:
            messages.error(request, "Error adding publication")
    pubs_form = AddBibtexPublicationForm(initial={"project_id": project.id})

    return render(
        request,
        "projects/add_publications.html",
        {
            "project": project,
            "project_nickname": project.nickname,
            "is_pi": request.user.username == project.pi.username,
            "pubs_form": pubs_form,
            "form": pubs_form,
        },
    )
Ejemplo n.º 2
0
def edit_nickname(request, project_id):
    mapper = ProjectAllocationMapper(request)
    project = mapper.get_project(project_id)
    if not project_pi_or_admin_or_superuser(request.user, project):
        messages.error(request, "Only the project PI can update nickname.")
        return EditNicknameForm()

    form = EditNicknameForm(request.POST)
    if form.is_valid(request):
        # try to update nickname
        try:
            nickname = form.cleaned_data["nickname"]
            ProjectAllocationMapper.update_project_nickname(
                project_id, nickname)
            form = EditNicknameForm()
            set_ks_project_nickname(project.chargeCode, nickname)
            messages.success(
                request,
                "Update successful! Click <a href='{}'>here</a> to reload".
                format(request.path),
            )
        except:
            messages.error(request, "Nickname not available")
    else:
        messages.error(request, "Nickname not available")

    return form
Ejemplo n.º 3
0
def view_project(request, project_id):
    mapper = ProjectAllocationMapper(request)
    try:
        project = mapper.get_project(project_id)
        if project.source != "Chameleon":
            raise Http404("The requested project does not exist!")
    except Exception as e:
        logger.error(e)
        raise Http404("The requested project does not exist!")

    form = ProjectAddUserForm()
    nickname_form = EditNicknameForm()
    pubs_form = AddBibtexPublicationForm()

    if request.POST and project_pi_or_admin_or_superuser(
            request.user, project):
        form = ProjectAddUserForm()
        if "add_user" in request.POST:
            form = ProjectAddUserForm(request.POST)
            if form.is_valid():
                try:
                    add_username = form.cleaned_data["username"]
                    if mapper.add_user_to_project(project, add_username):
                        sync_project_memberships(request, add_username)
                        messages.success(
                            request,
                            f'User "{add_username}" added to project!')
                        form = ProjectAddUserForm()
                except Exception as e:
                    logger.exception("Failed adding user")
                    messages.error(
                        request,
                        ("Unable to add user. Confirm that the username is "
                         "correct and corresponds to a current Chameleon user."
                         ),
                    )
            else:
                messages.error(
                    request,
                    ("There were errors processing your request. "
                     "Please see below for details."),
                )
        elif "del_user" in request.POST:
            try:
                del_username = request.POST["username"]
                # Ensure that it's not possible to remove the PI
                if del_username == project.pi.username:
                    raise PermissionDenied(
                        "Removing the PI from the project is not allowed.")
                if mapper.remove_user_from_project(project, del_username):
                    sync_project_memberships(request, del_username)
                    messages.success(
                        request,
                        'User "%s" removed from project' % del_username)
            except PermissionDenied as exc:
                messages.error(request, exc)
            except:
                logger.exception("Failed removing user")
                messages.error(
                    request,
                    "An unexpected error occurred while attempting "
                    "to remove this user. Please try again",
                )
        elif "nickname" in request.POST:
            nickname_form = edit_nickname(request, project_id)

    users = mapper.get_project_members(project)

    if not project_member_or_admin_or_superuser(request.user, project, users):
        raise PermissionDenied

    for a in project.allocations:
        if a.start and isinstance(a.start, str):
            a.start = datetime.strptime(a.start, "%Y-%m-%dT%H:%M:%SZ")
        if a.dateRequested:
            if isinstance(a.dateRequested, str):
                a.dateRequested = datetime.strptime(a.dateRequested,
                                                    "%Y-%m-%dT%H:%M:%SZ")
        if a.dateReviewed:
            if isinstance(a.dateReviewed, str):
                a.dateReviewed = datetime.strptime(a.dateReviewed,
                                                   "%Y-%m-%dT%H:%M:%SZ")
        if a.end:
            if isinstance(a.end, str):
                a.end = datetime.strptime(a.end, "%Y-%m-%dT%H:%M:%SZ")

    user_mashup = []
    for u in users:
        user = {
            "username": u.username,
            "role": u.role,
        }
        try:
            portal_user = User.objects.get(username=u.username)
            user["email"] = portal_user.email
            user["first_name"] = portal_user.first_name
            user["last_name"] = portal_user.last_name
        except User.DoesNotExist:
            logger.info("user: "******" not found")
        user_mashup.append(user)

    return render(
        request,
        "projects/view_project.html",
        {
            "project": project,
            "project_nickname": project.nickname,
            "users": user_mashup,
            "is_pi": request.user.username == project.pi.username,
            "form": form,
            "nickname_form": nickname_form,
            "pubs_form": pubs_form,
        },
    )
Ejemplo n.º 4
0
def create_allocation(request, project_id, allocation_id=-1):
    mapper = ProjectAllocationMapper(request)

    user = mapper.get_user(request.user.username)
    if user["piEligibility"].lower() != "eligible":
        messages.error(
            request,
            "Only PI Eligible users can request allocations. If you would "
            "like to request PI Eligibility, please "
            '<a href="/user/profile/edit/">submit a PI Eligibility '
            "request</a>.",
        )
        return HttpResponseRedirect(reverse("projects:user_projects"))

    project = mapper.get_project(project_id)

    allocation = None
    allocation_id = int(allocation_id)
    if allocation_id > 0:
        for a in project.allocations:
            if a.id == allocation_id:
                allocation = a

    # goofiness that we should clean up later; requires data cleansing
    abstract = project.description
    if "--- Supplemental details ---" in abstract:
        additional = abstract.split("\n\n--- Supplemental details ---\n\n")
        abstract = additional[0]
        additional = additional[1].split("\n\n--- Funding source(s) ---\n\n")
        justification = additional[0]
        if len(additional) > 1:
            funding_source = additional[1]
        else:
            funding_source = ""
    elif allocation:
        justification = allocation.justification
        if "--- Funding source(s) ---" in justification:
            parts = justification.split("\n\n--- Funding source(s) ---\n\n")
            justification = parts[0]
            funding_source = parts[1]
        else:
            funding_source = ""
    else:
        justification = ""
        funding_source = ""

    if request.POST:
        form = AllocationCreateForm(
            request.POST,
            initial={
                "description": abstract,
                "supplemental_details": justification,
                "funding_source": funding_source,
            },
        )
        if form.is_valid():
            allocation = form.cleaned_data.copy()
            allocation["computeRequested"] = 20000

            # Also update the project
            project.description = allocation.pop("description", None)

            supplemental_details = allocation.pop("supplemental_details", None)

            logger.error(supplemental_details)
            funding_source = allocation.pop("funding_source", None)

            # if supplemental_details == None:
            #    raise forms.ValidationError("Justifcation is required")
            # This is required
            if not supplemental_details:
                supplemental_details = "(none)"

            logger.error(supplemental_details)

            if funding_source:
                allocation[
                    "justification"] = "%s\n\n--- Funding source(s) ---\n\n%s" % (
                        supplemental_details,
                        funding_source,
                    )
            else:
                allocation["justification"] = supplemental_details

            allocation["projectId"] = project_id
            allocation["requestorId"] = mapper.get_portal_user_id(
                request.user.username)
            allocation["resourceId"] = "39"

            if allocation_id > 0:
                allocation["id"] = allocation_id

            try:
                logger.info(
                    "Submitting allocation request for project %s: %s" %
                    (project.id, allocation))
                updated_project = mapper.save_project(project.as_dict())
                mapper.save_allocation(allocation, project.chargeCode,
                                       request.get_host())
                messages.success(
                    request, "Your allocation request has been submitted!")
                return HttpResponseRedirect(
                    reverse("projects:view_project",
                            args=[updated_project["id"]]))
            except:
                logger.exception("Error creating allocation")
                form.add_error(
                    "__all__",
                    "An unexpected error occurred. Please try again")
        else:
            form.add_error(
                "__all__",
                "There were errors processing your request. "
                "Please see below for details.",
            )
    else:
        form = AllocationCreateForm(
            initial={
                "description": abstract,
                "supplemental_details": justification,
                "funding_source": funding_source,
            })
    context = {
        "form": form,
        "project": project,
        "alloc_id": allocation_id,
        "alloc": allocation,
    }
    return render(request, "projects/create_allocation.html", context)
Ejemplo n.º 5
0
def create_allocation(request, project_id, allocation_id=-1):
    mapper = ProjectAllocationMapper(request)

    user = mapper.get_user(request.user.username)
    if user["piEligibility"].lower() != "eligible":
        messages.error(
            request,
            "Only PI Eligible users can request allocations. If you would "
            "like to request PI Eligibility, please "
            '<a href="/user/profile/edit/">submit a PI Eligibility '
            "request</a>.",
        )
        return HttpResponseRedirect(reverse("projects:user_projects"))

    project = mapper.get_project(project_id)

    allocation = None
    allocation_id = int(allocation_id)
    if allocation_id > 0:
        for a in project.allocations:
            if a.id == allocation_id:
                allocation = a

    abstract = project.description
    if allocation:
        justification = allocation.justification
    else:
        justification = ""

    funding_source = [
        model_to_dict(f)
        for f in Funding.objects.filter(project__id=project_id, is_active=True)
    ]
    # add extra form
    funding_source.append({})

    if request.POST:
        form = AllocationCreateForm(
            request.POST,
            initial={
                "description": abstract,
                "justification": justification,
            },
        )
        formset = FundingFormset(
            request.POST,
            initial=funding_source,
        )
        consent_form = ConsentForm(request.POST)
        if form.is_valid() and formset.is_valid() and consent_form.is_valid():
            allocation = form.cleaned_data.copy()
            allocation["computeRequested"] = 20000

            # Also update the project and fundings
            project.description = allocation.pop("description", None)
            justification = allocation.pop("justification", None)

            allocation["projectId"] = project_id
            allocation["requestorId"] = mapper.get_portal_user_id(
                request.user.username)
            allocation["resourceId"] = "39"
            allocation["justification"] = justification

            if allocation_id > 0:
                allocation["id"] = allocation_id

            try:
                logger.info(
                    "Submitting allocation request for project %s: %s" %
                    (project.id, allocation))
                with transaction.atomic():
                    updated_project = mapper.save_project(project.as_dict())
                    mapper.save_allocation(allocation, project.chargeCode,
                                           request.get_host())
                    new_funding_source = _save_fundings(formset, project_id)
                    _remove_fundings(funding_source, new_funding_source)
                messages.success(
                    request, "Your allocation request has been submitted!")
                return HttpResponseRedirect(
                    reverse("projects:view_project",
                            args=[updated_project["id"]]))
            except:
                logger.exception("Error creating allocation")
                form.add_error(
                    "__all__",
                    "An unexpected error occurred. Please try again")
        else:
            form.add_error(
                "__all__",
                "There were errors processing your request. "
                "Please see below for details.",
            )
    else:
        form = AllocationCreateForm(initial={
            "description": abstract,
            "justification": justification,
        })
        formset = FundingFormset(initial=funding_source)
        consent_form = ConsentForm()
    context = {
        "form": form,
        "funding_formset": formset,
        "consent_form": consent_form,
        "project": project,
        "alloc_id": allocation_id,
        "alloc": allocation,
    }
    return render(request, "projects/create_allocation.html", context)
Ejemplo n.º 6
0
def view_project(request, project_id):
    mapper = ProjectAllocationMapper(request)
    keycloak_client = KeycloakClient()

    try:
        project = mapper.get_project(project_id)
        if project.source != "Chameleon":
            raise Http404("The requested project does not exist!")
    except Exception as e:
        logger.error(e)
        raise Http404("The requested project does not exist!")

    form = ProjectAddUserForm()
    nickname_form = EditNicknameForm()
    type_form_args = {"request": request}
    type_form = EditTypeForm(**type_form_args)
    pubs_form = AddBibtexPublicationForm()

    can_manage_project_membership, can_manage_project = get_user_permissions(
        keycloak_client, request.user.username, project)

    if (request.POST and can_manage_project_membership
            or is_admin_or_superuser(request.user)):
        form = ProjectAddUserForm()
        if "add_user" in request.POST:
            form = ProjectAddUserForm(request.POST)
            if form.is_valid():
                try:
                    add_username = form.cleaned_data["user_ref"]
                    user = User.objects.get(username=add_username)
                    if mapper.add_user_to_project(project, add_username):
                        messages.success(
                            request,
                            f'User "{add_username}" added to project!')
                        form = ProjectAddUserForm()
                except User.DoesNotExist:
                    # Try sending an invite
                    email_address = form.cleaned_data["user_ref"]
                    try:
                        validate_email(email_address)
                        if email_exists_on_project(project, email_address):
                            messages.error(
                                request,
                                "That email is tied to a user already on the "
                                "project!",
                            )
                        else:
                            add_project_invitation(
                                project_id,
                                email_address,
                                request.user,
                                request,
                                None,
                            )
                            messages.success(request, "Invite sent!")
                    except ValidationError:
                        messages.error(
                            request,
                            ("Unable to add user. Confirm that the username "
                             "is correct and corresponds to a current "
                             "Chameleon user. You can also send an invite "
                             "to an email address if the user does not yet "
                             "have an account."),
                        )
                    except Exception:
                        messages.error(
                            request,
                            "Problem sending invite, please try again.")
                except Exception:
                    logger.exception("Failed adding user")
                    messages.error(request,
                                   "Unable to add user. Please try again.")
            else:
                messages.error(
                    request,
                    ("There were errors processing your request. "
                     "Please see below for details."),
                )
        elif "del_user" in request.POST:
            try:
                del_username = request.POST["user_ref"]
                # Ensure that it's not possible to remove the PI
                if del_username in [project.pi.username, project.pi.email]:
                    raise PermissionDenied(
                        "Removing the PI from the project is not allowed.")
                if mapper.remove_user_from_project(project, del_username):
                    messages.success(
                        request,
                        'User "%s" removed from project' % del_username)
                user = User.objects.get(username=del_username)
                daypass = get_daypass(user.id, project_id)
                if daypass:
                    daypass.delete()
            except PermissionDenied as exc:
                messages.error(request, exc)
            except Exception:
                logger.exception("Failed removing user")
                messages.error(
                    request,
                    "An unexpected error occurred while attempting "
                    "to remove this user. Please try again",
                )
        elif "change_role" in request.POST:
            try:
                role_username = request.POST["user_ref"]
                role_name = request.POST["user_role"].lower()
                keycloak_client.set_user_project_role(role_username,
                                                      get_charge_code(project),
                                                      role_name)
            except Exception:
                logger.exception("Failed to change user role")
                messages.error(
                    request,
                    "An unexpected error occurred while attempting "
                    "to change role for this user. Please try again",
                )
        elif "del_invite" in request.POST:
            try:
                invite_id = request.POST["invite_id"]
                remove_invitation(invite_id)
                messages.success(request, "Invitation removed")
            except Exception:
                logger.exception("Failed to delete invitation")
                messages.error(
                    request,
                    "An unexpected error occurred while attempting "
                    "to remove this invitation. Please try again",
                )
        elif "resend_invite" in request.POST:
            try:
                invite_id = request.POST["invite_id"]
                resend_invitation(invite_id, request.user, request)
                messages.success(request, "Invitation resent")
            except Exception:
                logger.exception("Failed to resend invitation")
                messages.error(
                    request, "An unexpected error occurred while attempting "
                    "to resend this invitation. Please try again")
        elif "nickname" in request.POST:
            nickname_form = edit_nickname(request, project_id)
        elif "typeId" in request.POST:
            type_form = edit_type(request, project_id)

    for a in project.allocations:
        if a.start and isinstance(a.start, str):
            a.start = datetime.strptime(a.start, "%Y-%m-%dT%H:%M:%SZ")
        if a.dateRequested:
            if isinstance(a.dateRequested, str):
                a.dateRequested = datetime.strptime(a.dateRequested,
                                                    "%Y-%m-%dT%H:%M:%SZ")
        if a.dateReviewed:
            if isinstance(a.dateReviewed, str):
                a.dateReviewed = datetime.strptime(a.dateReviewed,
                                                   "%Y-%m-%dT%H:%M:%SZ")
        if a.end:
            if isinstance(a.end, str):
                a.end = datetime.strptime(a.end, "%Y-%m-%dT%H:%M:%SZ")

    users = get_project_members(project)
    if not project_member_or_admin_or_superuser(request.user, project, users):
        raise PermissionDenied

    user_roles = keycloak_client.get_roles_for_all_project_members(
        get_charge_code(project))
    users_mashup = []

    for u in users:
        if u.username == project.pi.username:
            continue
        u_role = user_roles.get(u.username, "member")
        user = {
            "id": u.id,
            "username": u.username,
            "role": u_role.title(),
        }
        try:
            portal_user = User.objects.get(username=u.username)
            user["email"] = portal_user.email
            user["first_name"] = portal_user.first_name
            user["last_name"] = portal_user.last_name
            # Add if the user is on a daypass
            existing_daypass = get_daypass(portal_user.id, project_id)
            if existing_daypass:
                user["daypass"] = format_timedelta(
                    existing_daypass.date_exceeds_duration() - timezone.now())
        except User.DoesNotExist:
            logger.info("user: "******" not found")
        users_mashup.append(user)

    invitations = Invitation.objects.filter(project=project_id)
    invitations = [i for i in invitations if i.can_accept()]

    clean_invitations = []
    for i in invitations:
        new_item = {}
        new_item["email_address"] = i.email_address
        new_item["id"] = i.id
        new_item["status"] = i.status.title()
        if i.duration:
            new_item["duration"] = i.duration
        clean_invitations.append(new_item)

    is_on_daypass = get_daypass(request.user.id, project_id) is not None

    return render(
        request,
        "projects/view_project.html",
        {
            "project": project,
            "project_nickname": project.nickname,
            "project_type": project.type,
            "users": users_mashup,
            "invitations": clean_invitations,
            "can_manage_project_membership": can_manage_project_membership,
            "can_manage_project": can_manage_project,
            "is_admin": request.user.is_superuser,
            "is_on_daypass": is_on_daypass,
            "form": form,
            "nickname_form": nickname_form,
            "type_form": type_form,
            "pubs_form": pubs_form,
            "roles": ROLES,
            "host": request.get_host(),
        },
    )