diff --git a/docker-compose.yml b/docker-compose.yml
index aa4cddb7bb..acb34df5a4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -455,4 +455,3 @@ volumes:
mongo_data:
# letsencrypt_etc:
# letsencrypt_html:
-
diff --git a/docker-compose2.yml b/docker-compose2.yml
index 64cbb9a4a0..95f4e36fab 100644
--- a/docker-compose2.yml
+++ b/docker-compose2.yml
@@ -455,4 +455,3 @@ volumes:
mongo_data:
# letsencrypt_etc:
# letsencrypt_html:
-
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/authorize.html b/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/authorize.html
index 921dc581b7..b4e90f95a9 100644
--- a/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/authorize.html
+++ b/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/authorize.html
@@ -3,8 +3,8 @@
This file is part of Invenio.
Copyright (C) 2015-2018 CERN.
- Invenio is free software; you can redistribute it and/or modify it
- under the terms of the MIT License; see LICENSE file for more details.
+Invenio 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.OAUTH2SERVER_COVER_TEMPLATE %}
@@ -13,54 +13,64 @@
{% block page_body %}
-
-
-{{ helpers.panel_start(_('Authorize application'), icon='fa fa-shield fa-fw') }}
-
{{ _('Authorize application') }}
-
{{ _("Application '%(client_name)s' by '%(client_user)s' wants permission to access your '%(current_user)s' account.",
- client_name=client.name, client_user=client.user.nickname or client.user.email, current_user=current_user.nickname or current_user.email) }}
-
-
-
-
+
+
+ {{ helpers.panel_start(_('Authorize application'), icon='fa fa-shield fa-fw') }}
+
{{ _('Authorize application') }}
+
{{ _("Application '%(client_name)s' by '%(client_user)s' wants permission to access your
+ '%(current_user)s' account.",
+ client_name=client.name, client_user=client.user.nickname or client.user.email,
+ current_user=current_user.nickname or current_user.email) }}
+
+
+
+
-
{{ _('Review permissions') }}
- {%- for group in scopes|groupby('group') %}
- {%- if loop.first %}
{% endif %}
-
- {{group.grouper}}
- {% for scope in group.list %}{{scope.help_text}} {% endfor %}
-
- {%- if loop.last %}
{% endif %}
- {%- else %}
-
No permissions granted.
- {%- endfor %}
-
-
-
-
-
-
{{ _('Application') }}
-
{{client.name}}
- {%- if client.description %}
{{client.description}}
{% endif %}
- {%- if client.website %}
{{ _('Visit application website') }}
{% endif %}
-
-
- {{ client.get_users }} {{ 'user' if client.get_users == 1 else 'users' }}
-
+
{{ _('Review permissions') }}
+ {%- for group in scopes|groupby('group') %}
+ {%- if loop.first %}
+ {% endif %}
+
+ {{group.grouper}}
+
+ {% for scope in group.list %}{{scope.help_text}} {% endfor %}
+
+
+ {%- if loop.last %}
+
+
{% endif %}
+ {%- else %}
+
{{ _("No permissions granted.") }}
+ {%- endfor %}
+
+
+
+
+
+
{{ _('Application') }}
+
{{client.name}}
+ {%- if client.description %}
{{client.description}}
{% endif %}
+ {%- if client.website %}
{{ _("Visit application website") }}
{%
+ endif %}
+
+
+ {{ client.get_users }} {{ 'user' if client.get_users == 1 else 'users' }}
+
+
+
+
+
+
+
+
+
+ {{ helpers.panel_end() }}
+
-
-
-
-
-
-
-
-{{ helpers.panel_end() }}
-
-
{% endblock %}
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/errors.html b/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/errors.html
index 13cea2a2d6..d2380e73ad 100644
--- a/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/errors.html
+++ b/modules/invenio-oauth2server/invenio_oauth2server/templates/invenio_oauth2server/errors.html
@@ -3,8 +3,8 @@
This file is part of Invenio.
Copyright (C) 2015-2018 CERN.
- Invenio is free software; you can redistribute it and/or modify it
- under the terms of the MIT License; see LICENSE file for more details.
+Invenio 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.OAUTH2SERVER_COVER_TEMPLATE %}
@@ -14,24 +14,36 @@
{%- block page_body %}
- {{ helpers.panel_start(
+ {{ helpers.panel_start(
_('Invalid authorization request'),
icon='fa fa-warning fa-fw'
- ) }}
-
- {{ _('Invalid authorization request') }}
-
- {{ _('The service that redirected your here made an invalid authorization request (error code: %(x_error)s).',
- x_error=error.error) }}
-
-
-
-
-
- {{ _('Get me out of here!') }}
-
+ ) }}
+
+
+ {{ _('You cannot access the service because there is an error in the authentication request.') }}
+ {% if error.error == unsupported_response_type %}
+ ({{ _('unsupported_response_type') }})
+ {% elif error.error == 'invalid_request' %}
+ {% if error.description is string and 'client_id' in error.description %}
+ ({{ _('invalid_client_id') }})
+ {% else %}
+ ({{ _('invalid_request') }})
+ {% endif %}
+ {% elif error.error == 'invalid_scope' %}
+ ({{ _('invalid_scope')}})
+ {% elif error.error == 'access_denied' %}
+ ({{ _('access_denied') }})
+ {% endif %}
+
+
+
+
+
+ {{ helpers.panel_end() }}
- {{ helpers.panel_end() }}
-
-{%- endblock %}
+ {%- endblock %}
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.mo b/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.mo
index 37cc8629ab..ddda3415eb 100644
Binary files a/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.mo and b/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.mo differ
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.po b/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.po
index 0906c42036..bd5a324cfb 100644
--- a/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.po
+++ b/modules/invenio-oauth2server/invenio_oauth2server/translations/en/LC_MESSAGES/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: invenio-oauth2server 1.0.0\n"
"Report-Msgid-Bugs-To: info@inveniosoftware.org\n"
-"POT-Creation-Date: 2025-10-03 14:53+0900\n"
+"POT-Creation-Date: 2025-12-17 12:38+0900\n"
"PO-Revision-Date: 2025-05-07 18:18+0900\n"
"Last-Translator: FULL NAME
\n"
"Language: en\n"
@@ -112,8 +112,8 @@ msgstr ""
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:18
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:19
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:58
-#: invenio_oauth2server/views/server.py:69
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:67
+#: invenio_oauth2server/views/server.py:71
msgid "Authorize application"
msgstr ""
@@ -121,41 +121,64 @@ msgstr ""
#, python-format
msgid ""
"Application '%(client_name)s' by '%(client_user)s' wants permission to "
-"access your '%(current_user)s' account."
+"access your\n"
+" '%(current_user)s' account."
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:27
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:29
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:29
msgid "Review permissions"
msgstr ""
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:43
+msgid "No permissions granted."
+msgstr ""
+
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:50
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:43
msgid "Application"
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:46
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:53
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:46
msgid "Visit application website"
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:59
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:69
msgid "Reject"
msgstr ""
#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:18
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:22
msgid "Invalid authorization request"
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:24
-#, python-format
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:23
msgid ""
-"The service that redirected your here made an invalid authorization "
-"request (error code: %(x_error)s)."
+"You cannot access the service because there is an error in the "
+"authentication request."
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:31
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:25
+msgid "unsupported_response_type"
+msgstr "error: This response type is not supported."
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:28
+msgid "invalid_client_id"
+msgstr "error: The client ID is incorrect."
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:30
+msgid "invalid_request"
+msgstr "error: The request is invalid."
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:33
+msgid "invalid_scope"
+msgstr "error: The scope is incorrect."
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:35
+msgid "access_denied"
+msgstr "error: Access has been denied."
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:43
msgid "Get me out of here!"
msgstr ""
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.mo b/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.mo
index d9eceed768..29454e17ea 100644
Binary files a/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.mo and b/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.mo differ
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.po b/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.po
index 2e6ae3943b..a5c11db316 100644
--- a/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.po
+++ b/modules/invenio-oauth2server/invenio_oauth2server/translations/ja/LC_MESSAGES/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: invenio-oauth2server 1.0.0\n"
"Report-Msgid-Bugs-To: info@inveniosoftware.org\n"
-"POT-Creation-Date: 2025-10-03 14:53+0900\n"
+"POT-Creation-Date: 2025-12-17 12:38+0900\n"
"PO-Revision-Date: 2025-05-07 18:18+0900\n"
"Last-Translator: FULL NAME \n"
"Language: ja\n"
@@ -112,50 +112,73 @@ msgstr ""
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:18
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:19
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:58
-#: invenio_oauth2server/views/server.py:69
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:67
+#: invenio_oauth2server/views/server.py:71
msgid "Authorize application"
-msgstr ""
+msgstr "アプリの使用を承諾する"
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:20
#, python-format
msgid ""
"Application '%(client_name)s' by '%(client_user)s' wants permission to "
-"access your '%(current_user)s' account."
-msgstr ""
+"access your\n"
+" '%(current_user)s' account."
+msgstr "「%(client_user)s」による「%(client_name)s」アプリケーションがあなたのアカウントへのアクセス許可を求めています。"
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:27
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:29
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:29
msgid "Review permissions"
-msgstr ""
+msgstr "権限を確認"
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:43
+msgid "No permissions granted."
+msgstr "権限が付与されていません。"
+
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:50
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:43
msgid "Application"
-msgstr ""
+msgstr "アプリケーション"
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:46
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:53
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:46
msgid "Visit application website"
-msgstr ""
+msgstr "アプリケーションのウェブサイト閲覧"
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:59
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:69
msgid "Reject"
-msgstr ""
+msgstr "拒否"
#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:18
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:22
msgid "Invalid authorization request"
-msgstr ""
+msgstr "無効な認証リクエスト"
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:24
-#, python-format
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:23
msgid ""
-"The service that redirected your here made an invalid authorization "
-"request (error code: %(x_error)s)."
-msgstr ""
+"You cannot access the service because there is an error in the "
+"authentication request."
+msgstr "認証リクエストに誤りがあるため、アクセスできません。"
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:25
+msgid "unsupported_response_type"
+msgstr "エラー: このレスポンスタイプはサポートされていません。"
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:28
+msgid "invalid_client_id"
+msgstr "エラー: クライアントIDに誤りがあります。"
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:30
+msgid "invalid_request"
+msgstr "エラー: 無効なリクエストです。"
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:33
+msgid "invalid_scope"
+msgstr "エラー: スコープに誤りがあります。"
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:35
+msgid "access_denied"
+msgstr "エラー: アクセスが拒否されました。"
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:31
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:43
msgid "Get me out of here!"
msgstr ""
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/translations/messages.pot b/modules/invenio-oauth2server/invenio_oauth2server/translations/messages.pot
index 92fb442353..2a2a8546ab 100644
--- a/modules/invenio-oauth2server/invenio_oauth2server/translations/messages.pot
+++ b/modules/invenio-oauth2server/invenio_oauth2server/translations/messages.pot
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: invenio-oauth2server 1.0.0\n"
"Report-Msgid-Bugs-To: info@inveniosoftware.org\n"
-"POT-Creation-Date: 2025-10-03 14:53+0900\n"
+"POT-Creation-Date: 2025-12-17 12:38+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -111,8 +111,8 @@ msgstr ""
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:18
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:19
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:58
-#: invenio_oauth2server/views/server.py:69
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:67
+#: invenio_oauth2server/views/server.py:71
msgid "Authorize application"
msgstr ""
@@ -120,41 +120,64 @@ msgstr ""
#, python-format
msgid ""
"Application '%(client_name)s' by '%(client_user)s' wants permission to "
-"access your '%(current_user)s' account."
+"access your\n"
+" '%(current_user)s' account."
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:27
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:29
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:29
msgid "Review permissions"
msgstr ""
#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:43
+msgid "No permissions granted."
+msgstr ""
+
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:50
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:43
msgid "Application"
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:46
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:53
#: invenio_oauth2server/templates/invenio_oauth2server/settings/token_permission_view.html:46
msgid "Visit application website"
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:59
+#: invenio_oauth2server/templates/invenio_oauth2server/authorize.html:69
msgid "Reject"
msgstr ""
#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:18
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:22
msgid "Invalid authorization request"
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:24
-#, python-format
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:23
msgid ""
-"The service that redirected your here made an invalid authorization "
-"request (error code: %(x_error)s)."
+"You cannot access the service because there is an error in the "
+"authentication request."
+msgstr ""
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:25
+msgid "unsupported_response_type"
+msgstr ""
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:28
+msgid "invalid_client_id"
+msgstr ""
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:30
+msgid "invalid_request"
+msgstr ""
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:33
+msgid "invalid_scope"
+msgstr ""
+
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:35
+msgid "access_denied"
msgstr ""
-#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:31
+#: invenio_oauth2server/templates/invenio_oauth2server/errors.html:43
msgid "Get me out of here!"
msgstr ""
diff --git a/modules/invenio-oauth2server/invenio_oauth2server/views/server.py b/modules/invenio-oauth2server/invenio_oauth2server/views/server.py
index 5e59143bb1..066c560b68 100644
--- a/modules/invenio-oauth2server/invenio_oauth2server/views/server.py
+++ b/modules/invenio-oauth2server/invenio_oauth2server/views/server.py
@@ -13,12 +13,14 @@
from functools import wraps
from flask import Blueprint, _request_ctx_stack, abort, current_app, jsonify, \
- redirect, render_template, request, session
+ redirect, render_template, request, make_response
from flask_babelex import lazy_gettext as _
from flask_breadcrumbs import register_breadcrumb
from flask_login import login_required
from flask_principal import Identity, identity_changed
-from oauthlib.oauth2.rfc6749.errors import InvalidClientError, OAuth2Error
+from oauthlib.oauth2.rfc6749.errors import InvalidClientError, OAuth2Error, \
+ AccessDeniedError, raise_from_error
+
from invenio_db import db
from ..models import Client
@@ -81,10 +83,14 @@ def authorize(*args, **kwargs):
abort(404)
scopes = current_oauth2server.scopes
+ scopes_list = [scopes[x] for x in kwargs.get('scopes', [])]
+ if not scopes_list:
+ return redirect('/oauth/errors?error=invalid_scope')
+
ctx = dict(
client=client,
oauth_request=kwargs.get('request'),
- scopes=[scopes[x] for x in kwargs.get('scopes', [])],
+ scopes=scopes_list
)
return render_template('invenio_oauth2server/authorize.html', **ctx)
@@ -120,14 +126,22 @@ def access_token():
@blueprint.route('/errors')
def errors():
"""Error view in case of invalid oauth requests."""
- from oauthlib.oauth2.rfc6749.errors import raise_from_error
+ status_code = 200
try:
error = None
- raise_from_error(request.values.get('error'), params=dict())
+ error_code = request.values.get('error')
+ description = request.values.get('error_description')
+ params = {}
+ if description:
+ params['error_description'] = description
+
+ raise_from_error(error_code, params=params)
except OAuth2Error as raised:
error = raised
- return render_template('invenio_oauth2server/errors.html', error=error)
-
+ if not isinstance(error, AccessDeniedError):
+ status_code = 400
+ response = make_response(render_template('invenio_oauth2server/errors.html', error=error), status_code)
+ return response
@blueprint.route('/ping', methods=['GET', 'POST'])
@oauth2.require_oauth()
@@ -163,10 +177,11 @@ def invalid():
@blueprint.teardown_request
def dbsession_clean(exception):
+ """Clean up the database session after each request."""
current_app.logger.debug("invenio_oauth2server dbsession_clean: {}".format(exception))
if exception is None:
try:
db.session.commit()
except:
db.session.rollback()
- db.session.remove()
\ No newline at end of file
+ db.session.remove()
diff --git a/modules/invenio-oauth2server/tests/conftest.py b/modules/invenio-oauth2server/tests/conftest.py
index 05e8fd0860..b7f35001ae 100644
--- a/modules/invenio-oauth2server/tests/conftest.py
+++ b/modules/invenio-oauth2server/tests/conftest.py
@@ -314,10 +314,20 @@ def provider_fixture(app):
'oauth2test.authorized', _external=True
),
_default_scopes='email')
+ c5 = Client(client_id='no-scopes',
+ client_secret='no-scopes',
+ name='no-scopes',
+ description='',
+ is_confidential=False,
+ user=user1,
+ _redirect_uris=url_for(
+ 'oauth2test.authorized', _external=True
+ ))
db.session.add(c1)
db.session.add(c2)
db.session.add(c3)
db.session.add(c4)
+ db.session.add(c5)
personal_token = Token.create_personal('test-personal',
user1.id,
scopes=[],
diff --git a/modules/invenio-oauth2server/tests/test_provider.py b/modules/invenio-oauth2server/tests/test_provider.py
index ab4963ffab..117d524668 100644
--- a/modules/invenio-oauth2server/tests/test_provider.py
+++ b/modules/invenio-oauth2server/tests/test_provider.py
@@ -136,7 +136,7 @@ def test_invalid_authorize_requests(provider_fixture):
assert error_url in next_url
r = client.get(next_url, query_string=data)
- assert 'invalid_request' in str(r.data)
+ assert 'an error in the authentication request' in str(r.data)
# Invalid redirect uri
r = client.get(url_for(
@@ -151,6 +151,27 @@ def test_invalid_authorize_requests(provider_fixture):
assert data['error'] == 'invalid_request'
assert error_url in next_url
+ for client_id in ['no-scopes']:
+ response_type = 'code'
+ error_url = url_for('invenio_oauth2server.errors',
+ _external=True)
+ # Missing scope
+ r = client.get(
+ url_for('invenio_oauth2server.authorize'),
+ data={
+ 'redirect_uri': redirect_uri,
+ 'response_type': response_type,
+ 'client_id': client_id,
+ })
+ next_url, data = parse_redirect(r.location)
+ assert r.status_code == 302
+ assert data['error'] == 'invalid_scope'
+ assert url_for('invenio_oauth2server.errors') in next_url
+
+ r = client.get(
+ url_for('invenio_oauth2server.errors'))
+ assert r.status_code == 400
+
def test_refresh_flow(provider_fixture):
app = provider_fixture
diff --git a/modules/weko-accounts/tests/test_views.py b/modules/weko-accounts/tests/test_views.py
index a91aa5ee1d..658ba64681 100644
--- a/modules/weko-accounts/tests/test_views.py
+++ b/modules/weko-accounts/tests/test_views.py
@@ -2,7 +2,7 @@
import pytest
import json
import redis
-from invenio_accounts.models import Role
+from invenio_accounts.models import Role, User
from flask import url_for,request,make_response,current_app,Flask
from flask_login.utils import login_user,logout_user
from flask_menu import current_menu
@@ -18,6 +18,7 @@
find_user_by_email,
shib_sp_login,
_adjust_shib_admin_DB,
+ generate_ams_login_url,
urlencode
)
from weko_admin.models import AdminSettings
@@ -26,6 +27,11 @@ def set_session(client,data):
with client.session_transaction() as session:
for k, v in data.items():
session[k] = v
+
+def del_session(client,key):
+ with client.session_transaction() as session:
+ del session[key]
+
#def _has_admin_access():
# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_has_admin_access -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
#def test_has_admin_access(request_context,users):
@@ -35,12 +41,12 @@ def set_session(client,data):
# logout_user()
# login_user(users[4]["obj"])
# result = _has_admin_access()
-# assert result == False
+# assert result is False
#def init_menu():
# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_init_menu -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_init_menu(request_context):
init_menu()
- assert current_menu.submenu("setting.admin").active == True
+ assert current_menu.submenu("setting.admin").active is True
assert current_menu.submenu("settings.admin").url == "/admin/"
assert current_menu.submenu("settings.admin").text == ' Administration'
@@ -96,6 +102,59 @@ def test_redirect_method(app,mocker):
_redirect_method(True)
mock_render.assert_called_with("http://test_server.localdomain/secure/login.py?next="+url)
+ url = 'ams'
+ with app.test_request_context(url):
+ current_app.config['WEKO_ACCOUNTS_SHIB_AMS_LOGIN_URL'] = '{}ams/login'
+ # Login is blocked.
+ mock_render = mocker.patch('weko_accounts.views.redirect',return_value=make_response())
+ ams_error = 'Login is blocked.'
+ _redirect_method(True, ams_error)
+ mock_render.assert_called_with(\
+ 'http://TEST_SERVER.localdomain/ams/login?error=Login+is+blocked.')
+ # There is no user information.
+ mock_render = mocker.patch('weko_accounts.views.redirect',return_value=make_response())
+ ams_error = 'There is no user information.'
+ _redirect_method(True, ams_error)
+ mock_render.assert_called_with(
+ 'http://TEST_SERVER.localdomain/ams/login?error=There+is+no+user+information.')
+ # server error
+ mock_render = mocker.patch('weko_accounts.views.redirect',return_value=make_response())
+ ams_error = 'Server error has occurred. Please contact server administrator.'
+ _redirect_method(True, ams_error)
+ mock_render.assert_called_with(\
+ 'http://TEST_SERVER.localdomain/ams/login?'\
+ 'error=Server+error+has+occurred.+Please+contact+server+administrator.')
+ # other error
+ mock_render = mocker.patch('weko_accounts.views.redirect',return_value=make_response())
+ ams_error = 'Error Message'
+ _redirect_method(True, ams_error)
+ mock_render.assert_called_with(\
+ 'http://TEST_SERVER.localdomain/ams/login?error=Error+Message')
+
+# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_generate_ams_login_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
+def test_generate_ams_login_url(app):
+ with app.test_request_context():
+ current_app.config['WEKO_ACCOUNTS_SHIB_AMS_LOGIN_URL'] = '{}ams/login'
+ # Missing Shib-Session-ID!
+ ams_error = 'Missing Shib-Session-ID!'
+ url = generate_ams_login_url(ams_error)
+ assert url == '/ams/login?error=Missing+Shib-Session-ID%21'
+
+ # Missing SHIB_ATTRs!
+ ams_error = 'Missing SHIB_ATTRs!'
+ url = generate_ams_login_url(ams_error)
+ assert url == '/ams/login?error=Missing+SHIB_ATTRs%21'
+
+ # Login is blocked.
+ ams_error = 'Login is blocked.'
+ url = generate_ams_login_url(ams_error)
+ assert url == '/ams/login?error=Login+is+blocked.'
+
+ # Server error has occurred. Please contact server administrator.
+ ams_error = 'Server error has occurred. Please contact server administrator.'
+ url = generate_ams_login_url(ams_error)
+ assert url == '/ams/login?error=Server+error+has+occurred.+Please+contact+server+administrator.'
+
#def index():
# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_index -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_index(client,mocker):
@@ -109,53 +168,101 @@ def test_shib_auto_login(client,redis_connect,mocker):
url = url_for("weko_accounts.shib_auto_login")
set_session(client,{"shib_session_id":None})
# not exist shib_session_id
- mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",return_value=make_response())
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
client.get(url)
mock_redirect_.assert_called_once()
+ # not exist shib_session_id(AMS)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url+"?next=ams")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing Shib-Session-ID!" in called_kwargs.get("ams_error", "")
- mocker.patch("weko_accounts.views.RedisConnection.connection",return_value=redis_connect)
# not exist cache
- mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",return_value=make_response())
+ mocker.patch("weko_accounts.views.RedisConnection.connection",
+ return_value=redis_connect)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
client.get(url+"?Shib-Session-ID=2222")
mock_redirect_.assert_called_once()
+ # not exist cache(AMS)
+ mocker.patch("weko_accounts.views.RedisConnection.connection",
+ return_value=redis_connect)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url+"?next=ams&Shib-Session-ID=2222")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_CACHE_PREFIX!" in called_kwargs.get("ams_error", "")
-
- redis_connect.put("Shib-Session-1111",bytes("","utf-8"))
# not cache_val
- mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",return_value=make_response())
+ redis_connect.put("Shib-Session-1111",bytes("","utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
client.get(url+"?Shib-Session-ID=1111")
mock_redirect_.assert_called_once()
- assert redis_connect.redis.exists("Shib-Session-1111") == False
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
+ # not cache_val(AMS)
+ redis_connect.put("Shib-Session-1111",bytes("","utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url+"?next=ams&Shib-Session-ID=1111")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_ATTR!" in called_kwargs.get("ams_error", "")
+ # is_auto_bind is false, check_in is error
mock_get_relation = mocker.patch("weko_accounts.views.ShibUser.get_relation_info")
mock_new_relation = mocker.patch("weko_accounts.views.ShibUser.new_relation_info")
mock_shib_login = mocker.patch("weko_accounts.views.ShibUser.shib_user_login")
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
- # is_auto_bind is false, check_in is error
- mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",return_value=make_response())
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
with patch("weko_accounts.views.ShibUser.check_in",return_value="test_error"):
client.get(url+"?Shib-Session-ID=1111")
mock_get_relation.assert_called_once()
mock_redirect_.assert_called_once()
- assert redis_connect.redis.exists("Shib-Session-1111") == False
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
+ # is_auto_bind is false, check_in is error(AMS)
+ mock_get_relation = mocker.patch("weko_accounts.views.ShibUser.get_relation_info")
+ mock_new_relation = mocker.patch("weko_accounts.views.ShibUser.new_relation_info")
+ mock_shib_login = mocker.patch("weko_accounts.views.ShibUser.shib_user_login")
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ with patch("weko_accounts.views.ShibUser.check_in",return_value="test_error"):
+ client.get(url+"?next=ams&Shib-Session-ID=1111")
+ mock_get_relation.assert_called_once()
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "test_error" in called_kwargs.get("ams_error", "")
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
set_session(client,{"shib_session_id":"1111"})
with patch("weko_accounts.views.ShibUser.check_in",return_value=None):
# is_auto_bind is true,shib_user is None
shibuser = ShibUser({})
shibuser.user = User(id=1)
with patch("weko_accounts.views.ShibUser",return_value=shibuser):
- mock_redirect = mocker.patch("weko_accounts.views.redirect",return_value=make_response())
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
client.get(url)
mock_new_relation.assert_called_once()
mock_shib_login.assert_not_called()
mock_redirect.assert_called_with("/")
- assert redis_connect.redis.exists("Shib-Session-1111") == False
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
# is_auto_bind is true,shib_user exis
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
@@ -165,19 +272,50 @@ def test_shib_auto_login(client,redis_connect,mocker):
shibuser.shib_user = "test_user"
shibuser.user = User(id=1)
with patch("weko_accounts.views.ShibUser",return_value=shibuser):
- mock_redirect = mocker.patch("weko_accounts.views.redirect",return_value=make_response())
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
client.get(url+'?next=/next_page')
mock_redirect.assert_called_with("/next_page")
mock_shib_login.assert_called_once()
- assert redis_connect.redis.exists("Shib-Session-1111") == False
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
+ # is_auto_bind is true,shib_user exis(AMS)
+ mock_shib_login.reset_mock()
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ set_session(client,{"shib_session_id":"1111","next":"/next_page"})
+
+ shibuser = ShibUser({})
+ shibuser.shib_user = "test_user"
+ shibuser.user = User(id=1)
+ with patch("weko_accounts.views.ShibUser",return_value=shibuser):
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
+ client.get(url+'?next=ams')
+ called_args, _ = mock_redirect.call_args
+ mock_redirect.assert_called_with("/?next=ams")
+ mock_shib_login.assert_called_once()
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
# raise BaseException
with patch("weko_accounts.views.RedisConnection",side_effect=BaseException("test_error")):
res = client.get(url+"?Shib-Session-ID=1111")
assert res.status_code == 400
+
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ with patch("weko_accounts.views.RedisConnection",side_effect=BaseException("test_error")):
+ res = client.get(url+"?next=ams&Shib-Session-ID=1111")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Server error has occurred. Please contact server " \
+ "administrator." in called_kwargs.get("ams_error", "")
+
#def confirm_user():
# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_confirm_user -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_confirm_user(client,redis_connect,mocker):
- mocker.patch("weko_accounts.views.RedisConnection.connection",return_value=redis_connect)
+ mocker.patch("weko_accounts.views.RedisConnection.connection",
+ return_value=redis_connect)
mocker.patch("weko_accounts.views.ShibUser.shib_user_login")
url = url_for("weko_accounts.confirm_user")
@@ -188,19 +326,53 @@ def test_confirm_user(client,redis_connect,mocker):
client.post(url,data=form)
mock_flash.assert_called_with("csrf_random",category="error")
+ # not correct csrf_random(AMS)
+ form = {"csrf_random":"test_csrf"}
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ set_session(client,{"next": "ams"})
+ client.post(url, data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "csrf_random" in called_kwargs.get("ams_error", "")
+
# not exist shib_session_id
set_session(client,{"csrf_random":"test_csrf","shib_session_id":None})
+ del_session(client, "next")
mock_flash = mocker.patch("weko_accounts.views.flash")
client.post(url,data=form)
mock_flash.assert_called_with("shib_session_id",category="error")
+ # not exist shib_session_id(AMS)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ set_session(client,{"next": "ams"})
+ client.post(url, data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing Shib-Session-ID!" in called_kwargs.get("ams_error", "")
+
# not exist cache_key
set_session(client,{"csrf_random":"test_csrf","shib_session_id":"2222"})
+ del_session(client, "next")
mock_flash = mocker.patch("weko_accounts.views.flash")
client.post(url,data=form)
mock_flash.assert_called_with("cache_key",category="error")
+ # not exist cache_key(AMS)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ set_session(client,{"next": "ams"})
+ client.post(url, data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_CACHE_PREFIX!" in called_kwargs.get("ams_error", "")
+
set_session(client,{"csrf_random":"test_csrf","shib_session_id":"1111"})
+ del_session(client, "next")
# not exist cache_value
redis_connect.put("Shib-Session-1111",bytes("","utf-8"))
mock_flash = mocker.patch("weko_accounts.views.flash")
@@ -208,20 +380,45 @@ def test_confirm_user(client,redis_connect,mocker):
mock_flash.assert_called_with("cache_val",category="error")
assert redis_connect.redis.exists("Shib-Session-1111") is False
+ # not exist cache_value(AMS)
+ redis_connect.put("Shib-Session-1111",bytes("","utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ set_session(client,{"next": "ams"})
+ client.post(url, data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_ATTR!" in called_kwargs.get("ams_error", "")
+
# shib_user.check_weko_user is false
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
with patch("weko_accounts.views.ShibUser.check_weko_user",return_value=False):
mock_flash = mocker.patch("weko_accounts.views.flash")
+ del_session(client, "next")
client.post(url,data=form)
mock_flash.assert_called_with("check_weko_user",category="error")
assert redis_connect.redis.exists("Shib-Session-1111") is False
+ # shib_user.check_weko_user is false(AMS)
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ with patch("weko_accounts.views.ShibUser.check_weko_user",return_value=False):
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ set_session(client, {"next": "ams"})
+ client.post(url,data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "There is no user information." in called_kwargs.get("ams_error", "")
+
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
with patch("weko_accounts.views.ShibUser.check_weko_user",return_value=True):
# shib_user.bind_relation_info is false
with patch("weko_accounts.views.ShibUser.bind_relation_info",return_value=False):
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
mock_flash = mocker.patch("weko_accounts.views.flash")
+ del_session(client, "next")
client.post(url,data=form)
mock_flash.assert_called_with("FAILED bind_relation_info!",category="error")
with patch("weko_accounts.views.ShibUser.bind_relation_info",return_value=True):
@@ -236,35 +433,87 @@ def test_confirm_user(client,redis_connect,mocker):
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
shibuser = ShibUser({})
shibuser.user = User(id=1)
- with patch("weko_accounts.views.ShibUser",return_value=shibuser):
- mock_redirect = mocker.patch("weko_accounts.views.redirect",return_value=make_response())
+ with patch("weko_accounts.views.ShibUser",
+ return_value=shibuser):
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
client.post(url,data=form)
mock_redirect.assert_called_with("/")
assert redis_connect.redis.exists("Shib-Session-1111") is False
- # exist ShibUser.shib_user
- set_session(client,{"csrf_random":"test_csrf","shib_session_id":"1111","next":"/next_page"})
- redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
-
+ # exist ShibUser.shib_user
+ set_session(client,{"csrf_random":"test_csrf",
+ "shib_session_id":"1111","next":"/next_page"})
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
shibuser = ShibUser({})
shibuser.shib_user = "test_user"
shibuser.user = User(id=1)
with patch("weko_accounts.views.ShibUser",return_value=shibuser):
- mock_redirect = mocker.patch("weko_accounts.views.redirect",return_value=make_response())
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
mock_flash = mocker.patch("weko_accounts.views.flash")
client.post(url,data=form)
mock_redirect.assert_called_with("/next_page")
assert redis_connect.redis.exists("Shib-Session-1111") is False
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ with patch("weko_accounts.views.ShibUser.check_weko_user",return_value=True):
+ # shib_user.bind_relation_info is false
+ with patch("weko_accounts.views.ShibUser.bind_relation_info",return_value=False):
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ set_session(client, {"next": "ams"})
+ client.post(url,data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "FAILED bind_relation_info!" in called_kwargs.get("ams_error", "")
+ with patch("weko_accounts.views.ShibUser.bind_relation_info",return_value=True):
+ # ShibUser.check_in is error
+ with patch("weko_accounts.views.ShibUser.check_in",return_value="test_error"):
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.post(url,data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "test_error" in called_kwargs.get("ams_error", "")
+ with patch("weko_accounts.views.ShibUser.check_in",return_value=None):
+ # ShibUser.shib_user is None,not exist next in session
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ shibuser = ShibUser({})
+ shibuser.user = User(id=1)
+ with patch("weko_accounts.views.ShibUser",return_value=shibuser):
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
+ client.post(url,data=form)
+ called_args, _ = mock_redirect.call_args
+ mock_redirect.assert_called_with("/?next=ams")
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
# raise BaseException
with patch("weko_accounts.views._redirect_method",side_effect=BaseException("test_error")):
+ del_session(client, "next")
res = client.post(url,data=form)
assert res.status_code == 400
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ with patch("weko_accounts.views.RedisConnection",side_effect=BaseException("test_error")):
+ set_session(client, {"next": "ams"})
+ res = client.post(url,data=form)
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Server error has occurred. Please contact server " \
+ "administrator." in called_kwargs.get("ams_error", "")
+
#def confirm_user_without_page():
# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_confirm_user_without_page -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_confirm_user_without_page(client,redis_connect,mocker):
- mocker.patch("weko_accounts.views.RedisConnection.connection",return_value=redis_connect)
+ mocker.patch("weko_accounts.views.RedisConnection.connection",
+ return_value=redis_connect)
mocker.patch("weko_accounts.views.ShibUser.shib_user_login")
url = url_for("weko_accounts.confirm_user_without_page")
@@ -273,11 +522,29 @@ def test_confirm_user_without_page(client,redis_connect,mocker):
client.get(url, query_string={"Shib-Session-ID":None})
mock_flash.assert_called_with("shib_session_id",category="error")
+ # not exist shib_session_id(AMS)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url+"?next=ams")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing Shib-Session-ID!" in called_kwargs.get("ams_error", "")
+
# not exist cache_key
mock_flash = mocker.patch("weko_accounts.views.flash")
client.get(url, query_string={"Shib-Session-ID":"2222"})
mock_flash.assert_called_with("cache_key",category="error")
+ # not exist cache_key(AMS)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"2222"})
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_CACHE_PREFIX!" in called_kwargs.get("ams_error", "")
+
# not exist cache_value
redis_connect.put("Shib-Session-1111",bytes("","utf-8"))
mock_flash = mocker.patch("weko_accounts.views.flash")
@@ -285,6 +552,16 @@ def test_confirm_user_without_page(client,redis_connect,mocker):
mock_flash.assert_called_with("cache_val",category="error")
assert redis_connect.redis.exists("Shib-Session-1111") is False
+ # not exist cache_value(AMS)
+ redis_connect.put("Shib-Session-1111",bytes("","utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"1111"})
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_ATTR!" in called_kwargs.get("ams_error", "")
+
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
with patch("weko_accounts.views.ShibUser.check_weko_user",return_value=True):
# shib_user.bind_relation_info is false
@@ -305,7 +582,8 @@ def test_confirm_user_without_page(client,redis_connect,mocker):
with patch("weko_accounts.views.ShibUser.check_in",return_value=None):
# ShibUser.shib_user is None,not exist next in session
redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
- mock_redirect = mocker.patch("weko_accounts.views.redirect",return_value=make_response())
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
client.get(url, query_string={"Shib-Session-ID":"1111"})
mock_redirect.assert_called_with("/")
assert redis_connect.redis.exists("Shib-Session-1111") is False
@@ -316,7 +594,8 @@ def test_confirm_user_without_page(client,redis_connect,mocker):
shibuser = ShibUser({})
shibuser.shib_user = "test_user"
with patch("weko_accounts.views.ShibUser",return_value=shibuser):
- mock_redirect = mocker.patch("weko_accounts.views.redirect",return_value=make_response())
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
mock_flash = mocker.patch("weko_accounts.views.flash")
client.get(url, query_string={"Shib-Session-ID":"1111"})
mock_redirect.assert_called_with("/")
@@ -328,22 +607,96 @@ def test_confirm_user_without_page(client,redis_connect,mocker):
shibuser = ShibUser({})
shibuser.shib_user = "test_user"
with patch("weko_accounts.views.ShibUser",return_value=shibuser):
- mock_redirect = mocker.patch("weko_accounts.views.redirect",return_value=make_response())
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
mock_flash = mocker.patch("weko_accounts.views.flash")
client.get(url, query_string={"Shib-Session-ID":"1111","next":"/next_page"})
mock_redirect.assert_called_with("/next_page")
assert redis_connect.redis.exists("Shib-Session-1111") is False
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ with patch("weko_accounts.views.ShibUser.check_weko_user",return_value=True):
+ # shib_user.bind_relation_info is false
+ with patch("weko_accounts.views.ShibUser.bind_relation_info",return_value=False):
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"1111"})
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "FAILED bind_relation_info!" in called_kwargs.get("ams_error", "")
+ with patch("weko_accounts.views.ShibUser.bind_relation_info",return_value=True):
+ # ShibUser.check_in is error
+ with patch("weko_accounts.views.ShibUser.check_in",return_value="test_error"):
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"1111"})
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "test_error" in called_kwargs.get("ams_error", "")
+ with patch("weko_accounts.views.ShibUser.check_in",return_value=None):
+ # ShibUser.shib_user is None,not exist next in session
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ shibuser = ShibUser({})
+ shibuser.user = User(id=1)
+ with patch("weko_accounts.views.ShibUser",return_value=shibuser):
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"1111"})
+ called_args, _ = mock_redirect.call_args
+ mock_redirect.assert_called_with("/?next=ams")
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
+ # exist ShibUser.shib_user
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+
+ shibuser = ShibUser({})
+ shibuser.shib_user = "test_user"
+ shibuser.user = User(id=1)
+ with patch("weko_accounts.views.ShibUser",return_value=shibuser):
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"1111"})
+ called_args, _ = mock_redirect.call_args
+ mock_redirect.assert_called_with("/?next=ams")
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
+ # exist ShibUser.shib_user
+ redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn"}',"utf-8"))
+ shibuser = ShibUser({})
+ shibuser.shib_user = "test_user"
+ shibuser.user = User(id=1)
+ with patch("weko_accounts.views.ShibUser",return_value=shibuser):
+ mock_redirect = mocker.patch("weko_accounts.views.redirect",
+ return_value=make_response())
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"1111"})
+ called_args, _ = mock_redirect.call_args
+ mock_redirect.assert_called_with("/?next=ams")
+ assert redis_connect.redis.exists("Shib-Session-1111") is False
+
# raise BaseException
with patch("weko_accounts.views._redirect_method",side_effect=BaseException("test_error")):
res = client.get(url)
assert res.status_code == 400
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ with patch("weko_accounts.views.RedisConnection",side_effect=BaseException("test_error")):
+ client.get(url, query_string={"next":"ams","Shib-Session-ID":"1111"})
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Server error has occurred. Please contact server " \
+ "administrator." in called_kwargs.get("ams_error", "")
#def shib_login():
# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_shib_login -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_shib_login(client,redis_connect,users,mocker):
- mocker.patch("weko_accounts.views.RedisConnection.connection",return_value=redis_connect)
+ mocker.patch("weko_accounts.views.RedisConnection.connection",
+ return_value=redis_connect)
mocker.patch("weko_accounts.views.generate_random_str",return_value="asdfghjkl")
url_base = url_for("weko_accounts.shib_login")
@@ -352,13 +705,32 @@ def test_shib_login(client,redis_connect,users,mocker):
client.get(url_base)
mock_flash.assert_called_with("Missing Shib-Session-ID!",category="error")
- url = url_base+"?Shib-Session-ID=2222"
+ # not shib_session_id(AMS)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url_base+"?next=ams")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing Shib-Session-ID!" in called_kwargs.get("ams_error", "")
+ url = url_base+"?Shib-Session-ID=2222"
# not exist cache_key
mock_flash = mocker.patch("weko_accounts.views.flash")
client.get(url)
mock_flash.assert_called_with("Missing SHIB_CACHE_PREFIX!",category="error")
+ # not exist cache_key(AMS)
+ mocker.patch("weko_accounts.views.RedisConnection.connection",
+ return_value=redis_connect)
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url+"&next=ams")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_CACHE_PREFIX!" in called_kwargs.get("ams_error", "")
+
url = url_base+"?Shib-Session-ID=1111"
# not cache_val
redis_connect.put("Shib-Session-1111",bytes('',"utf-8"))
@@ -367,23 +739,50 @@ def test_shib_login(client,redis_connect,users,mocker):
mock_flash.assert_called_with("Missing SHIB_ATTR!",category="error")
assert redis_connect.redis.exists("Shib-Session-1111") is False
+ # not cache_val(AMS)
+ redis_connect.put("Shib-Session-1111",bytes('',"utf-8"))
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ client.get(url+"&next=ams")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Missing SHIB_ATTR!" in called_kwargs.get("ams_error", "")
+
# exist user
- redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn","shib_mail":"user@test.org"}',"utf-8"))
- mock_render = mocker.patch("weko_accounts.views.render_template",return_value=make_response())
+ redis_connect.put("Shib-Session-1111",
+ bytes('{"shib_eppn":"test_eppn","shib_mail":"user@test.org"}',"utf-8"))
+ mock_render = mocker.patch("weko_accounts.views.render_template",
+ return_value=make_response())
client.get(url)
- mock_render.assert_called_with('weko_accounts/confirm_user.html',csrf_random="asdfghjkl",email="user@test.org")
+ mock_render.assert_called_with('weko_accounts/confirm_user.html',
+ csrf_random="asdfghjkl",email="user@test.org")
# not exist user
- redis_connect.put("Shib-Session-1111",bytes('{"shib_eppn":"test_eppn","shib_mail":"not_exist_user@test.org"}',"utf-8"))
- mock_render = mocker.patch("weko_accounts.views.render_template",return_value=make_response())
+ redis_connect.put("Shib-Session-1111",
+ bytes('{"shib_eppn":"test_eppn",' \
+ '"shib_mail":"not_exist_user@test.org"}',"utf-8"))
+ mock_render = mocker.patch("weko_accounts.views.render_template",
+ return_value=make_response())
client.get(url)
- mock_render.assert_called_with('weko_accounts/confirm_user.html',csrf_random="asdfghjkl",email="")
+ mock_render.assert_called_with('weko_accounts/confirm_user.html',
+ csrf_random="asdfghjkl",email="")
# raise BaseException
with patch("weko_accounts.views.flash",side_effect=BaseException("test_error")):
res = client.get(url_base)
assert res.status_code == 400
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+ with patch("weko_accounts.views.RedisConnection",side_effect=BaseException("test_error")):
+ res = client.get(url_base+"?Shib-Session-ID=1111&next=ams")
+ mock_redirect_.assert_called_once()
+ called_args, called_kwargs = mock_redirect_.call_args
+ assert called_args[0] is True
+ assert "Server error has occurred. Please contact server " \
+ "administrator." in called_kwargs.get("ams_error", "")
+
#def shib_sp_login():
# .tox/c1/bin/pytest --cov=weko_accounts tests/test_views.py::test_shib_sp_login -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_shib_sp_login(client, redis_connect,mocker, db, users):
@@ -397,6 +796,14 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
mock_flash.assert_called_with("Missing Shib-Session-ID!",category="error")
mock_redirect.assert_called_with(url_for("security.login"))
+ # not shib_session_id(AMS)
+ mock_generate_ams_login_url = mocker.patch("weko_accounts.views.generate_ams_login_url",
+ return_value=make_response())
+ client.post(url+"?next=ams")
+ mock_generate_ams_login_url.assert_called_once()
+ called_args, _ = mock_generate_ams_login_url.call_args
+ assert "Missing Shib-Session-ID!" in called_args[0]
+
current_app.config.update(
WEKO_ACCOUNTS_SHIB_LOGIN_ENABLED=True
)
@@ -410,6 +817,15 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
client.post(url,data=form)
mock_flash.assert_called_with("Missing SHIB_ATTRs!",category="error")
+ # parse_attribute is error(AMS)
+ with patch("weko_accounts.views.parse_attributes",return_value=("attr",True)):
+ mock_generate_ams_login_url = mocker.patch("weko_accounts.views.generate_ams_login_url",
+ return_value=make_response())
+ client.post(url+"?next=ams",data=form)
+ mock_generate_ams_login_url.assert_called_once()
+ called_args, _ = mock_generate_ams_login_url.call_args
+ assert "Missing SHIB_ATTRs!" in called_args[0]
+
# Check if shib_eppn is not included in the blocked user list
try:
db.session.add(AdminSettings(
@@ -418,7 +834,7 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
settings='{"blocked_ePPNs": ["ePPN1", "ePPN2", "ePPN3", "ePPN5", "ePPP*"]}'
))
db.session.commit()
- except Exception as e:
+ except Exception:
db.session.rollback()
raise
finally:
@@ -432,7 +848,16 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
}
client.post(url,data=form)
mock_flash.assert_called_with("Failed to login.",category="error")
- mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",return_value=make_response())
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
+
+ # Match with blocked user(AMS)
+ mock_generate_ams_login_url = mocker.patch("weko_accounts.views.generate_ams_login_url",
+ return_value=make_response())
+ client.post(url+"?next=ams",data=form)
+ mock_generate_ams_login_url.assert_called_once()
+ called_args, _ = mock_generate_ams_login_url.call_args
+ assert "Login is blocked." in called_args[0]
# Match found with a blocked user from the wildcard
mock_flash = mocker.patch("weko_accounts.views.flash")
@@ -442,7 +867,14 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
}
client.post(url,data=form)
mock_flash.assert_called_with("Failed to login.",category="error")
- mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",return_value=make_response())
+
+ # Match found with a blocked user from the wildcard(AMS)
+ mock_generate_ams_login_url = mocker.patch("weko_accounts.views.generate_ams_login_url",
+ return_value=make_response())
+ client.post(url+"?next=ams",data=form)
+ mock_generate_ams_login_url.assert_called_once()
+ called_args, _ = mock_generate_ams_login_url.call_args
+ assert "Login is blocked." in called_args[0]
# Not a blocked user
form = {
@@ -450,17 +882,24 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
"eppn":"test_eppn"
}
+ mock_redirect_ = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
# WEKO_ACCOUNTS_SHIB_BIND_GAKUNIN_MAP_GROUPSがTrueの場合のテスト
current_app.config.update(
WEKO_ACCOUNTS_SHIB_BIND_GAKUNIN_MAP_GROUPS=True
)
- mock_sync_shib_gakunin_map_groups = mocker.patch("weko_accounts.views.sync_shib_gakunin_map_groups", return_value=None)
+ mock_sync_shib_gakunin_map_groups = \
+ mocker.patch("weko_accounts.views.sync_shib_gakunin_map_groups",
+ return_value=None)
client.post(url, data=form)
mock_sync_shib_gakunin_map_groups.assert_called_once()
# sync_shib_gakunin_map_groupsが例外をスローする場合のテスト
- mock_sync_shib_gakunin_map_groups = mocker.patch("weko_accounts.views.sync_shib_gakunin_map_groups", side_effect=Exception("test_exception"))
- mock_redirect_method = mocker.patch("weko_accounts.views._redirect_method", return_value=make_response())
+ mock_sync_shib_gakunin_map_groups = mocker.patch(
+ "weko_accounts.views.sync_shib_gakunin_map_groups",
+ side_effect=Exception("test_exception"))
+ mock_redirect_method = mocker.patch("weko_accounts.views._redirect_method",
+ return_value=make_response())
res = client.post(url, data=form)
mock_redirect_method.assert_called_once()
assert res.status_code == 200 # _redirect_methodが呼び出されることを確認
@@ -474,22 +913,61 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
mock_sync_shib_gakunin_map_groups.assert_not_called()
# shib_user.get_relation_info is None
- with patch("weko_accounts.views.ShibUser.get_relation_info",return_value=None)\
- and patch("weko_accounts.views.redirect",return_value=make_response()):
+ with patch("weko_accounts.views.ShibUser.get_relation_info",
+ return_value=None)\
+ and patch("weko_accounts.views.redirect",
+ return_value=make_response()):
res = client.post(url,data=form)
assert res.status_code == 200
assert res.data.decode() == "/weko/shib/login?Shib-Session-ID=1111&next=%2F"
with client.session_transaction() as session:
assert 'shib_session_id' not in session
# shib_user.get_relation_info is not None
- with patch("weko_accounts.views.ShibUser.get_relation_info",return_value="chib_user")\
- and patch("weko_accounts.views.redirect",return_value=make_response()):
+ with patch("weko_accounts.views.ShibUser.get_relation_info",
+ return_value="chib_user")\
+ and patch("weko_accounts.views.redirect",
+ return_value=make_response()):
+ res = client.post(url,data=form)
+ assert res.status_code == 200
+ assert res.data.decode() == "/weko/shib/login?Shib-Session-ID=1111&next=%2F"
+ with client.session_transaction() as session:
+ assert 'shib_session_id' not in session
+
+ # test without blocked_user_settings
+ AdminSettings.query.filter_by(id=11).delete()
+ db.session.commit()
+ with patch("weko_accounts.views.ShibUser.get_relation_info",
+ return_value=None)\
+ and patch("weko_accounts.views.redirect",
+ return_value=make_response()):
res = client.post(url,data=form)
assert res.status_code == 200
assert res.data.decode() == "/weko/shib/login?Shib-Session-ID=1111&next=%2F"
with client.session_transaction() as session:
assert 'shib_session_id' not in session
+ # test with blocked_user_setting dict
+ db.session.add(AdminSettings(
+ id=11,
+ name="blocked_user_settings",
+ settings={"blocked_ePPNs": ["ePPN1", "ePPN2", "ePPN3", "ePPN5", "ePPP*"]}
+ ))
+ db.session.commit()
+ mock_flash = mocker.patch("weko_accounts.views.flash")
+ form_blocked = {
+ "Shib-Session-ID":"1111",
+ "eppn":"ePPN3"
+ }
+ client.post(url,data=form_blocked)
+ mock_flash.assert_called_with("Failed to login.",category="error")
+ AdminSettings.query.filter_by(id=11).delete()
+ db.session.add(AdminSettings(
+ id=11,
+ name="blocked_user_settings",
+ settings='{"blocked_ePPNs": ["ePPN1", "ePPN2", "ePPN3", "ePPN5", "ePPP*"]}'
+ ))
+ db.session.commit()
+
current_app.config.update(
WEKO_ACCOUNTS_SHIB_LOGIN_ENABLED=True,
WEKO_ACCOUNTS_SKIP_CONFIRMATION_PAGE=True
@@ -522,10 +1000,25 @@ def test_shib_sp_login(client, redis_connect,mocker, db, users):
# raise BaseException
with patch("weko_accounts.views.flash",side_effect=BaseException("test_error"))\
- and patch("weko_accounts.views._redirect_method",return_value=make_response()) as mock_redirect_:
+ and patch("weko_accounts.views._redirect_method",
+ return_value=make_response()) as mock_redirect_:
res = client.post(url,data={})
mock_redirect_.assert_called_once()
+ # raise BaseException(AMS)
+ mock_generate_ams_login_url = mocker.patch("weko_accounts.views.generate_ams_login_url",
+ return_value=make_response())
+ with patch("weko_accounts.views.RedisConnection",side_effect=BaseException("test_error")):
+ form = {
+ "Shib-Session-ID":"1111",
+ "eppn":"test_eppn"
+ }
+ res = client.post(url+"?next=ams",data=form)
+ mock_generate_ams_login_url.assert_called_once()
+ called_args, _ = mock_generate_ams_login_url.call_args
+ assert "Server error has occurred. Please contact server " \
+ "administrator." in called_args[0]
+
# all attributes have value and some shibboleth_user records don't have target eppn
current_app.config.update(
WEKO_ACCOUNTS_SHIB_LOGIN_ENABLED=True,
@@ -737,7 +1230,8 @@ def test_shib_stub_login(client,mocker):
WEKO_ACCOUNTS_SHIB_IDP_LOGIN_ENABLED=False
)
# WEKO_ACCOUNTS_SHIB_IDP_LOGIN_ENABLED is true
- mock_render_template = mocker.patch("weko_accounts.views.render_template",return_value=make_response())
+ mock_render_template = mocker.patch("weko_accounts.views.render_template",
+ return_value=make_response())
res = client.get(url)
mock_render_template.assert_called_with(
'weko_accounts/login_shibuser_pattern_1.html',
diff --git a/modules/weko-accounts/weko_accounts/config.py b/modules/weko-accounts/weko_accounts/config.py
index 069f93dc57..4805604d67 100644
--- a/modules/weko-accounts/weko_accounts/config.py
+++ b/modules/weko-accounts/weko_accounts/config.py
@@ -65,6 +65,8 @@
WEKO_ACCOUNTS_SHIB_IDP_LOGIN_URL = '{}secure/login.py'
"""Login proxy URL."""
+WEKO_ACCOUNTS_SHIB_AMS_LOGIN_URL = '{}ams/login'
+
WEKO_ACCOUNTS_SSO_ATTRIBUTE_MAP = {
'SHIB_ATTR_EPPN': (False, 'shib_eppn'),
# 'SHIB_ATTR_LOGIN_ID': (False, 'shib_uid'),
@@ -264,4 +266,4 @@
"""Disable user registration via WEKO-Accounts."""
SECURITY_RECOVERABLE = False
-"""Disable password recovery via WEKO-Accounts."""
\ No newline at end of file
+"""Disable password recovery via WEKO-Accounts."""
diff --git a/modules/weko-accounts/weko_accounts/views.py b/modules/weko-accounts/weko_accounts/views.py
index a26e313928..23247701fa 100644
--- a/modules/weko-accounts/weko_accounts/views.py
+++ b/modules/weko-accounts/weko_accounts/views.py
@@ -143,7 +143,7 @@ def _adjust_shib_admin_DB():
db.session.commit()
-def _redirect_method(has_next=False):
+def _redirect_method(has_next=False, ams_error=None):
"""Redirect method for instance login to IdP."""
shib_login = current_app.config['WEKO_ACCOUNTS_SHIB_LOGIN_ENABLED']
shib_login_url = current_app.config['WEKO_ACCOUNTS_SHIB_IDP_LOGIN_URL']
@@ -151,7 +151,13 @@ def _redirect_method(has_next=False):
idp_login_inst = current_app.config[
'WEKO_ACCOUNTS_SHIB_INST_LOGIN_DIRECTLY_ENABLED']
- if shib_login and idp_login and idp_login_inst:
+ if ams_error:
+ shib_ams_login_url = current_app.config['WEKO_ACCOUNTS_SHIB_AMS_LOGIN_URL']
+ ams_url = shib_ams_login_url.format(request.url_root)
+ encoded_error = quote_plus(str(ams_error), encoding='utf-8', errors='replace')
+ url = f'{ams_url}?error={encoded_error}'
+ return redirect(url)
+ elif shib_login and idp_login and idp_login_inst:
url = shib_login_url.format(request.url_root)
if has_next:
url += '?next=' + request.full_path
@@ -162,6 +168,28 @@ def _redirect_method(has_next=False):
next=request.full_path if has_next else None))
+def generate_ams_login_url(ams_error):
+ """
+ Generate a redirect URL for the AMS login page with error details.
+
+ The returned URL starts with a '/'.
+
+ Args:
+ ams_error (str): Error message for the AMS login page to include
+ in the redirect URL.
+
+ Returns:
+ str: URL for the AMS login page including the error
+ information as a query parameter.
+ """
+ shib_ams_login_url = current_app.config['WEKO_ACCOUNTS_SHIB_AMS_LOGIN_URL']
+ ams_url = shib_ams_login_url.format('/')
+ encoded_error = quote_plus(
+ str(ams_error), encoding='utf-8', errors='replace')
+ url = f'{ams_url}?error={encoded_error}'
+ return url
+
+
@blueprint.route('/')
def index():
"""Render a basic view."""
@@ -176,29 +204,42 @@ def shib_auto_login():
:return: next url
"""
+ ams_login = False
try:
is_auto_bind = False
shib_session_id = request.args.get('Shib-Session-ID', None)
- session['next'] = request.args.get('next', '/')
-
+ next_value = request.args.get('next')
+ if next_value != 'ams':
+ next_value = session.get('next', '/')
+ session['next'] = next_value
+ ams_login = next_value == 'ams'
if not shib_session_id:
shib_session_id = session['shib_session_id']
is_auto_bind = True
if not shib_session_id:
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing Shib-Session-ID!'))
+ else:
+ return _redirect_method()
redis_connection = RedisConnection()
datastore = redis_connection.connection(db=current_app.config['CACHE_REDIS_DB'], kv = True)
cache_key = current_app.config[
'WEKO_ACCOUNTS_SHIB_CACHE_PREFIX'] + shib_session_id
if not datastore.redis.exists(cache_key):
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_CACHE_PREFIX!'))
+ else:
+ return _redirect_method()
cache_val = datastore.get(cache_key)
if not cache_val:
datastore.delete(cache_key)
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_ATTR!'))
+ else:
+ return _redirect_method()
cache_val = json.loads(str(cache_val, encoding='utf-8'))
shib_user = ShibUser(cache_val)
@@ -212,8 +253,11 @@ def shib_auto_login():
if error:
datastore.delete(cache_key)
current_app.logger.error(error)
- flash(error, category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=error)
+ else:
+ flash(error, category='error')
+ return _redirect_method()
if shib_user.shib_user:
shib_user.shib_user_login()
@@ -225,7 +269,10 @@ def shib_auto_login():
target_key=shib_user.user.id,
remarks="Shibboleth login"
)
- return redirect(session['next'] if 'next' in session else '/')
+ if ams_login:
+ return redirect('/?next=ams')
+ else:
+ return redirect(session['next'] if 'next' in session else '/')
except BaseException:
db.session.rollback()
current_app.logger.error("Unexpected error: {}".format(sys.exc_info()))
@@ -235,6 +282,9 @@ def shib_auto_login():
operation="LOGIN",
remarks=tb_info[0]
)
+ if ams_login:
+ return _redirect_method(True, ams_error=_(
+ 'Server error has occurred. Please contact server administrator.'))
return abort(400)
@@ -244,15 +294,25 @@ def confirm_user():
:return:
"""
+ ams_login = False
try:
+ next_value = session['next'] if 'next' in session else ''
+ if next_value == 'ams':
+ ams_login = True
if request.form.get('csrf_random', '') != session['csrf_random']:
- flash('csrf_random', category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('csrf_random'))
+ else:
+ flash('csrf_random', category='error')
+ return _redirect_method()
shib_session_id = session['shib_session_id']
if not shib_session_id:
- flash('shib_session_id', category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing Shib-Session-ID!'))
+ else:
+ flash('shib_session_id', category='error')
+ return _redirect_method()
redis_connection = RedisConnection()
datastore = redis_connection.connection(db=current_app.config['CACHE_REDIS_DB'], kv = True)
@@ -260,34 +320,49 @@ def confirm_user():
'WEKO_ACCOUNTS_SHIB_CACHE_PREFIX'] + shib_session_id
if not datastore.redis.exists(cache_key):
- flash('cache_key', category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_CACHE_PREFIX!'))
+ else:
+ flash('cache_key', category='error')
+ return _redirect_method()
cache_val = datastore.get(cache_key)
if not cache_val:
- flash('cache_val', category='error')
- datastore.delete(cache_key)
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_ATTR!'))
+ else:
+ flash('cache_val', category='error')
+ datastore.delete(cache_key)
+ return _redirect_method()
cache_val = json.loads(str(cache_val, encoding='utf-8'))
shib_user = ShibUser(cache_val)
account = request.form.get('WEKO_ATTR_ACCOUNT', None)
password = request.form.get('WEKO_ATTR_PWD', None)
if not shib_user.check_weko_user(account, password):
- flash('check_weko_user', category='error')
- datastore.delete(cache_key)
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('There is no user information.'))
+ else:
+ flash('check_weko_user', category='error')
+ datastore.delete(cache_key)
+ return _redirect_method()
if not shib_user.bind_relation_info(account):
- flash('FAILED bind_relation_info!', category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('FAILED bind_relation_info!'))
+ else:
+ flash('FAILED bind_relation_info!', category='error')
+ return _redirect_method()
error = shib_user.check_in()
if error:
datastore.delete(cache_key)
- flash(error, category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=error)
+ else:
+ flash(error, category='error')
+ return _redirect_method()
if shib_user.shib_user:
shib_user.shib_user_login()
@@ -297,7 +372,10 @@ def confirm_user():
target_key=shib_user.user.id,
remarks="Shibboleth login"
)
- return redirect(session['next'] if 'next' in session else '/')
+ if ams_login:
+ return redirect('/?next=ams')
+ else:
+ return redirect(session['next'] if 'next' in session else '/')
except BaseException:
current_app.logger.error("Unexpected error: {}".format(sys.exc_info()))
exec_info = sys.exc_info()
@@ -306,6 +384,9 @@ def confirm_user():
operation="LOGIN",
remarks=tb_info[0]
)
+ if ams_login:
+ return _redirect_method(True, ams_error=_(
+ 'Server error has occurred. Please contact server administrator.'))
return abort(400)
@@ -315,12 +396,20 @@ def confirm_user_without_page():
:return:
"""
+ ams_login = False
try:
+ next_value = request.args.get('next', '')
+ if next_value == 'ams':
+ ams_login = True
+
# get shib_session_id from session
shib_session_id = request.args.get('Shib-Session-ID', None)
if not shib_session_id:
- flash('shib_session_id', category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing Shib-Session-ID!'))
+ else:
+ flash('shib_session_id', category='error')
+ return _redirect_method()
# get cache from redis
redis_connection = RedisConnection()
@@ -330,38 +419,56 @@ def confirm_user_without_page():
# check cache
if not datastore.redis.exists(cache_key):
- flash('cache_key', category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_CACHE_PREFIX!'))
+ else:
+ flash('cache_key', category='error')
+ return _redirect_method()
cache_val = datastore.get(cache_key)
if not cache_val:
- flash('cache_val', category='error')
- datastore.delete(cache_key)
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_ATTR!'))
+ else:
+ flash('cache_val', category='error')
+ datastore.delete(cache_key)
+ return _redirect_method()
cache_val = json.loads(str(cache_val, encoding='utf-8'))
shib_user = ShibUser(cache_val)
# bind relation info
if not shib_user.bind_relation_info(cache_val.get('shib_mail')):
- flash('FAILED bind_relation_info!', category='error')
datastore.delete(cache_key)
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('FAILED bind_relation_info!'))
+ else:
+ flash('FAILED bind_relation_info!', category='error')
+ return _redirect_method()
# check in
error = shib_user.check_in()
if error:
datastore.delete(cache_key)
- flash(error, category='error')
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=error)
+ else:
+ flash(error, category='error')
+ return _redirect_method()
if shib_user.shib_user:
shib_user.shib_user_login()
datastore.delete(cache_key)
- return redirect(request.args.get('next', '/'))
+ if ams_login:
+ return redirect('/?next=ams')
+ else:
+ return redirect(request.args.get('next', '/'))
except BaseException:
current_app.logger.error("Unexpected error: {}".format(sys.exc_info()))
+ if ams_login:
+ return _redirect_method(True, ams_error=_(
+ 'Server error has occurred. Please contact server administrator.'))
return abort(400)
@@ -371,14 +478,19 @@ def shib_login():
:return: confirm user page when relation is empty
"""
+ ams_login = False
try:
shib_session_id = request.args.get('Shib-Session-ID', None)
session['next'] = request.args.get('next', '/')
-
+ if session['next'] == 'ams':
+ ams_login = True
if not shib_session_id:
- current_app.logger.error(_("Missing Shib-Session-ID!"))
- flash(_("Missing Shib-Session-ID!"), category='error')
- return _redirect_method()
+ current_app.logger.error(_('Missing Shib-Session-ID!'))
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing Shib-Session-ID!'))
+ else:
+ flash(_('Missing Shib-Session-ID!'), category='error')
+ return _redirect_method()
redis_connection = RedisConnection()
datastore = redis_connection.connection(db=current_app.config['CACHE_REDIS_DB'], kv = True)
@@ -386,17 +498,23 @@ def shib_login():
'WEKO_ACCOUNTS_SHIB_CACHE_PREFIX'] + shib_session_id
if not datastore.redis.exists(cache_key):
- current_app.logger.error(_("Missing SHIB_CACHE_PREFIX!"))
- flash(_("Missing SHIB_CACHE_PREFIX!"), category='error')
- return _redirect_method()
+ current_app.logger.error(_('Missing SHIB_CACHE_PREFIX!'))
+ flash(_('Missing SHIB_CACHE_PREFIX!'), category='error')
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_CACHE_PREFIX!'))
+ else:
+ return _redirect_method()
cache_val = datastore.get(cache_key)
if not cache_val:
- current_app.logger.error(_("Missing SHIB_ATTR!"))
- flash(_("Missing SHIB_ATTR!"), category='error')
+ current_app.logger.error(_('Missing SHIB_ATTR!'))
datastore.delete(cache_key)
- return _redirect_method()
+ if ams_login:
+ return _redirect_method(True, ams_error=_('Missing SHIB_ATTR!'))
+ else:
+ flash(_('Missing SHIB_ATTR!'), category='error')
+ return _redirect_method()
cache_val = json.loads(str(cache_val, encoding='utf-8'))
session['shib_session_id'] = shib_session_id
@@ -412,6 +530,9 @@ def shib_login():
)
except BaseException:
current_app.logger.error("Unexpected error: {}".format(sys.exc_info()))
+ if ams_login:
+ return _redirect_method(True, ams_error=_(
+ 'Server error has occurred. Please contact server administrator.'))
return abort(400)
def find_user_by_email(shib_attributes):
@@ -432,7 +553,9 @@ def shib_sp_login():
_shib_username_config = current_app.config[
'WEKO_ACCOUNTS_SHIB_ALLOW_USERNAME_INST_EPPN']
next = request.args.get('next', '/')
-
+ ams_login = False
+ if next == 'ams':
+ ams_login = True
try:
# WEKO_ACCOUNTS_SHIB_BIND_GAKUNIN_MAP_GROUPSがTrueのときの処理
if current_app.config['WEKO_ACCOUNTS_SHIB_BIND_GAKUNIN_MAP_GROUPS']:
@@ -440,8 +563,11 @@ def shib_sp_login():
shib_session_id = request.form.get('Shib-Session-ID', None)
if not shib_session_id and not _shib_enable:
- flash(_("Missing Shib-Session-ID!"), category='error')
- return redirect(url_for_security('login'))
+ if ams_login:
+ return generate_ams_login_url(_('Missing Shib-Session-ID!'))
+ else:
+ flash(_('Missing Shib-Session-ID!'), category='error')
+ return redirect(url_for_security('login'))
shib_attr, error = parse_attributes()
@@ -449,8 +575,11 @@ def shib_sp_login():
if error or not (
shib_attr.get('shib_eppn', None)
or _shib_username_config and shib_attr.get('shib_user_name')):
- flash(_("Missing SHIB_ATTRs!"), category='error')
- return _redirect_method()
+ if ams_login:
+ return generate_ams_login_url(_('Missing SHIB_ATTRs!'))
+ else:
+ flash(_('Missing SHIB_ATTRs!'), category='error')
+ return _redirect_method()
# Check if shib_eppn is not included in the blocked user list
if AdminSettings.query.filter_by(name='blocked_user_settings').first():
@@ -468,8 +597,11 @@ def _wildcard_to_regex(pattern):
blocked = any(_wildcard_to_regex(pattern).match(shib_eppn) or pattern == shib_eppn for pattern in block_user_list)
if blocked:
- flash(_("Failed to login."), category='error')
- return _redirect_method()
+ if ams_login:
+ return generate_ams_login_url(_('Login is blocked.'))
+ else:
+ flash(_('Failed to login.'), category='error')
+ return _redirect_method()
# Redis connection
redis_connection = RedisConnection()
@@ -509,7 +641,11 @@ def _wildcard_to_regex(pattern):
return url_for(next_url, **query_string)
except BaseException:
current_app.logger.error("Unexpected error: {}".format(sys.exc_info()))
- return _redirect_method()
+ if ams_login:
+ return generate_ams_login_url(
+ _('Server error has occurred. Please contact server administrator.'))
+ else:
+ return _redirect_method()
@blueprint.route('/shib/sp/login', methods=['GET'])
diff --git a/modules/weko-deposit/requirements2.txt b/modules/weko-deposit/requirements2.txt
index 43d2bf48e9..b01f66293a 100644
--- a/modules/weko-deposit/requirements2.txt
+++ b/modules/weko-deposit/requirements2.txt
@@ -288,4 +288,4 @@ xmlschema==0.9.30
xmltodict==0.12.0
zipp==3.6.0
zope.interface==5.5.2
-pypdfium2==4.30.0
\ No newline at end of file
+pypdfium2==4.30.0
diff --git a/modules/weko-deposit/tests/test_utils.py b/modules/weko-deposit/tests/test_utils.py
index 130d61fba7..e16fda9f57 100644
--- a/modules/weko-deposit/tests/test_utils.py
+++ b/modules/weko-deposit/tests/test_utils.py
@@ -18,14 +18,14 @@
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
-from weko_deposit.api import WekoDeposit
-from weko_deposit.utils import update_pdf_contents_es, extract_text_from_pdf, extract_text_with_tika
-from sqlalchemy.orm.exc import NoResultFound
+import os
import types
+
+import pytest
+from sqlalchemy.orm.exc import NoResultFound
from unittest.mock import patch, MagicMock
-import uuid
-from tests.helpers import create_record_with_pdf
+from weko_deposit.utils import update_pdf_contents_es, extract_text_from_pdf, extract_text_with_tika
# .tox/c1/bin/pytest --cov=weko_deposit tests/test_utils.py::test_update_pdf_contents_es_with_index_api -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-deposit/.tox/c1/tmp
def test_update_pdf_contents_es(app, mocker):
@@ -60,9 +60,6 @@ def get_pdf_info(self): raise NoResultFound()
assert hasattr(dummy_trace, 'called')
-import os
-
-import pytest
# .tox/c1/bin/pytest --cov=weko_deposit tests/test_utils.py::test_extract_text_from_pdf -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-deposit/.tox/c1/tmp
def test_extract_text_from_pdf():
filepath = os.path.join(os.path.dirname(__file__),"data","test_files","test_file_1.2M.pdf")
@@ -94,21 +91,23 @@ def test_extract_text_with_tika():
data = extract_text_with_tika(filepath, 100)
assert str(e.value) == "not exist tika jar file."
- # error with subprocess
- mock_run = MagicMock()
- mock_run.returncode.return_value=1
- mock_run.stderr.decode.return_value="test_error"
- with patch("weko_deposit.utils.subprocess.run", return_value=mock_run):
- with pytest.raises(Exception) as e:
- data = extract_text_with_tika(filepath, 100)
- assert str(e.value) == "raise in tika: test_error"
+ mock_env_exist_tika = {"TIKA_JAR_FILE_PATH": "/code/tika/tika-app-2.6.0.jar"}
+ with patch.dict(os.environ, mock_env_exist_tika, clear=False):
+ # error with subprocess
+ mock_run = MagicMock()
+ mock_run.returncode.return_value=1
+ mock_run.stderr.decode.return_value="test_error"
+ with patch("weko_deposit.utils.subprocess.run", return_value=mock_run):
+ with pytest.raises(Exception) as e:
+ data = extract_text_with_tika(filepath, 100)
+ assert str(e.value) == "raise in tika: test_error"
- # file size > max_size
- data = extract_text_with_tika(filepath, 50)
- assert len(data.encode('utf-8')) < 50
- assert data == "これはテスト用のサンプルwordファイ"
+ # file size > max_size
+ data = extract_text_with_tika(filepath, 50)
+ assert len(data.encode('utf-8')) < 50
+ assert data == "これはテスト用のサンプルwordファイ"
- # file size <= max_size
- data = extract_text_with_tika(filepath, 5000)
- assert len(data.encode('utf-8')) > 50
- assert data == "これはテスト用のサンプルwordファイルです中身は特に意味がありません"
+ # file size <= max_size
+ data = extract_text_with_tika(filepath, 5000)
+ assert len(data.encode('utf-8')) > 50
+ assert data == "これはテスト用のサンプルwordファイルです中身は特に意味がありません"
diff --git a/modules/weko-index-tree/tests/test_rest.py b/modules/weko-index-tree/tests/test_rest.py
index 0320996b6d..25d7e4d217 100644
--- a/modules/weko-index-tree/tests/test_rest.py
+++ b/modules/weko-index-tree/tests/test_rest.py
@@ -1438,3 +1438,14 @@ def run_delete_index_server_error(self, app, client_rest, auth_headers):
with patch.object(Indexes, "delete", side_effect=SQLAlchemyError):
response = client_rest.delete(url, headers=auth_headers)
assert response.status_code == 500, f"{response.json}"
+
+# class GetIndex:
+# .tox/c1/bin/pytest --cov=weko_index_tree tests/test_rest.py::TestGetIndex -vv -s --cov-branch --cov-report=term --cov-report=html --basetemp=/code/modules/weko_index_tree/.tox/c1/tmp --full-trace
+class TestGetIndex:
+ # .tox/c1/bin/pytest --cov=weko_index_tree tests/test_rest.py::TestGetIndex::test_get_v1 -vv -s --cov-branch --cov-report=term --cov-report=html --basetemp=/code/modules/weko_index_tree/.tox/c1/tmp --full-trace
+ def test_get_v1(self, client_rest, users, test_indices, auth_headers_sysadmin):
+ res = client_rest.get('/v1/tree/index/1', headers=auth_headers_sysadmin)
+ assert res.status_code == 200
+ data = json.loads(res.get_data())
+ assert data['index']['name'] == 'Test index 1'
+ assert data['index']['public_date'] == '20220101'
diff --git a/modules/weko-index-tree/weko_index_tree/rest.py b/modules/weko-index-tree/weko_index_tree/rest.py
index 8a4edb36c5..271dc0d3d2 100644
--- a/modules/weko-index-tree/weko_index_tree/rest.py
+++ b/modules/weko-index-tree/weko_index_tree/rest.py
@@ -712,6 +712,21 @@ def get(self, **kwargs):
raise VersionNotFoundRESTError()
def get_v1(self, **kwargs):
+
+ def json_serialize(obj):
+ """Serialize object to JSON.
+
+ Args:
+ obj: The object to serialize.
+
+ Returns:
+ str: The serialized JSON string.
+ """
+ if isinstance(obj, (datetime, date)):
+ return obj.strftime("%Y%m%d")
+ else:
+ return str(obj)
+
try:
pid = kwargs.get('index_id')
@@ -1531,7 +1546,7 @@ def _get_allowed_group_roles(self, index_info):
Returns:
dict: A dictionary with allowed group roles.
"""
- def _get_allowed_list(self, group_str):
+ def _get_allowed_list(self, group_str):
"""Convert group string to allowed group roles."""
return {
"allow": [{"id": role} for role in group_str.split(",")]
diff --git a/modules/weko-records-ui/weko_records_ui/rest.py b/modules/weko-records-ui/weko_records_ui/rest.py
index 23d964d489..7e3fb0cd7f 100644
--- a/modules/weko-records-ui/weko_records_ui/rest.py
+++ b/modules/weko-records-ui/weko_records_ui/rest.py
@@ -67,6 +67,11 @@
InvalidTokenError, InvalidWorkflowError, ModeNotFoundRESTError, PermissionError, \
RecordsNotFoundRESTError, RequiredItemNotExistError, VersionNotFoundRESTError
from .permissions import page_permission_factory, file_permission_factory
+from .errors import AvailableFilesNotFoundRESTError, ContentsNotFoundError, \
+ InvalidRequestError, VersionNotFoundRESTError, InternalServerError, \
+ RecordsNotFoundRESTError, PermissionError, DateFormatRESTError, \
+ FilesNotFoundRESTError, ModeNotFoundRESTError, RequiredItemNotExistError, \
+ AuthenticationRequiredError
from .scopes import file_read_scope
from .views import escape_str, get_usage_workflow
@@ -711,7 +716,10 @@ def get_v1(self, **kwargs):
# Check Permission
if not page_permission_factory(record).can():
- raise PermissionError()
+ if current_user.is_authenticated:
+ raise PermissionError()
+ else:
+ raise AuthenticationRequiredError()
# Convert RO-Crate format
from .utils import RoCrateConverter
@@ -756,8 +764,10 @@ def get_v1(self, **kwargs):
return res
- except (PermissionError, SameContentException) as e:
- raise e
+ except (PermissionError,
+ SameContentException,
+ AuthenticationRequiredError) as e:
+ raise e
except PIDDoesNotExistError:
raise RecordsNotFoundRESTError()
diff --git a/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/output_detail_data.html b/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/output_detail_data.html
index 0c5c412a5c..44ed8e0f40 100644
--- a/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/output_detail_data.html
+++ b/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/output_detail_data.html
@@ -83,7 +83,7 @@
{% if parrent_name %}
{%- set labels = parrent_name.split('.') -%}
{%- if labels|length == 1 -%}
- {{ child_data(parrent_name, '', level) }}
+ {{ child_data(parrent_name, ' ', level) }}
{%- else -%}
{%- set displayflag = False -%}
{%- endif -%}
@@ -118,7 +118,7 @@
{{ content | escape_str }}
{%- elif content|url_to_link -%}
{{ content | escape_str }}
- {%- else -%}
+ {%- else -%}
{{ content | escape_str }}
{%- endif -%}
{% endautoescape %}
diff --git a/modules/weko-search-ui/requirements2.txt b/modules/weko-search-ui/requirements2.txt
index c4702c5184..b01f66293a 100644
--- a/modules/weko-search-ui/requirements2.txt
+++ b/modules/weko-search-ui/requirements2.txt
@@ -288,3 +288,4 @@ xmlschema==0.9.30
xmltodict==0.12.0
zipp==3.6.0
zope.interface==5.5.2
+pypdfium2==4.30.0
diff --git a/modules/weko-search-ui/tests/conftest.py b/modules/weko-search-ui/tests/conftest.py
index f134eb98ca..a81cf2ee36 100644
--- a/modules/weko-search-ui/tests/conftest.py
+++ b/modules/weko-search-ui/tests/conftest.py
@@ -137,7 +137,13 @@
from weko_deposit.api import WekoDeposit
from weko_deposit.api import WekoDeposit as aWekoDeposit
from weko_deposit.api import WekoIndexer, WekoRecord
-from weko_deposit.config import WEKO_BUCKET_QUOTA_SIZE, WEKO_MAX_FILE_SIZE
+from weko_deposit.config import (
+ WEKO_BUCKET_QUOTA_SIZE,
+ WEKO_MAX_FILE_SIZE,
+ WEKO_DEPOSIT_FILESIZE_LIMIT,
+ WEKO_MIMETYPE_WHITELIST_FOR_ES,
+ WEKO_DEPOSIT_TEXTMIMETYPE_WHITELIST_FOR_ES
+)
from weko_groups import WekoGroups
from weko_index_tree import WekoIndexTree, WekoIndexTreeREST
from weko_index_tree.api import Indexes
@@ -692,6 +698,9 @@ def base_app(instance_path, search_class, request):
WEKO_SEARCH_UI_BULK_EXPORT_RETRY = 5,
WEKO_SEARCH_UI_BULK_EXPORT_LIMIT = 100,
RECORDS_UI_ENDPOINTS = RECORDS_UI_ENDPOINTS,
+ WEKO_DEPOSIT_FILESIZE_LIMIT = WEKO_DEPOSIT_FILESIZE_LIMIT,
+ WEKO_MIMETYPE_WHITELIST_FOR_ES = WEKO_MIMETYPE_WHITELIST_FOR_ES,
+ WEKO_DEPOSIT_TEXTMIMETYPE_WHITELIST_FOR_ES = WEKO_DEPOSIT_TEXTMIMETYPE_WHITELIST_FOR_ES,
WEKO_SCHEMA_JPCOAR_V2_RESOURCE_TYPE_REPLACE={
"periodical": "journal",
"interview": "other",
diff --git a/modules/weko-search-ui/tests/data/ams/broken_word.docx b/modules/weko-search-ui/tests/data/ams/broken_word.docx
new file mode 100644
index 0000000000..3fa5f4e582
Binary files /dev/null and b/modules/weko-search-ui/tests/data/ams/broken_word.docx differ
diff --git a/modules/weko-search-ui/tests/data/ams/png_file.pdf b/modules/weko-search-ui/tests/data/ams/png_file.pdf
new file mode 100644
index 0000000000..cc8d7bda54
Binary files /dev/null and b/modules/weko-search-ui/tests/data/ams/png_file.pdf differ
diff --git a/modules/weko-search-ui/tests/data/ams/png_file.txt b/modules/weko-search-ui/tests/data/ams/png_file.txt
new file mode 100644
index 0000000000..cc8d7bda54
Binary files /dev/null and b/modules/weko-search-ui/tests/data/ams/png_file.txt differ
diff --git a/modules/weko-search-ui/tests/data/ams/sample.txt b/modules/weko-search-ui/tests/data/ams/sample.txt
new file mode 100644
index 0000000000..990383c64b
--- /dev/null
+++ b/modules/weko-search-ui/tests/data/ams/sample.txt
@@ -0,0 +1,2 @@
+This is a
+text file.
diff --git a/modules/weko-search-ui/tests/data/ams/with_two_extended_metadata.json b/modules/weko-search-ui/tests/data/ams/with_two_extended_metadata.json
new file mode 100644
index 0000000000..eb70def6c2
--- /dev/null
+++ b/modules/weko-search-ui/tests/data/ams/with_two_extended_metadata.json
@@ -0,0 +1,99 @@
+{
+ "@id": "./",
+ "@type": "Dataset",
+ "datePublished": "2025-10-22",
+ "name": "extract",
+ "description": "Item metadata for Item ID: 2000036. Title: extract.",
+ "wk:index": [
+ "1623632832836"
+ ],
+ "wk:publishStatus": "public",
+ "wk:feedbackMail": [],
+ "wk:requestMail": [],
+ "wk:grant": [],
+ "wk:editMode": "Keep",
+ "dc:title": [
+ {
+ "@id": "#:title_0",
+ "@type": "PropertyValue",
+ "value": "extract",
+ "language": "ja"
+ }
+ ],
+ "dc:type": {
+ "@id": "#:type_1",
+ "@type": "PropertyValue",
+ "rdf:resource": "departmental bulletin paper",
+ "value": "http://purl.org/coar/resource_type/c_6501"
+ },
+ "hasPart": [
+ {
+ "@id": "data/guide.pdf",
+ "@type": "File",
+ "dcterms:accessRights": "open_access",
+ "datePublished": "2025-10-22",
+ "name": "guide.pdf",
+ "jpcoar:extent": [
+ {
+ "@id": "#:extent_3",
+ "@type": "File",
+ "value": "844 KB"
+ }
+ ],
+ "jpcoar:mimeType": "application/pdf",
+ "jpcoar:URI": {
+ "@id": "#:URI_4",
+ "@type": "URL",
+ "value": "https://192.168.56.102/record/2000036/files/guide.pdf"
+ },
+ "wk:textExtraction": true,
+ "wk:extendedMetadata": true
+ },
+ {
+ "@id": "data/sample.txt",
+ "@type": "File",
+ "dcterms:accessRights": "open_access",
+ "datePublished": "2025-10-22",
+ "name": "sample.txt",
+ "jpcoar:extent": [
+ {
+ "@id": "#:extent_6",
+ "@type": "File",
+ "value": "51 B"
+ }
+ ],
+ "jpcoar:mimeType": "text/plain",
+ "jpcoar:URI": {
+ "@id": "#:URI_7",
+ "@type": "URL",
+ "value": "https://192.168.56.102/record/2000036/files/sample.txt"
+ },
+ "wk:textExtraction": true,
+ "wk:extendedMetadata": true
+ },
+ {
+ "@id": "data/pp.pptx",
+ "@type": "File",
+ "dcterms:accessRights": "open_access",
+ "datePublished": "2025-10-22",
+ "name": "pp.pptx",
+ "jpcoar:extent": [
+ {
+ "@id": "#:extent_9",
+ "@type": "File",
+ "value": "432 KB"
+ }
+ ],
+ "jpcoar:mimeType": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "jpcoar:URI": {
+ "@id": "#:URI_10",
+ "@type": "URL",
+ "value": "https://192.168.56.102/record/2000036/files/pp.pptx"
+ },
+ "wk:textExtraction": true,
+ "wk:extendedMetadata": false
+ }
+ ],
+ "wk:itemLinks": [],
+ "wk:metadataAutoFill": false
+}
diff --git a/modules/weko-search-ui/tests/data/ams/without_hasPart.json b/modules/weko-search-ui/tests/data/ams/without_hasPart.json
new file mode 100644
index 0000000000..a4a18e1ba1
--- /dev/null
+++ b/modules/weko-search-ui/tests/data/ams/without_hasPart.json
@@ -0,0 +1,31 @@
+{
+ "@id": "./",
+ "@type": "Dataset",
+ "datePublished": "2025-10-22",
+ "name": "extract",
+ "description": "Item metadata for Item ID: 2000036. Title: extract.",
+ "wk:index": [
+ "1623632832836"
+ ],
+ "wk:publishStatus": "public",
+ "wk:feedbackMail": [],
+ "wk:requestMail": [],
+ "wk:grant": [],
+ "wk:editMode": "Keep",
+ "dc:title": [
+ {
+ "@id": "#:title_0",
+ "@type": "PropertyValue",
+ "value": "extract",
+ "language": "ja"
+ }
+ ],
+ "dc:type": {
+ "@id": "#:type_1",
+ "@type": "PropertyValue",
+ "rdf:resource": "departmental bulletin paper",
+ "value": "http://purl.org/coar/resource_type/c_6501"
+ },
+ "wk:itemLinks": [],
+ "wk:metadataAutoFill": false
+}
diff --git "a/modules/weko-search-ui/tests/data/ams/\343\202\265\343\203\263\343\203\227\343\203\2532.txt" "b/modules/weko-search-ui/tests/data/ams/\343\202\265\343\203\263\343\203\227\343\203\2532.txt"
new file mode 100644
index 0000000000..793629ceea
--- /dev/null
+++ "b/modules/weko-search-ui/tests/data/ams/\343\202\265\343\203\263\343\203\227\343\203\2532.txt"
@@ -0,0 +1 @@
+上限:8バイト
diff --git a/modules/weko-search-ui/tests/test_mapper.py b/modules/weko-search-ui/tests/test_mapper.py
index c59f587991..c3fe1173d0 100644
--- a/modules/weko-search-ui/tests/test_mapper.py
+++ b/modules/weko-search-ui/tests/test_mapper.py
@@ -2,9 +2,11 @@
import pytest
import xmltodict
import uuid
+import json
from datetime import date
from unittest.mock import patch, MagicMock
from collections import OrderedDict
+from pypdfium2 import PdfiumError
from weko_records.api import Mapping
from weko_records.serializers.utils import get_full_mapping
@@ -4817,9 +4819,10 @@ def test_to_item_metadata(self, app, db, item_type2, item_type_mapping2):
# def deconstruct_json_ld(json_ld):
# .tox/c1/bin/pytest --cov=weko_search_ui tests/test_mapper.py::TestJsonLdMapper::test__deconstruct_json_ld -v -vv -s --cov-branch --cov-report=xml --basetemp=/code/modules/weko-search-ui/.tox/c1/tmp
- def test__deconstruct_json_ld(self, app):
+ def test__deconstruct_json_ld(self, app, item_type2):
json_ld = json_data("data/jsonld/ro-crate-metadata.json")
- deconstructed_metadata, format = JsonLdMapper._deconstruct_json_ld(json_ld)
+ mapper = JsonLdMapper(item_type2.model.id, None)
+ deconstructed_metadata, format = mapper._deconstruct_json_ld(json_ld)
metadata, system_info = deconstructed_metadata[0]
assert format == "ro-crate"
@@ -4847,7 +4850,8 @@ def test__deconstruct_json_ld(self, app):
assert not any("@type" in key for key in metadata.keys())
json_ld = json_data("data/jsonld/ro-crate-metadata2.json")
- deconstructed_metadata, format = JsonLdMapper._deconstruct_json_ld(json_ld)
+ mapper = JsonLdMapper(item_type2.model.id, None)
+ deconstructed_metadata, format = mapper._deconstruct_json_ld(json_ld)
thesis, system_info = deconstructed_metadata[0]
assert format == "ro-crate"
@@ -4877,7 +4881,8 @@ def test__deconstruct_json_ld(self, app):
assert evidence["dc:type.@id"] == "http://purl.org/coar/resource_type/c_1843"
with pytest.raises(ValueError) as ex:
- deconstructed_metadata, format = JsonLdMapper._deconstruct_json_ld({})
+ mapper = JsonLdMapper(item_type2.model.id, None)
+ deconstructed_metadata, format = mapper._deconstruct_json_ld({})
ex.match('Invalid json-ld format: "@context" is invalid.')
# def to_rocrate_metadata(self, metadata):
@@ -5279,6 +5284,103 @@ def test_to_item_metadata_ams_dict(self, app, db, item_type2):
assert item_metadata["item_1749689698804"]["subitem_relation_type"] == "isVersionOf"
+ # def extract_extended_metadata(self, list_extracted):
+ # .tox/c1/bin/pytest --cov=weko_search_ui tests/test_mapper.py::TestJsonLdMapper::test_extract_extended_metadata -v -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-search-ui/.tox/c1/tmp
+ def test_extract_extended_metadata(self, app, db, item_type2, mocker):
+ mapper = JsonLdMapper(item_type2.model.id, None)
+ values = ["first", "second"]
+ mocker.patch.object(mapper, "extract_text_from_files",
+ side_effect = values)
+
+ rocrate = json_data("data/ams/with_two_extended_metadata.json")
+ rocrate = mapper.extract_extended_metadata([rocrate])[0]
+
+ ids = [part["@id"]
+ for part in rocrate.get("hasPart", [])
+ if "@id" in part]
+ assert ids == ["data/pp.pptx"]
+
+ ext = rocrate["extended_metadata"]["value"]
+ ext = json.loads(ext)
+
+ assert len(ext) == 2
+ assert ext["data/sample.txt"] == "first"
+ assert ext["data/guide.pdf"] == "second"
+
+ # without hasPart
+ rocrate = json_data("data/ams/without_hasPart.json")
+ rocrate = mapper.extract_extended_metadata([rocrate])[0]
+ assert "extended_metadata" not in rocrate
+
+ # def extract_text_from_files(self, filename):
+ # .tox/c1/bin/pytest --cov=weko_search_ui tests/test_mapper.py::TestJsonLdMapper::test_extract_text_from_files -v -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-search-ui/.tox/c1/tmp
+ def test_extract_text_from_files(self, app, db, item_type2, mocker, tmp_path):
+ mapper = JsonLdMapper(item_type2.model.id, None)
+
+ mapper.data_path = str(tmp_path)
+ file_content = "これは\r\nテキストファイルです\r\n"
+
+ file_name = "サンプル.txt"
+ tmpfile = tmp_path / file_name
+ tmpfile.write_text(file_content, encoding="shift_jis")
+ extract_text = mapper.extract_text_from_files(file_name)
+ assert extract_text == file_content
+
+ file_name = "サンプル.TXT"
+ tmpfile = tmp_path / file_name
+ tmpfile.write_text(file_content, encoding="utf-8")
+ extract_text = mapper.extract_text_from_files(file_name)
+ assert extract_text == file_content
+
+ file_name = "サンプル.txt"
+ tmpfile = tmp_path / file_name
+ tmpfile.write_text(file_content, encoding="utf-8")
+ extract_text = mapper.extract_text_from_files(file_name)
+ assert extract_text == ""
+
+ mapper.data_path = "tests/data/ams"
+
+ app.config.update({"WEKO_DEPOSIT_FILESIZE_LIMIT": 8})
+ extract_text = mapper.extract_text_from_files("sample.txt")
+ assert extract_text == "This is "
+
+ app.config.update({"WEKO_DEPOSIT_FILESIZE_LIMIT": 8})
+ extract_text = mapper.extract_text_from_files("サンプル2.txt")
+ assert extract_text == "上限:8"
+
+ app.config.update({"WEKO_DEPOSIT_FILESIZE_LIMIT": 2 * 1024 * 1024})
+ extract_text = mapper.extract_text_from_files("sample.txt")
+ assert extract_text == "This is a\ntext file.\n"
+
+ with pytest.raises(ValueError) as e:
+ extract_text = mapper.extract_text_from_files("png_file.txt")
+ assert str(e.value) == "Failed to load text file: png_file.txt"
+
+ with pytest.raises(PdfiumError) as e:
+ extract_text = mapper.extract_text_from_files("png_file.pdf")
+ assert str(e.value) == "Failed to load PDF file: png_file.pdf"
+
+ with pytest.raises(ValueError) as e:
+ extract_text = mapper.extract_text_from_files("broken_word.docx")
+ assert str(e.value) == "Failed to load document: broken_word.docx"
+
+ with pytest.raises(FileNotFoundError) as e:
+ extract_text = mapper.extract_text_from_files("not_exist.txt")
+ assert str(e.value) == "File Not Found: not_exist.txt"
+
+ mocker.patch("weko_search_ui.mapper.extract_text_from_pdf",
+ return_value="This is a pdf file.")
+ mocker.patch("os.path.isfile", return_value=True)
+ extract_text = mapper.extract_text_from_files("pdffile.pdf")
+ assert extract_text == "This is a pdf file."
+
+ mocker.patch("weko_search_ui.mapper.extract_text_with_tika",
+ return_value="This is a pptx file.")
+ extract_text = mapper.extract_text_from_files("powerpoint.pptx")
+ assert extract_text == "This is a pptx file."
+
+ extract_text = mapper.extract_text_from_files("sample.other")
+ assert extract_text == ""
def test_set_by_jsonpath():
data = {}
diff --git a/modules/weko-search-ui/tests/test_rest.py b/modules/weko-search-ui/tests/test_rest.py
index d7255a5356..60d366e3e2 100644
--- a/modules/weko-search-ui/tests/test_rest.py
+++ b/modules/weko-search-ui/tests/test_rest.py
@@ -398,6 +398,10 @@ def test_IndexSearchResourceAPI(client_rest, db_register2, db_rocrate_mapping):
res = client_rest.get('/v1/records', headers=headers)
assert res.status_code == 200
+ headers = {'Accept-Language': 'ja,en-US;q=0.9,en;q=0.8'}
+ res = client_rest.get('/v1/records', headers=headers)
+ assert res.status_code == 200
+
with patch('weko_search_ui.rest.SearchSetting.get_sort_key', return_value=False):
res = client_rest.get('/v1/records')
assert res.status_code == 200
diff --git a/modules/weko-search-ui/tests/test_utils.py b/modules/weko-search-ui/tests/test_utils.py
index 850ebb8521..d8209889c5 100644
--- a/modules/weko-search-ui/tests/test_utils.py
+++ b/modules/weko-search-ui/tests/test_utils.py
@@ -1006,7 +1006,8 @@ def test_handle_convert_validate_msg_to_jp(i18n_app):
# def handle_validate_item_import(list_record, schema) -> list:
-def test_handle_validate_item_import(app, mocker_itemtype):
+# .tox/c1/bin/pytest --cov=weko_search_ui tests/test_utils.py::test_handle_validate_item_import -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-search-ui/.tox/c1/tmp
+def test_handle_validate_item_import(app, mocker_itemtype, mocker):
filepath = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "data", "csv", "data.json"
)
@@ -1040,6 +1041,96 @@ def test_handle_validate_item_import(app, mocker_itemtype):
== result
)
+ schema = {
+ "type": "object",
+ "properties": {
+ "item_xxx": {
+ "type": "object",
+ "properties": {
+ "subitem_yyy": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "subitem_zzz": {
+ "type": "string",
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ list_record = [
+ {
+ "metadata": {
+ 'item_xxx': {
+ 'subitem_yyy':[
+ {"subitem_zzz": 123}
+ ]
+ }
+ }
+ }
+ ]
+ with app.test_request_context():
+ with set_locale("en"):
+ result = handle_validate_item_import(list_record, schema)
+ warnings = result[0].get("warnings", [])
+ target = list_record[0]["metadata"]['item_xxx']['subitem_yyy'][0]["subitem_zzz"]
+ assert any("Replace value of" in w for w in warnings)
+ assert any("is different from existing" in w for w in warnings)
+ assert type(target) == str
+
+ list_record[0]["metadata"]['item_xxx']['subitem_yyy'][0]["subitem_zzz"] = 456
+
+ with app.test_request_context():
+ with set_locale("ja"):
+ result = handle_validate_item_import(list_record, schema)
+ warnings = result[0].get("warnings", [])
+ assert any("へ置き換えました。" in w for w in warnings)
+ assert any("と異なっています。" in w for w in warnings)
+
+ schema = {
+ "type": "object",
+ "properties": {
+ "item_aaa": {
+ "type": "object",
+ "properties": {
+ "subitem_bbb": {
+ "type": "object",
+ "properties": {
+ "subitem_ccc": {
+ "enum": [None, "Yes|Yes", "No|No"],
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ list_record = [
+ {
+ "metadata": {
+ 'item_aaa': {
+ 'subitem_bbb': {
+ "subitem_ccc": "Yes"
+ }
+ }
+ }
+ }
+ ]
+ with app.test_request_context():
+ with set_locale("en"):
+ result = handle_validate_item_import(list_record, schema)
+ assert "errors" in result[0]
+
+ with app.test_request_context():
+ with set_locale("ja"):
+ result = handle_validate_item_import(list_record, schema)
+ assert "errors" in result[0]
# def represents_int(s):
def test_represents_int():
diff --git a/modules/weko-search-ui/weko_search_ui/mapper.py b/modules/weko-search-ui/weko_search_ui/mapper.py
index aaa343878d..bfa57ac489 100644
--- a/modules/weko-search-ui/weko_search_ui/mapper.py
+++ b/modules/weko-search-ui/weko_search_ui/mapper.py
@@ -11,6 +11,9 @@
import os
import re
import json
+import chardet
+import mimetypes
+from pypdfium2 import PdfiumError
import itertools
import xmltodict
import traceback
@@ -28,6 +31,7 @@
Mapping, ItemTypes, FeedbackMailList, RequestMailList, ItemLink
)
from weko_records.serializers.utils import get_full_mapping
+from weko_deposit.utils import extract_text_from_pdf, extract_text_with_tika
from .config import ROCRATE_METADATA_FILE, ROCRATE_METADATA_WK_CONTEXT_V1
@@ -1571,8 +1575,7 @@ def is_url(s: str) -> bool:
# }
return mapped_metadata, system_info
- @classmethod
- def _deconstruct_json_ld(cls, json_ld):
+ def _deconstruct_json_ld(self, json_ld):
"""Deconstruct json-ld.
Deconstructing json-ld metadata values one by one
@@ -1682,10 +1685,11 @@ def _resolve_link(value):
list_extracted = [ extracted ]
else:
list_extracted = [ extracted ]
+ self.extract_extended_metadata(list_extracted)
list_deconstructed = []
for extracted in list_extracted:
- metadata = cls._deconstruct_dict(extracted)
+ metadata = self._deconstruct_dict(extracted)
system_info = {}
system_info.update(
{"id": metadata.pop("identifier")}
@@ -1863,6 +1867,91 @@ def _check_settable_path(self, json_path):
return settable_path
+ def extract_extended_metadata(self, list_extracted):
+ """
+ Store the content of files with wk:extendedMetadata set to True in extended_metadata,
+ and remove files with wk:extendedMetadata set to True from hasPart.
+
+ Args:
+ list_extracted (list): List of extracted metadata dictionaries.
+ Returns:
+ list: The updated list of extracted metadata with extended metadata merged.
+ """
+ for extracted in list_extracted:
+ extracted.pop('extended_metadata', None)
+ if 'hasPart' not in extracted:
+ continue
+ file_indices = [
+ idx for idx, item in enumerate(extracted['hasPart'])
+ if item.get('wk:extendedMetadata') is True
+ ]
+ if not file_indices:
+ continue
+ extended_metadatas = {}
+ extracted['extended_metadata'] = {}
+ for idx in reversed(file_indices):
+ filename = extracted['hasPart'].pop(idx).get('@id')
+ content = self.extract_text_from_files(filename)
+ extended_metadatas[filename] = content
+ extracted['extended_metadata']['value'] = json.dumps(
+ extended_metadatas, ensure_ascii=False)
+ return list_extracted
+
+ def extract_text_from_files(self, filename):
+ """
+ Extract text content from the specified file,
+ only if the file is of a specific MIME type.
+ Args:
+ filename (str): The name of the file to extract text from.
+
+ Returns:
+ str: The extracted text content from the file.
+ """
+ data_path = self.data_path
+ try:
+ file_path = os.path.join(data_path, filename)
+ if not os.path.isfile(file_path):
+ raise FileNotFoundError
+ data = ""
+ mimetype = mimetypes.guess_type(filename)[0]
+ file_size_limit = current_app.config['WEKO_DEPOSIT_FILESIZE_LIMIT']
+ # List of text-based MIME types allowed for text extraction and processing.
+ text_mimetypes = current_app.config["WEKO_DEPOSIT_TEXTMIMETYPE_WHITELIST_FOR_ES"]
+ # All mimetypes subject to text extraction (including text_mimetypes)
+ extract_mimetypes = current_app.config["WEKO_MIMETYPE_WHITELIST_FOR_ES"]
+ if mimetype not in extract_mimetypes:
+ return data
+
+ # Extract content from file
+ current_app.logger.debug(f"extracting content from {filename}")
+ if mimetype in text_mimetypes:
+ with open(file_path, "rb") as fp:
+ data = fp.read(file_size_limit)
+ inf = chardet.detect(data)
+ if inf["encoding"] is None:
+ raise ValueError(
+ f"Failed to load text file: {filename}")
+ data = data.decode(inf["encoding"], errors="replace")
+ elif mimetype == 'application/pdf':
+ data = extract_text_from_pdf(file_path, file_size_limit)
+ else:
+ try:
+ data = extract_text_with_tika(file_path, file_size_limit)
+ except Exception as e:
+ current_app.logger.error(e)
+ traceback.print_exc()
+ raise ValueError(
+ f"Failed to load document: {filename}") from e
+ except FileNotFoundError as e:
+ current_app.logger.error(e)
+ traceback.print_exc()
+ raise FileNotFoundError(f"File Not Found: {filename}") from e
+ except PdfiumError as e:
+ current_app.logger.error(e)
+ traceback.print_exc()
+ raise PdfiumError(f"Failed to load PDF file: {filename}") from e
+ return data
+
def to_rocrate_metadata(
self, record_metadata=None, tsv_row_metadata=None, **kwargs
):
@@ -2461,4 +2550,3 @@ def tokenize_jsonpath(json_path):
index = None
tokens.append((element, index, current_path))
return tokens
-
diff --git a/modules/weko-search-ui/weko_search_ui/rest.py b/modules/weko-search-ui/weko_search_ui/rest.py
index ee0095b6c8..2e797275cc 100644
--- a/modules/weko-search-ui/weko_search_ui/rest.py
+++ b/modules/weko-search-ui/weko_search_ui/rest.py
@@ -600,6 +600,8 @@ def get_v1(self, **kwargs):
try:
# Language setting
language = request.headers.get('Accept-Language')
+ if isinstance(language, str):
+ language = language.split(',')[0].split(';')[0].strip()
if language:
get_locale().language = language
diff --git a/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.mo b/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.mo
index 084df4f48b..cb7fc7ab93 100644
Binary files a/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.mo and b/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.mo differ
diff --git a/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.po b/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.po
index d4ba275c83..5a50d17255 100644
--- a/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.po
+++ b/modules/weko-search-ui/weko_search_ui/translations/en/LC_MESSAGES/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: weko-search-ui 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2025-11-11 20:49+0900\n"
+"POT-Creation-Date: 2025-12-17 13:33+0900\n"
"PO-Revision-Date: 2025-04-09 23:22+0900\n"
"Last-Translator: FULL NAME \n"
"Language: en\n"
@@ -19,69 +19,69 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
-#: tests/conftest.py:400
+#: tests/conftest.py:406
msgid "write your own license"
msgstr ""
-#: tests/conftest.py:405
+#: tests/conftest.py:411
msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
msgstr ""
-#: tests/conftest.py:421
+#: tests/conftest.py:427
msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
msgstr ""
-#: tests/conftest.py:433
+#: tests/conftest.py:439
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
msgstr ""
-#: tests/conftest.py:448
+#: tests/conftest.py:454
msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
msgstr ""
-#: tests/conftest.py:462
+#: tests/conftest.py:468
msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
msgstr ""
-#: tests/conftest.py:477
+#: tests/conftest.py:483
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC "
"BY-NC-SA 3.0)"
msgstr ""
-#: tests/conftest.py:492
+#: tests/conftest.py:498
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-"
"NC-ND 3.0)"
msgstr ""
-#: tests/conftest.py:508
+#: tests/conftest.py:514
msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
msgstr ""
-#: tests/conftest.py:520
+#: tests/conftest.py:526
msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
msgstr ""
-#: tests/conftest.py:535
+#: tests/conftest.py:541
msgid ""
"Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND "
"4.0)"
msgstr ""
-#: tests/conftest.py:550
+#: tests/conftest.py:556
msgid ""
"Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC "
"4.0)"
msgstr ""
-#: tests/conftest.py:565
+#: tests/conftest.py:571
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
"(CC BY-NC-SA 4.0)"
msgstr ""
-#: tests/conftest.py:580
+#: tests/conftest.py:586
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 "
"International (CC BY-NC-ND 4.0)"
@@ -215,42 +215,44 @@ msgstr ""
msgid "Import Result"
msgstr ""
-#: weko_search_ui/mapper.py:1347
+#: weko_search_ui/mapper.py:1351
msgid "\"{key}\" is required."
msgstr ""
-#: weko_search_ui/mapper.py:1368
+#: weko_search_ui/mapper.py:1372
+#, python-brace-format
msgid "\"{key}\" is not in itemtype."
msgstr ""
-#: weko_search_ui/mapper.py:1370
+#: weko_search_ui/mapper.py:1374
+#, python-brace-format
msgid "\"{key}\" is not in itemtype, did you mean \"{similar_key}\"?"
msgstr ""
-#: weko_search_ui/mapper.py:1491
+#: weko_search_ui/mapper.py:1495
#, python-format
msgid ""
"Cannot map to item type from json-ld; Mapping is not defined for the "
"metadata, \"%(key)s\": \"%(value)s\""
msgstr ""
-#: weko_search_ui/mapper.py:1517
+#: weko_search_ui/mapper.py:1521
#, python-format
msgid ""
"Cannot map to item type from json-ld; Not found mapping destination for "
"the metadata, \"%(key)s\": \"%(value)s\""
msgstr ""
-#: weko_search_ui/mapper.py:1527
+#: weko_search_ui/mapper.py:1531
#, python-format
msgid "Failed to set metadata for json-ld, \"%(key)s\": \"%(value)s\""
msgstr ""
-#: weko_search_ui/mapper.py:1547
+#: weko_search_ui/mapper.py:1553
msgid "Metadata which could not be mapped to item type will be set in 'Extra'."
msgstr ""
-#: weko_search_ui/mapper.py:1551
+#: weko_search_ui/mapper.py:1557
msgid "Metadata which could not be mapped to item type will be discarded."
msgstr ""
@@ -269,6 +271,7 @@ msgid ""
msgstr ""
#: weko_search_ui/utils.py:615
+#, python-brace-format
msgid ""
"The csv/tsv file was not found in the specified file {}. Check if the "
"directory structure is correct."
@@ -281,6 +284,7 @@ msgid ""
msgstr ""
#: weko_search_ui/utils.py:731
+#, python-brace-format
msgid ""
"The xml file was not found in the specified file {}. Check if the "
"directory structure is correct."
@@ -311,6 +315,7 @@ msgid ""
msgstr ""
#: weko_search_ui/utils.py:1244
+#, python-brace-format
msgid "The item type ID specified in the {} file does not exist."
msgstr ""
@@ -319,24 +324,29 @@ msgid "Cannot register because the specified item type is not the latest version
msgstr ""
#: weko_search_ui/utils.py:1268
+#, python-brace-format
msgid "The following metadata keys are duplicated. {}"
msgstr ""
#: weko_search_ui/utils.py:1289
+#, python-brace-format
msgid "The item does not consistent with the specified item type. {}"
msgstr ""
#: weko_search_ui/utils.py:1317
+#, python-brace-format
msgid "Cannot read {} file correctly."
msgstr ""
#: weko_search_ui/utils.py:1341
+#, python-brace-format
msgid ""
"The following items are not registered because they do not exist in the "
"specified item type. {}"
msgstr ""
#: weko_search_ui/utils.py:1351
+#, python-brace-format
msgid ""
"The {} file could not be read. Make sure the file format is {} and that "
"the file is UTF-8 encoded."
@@ -348,259 +358,269 @@ msgid ""
" the file is UTF-8 encoded."
msgstr ""
-#: weko_search_ui/utils.py:1454
+#: weko_search_ui/utils.py:1455
msgid "Please specify item ID by half-width number."
msgstr ""
-#: weko_search_ui/utils.py:1469
+#: weko_search_ui/utils.py:1477
+#, python-format
+msgid "Replace value of %(target_path)s from %(old_value)s to '%(new_value)s'."
+msgstr ""
+
+#: weko_search_ui/utils.py:1489
msgid "Specified item type does not exist."
msgstr ""
-#: weko_search_ui/utils.py:1540
+#: weko_search_ui/utils.py:1495
+#, python-format
+msgid "Specified %(type)s is different from existing %(existing_type)s."
+msgstr ""
+
+#: weko_search_ui/utils.py:1567
msgid "The same item may have been registered."
msgstr ""
-#: weko_search_ui/utils.py:1570
+#: weko_search_ui/utils.py:1597
msgid "Specified URI and system URI do not match."
msgstr ""
-#: weko_search_ui/utils.py:1582
+#: weko_search_ui/utils.py:1609
msgid "Item does not exist in the system."
msgstr ""
-#: weko_search_ui/utils.py:1589
+#: weko_search_ui/utils.py:1616
msgid "Item already DELETED in the system."
msgstr ""
-#: weko_search_ui/utils.py:1606
+#: weko_search_ui/utils.py:1633
msgid "Please specify either \"Keep\" or \"Upgrade\"."
msgstr ""
-#: weko_search_ui/utils.py:2565
+#: weko_search_ui/utils.py:2592
msgid "Title is required item."
msgstr ""
-#: weko_search_ui/utils.py:2582
+#: weko_search_ui/utils.py:2609
msgid "{} is required item."
msgstr ""
-#: weko_search_ui/utils.py:2585
+#: weko_search_ui/utils.py:2612
msgid "Please set \"public\" or \"private\" for {}."
msgstr ""
-#: weko_search_ui/utils.py:2626
+#: weko_search_ui/utils.py:2653
msgid "The specified {} does not exist in system."
msgstr ""
-#: weko_search_ui/utils.py:2636
+#: weko_search_ui/utils.py:2663
msgid "Specified {} does not match with existing index."
msgstr ""
-#: weko_search_ui/utils.py:2680
+#: weko_search_ui/utils.py:2707
msgid "Your role cannot register items in this index."
msgstr ""
-#: weko_search_ui/utils.py:2701
+#: weko_search_ui/utils.py:2728
msgid "Both of IndexID and POS_INDEX are not being set."
msgstr ""
-#: weko_search_ui/utils.py:2747 weko_search_ui/utils.py:2772
+#: weko_search_ui/utils.py:2774 weko_search_ui/utils.py:2799
msgid "Specified {} is invalid."
msgstr ""
-#: weko_search_ui/utils.py:2806
+#: weko_search_ui/utils.py:2833
msgid "If there is a info of content file, terms of use cannot be set."
msgstr "If there is a info of content file, terms of use cannot be set."
-#: weko_search_ui/utils.py:2813 weko_search_ui/utils.py:6063
+#: weko_search_ui/utils.py:2840 weko_search_ui/utils.py:6090
msgid "The specified provinding method does not exist in the system"
msgstr ""
-#: weko_search_ui/utils.py:2818 weko_search_ui/utils.py:6058
+#: weko_search_ui/utils.py:2845 weko_search_ui/utils.py:6085
msgid "The specified terms does not exist in the system"
msgstr ""
-#: weko_search_ui/utils.py:2910 weko_search_ui/utils.py:2943
-#: weko_search_ui/utils.py:3035 weko_search_ui/utils.py:3147
-#: weko_search_ui/utils.py:3169 weko_search_ui/utils.py:3204
+#: weko_search_ui/utils.py:2937 weko_search_ui/utils.py:2970
+#: weko_search_ui/utils.py:3062 weko_search_ui/utils.py:3174
+#: weko_search_ui/utils.py:3196 weko_search_ui/utils.py:3231
msgid "Please specify {}."
msgstr ""
-#: weko_search_ui/utils.py:2913 weko_search_ui/utils.py:3150
+#: weko_search_ui/utils.py:2940 weko_search_ui/utils.py:3177
msgid "The specified {} exceeds the maximum length."
msgstr ""
-#: weko_search_ui/utils.py:2928 weko_search_ui/utils.py:3085
-#: weko_search_ui/utils.py:3096 weko_search_ui/utils.py:3165
+#: weko_search_ui/utils.py:2955 weko_search_ui/utils.py:3112
+#: weko_search_ui/utils.py:3123 weko_search_ui/utils.py:3192
msgid "Specified Prefix of {} is incorrect."
msgstr ""
-#: weko_search_ui/utils.py:2936 weko_search_ui/utils.py:3079
-#: weko_search_ui/utils.py:3089
+#: weko_search_ui/utils.py:2963 weko_search_ui/utils.py:3106
+#: weko_search_ui/utils.py:3116
msgid "{} cannot be set."
msgstr ""
-#: weko_search_ui/utils.py:2945 weko_search_ui/utils.py:2949
-#: weko_search_ui/utils.py:3018 weko_search_ui/utils.py:3206
+#: weko_search_ui/utils.py:2972 weko_search_ui/utils.py:2976
+#: weko_search_ui/utils.py:3045 weko_search_ui/utils.py:3233
msgid "Specified {} is different from existing {}."
msgstr ""
-#: weko_search_ui/utils.py:2969
+#: weko_search_ui/utils.py:2996
msgid ""
"When assigning a DOI to an item, it must be associated with an index "
"whose index status is \"Public\" and Harvest Publishing is \"Public\"."
msgstr ""
-#: weko_search_ui/utils.py:2974
+#: weko_search_ui/utils.py:3001
msgid ""
"Since the item has a DOI, it must be associated with an index whose index"
" status is \"Public\" and whose Harvest Publishing is \"Public\"."
msgstr ""
-#: weko_search_ui/utils.py:2985
+#: weko_search_ui/utils.py:3012
msgid "You cannot keep an item private because it has a DOI."
msgstr ""
-#: weko_search_ui/utils.py:3039 weko_search_ui/utils.py:4335
+#: weko_search_ui/utils.py:3066 weko_search_ui/utils.py:4362
msgid "DOI_RA should be set by one of JaLC, Crossref, DataCite, NDL JaLC."
msgstr ""
-#: weko_search_ui/utils.py:3122
+#: weko_search_ui/utils.py:3149
msgid "Specified DOI was withdrawn. Please specify another DOI."
msgstr ""
-#: weko_search_ui/utils.py:3130
+#: weko_search_ui/utils.py:3157
msgid ""
"Specified DOI has been used already for another item. Please specify "
"another DOI."
msgstr ""
-#: weko_search_ui/utils.py:3226
+#: weko_search_ui/utils.py:3253
msgid ""
"Specified DOI is duplicated with another import item. Please specify "
"another DOI."
msgstr ""
-#: weko_search_ui/utils.py:3259
+#: weko_search_ui/utils.py:3286
msgid "Item Link type: '{}' is not one of {}."
msgstr ""
-#: weko_search_ui/utils.py:3263
+#: weko_search_ui/utils.py:3290
msgid "Please specify Item URL for item link."
msgstr ""
-#: weko_search_ui/utils.py:3277
+#: weko_search_ui/utils.py:3304
msgid "Specified Item Link URI and system URI do not match."
msgstr ""
-#: weko_search_ui/utils.py:3283
+#: weko_search_ui/utils.py:3310
msgid "Linking item does not exist in the system."
msgstr ""
-#: weko_search_ui/utils.py:3286
+#: weko_search_ui/utils.py:3313
msgid "Linking item already deleted in the system."
msgstr ""
-#: weko_search_ui/utils.py:3325
+#: weko_search_ui/utils.py:3352
msgid "It is not allowed to create links to the item itself."
msgstr ""
-#: weko_search_ui/utils.py:3330
+#: weko_search_ui/utils.py:3357
msgid "It is not allowed to create links other than {} between split items."
msgstr ""
-#: weko_search_ui/utils.py:3366
+#: weko_search_ui/utils.py:3393
msgid "Duplicate Item Link."
msgstr ""
-#: weko_search_ui/utils.py:3403
+#: weko_search_ui/utils.py:3430
msgid "'wk:metadataReplace' flag cannot be used when registering an item."
msgstr ""
-#: weko_search_ui/utils.py:3720
+#: weko_search_ui/utils.py:3747
msgid ""
"One of the following required values has not been "
"registered. {} "
msgstr ""
-#: weko_search_ui/utils.py:3725
+#: weko_search_ui/utils.py:3752
msgid ""
"The mapping of required items for DOI validation is not set. Please "
"recheck the following mapping settings. {}"
msgstr ""
-#: weko_search_ui/utils.py:3735
+#: weko_search_ui/utils.py:3762
msgid "The following metadata are required. {}"
msgstr ""
-#: weko_search_ui/utils.py:3740
+#: weko_search_ui/utils.py:3767
msgid "One of the following metadata is required. {} "
msgstr ""
-#: weko_search_ui/utils.py:3803 weko_search_ui/utils.py:3815
+#: weko_search_ui/utils.py:3830 weko_search_ui/utils.py:3842
msgid "Please specify the date with any format of YYYY-MM-DD, YYYY-MM, YYYY."
msgstr ""
-#: weko_search_ui/utils.py:3809
+#: weko_search_ui/utils.py:3836
msgid "Replace value of {} from {} to {}."
msgstr ""
-#: weko_search_ui/utils.py:3832
+#: weko_search_ui/utils.py:3859
msgid "Please specify PubDate with YYYY-MM-DD."
msgstr ""
-#: weko_search_ui/utils.py:3862
+#: weko_search_ui/utils.py:3889
msgid "ID is specified for the newly registered item. Ignore the ID and register."
msgstr ""
-#: weko_search_ui/utils.py:3945
+#: weko_search_ui/utils.py:3972
msgid "Please specify Open Access Date with YYYY-MM-DD."
msgstr ""
-#: weko_search_ui/utils.py:4172 weko_search_ui/utils.py:4320
-#: weko_search_ui/utils.py:4326
+#: weko_search_ui/utils.py:4199 weko_search_ui/utils.py:4347
+#: weko_search_ui/utils.py:4353
msgid "Please specify DOI prefix/suffix."
msgstr ""
-#: weko_search_ui/utils.py:4312
+#: weko_search_ui/utils.py:4339
msgid "The specified DOI is wrong and fixed with the registered DOI."
msgstr ""
-#: weko_search_ui/utils.py:4315
+#: weko_search_ui/utils.py:4342
msgid ""
"The specified DOI RA is wrong and fixed with the correct DOI RA of the "
"registered DOI."
msgstr ""
-#: weko_search_ui/utils.py:4322 weko_search_ui/utils.py:4328
+#: weko_search_ui/utils.py:4349 weko_search_ui/utils.py:4355
msgid "Please specify DOI suffix."
msgstr ""
-#: weko_search_ui/utils.py:4331
+#: weko_search_ui/utils.py:4358
msgid "Do not specify DOI suffix."
msgstr ""
-#: weko_search_ui/utils.py:4337
+#: weko_search_ui/utils.py:4364
msgid "Specified Prefix of DOI is incorrect."
msgstr ""
-#: weko_search_ui/utils.py:4369
+#: weko_search_ui/utils.py:4396
msgid ""
"Please specify the image file(gif, jpg, jpe, jpeg, png, bmp, tiff, tif) "
"for the thumbnail."
msgstr ""
-#: weko_search_ui/utils.py:5490
+#: weko_search_ui/utils.py:5517
msgid "The file specified in ({}) does not exist."
msgstr ""
-#: weko_search_ui/utils.py:5494
+#: weko_search_ui/utils.py:5521
msgid ""
"The file specified in ({}) does not exist. The file will not be "
"updated. Update only the metadata with csv/tsv contents."
msgstr ""
-#: weko_search_ui/utils.py:5781
+#: weko_search_ui/utils.py:5808
msgid "The file name specified in {} and {} do not match."
msgstr ""
@@ -1181,3 +1201,51 @@ msgstr ""
msgid "Failed to get mapping list."
msgstr ""
+#~ msgid "Bagging a parent of the current directory is not supported"
+#~ msgstr ""
+
+#~ msgid "Creating tag for directory %s"
+#~ msgstr ""
+
+#~ msgid "Bag directory %s does not exist"
+#~ msgstr ""
+
+#~ msgid "Bag directory %s does not contain a data directory"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Unable to write to the following directories and files:\n"
+#~ "%s"
+#~ msgstr ""
+
+#~ msgid "Missing permissions to move all files and directories"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "The following directories do not have read permissions:\n"
+#~ "%s"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "The following files do not have read permissions:\n"
+#~ "%s"
+#~ msgstr ""
+
+#~ msgid "Read permissions are required to calculate file fixities"
+#~ msgstr ""
+
+#~ msgid "Creating data directory"
+#~ msgstr ""
+
+#~ msgid "Creating bagit.txt"
+#~ msgstr ""
+
+#~ msgid "Creating bag-info.txt"
+#~ msgstr ""
+
+#~ msgid "An error occurred creating a bag in %s"
+#~ msgstr ""
+
+#~ msgid "`wk:metadata_replace` flag cannot be used in RO-Crate Import."
+#~ msgstr ""
+
diff --git a/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.mo b/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.mo
index 00ad3d906f..1c69f06441 100644
Binary files a/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.mo and b/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.mo differ
diff --git a/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.po b/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.po
index 0d30ef2d92..4a7b646a60 100644
--- a/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.po
+++ b/modules/weko-search-ui/weko_search_ui/translations/ja/LC_MESSAGES/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: weko-search-ui 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2025-11-11 20:49+0900\n"
+"POT-Creation-Date: 2025-12-17 13:33+0900\n"
"PO-Revision-Date: 2025-04-09 22:35+0900\n"
"Last-Translator: FULL NAME \n"
"Language: ja\n"
@@ -19,69 +19,69 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
-#: tests/conftest.py:400
+#: tests/conftest.py:406
msgid "write your own license"
msgstr ""
-#: tests/conftest.py:405
+#: tests/conftest.py:411
msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
msgstr ""
-#: tests/conftest.py:421
+#: tests/conftest.py:427
msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
msgstr ""
-#: tests/conftest.py:433
+#: tests/conftest.py:439
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
msgstr ""
-#: tests/conftest.py:448
+#: tests/conftest.py:454
msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
msgstr ""
-#: tests/conftest.py:462
+#: tests/conftest.py:468
msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
msgstr ""
-#: tests/conftest.py:477
+#: tests/conftest.py:483
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC "
"BY-NC-SA 3.0)"
msgstr ""
-#: tests/conftest.py:492
+#: tests/conftest.py:498
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-"
"NC-ND 3.0)"
msgstr ""
-#: tests/conftest.py:508
+#: tests/conftest.py:514
msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
msgstr ""
-#: tests/conftest.py:520
+#: tests/conftest.py:526
msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
msgstr ""
-#: tests/conftest.py:535
+#: tests/conftest.py:541
msgid ""
"Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND "
"4.0)"
msgstr ""
-#: tests/conftest.py:550
+#: tests/conftest.py:556
msgid ""
"Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC "
"4.0)"
msgstr ""
-#: tests/conftest.py:565
+#: tests/conftest.py:571
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
"(CC BY-NC-SA 4.0)"
msgstr ""
-#: tests/conftest.py:580
+#: tests/conftest.py:586
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 "
"International (CC BY-NC-ND 4.0)"
@@ -215,42 +215,42 @@ msgstr "ステータス"
msgid "Import Result"
msgstr "インポート結果"
-#: weko_search_ui/mapper.py:1347
+#: weko_search_ui/mapper.py:1351
msgid "\"{key}\" is required."
msgstr "「{key}」 に対応するマッピングが必要です。"
-#: weko_search_ui/mapper.py:1368
+#: weko_search_ui/mapper.py:1372
msgid "\"{key}\" is not in itemtype."
msgstr "「{key}」 はアイテムタイプに存在しません。"
-#: weko_search_ui/mapper.py:1370
+#: weko_search_ui/mapper.py:1374
msgid "\"{key}\" is not in itemtype, did you mean \"{similar_key}\"?"
msgstr "「{key}」 はアイテムタイプに存在しません。「{similar_key}」であれば存在します。"
-#: weko_search_ui/mapper.py:1491
+#: weko_search_ui/mapper.py:1495
#, python-format
msgid ""
"Cannot map to item type from json-ld; Mapping is not defined for the "
"metadata, \"%(key)s\": \"%(value)s\""
msgstr "対応するマッピングが定義されてないため、このメタデータはアイテムタイプに変換できません。\"%(key)s\": \"%(value)s\""
-#: weko_search_ui/mapper.py:1517
+#: weko_search_ui/mapper.py:1521
#, python-format
msgid ""
"Cannot map to item type from json-ld; Not found mapping destination for "
"the metadata, \"%(key)s\": \"%(value)s\""
msgstr "マッピング先が見つからないため、このメタデータはアイテムタイプに変換できません。\"%(key)s\": \"%(value)s\""
-#: weko_search_ui/mapper.py:1527
+#: weko_search_ui/mapper.py:1531
#, python-format
msgid "Failed to set metadata for json-ld, \"%(key)s\": \"%(value)s\""
msgstr "アイテムタイプへのマッピングに失敗しました。\"%(key)s\": \"%(value)s\""
-#: weko_search_ui/mapper.py:1547
+#: weko_search_ui/mapper.py:1553
msgid "Metadata which could not be mapped to item type will be set in 'Extra'."
msgstr "アイテムタイプにマッピングできなかったメタデータは、「Extra」プロパティに登録されます。"
-#: weko_search_ui/mapper.py:1551
+#: weko_search_ui/mapper.py:1557
msgid "Metadata which could not be mapped to item type will be discarded."
msgstr "アイテムタイプにマッピングできなかったメタデータは破棄されます。"
@@ -348,259 +348,269 @@ msgid ""
" the file is UTF-8 encoded."
msgstr ""
-#: weko_search_ui/utils.py:1454
+#: weko_search_ui/utils.py:1455
msgid "Please specify item ID by half-width number."
msgstr "アイテムIDは半角数字で指定してください。"
-#: weko_search_ui/utils.py:1469
+#: weko_search_ui/utils.py:1477
+#, python-format
+msgid "Replace value of %(target_path)s from %(old_value)s to '%(new_value)s'."
+msgstr "%(target_path)sの値を%(old_value)sから'%(new_value)s'へ置き換えました。"
+
+#: weko_search_ui/utils.py:1489
msgid "Specified item type does not exist."
msgstr "指定されたアイテムタイプが存在していません。"
-#: weko_search_ui/utils.py:1540
+#: weko_search_ui/utils.py:1495
+#, python-brace-format, python-format
+msgid "Specified %(type)s is different from existing %(existing_type)s."
+msgstr "指定された%(type)sは登録している%(existing_type)sと異なっています。"
+
+#: weko_search_ui/utils.py:1567
msgid "The same item may have been registered."
msgstr "同じアイテムが登録されている可能性があります。"
-#: weko_search_ui/utils.py:1570
+#: weko_search_ui/utils.py:1597
msgid "Specified URI and system URI do not match."
msgstr "指定されたURIとシステムURIが一致しません。"
-#: weko_search_ui/utils.py:1582
+#: weko_search_ui/utils.py:1609
msgid "Item does not exist in the system."
msgstr "アイテムがシステムに存在しません。"
-#: weko_search_ui/utils.py:1589
+#: weko_search_ui/utils.py:1616
msgid "Item already DELETED in the system."
msgstr "アイテムは削除済です。"
-#: weko_search_ui/utils.py:1606
+#: weko_search_ui/utils.py:1633
msgid "Please specify either \"Keep\" or \"Upgrade\"."
msgstr "Keep、Upgradeのいずれかを指定してください。"
-#: weko_search_ui/utils.py:2565
+#: weko_search_ui/utils.py:2592
msgid "Title is required item."
msgstr "タイトルは必須項目です。"
-#: weko_search_ui/utils.py:2582
+#: weko_search_ui/utils.py:2609
msgid "{} is required item."
msgstr "{}は必須項目です。"
-#: weko_search_ui/utils.py:2585
+#: weko_search_ui/utils.py:2612
msgid "Please set \"public\" or \"private\" for {}."
msgstr "{}はpublic、privateのいずれかを設定してください。"
-#: weko_search_ui/utils.py:2626
+#: weko_search_ui/utils.py:2653
msgid "The specified {} does not exist in system."
msgstr "指定された{}はシステムに存在しません。"
-#: weko_search_ui/utils.py:2636
+#: weko_search_ui/utils.py:2663
msgid "Specified {} does not match with existing index."
msgstr "指定された{}はシステムのものと一致していません。"
-#: weko_search_ui/utils.py:2680
+#: weko_search_ui/utils.py:2707
msgid "Your role cannot register items in this index."
msgstr "ロールの権限が足りずこのインデックスにアイテム登録ができません。"
-#: weko_search_ui/utils.py:2701
+#: weko_search_ui/utils.py:2728
msgid "Both of IndexID and POS_INDEX are not being set."
msgstr "IndexID, POS_INDEXがどちらも設定されていません。"
-#: weko_search_ui/utils.py:2747 weko_search_ui/utils.py:2772
+#: weko_search_ui/utils.py:2774 weko_search_ui/utils.py:2799
msgid "Specified {} is invalid."
msgstr "指定された{}は不正です。"
-#: weko_search_ui/utils.py:2806
+#: weko_search_ui/utils.py:2833
msgid "If there is a info of content file, terms of use cannot be set."
msgstr "コンテンツファイル情報がある場合、利用規約は設定できません。"
-#: weko_search_ui/utils.py:2813 weko_search_ui/utils.py:6063
+#: weko_search_ui/utils.py:2840 weko_search_ui/utils.py:6090
msgid "The specified provinding method does not exist in the system"
msgstr "指定する提供方法はシステムに存在しません。"
-#: weko_search_ui/utils.py:2818 weko_search_ui/utils.py:6058
+#: weko_search_ui/utils.py:2845 weko_search_ui/utils.py:6085
msgid "The specified terms does not exist in the system"
msgstr "指定する利用規約はシステムに存在しません。"
-#: weko_search_ui/utils.py:2910 weko_search_ui/utils.py:2943
-#: weko_search_ui/utils.py:3035 weko_search_ui/utils.py:3147
-#: weko_search_ui/utils.py:3169 weko_search_ui/utils.py:3204
+#: weko_search_ui/utils.py:2937 weko_search_ui/utils.py:2970
+#: weko_search_ui/utils.py:3062 weko_search_ui/utils.py:3174
+#: weko_search_ui/utils.py:3196 weko_search_ui/utils.py:3231
msgid "Please specify {}."
msgstr "{}を設定してください。"
-#: weko_search_ui/utils.py:2913 weko_search_ui/utils.py:3150
+#: weko_search_ui/utils.py:2940 weko_search_ui/utils.py:3177
msgid "The specified {} exceeds the maximum length."
msgstr "指定された{}が最大長を超えています。"
-#: weko_search_ui/utils.py:2928 weko_search_ui/utils.py:3085
-#: weko_search_ui/utils.py:3096 weko_search_ui/utils.py:3165
+#: weko_search_ui/utils.py:2955 weko_search_ui/utils.py:3112
+#: weko_search_ui/utils.py:3123 weko_search_ui/utils.py:3192
msgid "Specified Prefix of {} is incorrect."
msgstr "指定された{}のPrefixが誤っています。"
-#: weko_search_ui/utils.py:2936 weko_search_ui/utils.py:3079
-#: weko_search_ui/utils.py:3089
+#: weko_search_ui/utils.py:2963 weko_search_ui/utils.py:3106
+#: weko_search_ui/utils.py:3116
msgid "{} cannot be set."
msgstr "{}は設定できません。"
-#: weko_search_ui/utils.py:2945 weko_search_ui/utils.py:2949
-#: weko_search_ui/utils.py:3018 weko_search_ui/utils.py:3206
+#: weko_search_ui/utils.py:2972 weko_search_ui/utils.py:2976
+#: weko_search_ui/utils.py:3045 weko_search_ui/utils.py:3233
msgid "Specified {} is different from existing {}."
msgstr "指定された{}は登録している{}と異なっています。"
-#: weko_search_ui/utils.py:2969
+#: weko_search_ui/utils.py:2996
msgid ""
"When assigning a DOI to an item, it must be associated with an index "
"whose index status is \"Public\" and Harvest Publishing is \"Public\"."
msgstr ""
-#: weko_search_ui/utils.py:2974
+#: weko_search_ui/utils.py:3001
msgid ""
"Since the item has a DOI, it must be associated with an index whose index"
" status is \"Public\" and whose Harvest Publishing is \"Public\"."
msgstr "アイテムにDOIが付与されているため、インデックス状態が「公開」かつハーベスト公開が「公開」のインデックスに関連付けが必要です。"
-#: weko_search_ui/utils.py:2985
+#: weko_search_ui/utils.py:3012
msgid "You cannot keep an item private because it has a DOI."
msgstr "アイテムにDOIが付与されているため、アイテムを非公開にすることはできません。"
-#: weko_search_ui/utils.py:3039 weko_search_ui/utils.py:4335
+#: weko_search_ui/utils.py:3066 weko_search_ui/utils.py:4362
msgid "DOI_RA should be set by one of JaLC, Crossref, DataCite, NDL JaLC."
msgstr "DOI_RAはJaLC,Crossref,DataCite,NDL JaLCのいずれかを設定してください。"
-#: weko_search_ui/utils.py:3122
+#: weko_search_ui/utils.py:3149
msgid "Specified DOI was withdrawn. Please specify another DOI."
msgstr "指定されたDOIは取り下げられました。別のDOIを指定してください。"
-#: weko_search_ui/utils.py:3130
+#: weko_search_ui/utils.py:3157
msgid ""
"Specified DOI has been used already for another item. Please specify "
"another DOI."
msgstr "指定されたDOIは既に別のアイテムに付与されています。別のDOIを指定してください。"
-#: weko_search_ui/utils.py:3226
+#: weko_search_ui/utils.py:3253
msgid ""
"Specified DOI is duplicated with another import item. Please specify "
"another DOI."
msgstr "指定されたDOIはインポートファイル内で重複しています。別のDOIを指定してください。"
-#: weko_search_ui/utils.py:3259
+#: weko_search_ui/utils.py:3286
msgid "Item Link type: '{}' is not one of {}."
msgstr "リンクタイプ'{}'は次の決められた選択肢に含まれていません。{}"
-#: weko_search_ui/utils.py:3263
+#: weko_search_ui/utils.py:3290
msgid "Please specify Item URL for item link."
msgstr "アイテムリンク先のURLを指定してください。"
-#: weko_search_ui/utils.py:3277
+#: weko_search_ui/utils.py:3304
msgid "Specified Item Link URI and system URI do not match."
msgstr "指定されたアイテムリンク先URIとシステムURIが一致しません。"
-#: weko_search_ui/utils.py:3283
+#: weko_search_ui/utils.py:3310
msgid "Linking item does not exist in the system."
msgstr "リンク先アイテムがシステムに存在しません。"
-#: weko_search_ui/utils.py:3286
+#: weko_search_ui/utils.py:3313
msgid "Linking item already deleted in the system."
msgstr "リンク先アイテムは削除済です。"
-#: weko_search_ui/utils.py:3325
+#: weko_search_ui/utils.py:3352
msgid "It is not allowed to create links to the item itself."
msgstr "自身へのアイテムリンクを作成することはできません。"
-#: weko_search_ui/utils.py:3330
+#: weko_search_ui/utils.py:3357
msgid "It is not allowed to create links other than {} between split items."
msgstr "分割したアイテム間で{}以外のリンクを作成することはできません。"
-#: weko_search_ui/utils.py:3366
+#: weko_search_ui/utils.py:3393
msgid "Duplicate Item Link."
msgstr "重複するアイテムリンクを作成することはできません。"
-#: weko_search_ui/utils.py:3403
+#: weko_search_ui/utils.py:3430
msgid "'wk:metadataReplace' flag cannot be used when registering an item."
msgstr "RO-Crate インポートでは、`wk:metadataReplace`フラグを有効にできません。"
-#: weko_search_ui/utils.py:3720
+#: weko_search_ui/utils.py:3747
msgid ""
"One of the following required values has not been "
"registered. {} "
msgstr "次のいずれかの必要値が登録していません。 {} "
-#: weko_search_ui/utils.py:3725
+#: weko_search_ui/utils.py:3752
msgid ""
"The mapping of required items for DOI validation is not set. Please "
"recheck the following mapping settings. {}"
msgstr ""
-#: weko_search_ui/utils.py:3735
+#: weko_search_ui/utils.py:3762
msgid "The following metadata are required. {}"
msgstr "{}は必須項目です。"
-#: weko_search_ui/utils.py:3740
+#: weko_search_ui/utils.py:3767
msgid "One of the following metadata is required. {} "
msgstr "{}のいずれかを設定してください。"
-#: weko_search_ui/utils.py:3803 weko_search_ui/utils.py:3815
+#: weko_search_ui/utils.py:3830 weko_search_ui/utils.py:3842
msgid "Please specify the date with any format of YYYY-MM-DD, YYYY-MM, YYYY."
msgstr "日付はYYYY-MM-DD、YYYY-MM、YYYYのいずれかで指定してください。"
-#: weko_search_ui/utils.py:3809
+#: weko_search_ui/utils.py:3836
msgid "Replace value of {} from {} to {}."
msgstr "{}の値を{}から{}へ置き換えました。"
-#: weko_search_ui/utils.py:3832
+#: weko_search_ui/utils.py:3859
msgid "Please specify PubDate with YYYY-MM-DD."
msgstr "公開日はYYYY-MM-DDで指定してください。"
-#: weko_search_ui/utils.py:3862
+#: weko_search_ui/utils.py:3889
msgid "ID is specified for the newly registered item. Ignore the ID and register."
msgstr "新規登録アイテムにIDが指定されています。IDを無視して登録を行います。"
-#: weko_search_ui/utils.py:3945
+#: weko_search_ui/utils.py:3972
msgid "Please specify Open Access Date with YYYY-MM-DD."
msgstr "オープンアクセスの日付はYYYY-MM-DDで指定してください。"
-#: weko_search_ui/utils.py:4172 weko_search_ui/utils.py:4320
-#: weko_search_ui/utils.py:4326
+#: weko_search_ui/utils.py:4199 weko_search_ui/utils.py:4347
+#: weko_search_ui/utils.py:4353
msgid "Please specify DOI prefix/suffix."
msgstr "DOIは prefix/suffix の形式で指定して下さい。"
-#: weko_search_ui/utils.py:4312
+#: weko_search_ui/utils.py:4339
msgid "The specified DOI is wrong and fixed with the registered DOI."
msgstr ""
-#: weko_search_ui/utils.py:4315
+#: weko_search_ui/utils.py:4342
msgid ""
"The specified DOI RA is wrong and fixed with the correct DOI RA of the "
"registered DOI."
msgstr ""
-#: weko_search_ui/utils.py:4322 weko_search_ui/utils.py:4328
+#: weko_search_ui/utils.py:4349 weko_search_ui/utils.py:4355
msgid "Please specify DOI suffix."
msgstr ""
-#: weko_search_ui/utils.py:4331
+#: weko_search_ui/utils.py:4358
msgid "Do not specify DOI suffix."
msgstr ""
-#: weko_search_ui/utils.py:4337
+#: weko_search_ui/utils.py:4364
msgid "Specified Prefix of DOI is incorrect."
msgstr ""
-#: weko_search_ui/utils.py:4369
+#: weko_search_ui/utils.py:4396
msgid ""
"Please specify the image file(gif, jpg, jpe, jpeg, png, bmp, tiff, tif) "
"for the thumbnail."
msgstr "サムネイルは画像ファイル(gif, jpg, jpe, jpeg, png, bmp, tiff, tif)を指定してください。"
-#: weko_search_ui/utils.py:5490
+#: weko_search_ui/utils.py:5517
msgid "The file specified in ({}) does not exist."
msgstr "({})に指定したファイルが存在しません。"
-#: weko_search_ui/utils.py:5494
+#: weko_search_ui/utils.py:5521
msgid ""
"The file specified in ({}) does not exist. The file will not be "
"updated. Update only the metadata with csv/tsv contents."
msgstr "({})に指定したファイルが存在しません。 ファイルの更新はしません。csv/tsv内容でメタデータのみ更新します。"
-#: weko_search_ui/utils.py:5781
+#: weko_search_ui/utils.py:5808
msgid "The file name specified in {} and {} do not match."
msgstr "{}に指定されたファイル名と{}が一致しません。"
@@ -1181,3 +1191,48 @@ msgstr "マッピング"
msgid "Failed to get mapping list."
msgstr "マッピング定義リストの取得に失敗しました。"
+#~ msgid "Bagging a parent of the current directory is not supported"
+#~ msgstr ""
+
+#~ msgid "Creating tag for directory %s"
+#~ msgstr ""
+
+#~ msgid "Bag directory %s does not exist"
+#~ msgstr ""
+
+#~ msgid "Bag directory %s does not contain a data directory"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Unable to write to the following directories and files:\n"
+#~ "%s"
+#~ msgstr ""
+
+#~ msgid "Missing permissions to move all files and directories"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "The following directories do not have read permissions:\n"
+#~ "%s"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "The following files do not have read permissions:\n"
+#~ "%s"
+#~ msgstr ""
+
+#~ msgid "Read permissions are required to calculate file fixities"
+#~ msgstr ""
+
+#~ msgid "Creating data directory"
+#~ msgstr ""
+
+#~ msgid "Creating bagit.txt"
+#~ msgstr ""
+
+#~ msgid "Creating bag-info.txt"
+#~ msgstr ""
+
+#~ msgid "An error occurred creating a bag in %s"
+#~ msgstr ""
+
diff --git a/modules/weko-search-ui/weko_search_ui/translations/messages.pot b/modules/weko-search-ui/weko_search_ui/translations/messages.pot
index 0a30a6c702..66522c42fb 100644
--- a/modules/weko-search-ui/weko_search_ui/translations/messages.pot
+++ b/modules/weko-search-ui/weko_search_ui/translations/messages.pot
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: weko-search-ui 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2025-11-11 20:49+0900\n"
+"POT-Creation-Date: 2025-12-17 13:33+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -18,69 +18,69 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
-#: tests/conftest.py:400
+#: tests/conftest.py:406
msgid "write your own license"
msgstr ""
-#: tests/conftest.py:405
+#: tests/conftest.py:411
msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
msgstr ""
-#: tests/conftest.py:421
+#: tests/conftest.py:427
msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
msgstr ""
-#: tests/conftest.py:433
+#: tests/conftest.py:439
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
msgstr ""
-#: tests/conftest.py:448
+#: tests/conftest.py:454
msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
msgstr ""
-#: tests/conftest.py:462
+#: tests/conftest.py:468
msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
msgstr ""
-#: tests/conftest.py:477
+#: tests/conftest.py:483
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC "
"BY-NC-SA 3.0)"
msgstr ""
-#: tests/conftest.py:492
+#: tests/conftest.py:498
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-"
"NC-ND 3.0)"
msgstr ""
-#: tests/conftest.py:508
+#: tests/conftest.py:514
msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
msgstr ""
-#: tests/conftest.py:520
+#: tests/conftest.py:526
msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
msgstr ""
-#: tests/conftest.py:535
+#: tests/conftest.py:541
msgid ""
"Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND "
"4.0)"
msgstr ""
-#: tests/conftest.py:550
+#: tests/conftest.py:556
msgid ""
"Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC "
"4.0)"
msgstr ""
-#: tests/conftest.py:565
+#: tests/conftest.py:571
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
"(CC BY-NC-SA 4.0)"
msgstr ""
-#: tests/conftest.py:580
+#: tests/conftest.py:586
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 "
"International (CC BY-NC-ND 4.0)"
@@ -214,42 +214,42 @@ msgstr ""
msgid "Import Result"
msgstr ""
-#: weko_search_ui/mapper.py:1347
+#: weko_search_ui/mapper.py:1351
msgid "\"{key}\" is required."
msgstr ""
-#: weko_search_ui/mapper.py:1368
+#: weko_search_ui/mapper.py:1372
msgid "\"{key}\" is not in itemtype."
msgstr ""
-#: weko_search_ui/mapper.py:1370
+#: weko_search_ui/mapper.py:1374
msgid "\"{key}\" is not in itemtype, did you mean \"{similar_key}\"?"
msgstr ""
-#: weko_search_ui/mapper.py:1491
+#: weko_search_ui/mapper.py:1495
#, python-format
msgid ""
"Cannot map to item type from json-ld; Mapping is not defined for the "
"metadata, \"%(key)s\": \"%(value)s\""
msgstr ""
-#: weko_search_ui/mapper.py:1517
+#: weko_search_ui/mapper.py:1521
#, python-format
msgid ""
"Cannot map to item type from json-ld; Not found mapping destination for "
"the metadata, \"%(key)s\": \"%(value)s\""
msgstr ""
-#: weko_search_ui/mapper.py:1527
+#: weko_search_ui/mapper.py:1531
#, python-format
msgid "Failed to set metadata for json-ld, \"%(key)s\": \"%(value)s\""
msgstr ""
-#: weko_search_ui/mapper.py:1547
+#: weko_search_ui/mapper.py:1553
msgid "Metadata which could not be mapped to item type will be set in 'Extra'."
msgstr ""
-#: weko_search_ui/mapper.py:1551
+#: weko_search_ui/mapper.py:1557
msgid "Metadata which could not be mapped to item type will be discarded."
msgstr ""
@@ -347,259 +347,269 @@ msgid ""
" the file is UTF-8 encoded."
msgstr ""
-#: weko_search_ui/utils.py:1454
+#: weko_search_ui/utils.py:1455
msgid "Please specify item ID by half-width number."
msgstr ""
-#: weko_search_ui/utils.py:1469
+#: weko_search_ui/utils.py:1477
+#, python-format
+msgid "Replace value of %(target_path)s from %(old_value)s to '%(new_value)s'."
+msgstr ""
+
+#: weko_search_ui/utils.py:1489
msgid "Specified item type does not exist."
msgstr ""
-#: weko_search_ui/utils.py:1540
+#: weko_search_ui/utils.py:1495
+#, python-format
+msgid "Specified %(type)s is different from existing %(existing_type)s."
+msgstr ""
+
+#: weko_search_ui/utils.py:1567
msgid "The same item may have been registered."
msgstr ""
-#: weko_search_ui/utils.py:1570
+#: weko_search_ui/utils.py:1597
msgid "Specified URI and system URI do not match."
msgstr ""
-#: weko_search_ui/utils.py:1582
+#: weko_search_ui/utils.py:1609
msgid "Item does not exist in the system."
msgstr ""
-#: weko_search_ui/utils.py:1589
+#: weko_search_ui/utils.py:1616
msgid "Item already DELETED in the system."
msgstr ""
-#: weko_search_ui/utils.py:1606
+#: weko_search_ui/utils.py:1633
msgid "Please specify either \"Keep\" or \"Upgrade\"."
msgstr ""
-#: weko_search_ui/utils.py:2565
+#: weko_search_ui/utils.py:2592
msgid "Title is required item."
msgstr ""
-#: weko_search_ui/utils.py:2582
+#: weko_search_ui/utils.py:2609
msgid "{} is required item."
msgstr ""
-#: weko_search_ui/utils.py:2585
+#: weko_search_ui/utils.py:2612
msgid "Please set \"public\" or \"private\" for {}."
msgstr ""
-#: weko_search_ui/utils.py:2626
+#: weko_search_ui/utils.py:2653
msgid "The specified {} does not exist in system."
msgstr ""
-#: weko_search_ui/utils.py:2636
+#: weko_search_ui/utils.py:2663
msgid "Specified {} does not match with existing index."
msgstr ""
-#: weko_search_ui/utils.py:2680
+#: weko_search_ui/utils.py:2707
msgid "Your role cannot register items in this index."
msgstr ""
-#: weko_search_ui/utils.py:2701
+#: weko_search_ui/utils.py:2728
msgid "Both of IndexID and POS_INDEX are not being set."
msgstr ""
-#: weko_search_ui/utils.py:2747 weko_search_ui/utils.py:2772
+#: weko_search_ui/utils.py:2774 weko_search_ui/utils.py:2799
msgid "Specified {} is invalid."
msgstr ""
-#: weko_search_ui/utils.py:2806
+#: weko_search_ui/utils.py:2833
msgid "If there is a info of content file, terms of use cannot be set."
msgstr ""
-#: weko_search_ui/utils.py:2813 weko_search_ui/utils.py:6063
+#: weko_search_ui/utils.py:2840 weko_search_ui/utils.py:6090
msgid "The specified provinding method does not exist in the system"
msgstr ""
-#: weko_search_ui/utils.py:2818 weko_search_ui/utils.py:6058
+#: weko_search_ui/utils.py:2845 weko_search_ui/utils.py:6085
msgid "The specified terms does not exist in the system"
msgstr ""
-#: weko_search_ui/utils.py:2910 weko_search_ui/utils.py:2943
-#: weko_search_ui/utils.py:3035 weko_search_ui/utils.py:3147
-#: weko_search_ui/utils.py:3169 weko_search_ui/utils.py:3204
+#: weko_search_ui/utils.py:2937 weko_search_ui/utils.py:2970
+#: weko_search_ui/utils.py:3062 weko_search_ui/utils.py:3174
+#: weko_search_ui/utils.py:3196 weko_search_ui/utils.py:3231
msgid "Please specify {}."
msgstr ""
-#: weko_search_ui/utils.py:2913 weko_search_ui/utils.py:3150
+#: weko_search_ui/utils.py:2940 weko_search_ui/utils.py:3177
msgid "The specified {} exceeds the maximum length."
msgstr ""
-#: weko_search_ui/utils.py:2928 weko_search_ui/utils.py:3085
-#: weko_search_ui/utils.py:3096 weko_search_ui/utils.py:3165
+#: weko_search_ui/utils.py:2955 weko_search_ui/utils.py:3112
+#: weko_search_ui/utils.py:3123 weko_search_ui/utils.py:3192
msgid "Specified Prefix of {} is incorrect."
msgstr ""
-#: weko_search_ui/utils.py:2936 weko_search_ui/utils.py:3079
-#: weko_search_ui/utils.py:3089
+#: weko_search_ui/utils.py:2963 weko_search_ui/utils.py:3106
+#: weko_search_ui/utils.py:3116
msgid "{} cannot be set."
msgstr ""
-#: weko_search_ui/utils.py:2945 weko_search_ui/utils.py:2949
-#: weko_search_ui/utils.py:3018 weko_search_ui/utils.py:3206
+#: weko_search_ui/utils.py:2972 weko_search_ui/utils.py:2976
+#: weko_search_ui/utils.py:3045 weko_search_ui/utils.py:3233
msgid "Specified {} is different from existing {}."
msgstr ""
-#: weko_search_ui/utils.py:2969
+#: weko_search_ui/utils.py:2996
msgid ""
"When assigning a DOI to an item, it must be associated with an index "
"whose index status is \"Public\" and Harvest Publishing is \"Public\"."
msgstr ""
-#: weko_search_ui/utils.py:2974
+#: weko_search_ui/utils.py:3001
msgid ""
"Since the item has a DOI, it must be associated with an index whose index"
" status is \"Public\" and whose Harvest Publishing is \"Public\"."
msgstr ""
-#: weko_search_ui/utils.py:2985
+#: weko_search_ui/utils.py:3012
msgid "You cannot keep an item private because it has a DOI."
msgstr ""
-#: weko_search_ui/utils.py:3039 weko_search_ui/utils.py:4335
+#: weko_search_ui/utils.py:3066 weko_search_ui/utils.py:4362
msgid "DOI_RA should be set by one of JaLC, Crossref, DataCite, NDL JaLC."
msgstr ""
-#: weko_search_ui/utils.py:3122
+#: weko_search_ui/utils.py:3149
msgid "Specified DOI was withdrawn. Please specify another DOI."
msgstr ""
-#: weko_search_ui/utils.py:3130
+#: weko_search_ui/utils.py:3157
msgid ""
"Specified DOI has been used already for another item. Please specify "
"another DOI."
msgstr ""
-#: weko_search_ui/utils.py:3226
+#: weko_search_ui/utils.py:3253
msgid ""
"Specified DOI is duplicated with another import item. Please specify "
"another DOI."
msgstr ""
-#: weko_search_ui/utils.py:3259
+#: weko_search_ui/utils.py:3286
msgid "Item Link type: '{}' is not one of {}."
msgstr ""
-#: weko_search_ui/utils.py:3263
+#: weko_search_ui/utils.py:3290
msgid "Please specify Item URL for item link."
msgstr ""
-#: weko_search_ui/utils.py:3277
+#: weko_search_ui/utils.py:3304
msgid "Specified Item Link URI and system URI do not match."
msgstr ""
-#: weko_search_ui/utils.py:3283
+#: weko_search_ui/utils.py:3310
msgid "Linking item does not exist in the system."
msgstr ""
-#: weko_search_ui/utils.py:3286
+#: weko_search_ui/utils.py:3313
msgid "Linking item already deleted in the system."
msgstr ""
-#: weko_search_ui/utils.py:3325
+#: weko_search_ui/utils.py:3352
msgid "It is not allowed to create links to the item itself."
msgstr ""
-#: weko_search_ui/utils.py:3330
+#: weko_search_ui/utils.py:3357
msgid "It is not allowed to create links other than {} between split items."
msgstr ""
-#: weko_search_ui/utils.py:3366
+#: weko_search_ui/utils.py:3393
msgid "Duplicate Item Link."
msgstr ""
-#: weko_search_ui/utils.py:3403
+#: weko_search_ui/utils.py:3430
msgid "'wk:metadataReplace' flag cannot be used when registering an item."
msgstr ""
-#: weko_search_ui/utils.py:3720
+#: weko_search_ui/utils.py:3747
msgid ""
"One of the following required values has not been "
"registered. {} "
msgstr ""
-#: weko_search_ui/utils.py:3725
+#: weko_search_ui/utils.py:3752
msgid ""
"The mapping of required items for DOI validation is not set. Please "
"recheck the following mapping settings. {}"
msgstr ""
-#: weko_search_ui/utils.py:3735
+#: weko_search_ui/utils.py:3762
msgid "The following metadata are required. {}"
msgstr ""
-#: weko_search_ui/utils.py:3740
+#: weko_search_ui/utils.py:3767
msgid "One of the following metadata is required. {} "
msgstr ""
-#: weko_search_ui/utils.py:3803 weko_search_ui/utils.py:3815
+#: weko_search_ui/utils.py:3830 weko_search_ui/utils.py:3842
msgid "Please specify the date with any format of YYYY-MM-DD, YYYY-MM, YYYY."
msgstr ""
-#: weko_search_ui/utils.py:3809
+#: weko_search_ui/utils.py:3836
msgid "Replace value of {} from {} to {}."
msgstr ""
-#: weko_search_ui/utils.py:3832
+#: weko_search_ui/utils.py:3859
msgid "Please specify PubDate with YYYY-MM-DD."
msgstr ""
-#: weko_search_ui/utils.py:3862
+#: weko_search_ui/utils.py:3889
msgid "ID is specified for the newly registered item. Ignore the ID and register."
msgstr ""
-#: weko_search_ui/utils.py:3945
+#: weko_search_ui/utils.py:3972
msgid "Please specify Open Access Date with YYYY-MM-DD."
msgstr ""
-#: weko_search_ui/utils.py:4172 weko_search_ui/utils.py:4320
-#: weko_search_ui/utils.py:4326
+#: weko_search_ui/utils.py:4199 weko_search_ui/utils.py:4347
+#: weko_search_ui/utils.py:4353
msgid "Please specify DOI prefix/suffix."
msgstr ""
-#: weko_search_ui/utils.py:4312
+#: weko_search_ui/utils.py:4339
msgid "The specified DOI is wrong and fixed with the registered DOI."
msgstr ""
-#: weko_search_ui/utils.py:4315
+#: weko_search_ui/utils.py:4342
msgid ""
"The specified DOI RA is wrong and fixed with the correct DOI RA of the "
"registered DOI."
msgstr ""
-#: weko_search_ui/utils.py:4322 weko_search_ui/utils.py:4328
+#: weko_search_ui/utils.py:4349 weko_search_ui/utils.py:4355
msgid "Please specify DOI suffix."
msgstr ""
-#: weko_search_ui/utils.py:4331
+#: weko_search_ui/utils.py:4358
msgid "Do not specify DOI suffix."
msgstr ""
-#: weko_search_ui/utils.py:4337
+#: weko_search_ui/utils.py:4364
msgid "Specified Prefix of DOI is incorrect."
msgstr ""
-#: weko_search_ui/utils.py:4369
+#: weko_search_ui/utils.py:4396
msgid ""
"Please specify the image file(gif, jpg, jpe, jpeg, png, bmp, tiff, tif) "
"for the thumbnail."
msgstr ""
-#: weko_search_ui/utils.py:5490
+#: weko_search_ui/utils.py:5517
msgid "The file specified in ({}) does not exist."
msgstr ""
-#: weko_search_ui/utils.py:5494
+#: weko_search_ui/utils.py:5521
msgid ""
"The file specified in ({}) does not exist. The file will not be "
"updated. Update only the metadata with csv/tsv contents."
msgstr ""
-#: weko_search_ui/utils.py:5781
+#: weko_search_ui/utils.py:5808
msgid "The file name specified in {} and {} do not match."
msgstr ""
diff --git a/modules/weko-search-ui/weko_search_ui/utils.py b/modules/weko-search-ui/weko_search_ui/utils.py
index 7782a5e6d5..3c02cde998 100644
--- a/modules/weko-search-ui/weko_search_ui/utils.py
+++ b/modules/weko-search-ui/weko_search_ui/utils.py
@@ -574,7 +574,7 @@ def check_tsv_import_items(
list_record = handle_check_exist_record(list_record)
handle_item_title(list_record)
-
+
list_record = handle_check_date(list_record)
handle_check_id(list_record)
@@ -594,7 +594,7 @@ def check_tsv_import_items(
handle_check_authors_prefix(list_record)
handle_check_authors_affiliation(list_record)
-
+
if not is_gakuninrdm:
handle_check_cnri(list_record)
handle_check_doi_indexes(list_record)
@@ -768,7 +768,7 @@ def unpackage_import_file(data_path: str, file_name: str, file_format: str, forc
record["uri"] = None
current_app.logger.debug('list_record2: {}'.format(list_record))
-
+
handle_set_change_identifier_flag(list_record, is_change_identifier)
handle_fill_system_item(list_record)
@@ -930,7 +930,8 @@ def check_jsonld_import_items(
with open(f"{data_path}/{json_name}", "r") as f:
json_ld = json.load(f)
- item_metadatas, _fromat = mapper.to_item_metadata(json_ld)
+ mapper.data_path = data_path
+ item_metadatas, _ = mapper.to_item_metadata(json_ld)
list_record = [
{
"$schema": f"/items/jsonschema/{item_type.id}",
@@ -1262,7 +1263,7 @@ def read_stats_file(file_path: str, file_name: str, file_format: str) -> dict:
current_app.logger.debug(
"duplication_item_ids: {}".format(duplication_item_ids)
)
-
+
if duplication_item_ids:
msg = _("The following metadata keys are duplicated." " {}")
raise Exception(
@@ -1283,7 +1284,7 @@ def read_stats_file(file_path: str, file_name: str, file_format: str) -> dict:
current_app.logger.debug(
"not_consistent_list: {}".format(not_consistent_list)
)
-
+
if not_consistent_list:
msg = _(
"The item does not consistent with the "
@@ -1302,7 +1303,7 @@ def read_stats_file(file_path: str, file_name: str, file_format: str) -> dict:
current_app.logger.debug(
"item_path_not_existed: {}".format(item_path_not_existed)
)
-
+
elif (num == 4 or num == 5) and data_row[0].startswith("#"):
continue
@@ -1310,7 +1311,7 @@ def read_stats_file(file_path: str, file_name: str, file_format: str) -> dict:
data_parse_metadata = parse_to_json_form(
zip(item_path, data_row), item_path_not_existed
)
-
+
if not data_parse_metadata:
raise Exception(
{"error_msg": _("Cannot read {} file correctly.".format(file_format.upper()))}
@@ -1446,6 +1447,7 @@ def handle_validate_item_import(list_record, schema) -> list:
v2 = Draft4Validator(schema) if schema else None
for record in list_record:
errors = record.get("errors") or []
+ warnings = []
record_id = record.get("id")
if record_id and (
not represents_int(record_id) or re.search(r"([0-9])", record_id)
@@ -1457,19 +1459,45 @@ def handle_validate_item_import(list_record, schema) -> list:
if record.get("metadata"):
if v2:
a = v2.iter_errors(record.get("metadata"))
+ for error in a:
+ if (
+ error.validator == "type"
+ and error.validator_value == "string"
+ and isinstance(error.instance, int)
+ ):
+ target = record["metadata"]
+ path_list = list(error.path)
+ for key in path_list[:-1]:
+ target = target[key]
+ last_key = path_list[-1]
+ target[last_key] = str(target[last_key])
+ target_path = ".".join([str(p) for p in path_list[:-2]])
+ warnings.append(
+ _("Replace value of %(target_path)s from %(old_value)s to '%(new_value)s'.",
+ target_path=target_path, old_value=target[last_key], new_value=str(target[last_key])
+ )
+ )
+ b = v2.iter_errors(record.get("metadata"))
if current_i18n.language == "ja":
_errors = []
- for error in a:
+ for error in b:
_errors.append(handle_convert_validate_msg_to_jp(error.message))
errors = errors + _errors
else:
- errors = errors + [error.message for error in a]
+ errors = errors + [error.message for error in b]
else:
errors = errors = errors + [_("Specified item type does not exist.")]
- item_error = dict(**record)
- item_error["errors"] = errors if len(errors) else None
- result.append(item_error)
+ records = dict(**record)
+ records["errors"] = errors if len(errors) else None
+ if len(warnings) > 0:
+ warnings.append(
+ _("Specified %(type)s is different from existing %(existing_type)s.",
+ type="type:integer", existing_type="type:string"
+ )
+ )
+ records["warnings"] = warnings if len(warnings) else None
+ result.append(records)
return result
diff --git a/modules/weko-swordserver/weko_swordserver/utils.py b/modules/weko-swordserver/weko_swordserver/utils.py
index eded609e20..7bb2346672 100644
--- a/modules/weko-swordserver/weko_swordserver/utils.py
+++ b/modules/weko-swordserver/weko_swordserver/utils.py
@@ -570,4 +570,3 @@ def notify_about_item(case, recid, user_id, record=None, shared_ids=[]):
user_id, recid, user_id, record["item_title"], shared_ids
)
send_mail_item_deleted(recid, record, user_id, shared_ids)
-
\ No newline at end of file
diff --git a/nginx/Dockerfile.ams b/nginx/Dockerfile.ams
index 7e7e78e016..c514df78e1 100644
--- a/nginx/Dockerfile.ams
+++ b/nginx/Dockerfile.ams
@@ -37,7 +37,8 @@ RUN cd nginx-1.20.1 && dpkg-buildpackage -b
FROM ubuntu:focal AS nginx-stage_1
ENV DEBIAN_FRONTEND=noninteractive
-RUN apt-get update && apt-get install -y openssl wget curl unzip supervisor shibboleth-sp-common shibboleth-sp-utils php-fpm php-curl
+RUN apt-get update && apt-get install -y openssl wget curl unzip supervisor shibboleth-sp-common shibboleth-sp-utils php-fpm php-curl fcgiwrap python3-pip
+RUN pip3 install requests
WORKDIR /tmp
#COPY --from=nginx-with-shib /tmp/nginx_1.18.0-2~focal_amd64.deb .
@@ -76,7 +77,8 @@ RUN chmod 400 /etc/nginx/server.key
RUN mkdir /usr/share/nginx/html/secure
#ADD ./phpinfo.php /usr/share/nginx/html/secure/phpinfo.php
#ADD ./index.php /usr/share/nginx/html/secure/index.php
-ADD ./login.php /usr/share/nginx/html/secure/login.php
+ADD ./login.py /usr/share/nginx/html/secure/login.py
+RUN chmod 755 /usr/share/nginx/html/secure/login.py
ADD ./shib_clear_headers /etc/nginx/shib_clear_headers
ADD ./shib_fastcgi_params /etc/nginx/shib_fastcgi_params
@@ -97,4 +99,3 @@ RUN chmod +x /usr/local/startup.sh
RUN chmod +x /usr/local/ecosystem.config.js
CMD ["/usr/local/startup.sh"]
-
diff --git a/nginx/ams/weko-frontend/app.config.ts b/nginx/ams/weko-frontend/app.config.ts
index e9b36479b3..e38ac33a0b 100644
--- a/nginx/ams/weko-frontend/app.config.ts
+++ b/nginx/ams/weko-frontend/app.config.ts
@@ -3,6 +3,9 @@ const weko = 'ams-dev.ir.rcos.nii.ac.jp';
export default defineAppConfig({
wekoOrigin: 'https://' + weko,
wekoApi: 'https://' + weko + '/api/v1',
+ amsImage: '/img/ams',
+ amsPath: '/ams',
+ amsApi: '/api/ams',
export: {
jpcoar:
'https://' + weko + '/oai?verb=GetRecord&metadataPrefix=jpcoar_1.0&identifier=oai:ams-dev.ir.rcos.nii.ac.jp:',
@@ -24,27 +27,24 @@ export default defineAppConfig({
releaseRange: 'accessMode',
// 公開日
releaseDate: 'dateCreated',
- // 作成日
+ // メタデータ作成日
createDate: 'dateCreated',
- // 更新日
+ // メタデータ更新日
updateDate: 'reviews',
- // タイトル
+ // データセットの名称
title: 'subjectOf',
- // 分野
+ // データセットの分野
field: 'genre',
- // 作成者氏名
+ // データ作成者氏名
authorName: 'creator',
- // 作成者所属
+ // データ作成者所属
authorAffiliation: 'creativeWorkStatus',
- // ヒト/動物/その他
+ // 取得データの対象種別
target: 'character',
// アクセス権
accessMode: 'accessMode',
// キーワード
keywords: 'keywords',
- // プロジェクトID
- // TODO: valueはマッピング整理後に修正予定
- projectId: 'text',
// ファイル情報
file: {
// 格納場所
@@ -97,6 +97,10 @@ export default defineAppConfig({
}
}
},
+ grdm: {
+ url: '',
+ relationType: 'isVersionOf'
+ },
/** CC license setting */
cc: {
/**
@@ -147,5 +151,23 @@ export default defineAppConfig({
by_nc_nd_4: 'https://creativecommons.org/licenses/by-nc-nd/4.0/',
by_nc_nd_4_ja: 'https://creativecommons.org/licenses/by-nc-nd/4.0/deed.ja'
}
+ },
+ /**
+ * 閲覧権限が必要なアイテム詳細画面からログイン画面へ遷移するまでの時間設定
+ */
+ transitionTimeMs: 10000, // ミリ秒
+ /**
+ * フロントのShibboleth Login設定
+ */
+ shibLogin: {
+ // 本番環境
+ dsURL: 'https://ds.gakunin.nii.ac.jp/WAYF',
+ orthrosURL: 'https://core.orthros.gakunin.nii.ac.jp/idp',
+ // テスト環境
+ // dsURL: 'https://test-ds.gakunin.nii.ac.jp/WAYF',
+ // orthrosURL: 'https://core-stg.orthros.gakunin.nii.ac.jp/idp',
+ entityID: 'https://' + weko + '/shibboleth',
+ handlerURL: 'https://' + weko + '/Shibboleth.sso',
+ returnURL: 'https://' + weko + '/secure/login.py?next=ams'
}
});
diff --git a/nginx/ams/weko-frontend/assets/data/amsAlert.json b/nginx/ams/weko-frontend/assets/data/amsAlert.json
new file mode 100644
index 0000000000..93ba069761
--- /dev/null
+++ b/nginx/ams/weko-frontend/assets/data/amsAlert.json
@@ -0,0 +1,556 @@
+{
+ "INDEX_MESSAGE_ERROR_AUTH": {
+ "msgid": "INDEX_E_0001",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "INDEX_MESSAGE_ERROR_SERVER": {
+ "msgid": "INDEX_E_0002",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "INDEX_MESSAGE_ERROR_GET_LATEST_ITEM": {
+ "msgid": "INDEX_E_0003",
+ "msgstr": "message.error.getLatestItem",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "INDEX_MESSAGE_ERROR_FETCH": {
+ "msgid": "INDEX_E_0004",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "INDEX_MESSAGE_ERROR": {
+ "msgid": "INDEX_E_0005",
+ "msgstr": "message.error.error",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "CONTACT_MESSAGE_SENDING_FAILED": {
+ "msgid": "CONTACT_E_0001",
+ "msgstr": "message.sendingFailed",
+ "position": "toast-top pt-20",
+ "width": "w-auto",
+ "loglevel": "error"
+ },
+ "DETAIL_ITEM_MESSAGE_ERROR_AUTH": {
+ "msgid": "DETAIL_E_0001",
+ "msgstr": "message.error.noItemAuth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_ITEM_MESSAGE_OAUTH_ERROR": {
+ "msgid": "DETAIL_E_0002",
+ "msgstr": "message.error.oauthError",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_ITEM_MESSAGE_ERROR_SERVER": {
+ "msgid": "DETAIL_E_0003",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_ITEM_MESSAGE_ERROR_GET_ITEM_DETAIL": {
+ "msgid": "DETAIL_E_0004",
+ "msgstr": "message.error.getItemDetail",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_ITEM_MESSAGE_ERROR_FETCH": {
+ "msgid": "DETAIL_E_0005",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_SEARCH_MESSAGE_ERROR_AUTH": {
+ "msgid": "DETAIL_E_0006",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_SEARCH_MESSAGE_OAUTH_ERROR": {
+ "msgid": "DETAIL_E_0007",
+ "msgstr": "message.error.oauthError",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_SEARCH_MESSAGE_ERROR_SERVER": {
+ "msgid": "DETAIL_E_0008",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_SEARCH_MESSAGE_ERROR_GET_INDEX": {
+ "msgid": "DETAIL_E_0009",
+ "msgstr": "message.error.getIndex",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_SEARCH_MESSAGE_ERROR_FETCH": {
+ "msgid": "DETAIL_E_0010",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_INDEX_MESSAGE_ERROR_AUTH": {
+ "msgid": "DETAIL_E_0011",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_INDEX_MESSAGE_OAUTH_ERROR": {
+ "msgid": "DETAIL_E_0012",
+ "msgstr": "message.error.oauthError",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_INDEX_MESSAGE_ERROR_SERVER": {
+ "msgid": "DETAIL_E_0013",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_INDEX_MESSAGE_ERROR_GET_INDEX": {
+ "msgid": "DETAIL_E_0014",
+ "msgstr": "message.error.getIndex",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_INDEX_MESSAGE_ERROR_FETCH": {
+ "msgid": "DETAIL_E_0015",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DETAIL_MESSAGE_SENDING_FAILED": {
+ "msgid": "DETAIL_E_0016",
+ "msgstr": "message.sendingFailed",
+ "position": "toast-top pt-20",
+ "width": "w-auto",
+ "loglevel": "error"
+ },
+ "DETAIL_MESSAGE_ERROR": {
+ "msgid": "DETAIL_E_0017",
+ "msgstr": "message.error.error",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_DETAIL_MESSAGE_ERROR_AUTH": {
+ "msgid": "FILES_E_0001",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_DETAIL_MESSAGE_ERROR_SERVER": {
+ "msgid": "FILES_E_0002",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_DETAIL_MESSAGE_ERROR_GET_ITEM_DETAIL": {
+ "msgid": "FILES_E_0003",
+ "msgstr": "message.error.getItemDetail",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_DETAIL_MESSAGE_ERROR_FETCH": {
+ "msgid": "FILES_E_0004",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_ALL_MESSAGE_ERROR_AUTH": {
+ "msgid": "FILES_E_0005",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_ALL_MESSAGE_ERROR_SERVER": {
+ "msgid": "FILES_E_0006",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_ALL_MESSAGE_ERROR_DOWNLOAD_ALL": {
+ "msgid": "FILES_E_0007",
+ "msgstr": "message.error.downloadAll",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_ALL_MESSAGE_ERROR_FETCH": {
+ "msgid": "FILES_E_0008",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_SELECT_MESSAGE_ERROR_AUTH": {
+ "msgid": "FILES_E_0009",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_SELECT_MESSAGE_ERROR_SERVER": {
+ "msgid": "FILES_E_0010",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_SELECT_MESSAGE_ERROR_DOWNLOAD_SELECTED": {
+ "msgid": "FILES_E_0011",
+ "msgstr": "message.error.downloadSelected",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_SELECT_MESSAGE_ERROR_FETCH": {
+ "msgid": "FILES_E_0012",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "FILES_MESSAGE_ERROR": {
+ "msgid": "FILES_E_0013",
+ "msgstr": "message.error.error",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_SERVER": {
+ "msgid": "LOGIN_E_0001",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_REQUEST": {
+ "msgid": "LOGIN_E_0002",
+ "msgstr": "message.error.login",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_FETCH": {
+ "msgid": "LOGIN_E_0003",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_LOGIN_BLOCK": {
+ "msgid": "LOGIN_E_0004",
+ "msgstr": "message.error.loginFailed",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_NO_USER_INFORMATION": {
+ "msgid": "LOGIN_E_0005",
+ "msgstr": "message.error.noUserInformation",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_SHIB_MESSAGE_ERROR_SERVER": {
+ "msgid": "LOGIN_E_0006",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_SHIB_CACHE_PREFIX": {
+ "msgid": "LOGIN_E_0007",
+ "msgstr": "message.error.loginFailed",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_SHIB_SESSION_ID": {
+ "msgid": "LOGIN_E_0008",
+ "msgstr": "message.error.loginFailed",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_SHIB_ATTRS": {
+ "msgid": "LOGIN_E_0009",
+ "msgstr": "message.error.loginFailed",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_BIND_RELATION_INFO": {
+ "msgid": "LOGIN_E_0010",
+ "msgstr": "message.error.loginFailed",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_MESSAGE_ERROR_FAILED_GET_RELATION": {
+ "msgid": "LOGIN_E_0011",
+ "msgstr": "message.error.loginFailed",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "LOGIN_SHIB_MESSAGE_ERROR_LOGIN_FAILED": {
+ "msgid": "LOGIN_E_0012",
+ "msgstr": "message.error.loginFailed",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_SEARCH_MESSAGE_ERROR_AUTH": {
+ "msgid": "ID_E_0001",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_SEARCH_MESSAGE_ERROR_SERVER": {
+ "msgid": "ID_E_0002",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_SEARCH_MESSAGE_ERROR_REQUEST": {
+ "msgid": "ID_E_0003",
+ "msgstr": "message.error.search",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_SEARCH_MESSAGE_ERROR_FETCH": {
+ "msgid": "ID_E_0004",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_INDEX_MESSAGE_ERROR_AUTH": {
+ "msgid": "ID_E_0005",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_INDEX_MESSAGE_ERROR_SERVER": {
+ "msgid": "ID_E_0006",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_INDEX_MESSAGE_ERROR_GET_INDEX": {
+ "msgid": "ID_E_0007",
+ "msgstr": "message.error.getIndex",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_INDEX_MESSAGE_ERROR_FETCH": {
+ "msgid": "ID_E_0008",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_DOWNLOAD_MESSAGE_ERROR_AUTH": {
+ "msgid": "ID_E_0009",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_DOWNLOAD_MESSAGE_ERROR_SERVER": {
+ "msgid": "ID_E_0010",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_DOWNLOAD_MESSAGE_ERROR_DOWNLOAD_RESULT": {
+ "msgid": "ID_E_0011",
+ "msgstr": "message.error.downloadResult",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_DOWNLOAD_MESSAGE_ERROR_FETCH": {
+ "msgid": "ID_E_0012",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "ID_MESSAGE_ERROR": {
+ "msgid": "ID_E_0013",
+ "msgstr": "message.error.error",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+
+ "SEARCH_ITEM_MESSAGE_ERROR_AUTH": {
+ "msgid": "SEARCH_INDEX_E_0001",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_ITEM_MESSAGE_ERROR_SERVER": {
+ "msgid": "SEARCH_INDEX_E_0002",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_ITEM_MESSAGE_ERROR_REQUEST": {
+ "msgid": "SEARCH_INDEX_E_0003",
+ "msgstr": "message.error.search",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_ITEM_MESSAGE_ERROR_FETCH": {
+ "msgid": "SEARCH_INDEX_E_0004",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_DOWNLOAD_MESSAGE_ERROR_AUTH": {
+ "msgid": "SEARCH_INDEX_E_0005",
+ "msgstr": "message.error.auth",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_DOWNLOAD_MESSAGE_ERROR_SERVER": {
+ "msgid": "SEARCH_INDEX_E_0006",
+ "msgstr": "message.error.server",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_DOWNLOAD_MESSAGE_ERROR_RESULT": {
+ "msgid": "SEARCH_INDEX_E_0007",
+ "msgstr": "message.error.downloadResult",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_DOWNLOAD_MESSAGE_ERROR_FETCH": {
+ "msgid": "SEARCH_INDEX_E_0008",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "SEARCH_INDEX_MESSAGE_ERROR": {
+ "msgid": "SEARCH_INDEX_E_0009",
+ "msgstr": "message.error.error",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DOWNLOAD_RANK_MESSAGE_ERROR_DOWNLOAD": {
+ "msgid": "DOWNLOAD_RANK_E_0001",
+ "msgstr": "message.error.download",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "DOWNLOAD_RANK_MESSAGE_ERROR_FETCH": {
+ "msgid": "DOWNLOAD_RANK_E_0002",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "TABLE_STYLE_MESSAGE_ERROR_DOWNLOAD": {
+ "msgid": "TABLE_STYLE_E_0001",
+ "msgstr": "message.error.download",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "TABLE_STYLE_MESSAGE_ERROR_FETCH": {
+ "msgid": "TABLE_STYLE_E_0002",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "TABLE_STYLE_MESSAGE_ERROR_PREVIEW": {
+ "msgid": "TABLE_STYLE_E_0003",
+ "msgstr": "message.error.preview",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "TABLE_STYLE_MESSAGE_ERROR_FETCH_PREVIEW": {
+ "msgid": "TABLE_STYLE_E_0004",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "VIEWS_NUMBER_MESSAGE_ERROR": {
+ "msgid": "VIEWS_NUMBER_E_0001",
+ "msgstr": "message.error.error",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "VIEWS_NUMBER_MESSAGE_ERROR_GET_ITEM": {
+ "msgid": "VIEWS_NUMBER_E_0002",
+ "msgstr": "message.error.getItemViewsNumber",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ },
+ "VIEWS_NUMBER_MESSAGE_ERROR_FETCH": {
+ "msgid": "VIEWS_NUMBER_E_0003",
+ "msgstr": "message.error.fetch",
+ "position": "",
+ "width": "w-full",
+ "loglevel": "error"
+ }
+}
diff --git a/nginx/ams/weko-frontend/assets/sass/common.scss b/nginx/ams/weko-frontend/assets/sass/common.scss
index 21c110977f..ee53f5d30f 100644
--- a/nginx/ams/weko-frontend/assets/sass/common.scss
+++ b/nginx/ams/weko-frontend/assets/sass/common.scss
@@ -7,7 +7,7 @@
@include icons;
width: 20px;
height: 20px;
- background-image: url(/img/icon/icon_language.svg);
+ background-image: url(/img/ams/icon/icon_language.svg);
padding-left: 0px;
// vertical-align: baseline;
margin-bottom: 3px;
@@ -24,7 +24,7 @@
@include icons;
width: 10px;
height: 7px;
- background-image: url(/img/icon/icon_down-arrow.svg);
+ background-image: url(/img/ams/icon/icon_down-arrow.svg);
margin-left: 5px;
vertical-align: middle;
@@ -40,7 +40,7 @@
@include icons;
width: 14px;
height: 14px;
- background-image: url(/img/icon/icon_language02.svg);
+ background-image: url(/img/ams/icon/icon_language02.svg);
padding-right: 10px;
vertical-align: baseline;
}
@@ -59,7 +59,7 @@
@include icons;
width: 10px;
height: 7px;
- background-image: url(/img/icon/icon_down-arrow-bk.svg);
+ background-image: url(/img/ams/icon/icon_down-arrow-bk.svg);
margin-left: 5px;
vertical-align: middle;
}
@@ -68,7 +68,7 @@
@include icons;
width: 10px;
height: 7px;
- background-image: url(/img/icon/icon_up-arrow-bk.svg);
+ background-image: url(/img/ams/icon/icon_up-arrow-bk.svg);
margin-left: 5px;
vertical-align: middle;
}
@@ -77,7 +77,7 @@
@include icons;
width: 10px;
height: 10px;
- background-image: url(/img/icon/icon_left-arrow-bk.svg);
+ background-image: url(/img/ams/icon/icon_left-arrow-bk.svg);
margin-right: 5px;
vertical-align: baseline;
}
@@ -86,7 +86,7 @@
@include icons;
width: 10px;
height: 10px;
- background-image: url(/img/icon/icon_right-arrow-bk.svg);
+ background-image: url(/img/ams/icon/icon_right-arrow-bk.svg);
margin-left: 5px;
margin-right: 0;
vertical-align: baseline;
@@ -96,21 +96,21 @@
@include icons;
width: 17px;
height: 17px;
- background-image: url(/img/icon/icon_login.svg);
+ background-image: url(/img/ams/icon/icon_login.svg);
}
&.icon-out::before {
@include icons;
width: 17px;
height: 17px;
- background-image: url(/img/icon/icon_logout.svg);
+ background-image: url(/img/ams/icon/icon_logout.svg);
}
&.icon-menu::before {
@include icons;
width: 17px;
height: 17px;
- background-image: url(/img/icon/icon_menu.svg);
+ background-image: url(/img/ams/icon/icon_menu.svg);
}
&.icon-search::before {
@@ -118,63 +118,63 @@
width: 16px;
height: 16px;
vertical-align: baseline;
- background-image: url(/img/icon/icon_search.svg);
+ background-image: url(/img/ams/icon/icon_search.svg);
}
&.icon-listsearch::before {
@include icons;
width: 22px;
height: 15px;
- background-image: url(/img/icon/icon_detailed-search.svg);
+ background-image: url(/img/ams/icon/icon_detailed-search.svg);
}
&.icon-mylist::before {
@include icons;
width: 22px;
height: 15px;
- background-image: url(/img/icon/icon_mylist.svg);
+ background-image: url(/img/ams/icon/icon_mylist.svg);
}
&.icon-mylist-b::before {
@include icons;
width: 22px;
height: 15px;
- background-image: url(/img/icon/icon_mylist-blue.svg);
+ background-image: url(/img/ams/icon/icon_mylist-blue.svg);
}
&.icon-nord::before {
@include icons;
width: 14px;
height: 16px;
- background-image: url(/img/icon/icon_data.svg);
+ background-image: url(/img/ams/icon/icon_data.svg);
}
&.icon-norf::before {
@include icons;
width: 14px;
height: 16px;
- background-image: url(/img/icon/icon_file.svg);
+ background-image: url(/img/ams/icon/icon_file.svg);
}
&.icon-thesis::before {
@include icons;
width: 14px;
height: 16px;
- background-image: url(/img/icon/icon_thesis.svg);
+ background-image: url(/img/ams/icon/icon_thesis.svg);
}
&.icon-noro::before {
@include icons;
width: 14px;
height: 16px;
- background-image: url(/img/icon/icon_organization.svg);
+ background-image: url(/img/ams/icon/icon_organization.svg);
}
&.icon-news::before {
@include icons;
width: 18px;
height: 18px;
- background-image: url(/img/icon/icon_feed.svg);
+ background-image: url(/img/ams/icon/icon_feed.svg);
}
&.icon-info::before {
@@ -182,7 +182,7 @@
vertical-align: sup;
width: 20px;
height: 20px;
- background-image: url(/img/icon/icon_info.svg);
+ background-image: url(/img/ams/icon/icon_info.svg);
}
&.icon-publish::before {
@@ -190,14 +190,14 @@
width: 13px;
height: 13px;
vertical-align: baseline;
- background-image: url(/img/icon/icon_upload-date.svg);
+ background-image: url(/img/ams/icon/icon_upload-date.svg);
}
&.icon-update::before {
@include icons;
width: 13px;
height: 13px;
- background-image: url(/img/icon/icon_update-date.svg);
+ background-image: url(/img/ams/icon/icon_update-date.svg);
}
&.icon-rank::before {
@@ -205,7 +205,7 @@
width: 21px;
height: 15px;
margin-right: 10px;
- background-image: url(/img/icon/icon_ranking.svg);
+ background-image: url(/img/ams/icon/icon_ranking.svg);
}
&.icon-dl-rank::before {
@@ -213,7 +213,7 @@
width: 20px;
height: 20px;
margin-right: 10px;
- background-image: url(/img/icon/icon_dl-rank.svg);
+ background-image: url(/img/ams/icon/icon_dl-rank.svg);
}
&.icon-statistics::before {
@@ -221,7 +221,7 @@
width: 17px;
height: 17px;
margin-right: 10px;
- background-image: url(/img/icon/icon_statistics.svg);
+ background-image: url(/img/ams/icon/icon_statistics.svg);
}
&.icon-export::before {
@@ -229,7 +229,7 @@
width: 22px;
height: 22px;
margin-right: 10px;
- background-image: url(/img/icon/icon_export.svg);
+ background-image: url(/img/ams/icon/icon_export.svg);
}
&.icon-mail::before {
@@ -237,7 +237,7 @@
width: 24px;
height: 24px;
margin-right: 10px;
- background-image: url(/img/icon/icon_mail.svg);
+ background-image: url(/img/ams/icon/icon_mail.svg);
}
&.icon-external {
@@ -246,7 +246,7 @@
@include icons;
width: 10px;
height: 10px;
- background-image: url(/img/icon/icon_external.svg);
+ background-image: url(/img/ams/icon/icon_external.svg);
}
}
@@ -255,7 +255,7 @@
width: 27px;
height: 21px;
margin-right: 10px;
- background-image: url(/img/icon/icon_item.svg);
+ background-image: url(/img/ams/icon/icon_item.svg);
}
&.icon-index::before {
@@ -264,10 +264,10 @@
height: 21px;
vertical-align: bottom;
margin-right: 10px;
- background-image: url(/img/icon/icon_plus01.svg);
+ background-image: url(/img/ams/icon/icon_plus01.svg);
.active & {
- background-image: url(/img/icon/icon_minus.svg);
+ background-image: url(/img/ams/icon/icon_minus.svg);
}
}
@@ -276,7 +276,7 @@
width: 24px;
height: 24px;
margin-left: 10px;
- background-image: url(/img/icon/icon_remove.svg);
+ background-image: url(/img/ams/icon/icon_remove.svg);
}
&.icon-minus::before {
@@ -284,7 +284,7 @@
width: 19px;
height: 21px;
margin-right: 10px;
- background-image: url(/img/icon/icon_minus.svg);
+ background-image: url(/img/ams/icon/icon_minus.svg);
vertical-align: bottom;
}
@@ -292,14 +292,14 @@
@include icons;
width: 21px;
height: 21px;
- background-image: url(/img/icon/icon_search-results.svg);
+ background-image: url(/img/ams/icon/icon_search-results.svg);
}
&.icon-filter::before {
@include icons;
width: 22px;
height: 15px;
- background-image: url(/img/icon/icon_filter.svg);
+ background-image: url(/img/ams/icon/icon_filter.svg);
}
&.icon-table::before {
@@ -307,7 +307,7 @@
width: 22px;
height: 15px;
margin-right: 3px;
- background-image: url(/img/icon/icon_item-display.svg);
+ background-image: url(/img/ams/icon/icon_item-display.svg);
}
&.icon-display {
@@ -322,31 +322,31 @@
&.display1 {
&::before {
- background-image: url(/img/icon/icon_summary_inactive.svg);
+ background-image: url(/img/ams/icon/icon_summary_inactive.svg);
}
&.active::before {
- background-image: url(/img/icon/icon_summary_active.svg);
+ background-image: url(/img/ams/icon/icon_summary_active.svg);
}
}
&.display2 {
&::before {
- background-image: url(/img/icon/icon_table_inactive.svg);
+ background-image: url(/img/ams/icon/icon_table_inactive.svg);
}
&.active::before {
- background-image: url(/img/icon/icon_table_active.svg);
+ background-image: url(/img/ams/icon/icon_table_active.svg);
}
}
&.display3 {
&::before {
- background-image: url(/img/icon/icon_block_inactive.svg);
+ background-image: url(/img/ams/icon/icon_block_inactive.svg);
}
&.active::before {
- background-image: url(/img/icon/icon_block_active.svg);
+ background-image: url(/img/ams/icon/icon_block_active.svg);
}
}
}
@@ -355,7 +355,7 @@
&::before {
@include icon-display;
background-size: 26px 14px;
- background-image: url(/img/icon/icon_sort01.svg);
+ background-image: url(/img/ams/icon/icon_sort01.svg);
}
&.desc::before {
@@ -369,7 +369,7 @@
@include icons;
width: 13px;
height: 13px;
- background-image: url(/img/icon/icon_download.svg);
+ background-image: url(/img/ams/icon/icon_download.svg);
}
}
@@ -378,7 +378,7 @@
margin-right: 10px;
width: 14px;
height: 16px;
- background-image: url(/img/icon/icon_add.svg);
+ background-image: url(/img/ams/icon/icon_add.svg);
}
&.icon-date::after {
@@ -386,7 +386,7 @@
margin-right: 10px;
width: 10px;
height: 10px;
- background-image: url(/img/icon/icon_calendar.svg);
+ background-image: url(/img/ams/icon/icon_calendar.svg);
}
&.icon-checkbox {
@@ -435,19 +435,19 @@
}
&.icon-group::before {
- background-image: url(/img/icon/icon_group.svg);
+ background-image: url(/img/ams/icon/icon_group.svg);
}
&.icon-member::before {
- background-image: url(/img/icon/icon_member.svg);
+ background-image: url(/img/ams/icon/icon_member.svg);
}
&.icon-private::before {
- background-image: url(/img/icon/icon_private.svg);
+ background-image: url(/img/ams/icon/icon_private.svg);
}
&.icon-public::before {
- background-image: url(/img/icon/icon_public.svg);
+ background-image: url(/img/ams/icon/icon_public.svg);
}
}
@@ -460,25 +460,25 @@
&.icon-preview::before {
width: 12px;
height: 12px;
- background-image: url(/img/icon/icon_preview.svg);
+ background-image: url(/img/ams/icon/icon_preview.svg);
}
&.icon-download::before {
width: 12px;
height: 12px;
- background-image: url(/img/icon/icon_download-bk.svg);
+ background-image: url(/img/ams/icon/icon_download-bk.svg);
}
&.icon-info-bk::before {
width: 12px;
height: 12px;
- background-image: url(/img/icon/icon_information-bk.svg);
+ background-image: url(/img/ams/icon/icon_information-bk.svg);
}
&.icon-approval::before {
width: 12px;
height: 12px;
- background-image: url(/img/icon/icon_approval.svg);
+ background-image: url(/img/ams/icon/icon_approval.svg);
}
}
@@ -487,7 +487,7 @@
@include icons;
width: 14px;
height: 7px;
- background-image: url(/img/icon/icon_down-arrow.svg);
+ background-image: url(/img/ams/icon/icon_down-arrow.svg);
vertical-align: middle;
margin-right: 12px;
}
@@ -498,7 +498,7 @@
@include icons;
width: 14px;
height: 7px;
- background-image: url(/img/icon/icon_up-arrow.svg);
+ background-image: url(/img/ams/icon/icon_up-arrow.svg);
vertical-align: middle;
margin-right: 12px;
}
@@ -975,7 +975,7 @@ dialog {
color: $miby-black;
font-weight: 500;
cursor: pointer;
- list-style-image: url(/img/icon/icon_plus01.svg);
+ list-style-image: url(/img/ams/icon/icon_plus01.svg);
&::before {
content: '';
@@ -983,7 +983,7 @@ dialog {
left: 0;
width: 19px;
height: 21px;
- background-image: url(/img/icon/icon_plus01.svg);
+ background-image: url(/img/ams/icon/icon_plus01.svg);
background-position: center;
background-size: 19px 21px;
background-repeat: no-repeat;
@@ -994,7 +994,7 @@ dialog {
font-weight: 700;
&::before {
- background-image: url(/img/icon/icon_minus.svg);
+ background-image: url(/img/ams/icon/icon_minus.svg);
}
}
}
@@ -1019,7 +1019,7 @@ dialog {
height: 25px;
margin-right: 10px;
margin-top: 1px;
- background-image: url(/img/icon/icon_rhombus.svg);
+ background-image: url(/img/ams/icon/icon_rhombus.svg);
background-position: center;
background-size: 19px 21px;
background-repeat: no-repeat;
@@ -1083,7 +1083,7 @@ dialog {
select {
AddCondition {
&:not([size]) {
- background-image: url(/img/icon/icon_down-arrow.svg);
+ background-image: url(/img/ams/icon/icon_down-arrow.svg);
background-size: 10px 7px;
padding-right: 2rem;
}
@@ -1097,7 +1097,7 @@ select {
margin-right: 10px;
width: 10px;
height: 10px;
- background-image: url(/img/icon/icon_add.svg);
+ background-image: url(/img/ams/icon/icon_add.svg);
}
}
}
@@ -1179,7 +1179,7 @@ input[type='file'] {
border-color: $miby-link-blue;
background-color: $miby-link-blue;
cursor: pointer;
- background-image: url(/img/icon/icon_check.svg);
+ background-image: url(/img/ams/icon/icon_check.svg);
background-repeat: no-repeat;
background-size: 100%;
vertical-align: text-top;
diff --git a/nginx/ams/weko-frontend/assets/sass/styles.scss b/nginx/ams/weko-frontend/assets/sass/styles.scss
index 0668053f9a..2cbea04804 100644
--- a/nginx/ams/weko-frontend/assets/sass/styles.scss
+++ b/nginx/ams/weko-frontend/assets/sass/styles.scss
@@ -96,7 +96,7 @@
right: 20px;
width: 12px;
height: 12px;
- background-image: url(/img/icon/icon_close02.svg);
+ background-image: url(/img/ams/icon/icon_close02.svg);
background-position: center;
background-size: 12px;
background-repeat: no-repeat;
@@ -115,7 +115,7 @@
width: 20px;
height: 20px;
vertical-align: bottom;
- background-image: url(/img/icon/icon_q.svg);
+ background-image: url(/img/ams/icon/icon_q.svg);
}
}
}
@@ -133,7 +133,7 @@
width: 20px;
height: 20px;
vertical-align: bottom;
- background-image: url(/img/icon/icon_a.svg);
+ background-image: url(/img/ams/icon/icon_a.svg);
}
}
@@ -182,3 +182,25 @@
}
}
}
+
+.text-divider {
+ display: flex;
+ align-items: center;
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ padding-left: 40px;
+ padding-right: 40px;
+}
+.text-divider::before,
+.text-divider::after {
+ content: '';
+ height: 1px;
+ background-color: #a3a3a3;
+ flex-grow: 1;
+}
+.text-divider::before {
+ margin-right: 1rem;
+}
+.text-divider::after {
+ margin-left: 1rem;
+}
diff --git a/nginx/ams/weko-frontend/components/common/Alert.vue b/nginx/ams/weko-frontend/components/common/Alert.vue
index f68775dba7..f196eed28d 100644
--- a/nginx/ams/weko-frontend/components/common/Alert.vue
+++ b/nginx/ams/weko-frontend/components/common/Alert.vue
@@ -92,7 +92,12 @@
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
- {{ $t(message) + (code ? ' (' + code + ')' : '') }}
+
+ {{ $t('message.error.oauthError', { time: transitionSecond }) }}
+ {{ loginPage }}
+ {{ code ? ' (' + code + ')' : '' }}
+
+ {{ $t(message) + (code ? ' (' + code + ')' : '') }}
({
+ msgid: '',
+ msgstr: '',
+ position: '',
+ width: 'w-full',
+ loglevel: 'info'
+ })
}
});
@@ -152,4 +143,8 @@ defineProps({
/////////////////////////////////// */
const emits = defineEmits(['clickClose']);
+const appConf = useAppConfig();
+const transitionSecond = appConf.transitionTimeMs / 1000;
+const loginPage = window.location.origin + `${appConf.amsPath ?? ''}/login?source=detail`;
+const { msgid: code, msgstr: message, position, width, loglevel: type } = toRefs(props.alert);
diff --git a/nginx/ams/weko-frontend/components/common/Footer.vue b/nginx/ams/weko-frontend/components/common/Footer.vue
index 8f171b59ab..b79ded1e42 100644
--- a/nginx/ams/weko-frontend/components/common/Footer.vue
+++ b/nginx/ams/weko-frontend/components/common/Footer.vue
@@ -24,7 +24,7 @@
-->
-
+
CONTACT
@@ -56,7 +56,7 @@
-
+
@@ -70,6 +70,12 @@
diff --git a/nginx/ams/weko-frontend/components/common/SearchForm.vue b/nginx/ams/weko-frontend/components/common/SearchForm.vue
index 166da2a572..2525739efb 100644
--- a/nginx/ams/weko-frontend/components/common/SearchForm.vue
+++ b/nginx/ams/weko-frontend/components/common/SearchForm.vue
@@ -200,7 +200,7 @@
@@ -325,6 +325,7 @@ const titleSearchType = reactive({
name: 'exactMatch'
}
});
+const appConf = useAppConfig();
/* ///////////////////////////////////
// function
@@ -414,7 +415,7 @@ function search() {
emits('clickSearch');
} else {
sessionStorage.setItem('conditions', JSON.stringify(conditions));
- navigateTo('/search');
+ navigateTo(`${appConf.amsPath ?? ''}/search`);
}
}
@@ -592,6 +593,7 @@ try {
$fetch(useAppConfig().wekoApi + '/records', {
timeout: useRuntimeConfig().public.apiTimeout,
method: 'GET',
+ credentials: 'omit',
headers: {
'Cache-Control': 'no-store',
Pragma: 'no-cache',
@@ -610,6 +612,7 @@ try {
$fetch(useAppConfig().wekoApi + '/records', {
timeout: useRuntimeConfig().public.apiTimeout,
method: 'GET',
+ credentials: 'omit',
headers: {
'Cache-Control': 'no-store',
Pragma: 'no-cache',
@@ -643,6 +646,7 @@ try {
await $fetch(useAppConfig().wekoApi + '/tree/index', {
timeout: useRuntimeConfig().public.apiTimeout,
method: 'GET',
+ credentials: 'omit',
headers: {
'Cache-Control': 'no-store',
Pragma: 'no-cache',
diff --git a/nginx/ams/weko-frontend/components/common/modal/CreaterInfo.vue b/nginx/ams/weko-frontend/components/common/modal/CreaterInfo.vue
index 90488fe568..f623380bf7 100644
--- a/nginx/ams/weko-frontend/components/common/modal/CreaterInfo.vue
+++ b/nginx/ams/weko-frontend/components/common/modal/CreaterInfo.vue
@@ -7,7 +7,7 @@
-
+
@@ -55,6 +55,7 @@ defineExpose({
/////////////////////////////////// */
const modalShowFlag = ref(false);
+const appConf = useAppConfig();
/* ///////////////////////////////////
// function
diff --git a/nginx/ams/weko-frontend/components/common/modal/DetailSearch.vue b/nginx/ams/weko-frontend/components/common/modal/DetailSearch.vue
index 7f805c4ed4..29756cd2e6 100644
--- a/nginx/ams/weko-frontend/components/common/modal/DetailSearch.vue
+++ b/nginx/ams/weko-frontend/components/common/modal/DetailSearch.vue
@@ -10,7 +10,7 @@
-
+
@@ -196,6 +196,7 @@ const conditions = reactive({ type: '0', keyword: '', detail: {}, detailData: {}
const columnList = ref([]);
const selected = ref(selectorDefault);
let selector = JSON.parse(JSON.stringify(DetailColumn));
+const appConf = useAppConfig();
/* ///////////////////////////////////
// function
@@ -280,7 +281,7 @@ function search() {
closeModal();
} else {
sessionStorage.setItem('conditions', JSON.stringify(conditions));
- navigateTo('/search');
+ navigateTo(`${appConf.amsPath ?? ''}/search`);
closeModal();
}
}
@@ -358,6 +359,7 @@ try {
await $fetch(useAppConfig().wekoApi + '/tree/index', {
timeout: useRuntimeConfig().public.apiTimeout,
method: 'GET',
+ credentials: 'omit',
headers: {
'Cache-Control': 'no-store',
Pragma: 'no-cache',
diff --git a/nginx/ams/weko-frontend/components/contact/modal/ContactConfirm.vue b/nginx/ams/weko-frontend/components/contact/modal/ContactConfirm.vue
index e41ee1c1fb..96b706df0d 100644
--- a/nginx/ams/weko-frontend/components/contact/modal/ContactConfirm.vue
+++ b/nginx/ams/weko-frontend/components/contact/modal/ContactConfirm.vue
@@ -10,7 +10,7 @@
-
+
@@ -192,7 +192,7 @@ function getCaptcha() {
dirtyAnswer.value = false;
answeResult.value = false;
- $fetch(appConf.wekoApi + '/captcha/image', {
+ $fetch(`${appConf.amsApi ?? '/api'}/captcha/image`, {
timeout: useRuntimeConfig().public.apiTimeout,
method: 'GET',
headers: {
@@ -227,7 +227,7 @@ async function send() {
locale.value = String(localStorage.getItem('locale'));
const contactType = t(props.type);
- await useFetch('/api/mail/send', {
+ await useFetch(`${appConf.amsApi ?? '/api'}/mail/send`, {
method: 'POST',
body: JSON.stringify({
key: captchaKey,
diff --git a/nginx/ams/weko-frontend/components/detail/DownloadRank.vue b/nginx/ams/weko-frontend/components/detail/DownloadRank.vue
index e359364acf..f03228eec2 100644
--- a/nginx/ams/weko-frontend/components/detail/DownloadRank.vue
+++ b/nginx/ams/weko-frontend/components/detail/DownloadRank.vue
@@ -43,6 +43,7 @@
diff --git a/nginx/ams/weko-frontend/components/detail/ViewsNumber.vue b/nginx/ams/weko-frontend/components/detail/ViewsNumber.vue
index 53e7251e78..b7c7ac3dd4 100644
--- a/nginx/ams/weko-frontend/components/detail/ViewsNumber.vue
+++ b/nginx/ams/weko-frontend/components/detail/ViewsNumber.vue
@@ -30,6 +30,7 @@
diff --git a/nginx/ams/weko-frontend/components/search/SummaryStyle.vue b/nginx/ams/weko-frontend/components/search/SummaryStyle.vue
index 2c51e03f2d..81e231c7da 100644
--- a/nginx/ams/weko-frontend/components/search/SummaryStyle.vue
+++ b/nginx/ams/weko-frontend/components/search/SummaryStyle.vue
@@ -66,7 +66,7 @@
to=""
event=""
style="cursor: pointer"
- @click="throughDblClick(`/detail?sess=search&number=${item.id}`)">
+ @click="throughDblClick(`${appConf.amsPath ?? ''}/detail?sess=search&number=${item.id}`)">
{{ itemInfo[appConf.roCrate.root.title][0] }}
@@ -130,7 +130,7 @@
{{ $t('file') + ':' }}
-
+
{{ $t('unexist') }}
+ @click="throughDblClick(`${appConf.amsPath ?? ''}/files?number=${item.id}`)">
{{ $t('exist') + `(${getFileLength(itemInfo.mainEntity)})` }}
@@ -150,18 +150,18 @@
@@ -202,7 +202,7 @@ const thumbnailName = Object.prototype.hasOwnProperty.call(itemInfo, appConf.roC
? itemInfo[appConf.roCrate.root.thumbnail][0]
: '';
const loading = ref(true);
-const thumbnailPath = ref('/img/noimage_thumbnail.jpg');
+const thumbnailPath = ref(appConf.amsImage + '/noimage_thumbnail.jpg');
/* ///////////////////////////////////
// function
@@ -247,6 +247,7 @@ onMounted(() => {
$fetch(appConf.wekoApi + '/records/' + props.item.id + '/files/' + thumbnailName, {
timeout: useRuntimeConfig().public.apiTimeout,
method: 'GET',
+ credentials: 'omit',
headers: {
'Cache-Control': 'no-store',
Pragma: 'no-cache',
@@ -283,37 +284,37 @@ onMounted(() => {
const field = itemInfo[appConf.roCrate.root.field][0];
// 自然科学一般|Natural Science
if (field.includes('自然科学一般') || /Natural\s?Science/.test(field)) {
- thumbnailPath.value = '/img/naturalScience-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/naturalScience-sample.png';
// ライフサイエンス|Life Science
} else if (field.includes('ライフサイエンス') || /Life\s?Science/.test(field)) {
- thumbnailPath.value = '/img/lifeScience-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/lifeScience-sample.png';
// 情報通信|Informatics
} else if (field.includes('情報通信') || field.includes('Informatics')) {
- thumbnailPath.value = '/img/informatics-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/informatics-sample.png';
// 環境|Environmental science
} else if (field.includes('環境') || /Environmental\s?science/.test(field)) {
- thumbnailPath.value = '/img/environmental-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/environmental-sample.png';
// ナノテク・材料|Nanotechnology/Materials
} else if (/ナノテク\s?・?\s?材料/.test(field) || /Nanotechnology\s?\/?\s?Materials/.test(field)) {
- thumbnailPath.value = '/img/nanotech-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/nanotech-sample.png';
// エネルギー|Energy Engineering
} else if (field.includes('エネルギー') || /Energy\s?Engineering/.test(field)) {
- thumbnailPath.value = '/img/energy-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/energy-sample.png';
// ものづくり技術|Manufacturing Technology
} else if (field.includes('ものづくり技術') || /Manufacturing\s?Technology/.test(field)) {
- thumbnailPath.value = '/img/manufacturing-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/manufacturing-sample.png';
// 社会基盤|Social Infrastructure
} else if (field.includes('社会基盤') || /Social\s?Infrastructure/.test(field)) {
- thumbnailPath.value = '/img/social-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/social-sample.png';
// フロンティア|Frontier Technology
} else if (field.includes('フロンティア') || /Frontier\s?Technology/.test(field)) {
- thumbnailPath.value = '/img/frontier-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/frontier-sample.png';
// 人文・社会|Humanities & Social Sciences
} else if (/人文\s?・?\s?社会/.test(field) || /Humanities\s?&?\s?Social\s?Sciences/.test(field)) {
- thumbnailPath.value = '/img/humanities-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/humanities-sample.png';
// その他|Others
} else if (field.includes('その他') || field.includes('Others')) {
- thumbnailPath.value = '/img/others-sample.png';
+ thumbnailPath.value = appConf.amsImage + '/others-sample.png';
}
}
});
diff --git a/nginx/ams/weko-frontend/composables/refreshToken.ts b/nginx/ams/weko-frontend/composables/refreshToken.ts
index 6a746278d5..bab49021a5 100644
--- a/nginx/ams/weko-frontend/composables/refreshToken.ts
+++ b/nginx/ams/weko-frontend/composables/refreshToken.ts
@@ -1,13 +1,14 @@
export default function () {
const expires = Number(localStorage.getItem('token:expires'));
const issue = Number(localStorage.getItem('token:issue')) ?? 0;
+ const appConf = useAppConfig();
if (expires) {
if (
issue + expires * 1000 >= Date.now() &&
issue + (expires - useRuntimeConfig().public.tokenRefreshLimit) * 1000 <= Date.now()
) {
- useFetch('/api/token/refresh', {
+ useFetch(`${appConf.amsApi ?? '/api'}/token/refresh`, {
method: 'GET',
params: { refreshToken: String(localStorage.getItem('token:refresh')) }
}).then((response) => {
diff --git a/nginx/ams/weko-frontend/locales/en.json b/nginx/ams/weko-frontend/locales/en.json
index 372503b968..08ac4ab747 100644
--- a/nginx/ams/weko-frontend/locales/en.json
+++ b/nginx/ams/weko-frontend/locales/en.json
@@ -155,7 +155,8 @@
"mail": "Enter your email address",
"contents": "Enter your inquiry details",
"contactType": "Enter contact type",
- "request": "Enter your request"
+ "request": "Enter your request",
+ "result": "Enter result"
},
"alert": {
"requiredField": "This field is required",
@@ -172,6 +173,7 @@
"error": "Error has occurred. Please contact server administrator.",
"server": "Server error has occurred. Please contact server administrator.",
"auth": "Authentication error has occurred. Authentication status is invalid.",
+ "noItemAuth": "You do not have permission to view this item.",
"fetch": "Failed to send data.",
"login": "Failed to login.",
"search": "Failed to search items.",
@@ -185,7 +187,14 @@
"getItemDetail": "Failed to get item details.",
"getItemViewsNumber": "Failed to get the number of views for the item.",
"getDownloadRanking": "Failed to get download ranking.",
- "getFileDlNumber": "Failed to get the number of downloaded."
+ "getFileDlNumber": "Failed to get the number of downloaded.",
+ "loginFailed": "Failed to Login. Please contact server administrator.",
+ "noUserInformation": "There is no user information.",
+ "oauthError": "Login is required to view items. You will be automatically redirected to the login screen in {time} seconds. Login screen:"
+ },
+ "copySearch": {
+ "copySuccess": "URL copied to clipboard.",
+ "copyFailed": "Copy failed."
}
},
"overview": "Overview",
@@ -293,5 +302,7 @@
"conflictOfInterestYes": "conflict of interest (Yes) ",
"remarks": "Remarks",
"identifierText": "identifier",
- "identifierType": "identifier type"
-}
+ "identifierType": "identifier type",
+ "Institutional Login for institutions in Japan.": "Institutional Login for institutions in Japan.",
+ "needToLogin": "This item requires login."
+}
\ No newline at end of file
diff --git a/nginx/ams/weko-frontend/locales/ja.json b/nginx/ams/weko-frontend/locales/ja.json
index 053f575d3b..ad531a6884 100644
--- a/nginx/ams/weko-frontend/locales/ja.json
+++ b/nginx/ams/weko-frontend/locales/ja.json
@@ -156,7 +156,8 @@
"mail": "メールアドレスを入力",
"contents": "お問い合わせ内容を入力",
"contactType": "お問い合わせ種別を入力",
- "request": "リクエスト内容を入力"
+ "request": "リクエスト内容を入力",
+ "result": "計算結果を入力"
},
"alert": {
"requiredField": "必須入力",
@@ -173,6 +174,7 @@
"error": "エラーが発生しました。管理者に連絡してください。",
"server": "サーバエラーが発生しました。管理者に連絡してください。",
"auth": "認証エラーが発生しました。認証状態が不正です。",
+ "noItemAuth": "アイテムの閲覧権限がありません。",
"fetch": "データ送信に失敗しました。",
"login": "ログインに失敗しました。",
"search": "アイテム検索に失敗しました。",
@@ -186,7 +188,14 @@
"getItemDetail": "アイテム詳細情報の取得に失敗しました。",
"getItemViewsNumber": "アイテムの閲覧数取得に失敗しました。",
"getDownloadRanking": "ダウンロードランキングの取得に失敗しました。",
- "getFileDlNumber": "ファイルのダウンロード数取得に失敗しました。"
+ "getFileDlNumber": "ファイルのダウンロード数取得に失敗しました。",
+ "loginFailed": "ログインに失敗しました。管理者に連絡してください。",
+ "noUserInformation": "ユーザ情報がありません。",
+ "oauthError": "アイテム閲覧にはログインが必要です。{time} 秒後にログイン画面に遷移します。ログイン画面:"
+ },
+ "copySearch": {
+ "copySuccess": "URLをクリップボードにコピーしました。",
+ "copyFailed": "コピーに失敗しました。"
}
},
"overview": "概要",
@@ -294,5 +303,7 @@
"conflictOfInterestYes": "利益相反の有無(有の場合)",
"remarks": "備考",
"identifierText": "識別子",
- "identifierType": "識別子タイプ"
-}
+ "identifierType": "識別子タイプ",
+ "Institutional Login for institutions in Japan.": "所属機関のIdPでログインする方",
+ "needToLogin": "ログインが必要なアイテムです。"
+}
\ No newline at end of file
diff --git a/nginx/ams/weko-frontend/nuxt.config.ts b/nginx/ams/weko-frontend/nuxt.config.ts
index 20df6d4800..30ce604dfb 100644
--- a/nginx/ams/weko-frontend/nuxt.config.ts
+++ b/nginx/ams/weko-frontend/nuxt.config.ts
@@ -17,6 +17,7 @@ export default defineNuxtConfig({
css: ['@/assets/sass/styles.scss'],
ssr: false,
app: {
+ buildAssetsDir: '/ams/_nuxt/',
head: {
htmlAttrs: { lang: 'ja' },
title: 'AMS-alpha',
diff --git a/nginx/ams/weko-frontend/pages/contact.vue b/nginx/ams/weko-frontend/pages/ams/contact.vue
similarity index 96%
rename from nginx/ams/weko-frontend/pages/contact.vue
rename to nginx/ams/weko-frontend/pages/ams/contact.vue
index 7a321f268a..fb3210b27d 100644
--- a/nginx/ams/weko-frontend/pages/contact.vue
+++ b/nginx/ams/weko-frontend/pages/ams/contact.vue
@@ -169,19 +169,14 @@
-
+
diff --git a/nginx/ams/weko-frontend/pages/files.vue b/nginx/ams/weko-frontend/pages/ams/files.vue
similarity index 87%
rename from nginx/ams/weko-frontend/pages/files.vue
rename to nginx/ams/weko-frontend/pages/ams/files.vue
index 8178895a53..30106651af 100644
--- a/nginx/ams/weko-frontend/pages/files.vue
+++ b/nginx/ams/weko-frontend/pages/ams/files.vue
@@ -170,7 +170,7 @@
{{ $t('comment') }}
-
+
-
+
{{ $t('download') }} ({{ selectedFiles.length }} {{ $t('items') }})
@@ -209,18 +209,14 @@
-
+
diff --git a/nginx/ams/weko-frontend/pages/logout.vue b/nginx/ams/weko-frontend/pages/ams/logout.vue
similarity index 90%
rename from nginx/ams/weko-frontend/pages/logout.vue
rename to nginx/ams/weko-frontend/pages/ams/logout.vue
index 4f2fbeb864..d97fa92976 100644
--- a/nginx/ams/weko-frontend/pages/logout.vue
+++ b/nginx/ams/weko-frontend/pages/ams/logout.vue
@@ -2,7 +2,7 @@
-
+
-
+
{{ $t('logout') }}
@@ -49,13 +49,14 @@
/////////////////////////////////// */
const isLogout = ref(false);
+const appConf = useAppConfig();
/* ///////////////////////////////////
// function
/////////////////////////////////// */
function logout() {
- $fetch(useAppConfig().wekoApi + '/logout', {
+ $fetch(appConf.wekoApi + '/logout', {
timeout: useRuntimeConfig().public.apiTimeout,
method: 'POST',
onResponse() {
diff --git a/nginx/ams/weko-frontend/pages/preview.vue b/nginx/ams/weko-frontend/pages/ams/preview.vue
similarity index 100%
rename from nginx/ams/weko-frontend/pages/preview.vue
rename to nginx/ams/weko-frontend/pages/ams/preview.vue
diff --git a/nginx/ams/weko-frontend/pages/search/[id].vue b/nginx/ams/weko-frontend/pages/ams/search/[id].vue
similarity index 76%
rename from nginx/ams/weko-frontend/pages/search/[id].vue
rename to nginx/ams/weko-frontend/pages/ams/search/[id].vue
index d53bfbc6ef..d758860507 100644
--- a/nginx/ams/weko-frontend/pages/search/[id].vue
+++ b/nginx/ams/weko-frontend/pages/ams/search/[id].vue
@@ -6,16 +6,13 @@
-
+
{{ index.name }}
{{ index.name }}
- /
+ /
@@ -109,16 +106,14 @@
-
+