mirror of
https://github.com/Cian-H/invenio-theme-iform.git
synced 2026-08-16 08:32:48 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca9b574669 | ||
|
|
0d544fdc8e | ||
|
|
154d77e187 | ||
|
|
c177eaffc3 | ||
|
|
cdee2d929d | ||
|
|
fc920e1b04 | ||
|
|
9963c3e7fe | ||
|
|
9040da0172 | ||
|
|
4ff4e83e05 |
@@ -20,6 +20,8 @@ jobs:
|
|||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-dependency-glob: |
|
cache-dependency-glob: |
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
|
- name: Compile translations
|
||||||
|
run: uv run pybabel compile -d invenio_theme_iform/translations/
|
||||||
- name: Build package
|
- name: Build package
|
||||||
run: uv build
|
run: uv build
|
||||||
- name: Publish to PyPI
|
- name: Publish to PyPI
|
||||||
|
|||||||
@@ -8,4 +8,4 @@
|
|||||||
|
|
||||||
"""Metadata for this python module."""
|
"""Metadata for this python module."""
|
||||||
|
|
||||||
__version__ = "2026.8.12"
|
__version__ = "2026.8.14"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 I-Form.
|
||||||
|
#
|
||||||
|
# invenio-theme-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Administration views."""
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 I-Form.
|
||||||
|
#
|
||||||
|
# invenio-theme-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""I-Form administration views."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from flask import current_app, flash, redirect, request, url_for
|
||||||
|
from invenio_accounts.models import Role, User
|
||||||
|
from invenio_accounts.proxies import current_accounts
|
||||||
|
from invenio_administration.views.base import AdminView
|
||||||
|
from invenio_db import db
|
||||||
|
from invenio_i18n import lazy_gettext as _
|
||||||
|
|
||||||
|
|
||||||
|
def get_site_settings_path():
|
||||||
|
"""Get the path to site_settings.json."""
|
||||||
|
app_data_dir = os.path.join(current_app.instance_path, "app_data")
|
||||||
|
os.makedirs(app_data_dir, exist_ok=True)
|
||||||
|
return os.path.join(app_data_dir, "site_settings.json")
|
||||||
|
|
||||||
|
|
||||||
|
def get_site_settings():
|
||||||
|
"""Load site settings from JSON file."""
|
||||||
|
path = get_site_settings_path()
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return {"registration_enabled": True}
|
||||||
|
try:
|
||||||
|
with open(path, "r") as f:
|
||||||
|
return json.load(f)
|
||||||
|
except Exception:
|
||||||
|
return {"registration_enabled": True}
|
||||||
|
|
||||||
|
|
||||||
|
def set_site_settings(settings):
|
||||||
|
"""Save site settings to JSON file."""
|
||||||
|
path = get_site_settings_path()
|
||||||
|
with open(path, "w") as f:
|
||||||
|
json.dump(settings, f, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
class RoleManagementView(AdminView):
|
||||||
|
"""Admin view for managing user roles."""
|
||||||
|
|
||||||
|
name = "roles"
|
||||||
|
category = "User management"
|
||||||
|
template = "invenio_theme_iform/administration/roles.html"
|
||||||
|
url = "/roles"
|
||||||
|
menu_label = _("Role Assignment")
|
||||||
|
icon = "users"
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
"""Render the role management template."""
|
||||||
|
roles = Role.query.order_by(Role.name).all()
|
||||||
|
selected_role_id = request.args.get("role_id")
|
||||||
|
|
||||||
|
users = []
|
||||||
|
selected_role = None
|
||||||
|
if selected_role_id:
|
||||||
|
selected_role = Role.query.get(selected_role_id)
|
||||||
|
if selected_role:
|
||||||
|
users = User.query.order_by(User.email).all()
|
||||||
|
|
||||||
|
return self.render(
|
||||||
|
roles=roles,
|
||||||
|
selected_role=selected_role,
|
||||||
|
users=users,
|
||||||
|
)
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
"""Handle role assignment/revocation."""
|
||||||
|
user_id = request.form.get("user_id")
|
||||||
|
role_id = request.form.get("role_id")
|
||||||
|
action = request.form.get("action")
|
||||||
|
|
||||||
|
if not (user_id and role_id and action):
|
||||||
|
flash(_("Missing required fields."), "error")
|
||||||
|
return redirect(url_for("administration.roles", role_id=role_id))
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = User.query.get(int(user_id))
|
||||||
|
except ValueError:
|
||||||
|
user = None
|
||||||
|
|
||||||
|
role = Role.query.get(role_id)
|
||||||
|
|
||||||
|
if not user or not role:
|
||||||
|
flash(_("User or role not found."), "error")
|
||||||
|
return redirect(url_for("administration.roles", role_id=role_id))
|
||||||
|
|
||||||
|
if action == "enable":
|
||||||
|
if role not in user.roles:
|
||||||
|
current_accounts.datastore.add_role_to_user(user, role)
|
||||||
|
flash(
|
||||||
|
_("Role {role} enabled for {email}.").format(
|
||||||
|
role=role.name, email=user.email
|
||||||
|
),
|
||||||
|
"success",
|
||||||
|
)
|
||||||
|
elif action == "disable":
|
||||||
|
if role in user.roles:
|
||||||
|
current_accounts.datastore.remove_role_from_user(user, role)
|
||||||
|
flash(
|
||||||
|
_("Role {role} disabled for {email}.").format(
|
||||||
|
role=role.name, email=user.email
|
||||||
|
),
|
||||||
|
"success",
|
||||||
|
)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for("administration.roles", role_id=role_id))
|
||||||
|
|
||||||
|
|
||||||
|
class RegistrationSettingsView(AdminView):
|
||||||
|
"""Admin view for controlling site registration settings."""
|
||||||
|
|
||||||
|
name = "registration-settings"
|
||||||
|
category = "Site Settings"
|
||||||
|
template = "invenio_theme_iform/administration/registration_settings.html"
|
||||||
|
url = "/registration-settings"
|
||||||
|
menu_label = _("Registration Settings")
|
||||||
|
icon = "setting"
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
"""Render registration settings page."""
|
||||||
|
settings = get_site_settings()
|
||||||
|
return self.render(
|
||||||
|
registration_enabled=settings.get("registration_enabled", True)
|
||||||
|
)
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
"""Handle registration settings update."""
|
||||||
|
enabled = request.form.get("registration_enabled") == "true"
|
||||||
|
settings = get_site_settings()
|
||||||
|
settings["registration_enabled"] = enabled
|
||||||
|
set_site_settings(settings)
|
||||||
|
|
||||||
|
status_str = _("enabled") if enabled else _("disabled")
|
||||||
|
flash(
|
||||||
|
_("Public user registration has been {status}.").format(
|
||||||
|
status=status_str
|
||||||
|
),
|
||||||
|
"success",
|
||||||
|
)
|
||||||
|
return redirect(url_for("administration.registration-settings"))
|
||||||
|
|
||||||
|
|
||||||
|
class UserCreateView(AdminView):
|
||||||
|
"""Admin view for creating users."""
|
||||||
|
|
||||||
|
name = "create-user"
|
||||||
|
category = "User management"
|
||||||
|
template = "invenio_theme_iform/administration/user_create.html"
|
||||||
|
url = "/create-user"
|
||||||
|
menu_label = _("Create User")
|
||||||
|
icon = "user plus"
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
"""Render user creation page."""
|
||||||
|
return self.render()
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
"""Handle manual user creation."""
|
||||||
|
from flask_security.utils import hash_password
|
||||||
|
from invenio_access.permissions import system_identity
|
||||||
|
from invenio_users_resources.proxies import current_users_service
|
||||||
|
|
||||||
|
email = request.form.get("email", "").strip()
|
||||||
|
password = request.form.get("password", "").strip()
|
||||||
|
confirm_email = request.form.get("confirm_email") == "true"
|
||||||
|
|
||||||
|
if not email or not password:
|
||||||
|
flash(_("Email and Password are required."), "error")
|
||||||
|
return redirect(url_for("administration.create-user"))
|
||||||
|
|
||||||
|
if User.query.filter_by(email=email).first():
|
||||||
|
flash(_("A user with this email already exists."), "error")
|
||||||
|
return redirect(url_for("administration.create-user"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
user_kwargs = {
|
||||||
|
"email": email,
|
||||||
|
"password": hash_password(password),
|
||||||
|
"active": True,
|
||||||
|
}
|
||||||
|
if confirm_email:
|
||||||
|
user_kwargs["confirmed_at"] = datetime.utcnow()
|
||||||
|
|
||||||
|
user = current_accounts.datastore.create_user(**user_kwargs)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# Index the newly created user in search engine
|
||||||
|
try:
|
||||||
|
from invenio_search import current_search_client
|
||||||
|
current_users_service.reindex(system_identity, uids=[user.id])
|
||||||
|
current_users_service.indexer.process_bulk_queue()
|
||||||
|
current_search_client.indices.refresh(index="*")
|
||||||
|
except Exception as ie:
|
||||||
|
current_app.logger.warning("Failed to index user %s: %s", user.id, str(ie))
|
||||||
|
|
||||||
|
flash(
|
||||||
|
_("User {email} created successfully.").format(email=email),
|
||||||
|
"success",
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
flash(
|
||||||
|
_("Failed to create user: {error}").format(error=str(e)),
|
||||||
|
"error",
|
||||||
|
)
|
||||||
|
|
||||||
|
return redirect(url_for("administration.create-user"))
|
||||||
@@ -39,8 +39,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div .logos a:hover {
|
div .logos {
|
||||||
background-color: transparent !important;
|
--invenio-logo-glass-color: @invenioLogoGlassColor;
|
||||||
|
--ri-logo-color: @riLogoColor;
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
#footer div .logos {
|
||||||
|
--invenio-logo-glass-color: #ffffff;
|
||||||
|
--ri-logo-color: @riLogoColorDark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,9 @@
|
|||||||
// footer specific
|
// footer specific
|
||||||
@footerGrey: #5e5e5e;
|
@footerGrey: #5e5e5e;
|
||||||
@footerBottomBackground: #f2f2f2;
|
@footerBottomBackground: #f2f2f2;
|
||||||
|
@invenioLogoGlassColor: #333333;
|
||||||
|
@riLogoColor: #19261b;
|
||||||
|
@riLogoColorDark: #decbe9;
|
||||||
|
|
||||||
// record specific
|
// record specific
|
||||||
@recordVersionBackground: #f2f2f2;
|
@recordVersionBackground: #f2f2f2;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"""invenio module for I-Form theme."""
|
"""invenio module for I-Form theme."""
|
||||||
|
|
||||||
from flask_babel import lazy_gettext as _
|
from flask_babel import lazy_gettext as _
|
||||||
|
|
||||||
I18N_LANGUAGES = [
|
I18N_LANGUAGES = [
|
||||||
("en", _("English")),
|
("en", _("English")),
|
||||||
("ga", _("Irish")),
|
("ga", _("Irish")),
|
||||||
@@ -53,6 +54,9 @@ THEME_500_TEMPLATE = "invenio_theme_iform/default_error.html"
|
|||||||
THEME_LOGO = "images/iform_logo.png"
|
THEME_LOGO = "images/iform_logo.png"
|
||||||
"""I-Form logo"""
|
"""I-Form logo"""
|
||||||
|
|
||||||
|
THEME_FAVICON = "images/iform-favicon.ico"
|
||||||
|
"""I-Form favicon"""
|
||||||
|
|
||||||
THEME_SEARCHBAR = False
|
THEME_SEARCHBAR = False
|
||||||
"""Enable or disable the header search bar."""
|
"""Enable or disable the header search bar."""
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
"""invenio module for I-Form theme."""
|
"""invenio module for I-Form theme."""
|
||||||
|
|
||||||
from flask import g, has_request_context
|
from flask import g, has_request_context, request
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from . import config
|
from . import config
|
||||||
@@ -32,8 +32,36 @@ class InvenioThemeIform(object):
|
|||||||
|
|
||||||
app.register_error_handler(423, locked)
|
app.register_error_handler(423, locked)
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
def block_registration_if_disabled():
|
||||||
|
if request.endpoint == "security.register":
|
||||||
|
from flask import current_app, render_template
|
||||||
|
from .administration.views import get_site_settings
|
||||||
|
settings = get_site_settings()
|
||||||
|
if not settings.get("registration_enabled", True):
|
||||||
|
admin_email = (
|
||||||
|
current_app.config.get("APP_RDM_ADMIN_EMAIL_RECIPIENT")
|
||||||
|
or current_app.config.get("SUPPORT_EMAIL")
|
||||||
|
or current_app.config.get("THEME_SUPPORT_EMAIL")
|
||||||
|
or current_app.config.get("SECURITY_EMAIL_SENDER")
|
||||||
|
or "info@repo.i-form.ie"
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
render_template(
|
||||||
|
"invenio_theme_iform/accounts/registration_disabled.html",
|
||||||
|
admin_email=admin_email,
|
||||||
|
),
|
||||||
|
403,
|
||||||
|
)
|
||||||
|
|
||||||
app.extensions["invenio-theme-iform"] = self
|
app.extensions["invenio-theme-iform"] = self
|
||||||
|
|
||||||
|
@app.context_processor
|
||||||
|
def inject_site_settings():
|
||||||
|
from .administration.views import get_site_settings
|
||||||
|
settings = get_site_settings()
|
||||||
|
return dict(registration_enabled=settings.get("registration_enabled", True))
|
||||||
|
|
||||||
def init_config(self, app):
|
def init_config(self, app):
|
||||||
"""Initialize configuration."""
|
"""Initialize configuration."""
|
||||||
for k in dir(config):
|
for k in dir(config):
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 330 KiB After Width: | Height: | Size: 330 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 29.069883 10.420284">
|
||||||
|
<g transform="translate(1142.2809,279.38339)">
|
||||||
|
<a transform="matrix(0.26458333,0,0,0.26458333,-1279.7936,-339.14401)" id="a9715" xlink:href="/products/rdm/">
|
||||||
|
<g transform="translate(0.9420447)">
|
||||||
|
<g aria-label="RDM" transform="scale(0.96631971,1.0348542)" style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:37.37073898px;font-family:Oswald;fill:#fb8273;stroke:none">
|
||||||
|
<path d="m 628.93512,251.59732 0.52319,-30.2703 h 6.53987 l 3.73708,19.09645 3.99867,-19.09645 h 6.31565 l 0.52319,30.2703 h -4.48449 l -0.48582,-20.51654 -3.84918,20.51654 h -3.84919 l -4.03604,-20.66602 -0.41108,20.66602 z m -21.27388,0 v -30.2703 h 7.3994 q 3.84919,0 5.97932,1.00901 2.1675,0.97164 3.0644,3.10177 0.8969,2.09276 0.8969,5.38139 v 11.02437 q 0,3.36336 -0.8969,5.53087 -0.8969,2.1675 -3.02703,3.21388 -2.09276,1.00901 -5.8672,1.00901 z m 6.16617,-4.29763 h 1.30798 q 1.71905,0 2.42909,-0.52319 0.74742,-0.56057 0.93427,-1.60695 0.18686,-1.08375 0.18686,-2.65332 V 230.0344 q 0,-1.56957 -0.2616,-2.50384 -0.22422,-0.97163 -0.97164,-1.42008 -0.71004,-0.44845 -2.35436,-0.44845 h -1.2706 z m -27.84412,4.29763 v -30.2703 h 7.84785 q 3.06441,0 5.23191,0.71005 2.20487,0.67267 3.36336,2.42909 1.19587,1.75643 1.19587,4.8582 0,1.86854 -0.33634,3.326 -0.29896,1.42008 -1.12112,2.50384 -0.78479,1.04638 -2.24224,1.68168 l 4.18552,14.76144 h -6.31566 l -3.47548,-13.71506 h -2.1675 v 13.71506 z m 6.16617,-17.37739 h 1.7938 q 1.49483,0 2.35435,-0.48582 0.85953,-0.48582 1.19587,-1.45746 0.3737,-1.00901 0.3737,-2.46647 0,-2.09276 -0.78478,-3.17651 -0.74742,-1.12113 -2.84018,-1.12113 h -2.09276 z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.43046721,0,0,0.43046721,198.64479,126.38329)">
|
||||||
|
<g transform="translate(474.21725,226.44114)">
|
||||||
|
<path d="m 328.162,4.665 c -18.767,0 -34.032,15.268 -34.032,34.034 0,7.28 2.306,14.028 6.214,19.568 l -30.078,26.432 c -1.881,1.878 0.067,6.867 1.944,8.749 1.879,1.876 6.87,3.822 8.748,1.943 l 26.265,-29.894 c 5.779,4.525 13.047,7.233 20.939,7.233 18.768,0 34.034,-15.267 34.034,-34.032 0,-18.765 -15.266,-34.033 -34.034,-34.033 z m 0,56.722 c -12.51,0 -22.689,-10.177 -22.689,-22.688 0,-12.511 10.18,-22.69 22.689,-22.69 12.513,0 22.688,10.18 22.688,22.69 0,12.51 -10.175,22.688 -22.688,22.688 z" style="fill:var(--invenio-logo-glass-color, #000000)"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.38742049,0,0,0.38742049,670.93796,251.12579)">
|
||||||
|
<path d="m 375.104,38.079 c 0.174,18.184 -8.123,32.126 -11.51,37.52 8.183,-5.347 19.898,-19.36 19.674,-37.661 0.174,-18.183 -11.431,-32.127 -19.631,-37.52 3.323,5.347 11.691,19.36 11.467,37.661 z" style="fill:var(--invenio-logo-glass-color, #000000)"/>
|
||||||
|
<path d="m 375.104,38.079 c 0.174,18.184 -8.123,32.126 -11.51,37.52 8.183,-5.347 19.898,-19.36 19.674,-37.661 0.174,-18.183 -11.431,-32.127 -19.631,-37.52 3.323,5.347 11.691,19.36 11.467,37.661 z" style="fill:none;stroke:var(--invenio-logo-glass-color, #000000)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</a>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.6 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.6 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.8 KiB |
@@ -39,7 +39,7 @@
|
|||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
{%- endblock head_title %}
|
{%- endblock head_title %}
|
||||||
{%- block head_links %}
|
{%- block head_links %}
|
||||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" />
|
<link rel="shortcut icon" href="{{ url_for('static', filename=config.THEME_FAVICON or 'images/iform-favicon.ico') }}" />
|
||||||
{%- if keywords %}<link rel="canonical" href="{{ canonical_url }}" />{% endif %}
|
{%- if keywords %}<link rel="canonical" href="{{ canonical_url }}" />{% endif %}
|
||||||
{%- block head_links_langs %}
|
{%- block head_links_langs %}
|
||||||
{%- if alternate_urls %}
|
{%- if alternate_urls %}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{%- if not current_user.is_authenticated %}
|
{%- if not current_user.is_authenticated %}
|
||||||
|
|
||||||
{%- if config.SECURITY_REGISTERABLE %}
|
{%- if config.SECURITY_REGISTERABLE and registration_enabled %}
|
||||||
<div class="short-menu-right-button">
|
<div class="short-menu-right-button">
|
||||||
<a href="{{ url_for('security.register') }}" class="no-decoration">
|
<a href="{{ url_for('security.register') }}" class="no-decoration">
|
||||||
{{ _ ("Sign up") }}
|
{{ _ ("Sign up") }}
|
||||||
@@ -22,6 +22,13 @@
|
|||||||
<i class="user icon"></i> {{ current_user.email }}
|
<i class="user icon"></i> {{ current_user.email }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
{%- for item in current_menu.submenu('profile-admin').children if item.visible %}
|
||||||
|
<div class="short-menu-right-button">
|
||||||
|
<a class="dropdown-item no-decoration" href="{{ item.url }}">
|
||||||
|
{{ item.text|safe }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{%- endfor %}
|
||||||
<div class="short-menu-right-button">
|
<div class="short-menu-right-button">
|
||||||
<a class="dropdown-item no-decoration" href="{{ url_for_security('logout') }}"
|
<a class="dropdown-item no-decoration" href="{{ url_for_security('logout') }}"
|
||||||
>{{ _("Sign out") }}</a
|
>{{ _("Sign out") }}</a
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{#
|
||||||
|
Copyright (C) 2024 I-Form.
|
||||||
|
|
||||||
|
invenio-theme-iform is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the MIT License; see LICENSE file for more details.
|
||||||
|
#}
|
||||||
|
{% extends config.THEME_ERROR_TEMPLATE %}
|
||||||
|
|
||||||
|
{% block message %}
|
||||||
|
<div class="ui container center aligned rel-mt-5 rel-mb-5">
|
||||||
|
<h1 class="ui icon header">
|
||||||
|
<i class="user cancel icon red"></i>
|
||||||
|
<div class="content">
|
||||||
|
{{ _("Public Registration Disabled") }}
|
||||||
|
<div class="sub header rel-mt-2">
|
||||||
|
{{ _("Public user registration is currently closed on this repository.") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="ui message info left aligned" style="max-width: 600px; margin: 2em auto;">
|
||||||
|
<div class="header">
|
||||||
|
{{ _("Need an account?") }}
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
{{ _("If you require an account to upload or manage research data, please contact an administrator at:") }}
|
||||||
|
</p>
|
||||||
|
<p style="font-size: 1.1em; font-weight: bold; text-align: center;">
|
||||||
|
<a href="mailto:{{ admin_email }}"><i class="envelope icon"></i> {{ admin_email }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rel-mt-3">
|
||||||
|
<a href="{{ url_for('security.login') }}" class="ui button primary">
|
||||||
|
<i class="sign-in icon"></i> {{ _("Back to Log In") }}
|
||||||
|
</a>
|
||||||
|
<a href="{{ url_for('index') }}" class="ui button">
|
||||||
|
<i class="home icon"></i> {{ _("Home Page") }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock message %}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
{#
|
||||||
|
Copyright (C) 2024 I-Form.
|
||||||
|
|
||||||
|
invenio-theme-iform is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the MIT License; see LICENSE file for more details.
|
||||||
|
#}
|
||||||
|
{% extends "invenio_administration/base.html" %}
|
||||||
|
|
||||||
|
{% block admin_page_content %}
|
||||||
|
<div class="ui container dashboard rel-mt-5">
|
||||||
|
<div class="ui grid">
|
||||||
|
<div class="sixteen wide column">
|
||||||
|
<h2 class="ui header">
|
||||||
|
<i class="setting icon"></i>
|
||||||
|
<div class="content">
|
||||||
|
{{ _("Registration Settings") }}
|
||||||
|
<div class="sub header">{{ _("Enable or disable public user registration on the website.") }}</div>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="ui {{ 'positive' if category == 'success' else 'negative' }} message">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
<div class="ui segment">
|
||||||
|
<h3 class="ui header">{{ _("Public Sign-up Status") }}</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{% if registration_enabled %}
|
||||||
|
<span class="ui green large label"><i class="check icon"></i> {{ _("Public Sign-ups ENABLED") }}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="ui red large label"><i class="ban icon"></i> {{ _("Public Sign-ups DISABLED") }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
|
||||||
|
<form method="POST" class="ui form">
|
||||||
|
{% if registration_enabled %}
|
||||||
|
<input type="hidden" name="registration_enabled" value="false">
|
||||||
|
<button type="submit" class="ui red button">
|
||||||
|
<i class="ban icon"></i> {{ _("Disable Public Sign-ups") }}
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<input type="hidden" name="registration_enabled" value="true">
|
||||||
|
<button type="submit" class="ui green button">
|
||||||
|
<i class="check icon"></i> {{ _("Enable Public Sign-ups") }}
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
{#
|
||||||
|
Copyright (C) 2024 I-Form.
|
||||||
|
|
||||||
|
invenio-theme-iform is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the MIT License; see LICENSE file for more details.
|
||||||
|
#}
|
||||||
|
{% extends "invenio_administration/base.html" %}
|
||||||
|
|
||||||
|
{% block admin_page_content %}
|
||||||
|
<div class="ui container dashboard rel-mt-5">
|
||||||
|
<div class="ui grid">
|
||||||
|
<div class="sixteen wide column">
|
||||||
|
<h2 class="ui header">
|
||||||
|
<i class="users icon"></i>
|
||||||
|
<div class="content">
|
||||||
|
{{ _("Role Assignment") }}
|
||||||
|
<div class="sub header">{{ _("Select a role and enable or disable it for users.") }}</div>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="ui {{ 'positive' if category == 'success' else 'negative' }} message">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
<div class="ui segment">
|
||||||
|
<form method="GET" class="ui form">
|
||||||
|
<div class="field">
|
||||||
|
<label>{{ _("Select a Role") }}</label>
|
||||||
|
<div class="ui action input">
|
||||||
|
<select name="role_id" class="ui dropdown">
|
||||||
|
<option value="">{{ _("-- Select a role --") }}</option>
|
||||||
|
{% for r in roles %}
|
||||||
|
<option value="{{ r.id }}" {% if selected_role and selected_role.id == r.id %}selected{% endif %}>
|
||||||
|
{{ r.name }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<button class="ui button primary" type="submit">{{ _("Select") }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if selected_role %}
|
||||||
|
<div class="ui segment">
|
||||||
|
<h3 class="ui header">
|
||||||
|
{{ _("Users assigned to:") }} {{ selected_role.name }}
|
||||||
|
{% if selected_role.description %}
|
||||||
|
<div class="sub header" style="margin-top: 5px;">
|
||||||
|
<i class="info circle icon"></i> {{ selected_role.description }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</h3>
|
||||||
|
<table class="ui celled striped table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ _("Email") }}</th>
|
||||||
|
<th>{{ _("Active") }}</th>
|
||||||
|
<th class="center aligned">{{ _("Has Role?") }}</th>
|
||||||
|
<th class="center aligned">{{ _("Actions") }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ user.email }}</td>
|
||||||
|
<td>
|
||||||
|
{% if user.active %}
|
||||||
|
<div class="ui green horizontal label">{{ _("Active") }}</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="ui grey horizontal label">{{ _("Inactive") }}</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{% set has_role = selected_role in user.roles %}
|
||||||
|
<td class="center aligned">
|
||||||
|
{% if has_role %}
|
||||||
|
<i class="green check large icon"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="red times large icon"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="center aligned">
|
||||||
|
<form method="POST" style="display:inline;">
|
||||||
|
<input type="hidden" name="user_id" value="{{ user.id }}">
|
||||||
|
<input type="hidden" name="role_id" value="{{ selected_role.id }}">
|
||||||
|
{% if has_role %}
|
||||||
|
<input type="hidden" name="action" value="disable">
|
||||||
|
<button class="ui tiny red button" type="submit">
|
||||||
|
<i class="minus icon"></i> {{ _("Disable") }}
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<input type="hidden" name="action" value="enable">
|
||||||
|
<button class="ui tiny green button" type="submit">
|
||||||
|
<i class="plus icon"></i> {{ _("Enable") }}
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" class="center aligned">{{ _("No users found.") }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
{#
|
||||||
|
Copyright (C) 2024 I-Form.
|
||||||
|
|
||||||
|
invenio-theme-iform is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the MIT License; see LICENSE file for more details.
|
||||||
|
#}
|
||||||
|
{% extends "invenio_administration/base.html" %}
|
||||||
|
|
||||||
|
{% block admin_page_content %}
|
||||||
|
<div class="ui container dashboard rel-mt-5">
|
||||||
|
<div class="ui grid">
|
||||||
|
<div class="sixteen wide column">
|
||||||
|
<h2 class="ui header">
|
||||||
|
<i class="user plus icon"></i>
|
||||||
|
<div class="content">
|
||||||
|
{{ _("Create User") }}
|
||||||
|
<div class="sub header">{{ _("Manually add a new user account.") }}</div>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="ui {{ 'positive' if category == 'success' else 'negative' }} message">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
<div class="ui segment">
|
||||||
|
<form method="POST" class="ui form">
|
||||||
|
<div class="field required">
|
||||||
|
<label>{{ _("Email Address") }}</label>
|
||||||
|
<input type="email" name="email" placeholder="user@example.com" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field required">
|
||||||
|
<label>{{ _("Password") }}</label>
|
||||||
|
<input type="password" name="password" placeholder="Password" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" name="confirm_email" value="true" id="confirm_email" checked>
|
||||||
|
<label for="confirm_email">{{ _("Automatically confirm email address (allow immediate login)") }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="ui button primary">
|
||||||
|
<i class="user plus icon"></i> {{ _("Create User") }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
{%- endblock head_title %}
|
{%- endblock head_title %}
|
||||||
|
|
||||||
{%- block head_links %}
|
{%- block head_links %}
|
||||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" />
|
<link rel="shortcut icon" href="{{ url_for('static', filename=config.THEME_FAVICON or 'images/iform-favicon.ico') }}" />
|
||||||
|
|
||||||
{%- if keywords %}
|
{%- if keywords %}
|
||||||
<link rel="canonical" href="{{ canonical_url }}" />
|
<link rel="canonical" href="{{ canonical_url }}" />
|
||||||
|
|||||||
@@ -108,12 +108,12 @@
|
|||||||
<a
|
<a
|
||||||
href="http://inveniosoftware.org/products/rdm"
|
href="http://inveniosoftware.org/products/rdm"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
title="invenioRDM"
|
title="InvenioRDM"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="{{ url_for('static', filename='images/inveniordm-tail.svg') }}"
|
src="{{ url_for('static', filename='images/invenio-favicon.svg') }}"
|
||||||
alt="InvenioRDM logo"
|
alt="InvenioRDM logo"
|
||||||
style="display: block; height: 90px; margin-top: 8px;"
|
style="display: block; height: 50px; margin-top: 8px;"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -122,13 +122,13 @@
|
|||||||
<div class="logos">
|
<div class="logos">
|
||||||
<strong>{{ _("Funded by") }}</strong>
|
<strong>{{ _("Funded by") }}</strong>
|
||||||
<a
|
<a
|
||||||
href="https://www.sfi.ie"
|
href="https://www.researchireland.ie"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
title="Science Foundation Ireland"
|
title="Research Ireland"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="{{ url_for('static', filename='images/SFI_logo.png') }}"
|
src="{{ url_for('static', filename='images/research-ireland-logo.svg') }}"
|
||||||
alt="Science Foundation Ireland"
|
alt="Research Ireland"
|
||||||
style="display: block; height: auto; margin-top: 15px; width: 230px;"
|
style="display: block; height: auto; margin-top: 15px; width: 230px;"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
+8
-2
@@ -55,6 +55,12 @@ invenio_theme_iform = "invenio_theme_iform.config"
|
|||||||
[project.entry-points."invenio_base.finalize_app"]
|
[project.entry-points."invenio_base.finalize_app"]
|
||||||
invenio_theme_iform = "invenio_theme_iform.ext:finalize_app"
|
invenio_theme_iform = "invenio_theme_iform.ext:finalize_app"
|
||||||
|
|
||||||
|
[project.entry-points."invenio_administration.views"]
|
||||||
|
invenio_theme_iform_roles = "invenio_theme_iform.administration.views:RoleManagementView"
|
||||||
|
invenio_theme_iform_registration_settings = "invenio_theme_iform.administration.views:RegistrationSettingsView"
|
||||||
|
invenio_theme_iform_user_create = "invenio_theme_iform.administration.views:UserCreateView"
|
||||||
|
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = [
|
||||||
"hatch>=1.14.1",
|
"hatch>=1.14.1",
|
||||||
@@ -94,12 +100,12 @@ ignore-vcs = true
|
|||||||
|
|
||||||
# Testing configuration
|
# Testing configuration
|
||||||
[tool.pytest]
|
[tool.pytest]
|
||||||
addopts = "--ruff --ruff-format --pydocstyle --doctest-glob=\"*.rst\" --doctest-modules --cov=invenio_config_iform --cov-report=term-missing tests invenio_theme_iform"
|
addopts = "--ruff --ruff-format --pydocstyle --doctest-glob=\"*.rst\" --doctest-modules --cov=invenio_theme_iform --cov-report=term-missing tests invenio_theme_iform"
|
||||||
testpaths = ["tests", "invenio_theme_iform"]
|
testpaths = ["tests", "invenio_theme_iform"]
|
||||||
live_server_scope = "module"
|
live_server_scope = "module"
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
addopts = "--ruff --ruff-format --pydocstyle --doctest-glob=\"*.rst\" --doctest-modules --cov=invenio_config_iform --cov-report=term-missing tests invenio_theme_iform"
|
addopts = "--ruff --ruff-format --pydocstyle --doctest-glob=\"*.rst\" --doctest-modules --cov=invenio_theme_iform --cov-report=term-missing tests invenio_theme_iform"
|
||||||
testpaths = ["tests", "invenio_theme_iform"]
|
testpaths = ["tests", "invenio_theme_iform"]
|
||||||
live_server_scope = "module"
|
live_server_scope = "module"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user