Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

guard views/dashboard by tugraz_authenticated #322

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (C) 2024 Graz University of Technology.
//
// invenio-theme-tugraz is free software; you can redistribute it and/or modify it
// under the terms of the MIT License; see LICENSE file for more details.

import $ from "jquery";

async function generateForm() {
// get email from `/api/me`
let email = "???";
const response = await fetch("/api/me");
if (response.ok) {
const json = await response.json();
email = json?.email || "???";
}

// show form
$.getScript("https://ub-support.tugraz.at/assets/form/form.js", () => {
$("#anchor-unlock-form").ZammadForm({
attributes: [
{},
{ defaultValue: email },
{
defaultValue: `Could you unlock my account (${email}) for research-uploads?`,
// TODO: add to defaultValue once policy on how to get accepted is decided...
},
],
modal: false,
});

// focus first entry of now-shown form
document.getElementById("zammad-form-name-inline").focus();
});
}

$(function () {
// called when DOM is ready
const generateFormElement = document.getElementById("generate-unlock-form");
if (generateFormElement) {
generateFormElement.onclick = generateForm;
}
});
30 changes: 29 additions & 1 deletion invenio_theme_tugraz/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

"""invenio module for TUGRAZ theme."""

from flask_login import login_required
from invenio_i18n import lazy_gettext as _
from invenio_records_marc21.ui.theme import current_identity_can_view

from . import config
from .views import index, locked
from .views import index, locked, require_tugraz_authenticated


class InvenioThemeTugraz(object):
Expand Down Expand Up @@ -48,6 +49,7 @@ def init_config(self, app):
def finalize_app(app):
"""Finalize app."""
modify_user_dashboard(app)
guard_view_functions(app)


def modify_user_dashboard(app):
Expand All @@ -66,3 +68,29 @@ def modify_user_dashboard(app):
_("My dashboard"),
order=1,
)


def guard_view_functions(app):
"""Guard view-functions against unauthenticated access."""
endpoints_to_guard = [
"invenio_app_rdm_users.communities",
"invenio_app_rdm_users.requests",
"invenio_app_rdm_users.uploads",
]

for endpoint in endpoints_to_guard:
view_func = app.view_functions.get(endpoint)
if not view_func:
continue

# decorate view-func
# same as if view-func were defined with:
# @login_required
# @require_tugraz_authenticated_user
view_func = login_required(
require_tugraz_authenticated(
view_func,
),
)

app.view_functions[endpoint] = view_func
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
{%- set active_dashboard_menu_item = "overview" %}
{%- set title = _("Overview") %}

{% block javascript %}
{{ super() }}
{{ webpack['invenio-theme-tugraz-unlock.js'] }}
{% endblock javascript %}

{%- block page_body %}
{%- block user_dashboard_header %}
{% include "invenio_app_rdm/users/header.html" %}
Expand All @@ -19,8 +24,9 @@
<div class="ui container rel-mt-2">
<h2>Overview</h2>


<div class="ui five column stackable grid overview">
{% if is_tugraz_authenticated %}
{# 3 columns: Research-Uploads, Communities, and Requests #}
<div class="column">
<div class="ui segment" style="height: 480px">
<h2>{{ _("Research Results") }}</h2>
Expand Down Expand Up @@ -54,6 +60,46 @@ <h2>{{ _("Requests") }}</h2>
</div>
</div>
</div>
{% else %} {# not is_tugraz_authenticated #}
{# 1 column: greyed out Research-Uploads #}
<div class="column">
{# a modal's HTML can be placed anywhere, so I placed it here, right before it's used #}
<div class="ui small modal" id="tugraz-unlock-modal">
<div class="header">{{ _("On unlocking research uploads") }}</div>
<div class="content">
<p>
{{ _('To ensure a well-curated repository, new users need to get unlocked
before being allowed to upload. Once unlocked, you can upload your research,
request its inclusion in a community, generate a DOI for it, and publish it.') }}
{# TODO: extra lines on policy about who gets accepted how for Research-Uploads #}
</p>
<div id="anchor-unlock-form"> {# will be replaced with ZammadForm when generating it #}
<button class="ui fluid button" onclick="
$('#tugraz-unlock-modal')
.modal('hide')"
>Got it!</button>
<button id="generate-unlock-form" class="ui fluid button">
{{ _("Request unlocking") }}
</button>
</div>
</div>
</div>

{# actual column contents start here #}
<div class="ui disabled segment" style="height: 480px">
<h2>{{ _("Research Results") }}</h2>
<div class="ui left floated image" style="cursor: pointer" onclick="
$('#tugraz-unlock-modal')
.modal('show')"
>
<img width="400px" alt="Research Results" src="{{ url_for("static", filename="images/diamond.svg") }}">
</div>
<div class="ui right floated text">
{{ _("Overview: Description for research results") }}
</div>
</div>
</div>
{% endif %}
{% if can_view_marc21 %}
<div class="column">
<div class="ui segment" style="height: 480px">
Expand Down
32 changes: 31 additions & 1 deletion invenio_theme_tugraz/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@

"""invenio module for TUGRAZ theme."""

from functools import wraps
from typing import Dict

from flask import Blueprint, g, render_template
from flask import Blueprint, g, redirect, render_template, url_for
from flask_login import current_user, login_required
from invenio_rdm_records.proxies import current_rdm_records
from invenio_records_global_search.resources.serializers import (
GlobalSearchJSONSerializer,
)
Expand All @@ -28,15 +30,43 @@
)


def current_identity_is_tugraz_authenticated() -> bool:
"""Checks whether current identity has tugraz-authentication.

NOTE: Default permission-policy has no field for `tugraz_authenticated`.
Should the field not exist, the service checks against admin-permissions instead.
You probably meant to configure a custom permission-policy.
"""
rdm_service = current_rdm_records.records_service
return rdm_service.check_permission(g.identity, "tugraz_authenticated")


def require_tugraz_authenticated(view_func):
"""Decorator for guarding view-functions against unauthenticated users.

Redirects un-authenticated users to their personal dashboard's overview.
"""

@wraps(view_func)
def decorated_view(*args, **kwargs):
if not current_identity_is_tugraz_authenticated():
return redirect(url_for("invenio_theme_tugraz.overview"))
return view_func(*args, **kwargs)

return decorated_view


@blueprint.route("/me/overview")
@login_required
def overview():
"""Overview."""
url = current_user_resources.users_service.links_item_tpl.expand(
g.identity, current_user
)["avatar"]
is_tugraz_authenticated = current_identity_is_tugraz_authenticated()
return render_template(
"invenio_theme_tugraz/overview.html",
is_tugraz_authenticated=is_tugraz_authenticated,
user_avatar=url,
)

Expand Down
3 changes: 2 additions & 1 deletion invenio_theme_tugraz/webpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
entry={
"invenio-theme-tugraz-theme": "./less/invenio_theme_tugraz/theme.less",
"invenio-theme-tugraz-js": "./js/invenio_theme_tugraz/theme.js",
"invenio-theme-tugraz-unlock": "./js/invenio_theme_tugraz/unlock.js",
},
dependencies={
# add any additional npm dependencies here...
"jquery": "^3.2.1", # zammad-form, semantic-ui's modals
},
)
},
Expand Down