mirror of
https://github.com/Cian-H/invenio-theme-iform.git
synced 2025-12-23 05:01:58 +00:00
doi plugin
* feature: encrypt doi password * bugfix: add URL rule for pages
This commit is contained in:
@@ -105,22 +105,10 @@ DEPOSITS_HEADER_TEMPLATE = "invenio_theme_tugraz/header.html"
|
||||
TUG_ROUTES = {
|
||||
"index": "/",
|
||||
"comingsoon": "/comingsoon",
|
||||
"deposit_create": "/uploads/new",
|
||||
}
|
||||
|
||||
# Invenio-app-rdm
|
||||
# =============
|
||||
# See https://invenio-app-rdm.readthedocs.io/en/latest/configuration.html
|
||||
# """override the default search page"""
|
||||
# Keep this in sync
|
||||
APP_RDM_ROUTES = {
|
||||
"index": "/notvalid/notvalid/notvalid",
|
||||
"help_search": "/help/search",
|
||||
"record_search": "/search2",
|
||||
"record_detail": "/records/<pid_value>",
|
||||
"record_export": "/records/<pid_value>/export/<export_format>",
|
||||
"record_file_preview": "/records/<pid_value>/preview/<path:filename>",
|
||||
"record_file_download": "/records/<pid_value>/files/<path:filename>",
|
||||
"deposit_search": "/uploads",
|
||||
"deposit_create": "/uploads/new",
|
||||
"deposit_edit": "/uploads/<pid_value>",
|
||||
}
|
||||
INVENIO_DATACITE_URL = ""
|
||||
INVENIO_DATACITE_UNAME = ""
|
||||
INVENIO_DATACITE_PASS = "password"
|
||||
INVENIO_DATACITE_PREFIX = ""
|
||||
|
||||
88
invenio_theme_tugraz/crypto.py
Normal file
88
invenio_theme_tugraz/crypto.py
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""crypto helper module. see https://gist.github.com/marcoslin/8026990."""
|
||||
|
||||
import binascii
|
||||
|
||||
from Crypto import Random
|
||||
from Crypto.Cipher import AES
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# DEFINE Encryption Class
|
||||
class Cryptor(object):
|
||||
"""Crypto class implementation.
|
||||
|
||||
Provide encryption and decryption function that works with crypto-js.
|
||||
https://code.google.com/p/crypto-js/
|
||||
|
||||
Padding implemented as per RFC 2315: PKCS#7 page 21
|
||||
http://www.ietf.org/rfc/rfc2315.txt
|
||||
|
||||
The key to make pycrypto work with crypto-js are:
|
||||
1. Use MODE_CFB. For some reason, crypto-js decrypted result from MODE_CBC
|
||||
gets truncated
|
||||
2. Use Pkcs7 padding as per RFC 2315, the default padding used by CryptoJS
|
||||
3. On the JS side, make sure to wrap ciphertext with CryptoJS.lib.CipherParams.create()
|
||||
"""
|
||||
|
||||
# AES-256 key (32 bytes)
|
||||
KEY = "01ab38d5e05c92aa098921d9d4626107133c7e2ab0e4849558921ebcc242bcb0"
|
||||
BLOCK_SIZE = 16
|
||||
|
||||
@classmethod
|
||||
def _pad_string(cls, in_string):
|
||||
"""Pad an input string according to PKCS#7."""
|
||||
in_len = len(in_string)
|
||||
pad_size = cls.BLOCK_SIZE - (in_len % cls.BLOCK_SIZE)
|
||||
return in_string.ljust(in_len + pad_size, chr(pad_size))
|
||||
|
||||
@classmethod
|
||||
def _unpad_string(cls, in_string):
|
||||
"""Remove the PKCS#7 padding from a text string."""
|
||||
in_len = len(in_string)
|
||||
pad_size = ord(in_string[-1])
|
||||
if pad_size > cls.BLOCK_SIZE:
|
||||
raise ValueError("Input is not padded or padding is corrupt")
|
||||
return in_string[: in_len - pad_size]
|
||||
|
||||
@classmethod
|
||||
def generate_iv(cls, size=16):
|
||||
"""Generate initialization vector."""
|
||||
return Random.get_random_bytes(size)
|
||||
|
||||
@classmethod
|
||||
def encrypt(cls, in_string, in_key, in_iv=None):
|
||||
"""Return encrypted string.
|
||||
|
||||
@in_string: Simple str to be encrypted
|
||||
@key: hexified key
|
||||
@iv: hexified iv
|
||||
"""
|
||||
key = binascii.a2b_hex(in_key)
|
||||
|
||||
if in_iv is None:
|
||||
iv = cls.generate_iv()
|
||||
in_iv = binascii.b2a_hex(iv)
|
||||
else:
|
||||
iv = binascii.a2b_hex(in_iv)
|
||||
|
||||
aes = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
padded = cls._pad_string(in_string).encode("utf-8")
|
||||
encrypted = aes.encrypt(padded)
|
||||
return in_iv, encrypted
|
||||
|
||||
@classmethod
|
||||
def decrypt(cls, in_encrypted, in_key, in_iv):
|
||||
"""Return encrypted string.
|
||||
|
||||
@in_encrypted: Base64 encoded
|
||||
@key: hexified key
|
||||
@iv: hexified iv
|
||||
"""
|
||||
key = binascii.a2b_hex(in_key)
|
||||
iv = binascii.a2b_hex(in_iv)
|
||||
aes = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
|
||||
decrypted = aes.decrypt(binascii.a2b_base64(in_encrypted).rstrip())
|
||||
return cls._unpad_string(decrypted)
|
||||
@@ -9,6 +9,7 @@
|
||||
"""invenio module for TUGRAZ theme."""
|
||||
|
||||
from . import config
|
||||
from .views import deposit_create, index
|
||||
|
||||
|
||||
class InvenioThemeTugraz(object):
|
||||
@@ -21,6 +22,10 @@ class InvenioThemeTugraz(object):
|
||||
|
||||
def init_app(self, app):
|
||||
"""Flask application initialization."""
|
||||
# add index route rule
|
||||
# https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.add_url_rule
|
||||
app.add_url_rule("/", "index", index)
|
||||
app.add_url_rule("/uploads/new", "deposit_create", deposit_create)
|
||||
self.init_config(app)
|
||||
app.extensions["invenio-theme-tugraz"] = self
|
||||
|
||||
|
||||
@@ -8,12 +8,20 @@
|
||||
|
||||
"""invenio module for TUGRAZ theme."""
|
||||
|
||||
import binascii
|
||||
from typing import Dict
|
||||
|
||||
from elasticsearch_dsl.utils import AttrDict
|
||||
from flask import Blueprint, render_template
|
||||
from flask import Blueprint, current_app, render_template
|
||||
from flask_login import login_required
|
||||
from flask_menu import current_menu
|
||||
from invenio_app_rdm.records_ui.views.deposits import (
|
||||
get_form_config,
|
||||
get_search_url,
|
||||
new_record,
|
||||
)
|
||||
|
||||
from .crypto import Cryptor
|
||||
from .search import FrontpageRecordsSearch
|
||||
|
||||
|
||||
@@ -30,6 +38,7 @@ def ui_blueprint(app):
|
||||
|
||||
blueprint.add_url_rule(routes["index"], view_func=index)
|
||||
blueprint.add_url_rule(routes["comingsoon"], view_func=comingsoon)
|
||||
blueprint.add_url_rule(routes["deposit_create"], view_func=deposit_create)
|
||||
|
||||
@blueprint.app_template_filter("make_dict_like")
|
||||
def make_dict_like(value: str, key: str) -> Dict[str, str]:
|
||||
@@ -51,9 +60,42 @@ def index():
|
||||
"""Frontpage."""
|
||||
return render_template(
|
||||
"invenio_theme_tugraz/index.html",
|
||||
records=FrontpageRecordsSearch()[:5].sort("-created").execute())
|
||||
records=FrontpageRecordsSearch()[:5].sort("-created").execute(),
|
||||
)
|
||||
|
||||
|
||||
def comingsoon():
|
||||
"""Frontpage."""
|
||||
return render_template("invenio_theme_tugraz/comingsoon.html")
|
||||
|
||||
|
||||
def get_application_details():
|
||||
"""Application credentials for DOI."""
|
||||
url = current_app.config.get("invenio_datacite_url") or ""
|
||||
username = current_app.config.get("INVENIO_DATACITE_UNAME") or ""
|
||||
password = current_app.config.get("INVENIO_DATACITE_PASS") or ""
|
||||
prefix = current_app.config.get("INVENIO_DATACITE_PREFIX") or ""
|
||||
|
||||
password_iv, encrypted_password = Cryptor.encrypt(password, Cryptor.KEY)
|
||||
|
||||
details = {
|
||||
"datacite_url": url,
|
||||
"datacite_uname": username,
|
||||
"datacite_pass": binascii.b2a_base64(encrypted_password).rstrip(),
|
||||
"datacite_prefix": prefix,
|
||||
"datacite_password_iv": password_iv,
|
||||
}
|
||||
return details
|
||||
|
||||
|
||||
@login_required
|
||||
def deposit_create():
|
||||
"""Create a new deposit."""
|
||||
return render_template(
|
||||
"invenio_app_rdm/records/deposit.html",
|
||||
forms_config=get_form_config(createUrl=("/api/records")),
|
||||
datacite_config=get_application_details(),
|
||||
searchbar_config=dict(searchUrl=get_search_url()),
|
||||
record=new_record(),
|
||||
files=dict(default_preview=None, enabled=True, entries=[], links={}),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user