diff --git a/modules/weko-admin/weko_admin/config.py b/modules/weko-admin/weko_admin/config.py
index 7f773dd66d..307ab0ecd3 100644
--- a/modules/weko-admin/weko_admin/config.py
+++ b/modules/weko-admin/weko_admin/config.py
@@ -1240,8 +1240,10 @@
WEKO_ADMIN_RESTRICTED_ACCESS_SETTINGS = {
"secret_URL_file_download": {
"secret_expiration_date": 30,
+ "max_secret_expiration_date":30,
"secret_expiration_date_unlimited_chk": False,
"secret_download_limit": 10,
+ "max_secret_download_limit":10,
"secret_download_limit_unlimited_chk": False,
},
"content_file_download": {
diff --git a/modules/weko-admin/weko_admin/static/js/weko_admin/restricted_access.js b/modules/weko-admin/weko_admin/static/js/weko_admin/restricted_access.js
index 0e6d25e58a..1f9cb325be 100644
--- a/modules/weko-admin/weko_admin/static/js/weko_admin/restricted_access.js
+++ b/modules/weko-admin/weko_admin/static/js/weko_admin/restricted_access.js
@@ -2,12 +2,18 @@ const {useState, useEffect} = React;
const CONTENT_FILE_DOWNLOAD_LABEL = document.getElementById('content_file_download_label').value;
const DOWNLOAD_LIMIT_LABEL = document.getElementById('download_limit_label').value;
const EXPIRATION_DATE_LABEL = document.getElementById('expiration_date_label').value;
+const MAX_DOWNLOAD_LIMIT_LABEL= document.getElementById('max_download_limit_label').value
+const MAX_EXPIRATION_DATE_LABEL= document.getElementById('max_expiration_date_label').value
+const EXPIRATION_DATE_INITIAL_LABEL = document.getElementById('expiration_date_initial_label').value;
+const DOWNLOAD_LIMIT_INITIAL_LABEL = document.getElementById('download_limit_initial_label').value;
const UNLIMITED_LABEL = document.getElementById('unlimited_label').value;
const SAVE_LABEL = document.getElementById('save_label').value;
const CHECK_INPUT_DOWNLOAD = document.getElementById('check_input_download').value;
const CHECK_INPUT_EXPIRATION_DATE = document.getElementById('check_input_expiration_date').value;
const EMPTY_DOWNLOAD = document.getElementById('empty_download').value;
const EMPTY_EXPIRATION_DATE = document.getElementById('empty_expiration_date').value;
+const EMPTY_MAX_EXPIRATION_DATE = document.getElementById('empty_max_expiration_date').value;
+const EMPTY_MAX_DOWNLOAD_LIMIT = document.getElementById('empty_max_download_limit').value;
const USAGE_REPORT_WORKFLOW_ACCESS_LABEL = document.getElementById('usage_report_workflow_access_label').value
const MAXINT = Number(document.getElementById('maxint').value)
const MAX_DOWNLOAD_LIMIT = MAXINT;
@@ -64,45 +70,65 @@ function InputComponent({
label,
currentValue,
checkboxValue,
+ canSetUnlimited,
value,
setValue,
inputId,
checkboxId,
- disabledAll=false
+ disabledAll=false,
+ maxLength=String(MAXINT).length,
+ max=MAXINT
}) {
- const style = {marginRight: "5px", marginLeft: "15px"}
+ const style = {marginRight: "5px", marginLeft: "15px"};
+ const containerStyle ={display: 'flex',gap:'15px',marginBottom:'2px'};
function handleChange(event) {
event.preventDefault();
let target = event.target;
let key = target.id;
- let updateValue = target.type === 'checkbox' ? target.checked : target.value;
+ let updateValue = target.value;
- if (target.type !== 'checkbox') {
- if (!event.target.validity.valid) {
- updateValue = value[key];
- }
- if (isNaN(updateValue)) {
- try {
- updateValue = parseInt(updateValue);
- } catch (e) {
- console.log(e);
- }
+ if (parseInt(updateValue) > max) {
+ updateValue = max;
+ }
+
+ if (!event.target.validity.valid) {
+ updateValue = value[key];
+ }
+ if (isNaN(updateValue)) {
+ try {
+ updateValue = parseInt(updateValue);
+ } catch (e) {
+ console.log(e);
}
}
setValue({...value, ...{[key]: updateValue}});
}
+ function handleUnlimited(event) {
+ let target = event.target;
+ let key = target.id;
+ let updateValue = target.type === 'checkbox' ? target.checked : target.value;
+ if (canSetUnlimited) {
+ if (!event.target.validity.valid) {
+ updateValue = value[key];
+ }
+ setValue({...value, ...{[key]: updateValue}});
+ }
+ }
return (
-
-
-
+
+
+ {canSetUnlimited && (
+ )}
)
}
@@ -121,9 +148,9 @@ function InputComponent({
function SecretURLFileDownloadLayout({value, setValue}) {
const {
secret_download_limit,
- secret_download_limit_unlimited_chk,
secret_expiration_date,
- secret_expiration_date_unlimited_chk,
+ max_secret_expiration_date,
+ max_secret_download_limit,
secret_enable
} = value;
@@ -162,26 +189,50 @@ function SecretURLFileDownloadLayout({value, setValue}) {
{/* end enabled checkbox */}
-
-
+
+
+
+
@@ -193,9 +244,7 @@ function SecretURLFileDownloadLayout({value, setValue}) {
function ContentFileDownloadLayout({value, setValue}) {
const {
download_limit,
- download_limit_unlimited_chk,
expiration_date,
- expiration_date_unlimited_chk
} = value;
return (
@@ -210,18 +259,16 @@ function ContentFileDownloadLayout({value, setValue}) {
@@ -250,6 +297,7 @@ function UsageReportWorkflowAccessLayout({value, setValue}) {
checkboxValue={expiration_date_access_unlimited_chk}
inputId="expiration_date_access"
checkboxId="expiration_date_access_unlimited_chk"
+ canSetUnlimited={true}
value={value}
setValue={setValue}
/>
@@ -480,13 +528,22 @@ function RestrictedAccessLayout({
showErrorMessage(MESSAGE_MISSING_DATA);
return false;
}
-
+
+ // Ensure the values are integers
+ const parsedSecretURLFileDownload = {
+ ...secretURLFileDownload,
+ secret_download_limit: parseInt(secretURLFileDownload.secret_download_limit, 10),
+ max_secret_expiration_date: parseInt(secretURLFileDownload.max_secret_expiration_date, 10),
+ max_secret_download_limit: parseInt(secretURLFileDownload.max_secret_download_limit, 10),
+ secret_expiration_date: parseInt(secretURLFileDownload.secret_expiration_date, 10)
+ };
+
let data = {
- secret_URL_file_download:secretURLFileDownload,
+ secret_URL_file_download:parsedSecretURLFileDownload,
content_file_download: contentFileDownload,
usage_report_workflow_access: usageReportWorkflowAccess,
terms_and_conditions: terms_data["data"]
- }
+ };
$.ajax({
url: URL,
@@ -510,46 +567,51 @@ function RestrictedAccessLayout({
function validateSecretURLFileDownload() {
const {
secret_download_limit,
- secret_download_limit_unlimited_chk,
secret_expiration_date,
- secret_expiration_date_unlimited_chk
+ max_secret_expiration_date,
+ max_secret_download_limit
} = secretURLFileDownload;
let errorMessage;
- if (secret_expiration_date === "" && !secret_expiration_date_unlimited_chk) {
+ if (secret_expiration_date === "" ) {
errorMessage = EMPTY_EXPIRATION_DATE;
- } else if (secret_download_limit === "" && !secret_download_limit_unlimited_chk) {
+ } else if (secret_download_limit === "" ) {
errorMessage = EMPTY_DOWNLOAD;
- } else if ((secret_expiration_date < 1 && !secret_expiration_date_unlimited_chk)
- || secret_expiration_date > MAX_EXPIRATION_DATE) {
+ } else if ((secret_expiration_date < 1 )
+ || secret_expiration_date > max_secret_expiration_date) {
errorMessage = CHECK_INPUT_EXPIRATION_DATE;
- } else if ((secret_download_limit < 1 && !secret_download_limit_unlimited_chk)
- || secret_download_limit > MAX_DOWNLOAD_LIMIT) {
+ } else if ((secret_download_limit < 1 )
+ || secret_download_limit > max_secret_download_limit) {
errorMessage = CHECK_INPUT_DOWNLOAD;
+ } else if (max_secret_expiration_date === ""){
+ errorMessage = EMPTY_MAX_EXPIRATION_DATE;
+ } else if (max_secret_download_limit === ""){
+ errorMessage = EMPTY_DOWNLOAD;
+ } else if (max_secret_expiration_date < 1 ){
+ errorMessage = EMPTY_MAX_DOWNLOAD_LIMIT;
+ } else if (max_secret_download_limit < 1 ){
+ errorMessage = EMPTY_DOWNLOAD;
}
-
return errorMessage;
}
function validateContentFileDownload() {
const {
download_limit,
- download_limit_unlimited_chk,
expiration_date,
- expiration_date_unlimited_chk
} = contentFileDownload;
let errorMessage;
- if (expiration_date === "" && !expiration_date_unlimited_chk) {
+ if (expiration_date === "" ) {
errorMessage = EMPTY_EXPIRATION_DATE;
- } else if (download_limit === "" && !download_limit_unlimited_chk) {
+ } else if (download_limit === "" ) {
errorMessage = EMPTY_DOWNLOAD;
- } else if ((expiration_date < 1 && !expiration_date_unlimited_chk)
+ } else if ((expiration_date < 1 )
|| expiration_date > MAX_EXPIRATION_DATE) {
errorMessage = CHECK_INPUT_EXPIRATION_DATE;
- } else if ((download_limit < 1 && !download_limit_unlimited_chk)
+ } else if ((download_limit < 1 )
|| download_limit > MAX_DOWNLOAD_LIMIT) {
errorMessage = CHECK_INPUT_DOWNLOAD;
}
diff --git a/modules/weko-admin/weko_admin/templates/weko_admin/admin/restricted_access_settings.html b/modules/weko-admin/weko_admin/templates/weko_admin/admin/restricted_access_settings.html
index 715e652a74..3efa7d2f0c 100644
--- a/modules/weko-admin/weko_admin/templates/weko_admin/admin/restricted_access_settings.html
+++ b/modules/weko-admin/weko_admin/templates/weko_admin/admin/restricted_access_settings.html
@@ -44,20 +44,29 @@
{% from "weko_theme/macros/modal_page.html" import all_modal %}
{% set download_limit = _("Download Limit") %}
{% set expiration_date = _("Expiration Date") %}
+ {% set max_download_limit = _("Max Download Limit") %}
+ {% set max_expiration_date = _("Max Expiration Date") %}
+ {% set expiration_date_initial = _("Expiration Date Initial Value") %}
+ {% set download_limit_initial = _("Download Limit Initial Value") %}
+
+
+
+
+ value='{{ _("Must set a positive integer and less than %(name1)s for %(name2)s.", name1=max_download_limit, name2=download_limit_initial) }}'/>
+ value='{{ _("Must set a positive integer and less than %(name1)s for %(name2)s.", name1=max_expiration_date, name2=expiration_date_initial) }}'/>
-
+
+
diff --git a/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.mo b/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.mo
index a9b27e75fd..c57d163986 100644
Binary files a/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.mo and b/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.mo differ
diff --git a/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.po b/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.po
index ee0d04ea03..1cf47d373c 100644
--- a/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.po
+++ b/modules/weko-admin/weko_admin/translations/en/LC_MESSAGES/messages.po
@@ -1105,6 +1105,14 @@ msgstr ""
msgid "Expiration Date"
msgstr ""
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:47
+msgid "Max Expiration Date"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:488
+msgid "Max Download Limit"
+msgstr ""
+
#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:48
msgid "Content File Download"
msgstr ""
@@ -1118,10 +1126,14 @@ msgid "Usage Report Workflow Access"
msgstr "Usage Report Workflow Access"
#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:55
+#, python-format
+msgid "Must set a positive integer and less than %(name1)s for %(name2)s."
+msgstr ""
+
#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:57
#, python-format
-msgid "Must set a positive integer for %(name)s."
-msgstr "Must set a positive integer for %(name)s."
+msgid "Must set a positive integer and less than %(name1)s for %(name2)s."
+msgstr ""
#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:58
#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:59
diff --git a/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.mo b/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.mo
index f653912324..1c1e4a342a 100644
Binary files a/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.mo and b/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.mo differ
diff --git a/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.po b/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.po
index 16f7cff6c3..1b102bbcf8 100644
--- a/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.po
+++ b/modules/weko-admin/weko_admin/translations/ja/LC_MESSAGES/messages.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: weko-admin 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2021-07-29 21:12+0900\n"
+"POT-Creation-Date: 2025-02-25 09:34+0900\n"
"PO-Revision-Date: 2018-01-19 19:54+0900\n"
"Last-Translator: FULL NAME \n"
"Language: ja\n"
@@ -18,625 +18,635 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
-#: weko_admin/admin.py:105
+#: tests/test_admin.py:1669 tests/test_admin.py:1675 tests/test_admin.py:1677
+#: tests/test_admin.py:1694 tests/test_admin.py:1702 tests/test_admin.py:1710
+#: tests/test_admin.py:1718 weko_admin/admin.py:134
+msgid "completed"
+msgstr "処理が完了しました。"
+
+#: tests/test_admin.py:1727 weko_admin/admin.py:127
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:43
+msgid "executing..."
+msgstr "実行中..."
+
+#: tests/test_admin.py:1737 weko_admin/admin.py:125
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:42
+msgid "haserror"
+msgstr "エラー発生中につき実行できません。"
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:152
+msgid "15 mins"
+msgstr "15分"
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:153
+msgid "30 mins"
+msgstr "30分"
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:154
+msgid "45 mins"
+msgstr "45分"
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:155
+msgid "60 mins"
+msgstr "1時間"
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:156
+msgid "180 mins"
+msgstr "3時間"
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:157
+msgid "360 mins"
+msgstr "6時間"
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:158
+msgid "720 mins"
+msgstr "12時間"
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:159
+msgid "1440 mins"
+msgstr "1日"
+
+#: weko_admin/admin.py:220
msgid "deny access"
msgstr "アクセス拒否"
-#: weko_admin/admin.py:124
+#: weko_admin/admin.py:239
#, fuzzy
msgid "Successfully update color."
msgstr "スケジュールを変更しました"
-#: weko_admin/admin.py:310
+#: weko_admin/admin.py:438
msgid "Monday"
msgstr "月曜日"
-#: weko_admin/admin.py:310
+#: weko_admin/admin.py:438
msgid "Tuesday"
msgstr "火曜日"
-#: weko_admin/admin.py:310
+#: weko_admin/admin.py:438
msgid "Wednesday"
msgstr "水曜日"
-#: weko_admin/admin.py:311
+#: weko_admin/admin.py:439
msgid "Thursday"
msgstr "木曜日"
-#: weko_admin/admin.py:311
+#: weko_admin/admin.py:439
msgid "Friday"
msgstr "金曜日"
-#: weko_admin/admin.py:311
+#: weko_admin/admin.py:439
msgid "Saturday"
msgstr "土曜日"
-#: weko_admin/admin.py:312
+#: weko_admin/admin.py:440
msgid "Sunday"
msgstr "日曜日"
-#: weko_admin/admin.py:342 weko_admin/tasks.py:92
+#: weko_admin/admin.py:469 weko_admin/tasks.py:161
msgid " Log report."
msgstr "ログレポート"
-#: weko_admin/admin.py:353
+#: weko_admin/admin.py:480
msgid "Successfully sent the reports to the recepients."
msgstr "レポートを送信しました"
-#: weko_admin/admin.py:363
+#: weko_admin/admin.py:490
msgid "Unexpected error occurred."
msgstr "予期しないエラーが発生しました"
-#: weko_admin/admin.py:397
+#: weko_admin/admin.py:521
msgid "Successfully Changed Schedule."
msgstr "スケジュールを変更しました"
-#: weko_admin/admin.py:399
+#: weko_admin/admin.py:523
msgid "Could Not Save Changes."
msgstr "変更を保存できませんでした"
-#: weko_admin/admin.py:464 weko_admin/admin.py:572 weko_admin/admin.py:806
+#: weko_admin/admin.py:578 weko_admin/admin.py:604 weko_admin/admin.py:705
+#: weko_admin/admin.py:957
msgid "Successfully Changed Settings."
msgstr "設定を変更しました"
-#: weko_admin/admin.py:485 weko_admin/views.py:564
+#: weko_admin/admin.py:608 weko_admin/views.py:665
msgid "Could not save data."
msgstr "データを保存できませんでした"
-#: weko_admin/admin.py:496
-msgid "Could not get restricted data: "
+#: weko_admin/admin.py:619
+#, fuzzy, python-format
+msgid "Could not get restricted data: %s"
msgstr "制限付きデータを取得できませんでした"
-#: weko_admin/admin.py:497
+#: weko_admin/admin.py:620
msgid "Could not get restricted data."
msgstr "制限付きデータを取得できませんでした"
-#: weko_admin/admin.py:576 weko_admin/admin.py:809 weko_admin/admin.py:812
+#: weko_admin/admin.py:709 weko_admin/admin.py:960 weko_admin/admin.py:963
msgid "Failurely Changed Settings."
msgstr "設定変更に失敗しました"
-#: weko_admin/admin.py:849
+#: weko_admin/admin.py:1000
#, fuzzy
msgid "Successfully Changed Settings"
msgstr "設定を変更しました"
-#: weko_admin/admin.py:853
+#: weko_admin/admin.py:1004
#, fuzzy
msgid "Failed To Change Settings"
msgstr "設定変更に失敗しました"
-#: weko_admin/admin.py:913
+#: weko_admin/admin.py:1066
msgid "Prefix"
msgstr ""
-#: weko_admin/admin.py:919
+#: weko_admin/admin.py:1072
msgid "Suffix"
msgstr ""
-#: weko_admin/admin.py:921
+#: weko_admin/admin.py:1074
msgid "Enable/Disable"
msgstr ""
-#: weko_admin/admin.py:931
+#: weko_admin/admin.py:1084
msgid "Repository"
msgstr ""
-#: weko_admin/admin.py:931
+#: weko_admin/admin.py:1084
msgid "JaLC DOI"
msgstr ""
-#: weko_admin/admin.py:932
+#: weko_admin/admin.py:1085
msgid "JaLC CrossRef DOI"
msgstr ""
-#: weko_admin/admin.py:933
+#: weko_admin/admin.py:1086
msgid "JaLC DataCite DOI"
msgstr ""
-#: weko_admin/admin.py:934
+#: weko_admin/admin.py:1087
msgid "NDL JaLC DOI"
msgstr ""
-#: weko_admin/admin.py:935
+#: weko_admin/admin.py:1088
msgid "Semi-automatic Suffix"
msgstr ""
-#: weko_admin/admin.py:952
+#: weko_admin/admin.py:1105
msgid "Only allow half with 1-bytes character in input"
msgstr ""
-#: weko_admin/admin.py:1017
+#: weko_admin/admin.py:1170
msgid "Specified repository is already registered."
msgstr "指定したリポジトリが既に登録されています。"
-#: weko_admin/admin.py:1137
+#: weko_admin/admin.py:1298
msgid "ID"
msgstr ""
-#: weko_admin/admin.py:1138
+#: weko_admin/admin.py:1299
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:50
msgid "Item Name(EN)"
msgstr "項目名(英)"
-#: weko_admin/admin.py:1139
+#: weko_admin/admin.py:1300
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:51
msgid "Item Name(JP)"
msgstr "項目名(日)"
-#: weko_admin/admin.py:1140
+#: weko_admin/admin.py:1301
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:52
msgid "Mapping"
msgstr "マッピング"
-#: weko_admin/admin.py:1141
+#: weko_admin/admin.py:1302
+msgid "UI"
+msgstr ""
+
+#: weko_admin/admin.py:1303
#, fuzzy
msgid "Active"
msgstr "保存"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:59
-msgid "UiType"
-msgstr "UI"
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:60
-msgid "DisplayNumber"
-msgstr "表示件数"
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:61
-msgid "OpenClose"
-msgstr "開閉状態"
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:62
-msgid "OpenClose Open"
-msgstr "開"
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:63
-msgid "OpenClose Close"
-msgstr "閉"
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:64
-msgid "DisplayNumber Validation1"
-msgstr "表示件数は1以上99以下の整数値で入力する必要があります。"
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:65
-msgid "DisplayNumber Validation2"
-msgstr "CheckboxListを選択した場合は表示件数を入力する必要があります。"
-
-#: weko_admin/admin.py:1210 weko_admin/admin.py:1237 weko_admin/admin.py:1246
-#: weko_admin/admin.py:1255 weko_admin/admin.py:1264 weko_admin/admin.py:1273
-#: weko_admin/admin.py:1282 weko_admin/admin.py:1291 weko_admin/admin.py:1309
-#: weko_admin/admin.py:1318 weko_admin/admin.py:1327 weko_admin/admin.py:1336
-#: weko_admin/admin.py:1344 weko_admin/admin.py:1352
+#: weko_admin/admin.py:1372 weko_admin/admin.py:1399 weko_admin/admin.py:1408
+#: weko_admin/admin.py:1417 weko_admin/admin.py:1426 weko_admin/admin.py:1435
+#: weko_admin/admin.py:1444 weko_admin/admin.py:1453 weko_admin/admin.py:1471
+#: weko_admin/admin.py:1480 weko_admin/admin.py:1489 weko_admin/admin.py:1498
+#: weko_admin/admin.py:1506 weko_admin/admin.py:1514
msgid "Setting"
msgstr "設定"
-#: weko_admin/admin.py:1211
+#: weko_admin/admin.py:1373
msgid "Style"
msgstr "様式"
-#: weko_admin/admin.py:1219 weko_admin/admin.py:1228 weko_admin/admin.py:1300
+#: weko_admin/admin.py:1381 weko_admin/admin.py:1390 weko_admin/admin.py:1462
msgid "Statistics"
msgstr "統計"
-#: weko_admin/admin.py:1220
+#: weko_admin/admin.py:1382
msgid "Report"
msgstr "レポート"
-#: weko_admin/admin.py:1229
+#: weko_admin/admin.py:1391
msgid "Feedback Mail"
msgstr ""
-#: weko_admin/admin.py:1238
+#: weko_admin/admin.py:1400
msgid "Stats"
msgstr "統計"
-#: weko_admin/admin.py:1247
+#: weko_admin/admin.py:1409
#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:45
msgid "Log Analysis"
msgstr "ログ分析"
-#: weko_admin/admin.py:1256
-#: weko_admin/templates/weko_admin/admin/site_info.html:48
+#: weko_admin/admin.py:1418
+#: weko_admin/templates/weko_admin/admin/site_info.html:50
#, fuzzy
msgid "Language"
msgstr "言語"
-#: weko_admin/admin.py:1265
+#: weko_admin/admin.py:1427
msgid "WebAPI Account"
msgstr ""
-#: weko_admin/admin.py:1274
+#: weko_admin/admin.py:1436
msgid "Ranking"
msgstr "ランキング"
-#: weko_admin/admin.py:1283
+#: weko_admin/admin.py:1445
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:61
msgid "Search"
msgstr "検索"
-#: weko_admin/admin.py:1292 weko_admin/admin.py:1301 weko_admin/config.py:154
-#: weko_admin/config.py:159
+#: weko_admin/admin.py:1454 weko_admin/admin.py:1463 weko_admin/config.py:168
+#: weko_admin/config.py:173
msgid "Site License"
msgstr "サイトライセンス"
-#: weko_admin/admin.py:1310
+#: weko_admin/admin.py:1472
#, fuzzy
msgid "File Preview"
msgstr "ファイルプレビュー"
-#: weko_admin/admin.py:1319
+#: weko_admin/admin.py:1481
#, fuzzy
msgid "Item Export"
msgstr "定型レポート"
-#: weko_admin/admin.py:1328
+#: weko_admin/admin.py:1490
msgid "Site Info"
msgstr ""
-#: weko_admin/admin.py:1337
+#: weko_admin/admin.py:1499
#, fuzzy
msgid "Restricted Access"
msgstr "サイトアクセス"
-#: weko_admin/admin.py:1345
+#: weko_admin/admin.py:1507
msgid "Identifier"
msgstr ""
-#: weko_admin/admin.py:1353
+#: weko_admin/admin.py:1515
#, fuzzy
msgid "Faceted Search"
msgstr "ファセット検索一覧"
-#: weko_admin/api.py:82
+#: weko_admin/admin.py:1522
+msgid "Maintenance"
+msgstr "メンテナンス"
+
+#: weko_admin/admin.py:1523
+msgid "ElasticSearch Index"
+msgstr "インデックス再作成"
+
+#: weko_admin/api.py:127
#, fuzzy
msgid "statistics report"
msgstr "統計設定"
-#: weko_admin/config.py:129
+#: weko_admin/config.py:143
msgid "No. Of File Downloads"
msgstr "ファイルダウンロード数"
-#: weko_admin/config.py:130
+#: weko_admin/config.py:144
msgid "No. Of File Previews"
msgstr "ファイルプレビュー数"
-#: weko_admin/config.py:131
+#: weko_admin/config.py:145
#, fuzzy
msgid "No. Of Paid File Downloads"
msgstr "ファイルダウンロード数"
-#: weko_admin/config.py:132
+#: weko_admin/config.py:146
#, fuzzy
msgid "No. Of Paid File Previews"
msgstr "ファイルプレビュー数"
-#: weko_admin/config.py:133
+#: weko_admin/config.py:147
msgid "Detail Views Per Index"
msgstr "インデックス毎の詳細ビュー"
-#: weko_admin/config.py:134
+#: weko_admin/config.py:148
msgid "Detail Views Count"
msgstr "詳細ビュー数"
-#: weko_admin/config.py:135
+#: weko_admin/config.py:149
msgid "Usage Count By User"
msgstr "ユーザー別使用数"
-#: weko_admin/config.py:136
+#: weko_admin/config.py:150
msgid "Search Keyword Ranking"
msgstr "検索キーワードランキング"
-#: weko_admin/config.py:137
+#: weko_admin/config.py:151
msgid "Number Of Access By Host"
msgstr "ホスト別アクセス数"
-#: weko_admin/config.py:138
+#: weko_admin/config.py:152
msgid "User Affiliation Information"
msgstr "ユーザー所属情報"
-#: weko_admin/config.py:139
+#: weko_admin/config.py:153
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:21
msgid "Access Count By Site License"
msgstr "サイトライセンス別アクセス数"
-#: weko_admin/config.py:144
+#: weko_admin/config.py:158
msgid "Open-Access No. Of File Downloads"
msgstr "オープンアクセスファイルダウンロード数"
-#: weko_admin/config.py:145
+#: weko_admin/config.py:159
msgid "Open-Access No. Of File Previews"
msgstr "オープンアクセスファイルプレビュー数"
-#: weko_admin/config.py:146
+#: weko_admin/config.py:160
msgid "Access Number Breakdown By Site License"
msgstr "サイトライセンス別アクセス番号内訳"
-#: weko_admin/config.py:152 weko_admin/config.py:157
+#: weko_admin/config.py:166 weko_admin/config.py:171
msgid "File Name"
msgstr "ファイル名"
-#: weko_admin/config.py:152 weko_admin/config.py:157 weko_admin/config.py:163
+#: weko_admin/config.py:166 weko_admin/config.py:171 weko_admin/config.py:177
msgid "Registered Index Name"
msgstr "登録インデックス名"
-#: weko_admin/config.py:153
+#: weko_admin/config.py:167
#, fuzzy
msgid "No. Of Times Downloaded"
msgstr "ダウンロード/表示回数"
-#: weko_admin/config.py:153 weko_admin/config.py:158
+#: weko_admin/config.py:167 weko_admin/config.py:172
msgid "Non-Logged In User"
msgstr "非ログインユーザー"
-#: weko_admin/config.py:154 weko_admin/config.py:159
+#: weko_admin/config.py:168 weko_admin/config.py:173
msgid "Logged In User"
msgstr "ログインユーザー"
-#: weko_admin/config.py:154 weko_admin/config.py:159
+#: weko_admin/config.py:168 weko_admin/config.py:173
msgid "Admin"
msgstr "管理者"
-#: weko_admin/config.py:155 weko_admin/config.py:160
+#: weko_admin/config.py:169 weko_admin/config.py:174
msgid "Registrar"
msgstr "登録者"
-#: weko_admin/config.py:158
+#: weko_admin/config.py:172
#, fuzzy
msgid "No. Of Times Viewed"
msgstr "ファイルプレビュー数"
-#: weko_admin/config.py:161
+#: weko_admin/config.py:175
msgid "Index"
msgstr "インデックス"
-#: weko_admin/config.py:161
+#: weko_admin/config.py:175
msgid "No. Of Views"
msgstr "ビュー数"
-#: weko_admin/config.py:163
+#: weko_admin/config.py:177
msgid "Title"
msgstr "タイトル"
-#: weko_admin/config.py:163
+#: weko_admin/config.py:177
msgid "View Count"
msgstr "ビュー数"
-#: weko_admin/config.py:164
+#: weko_admin/config.py:178
msgid "Non-logged-in User"
msgstr "非ログインユーザー"
-#: weko_admin/config.py:165
+#: weko_admin/config.py:179
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:49
msgid "Mail address"
msgstr "メールアドレス"
-#: weko_admin/config.py:166
+#: weko_admin/config.py:180
msgid "Username"
msgstr "ユーザー名"
-#: weko_admin/config.py:167
+#: weko_admin/config.py:181
msgid "File download count"
msgstr "ファイルダウンロード数"
-#: weko_admin/config.py:168
+#: weko_admin/config.py:182
msgid "File playing count"
msgstr "ファイル再生回数"
-#: weko_admin/config.py:169
+#: weko_admin/config.py:183
#: weko_admin/templates/weko_admin/admin/report.html:116
msgid "Search Keyword"
msgstr "検索キーワード"
-#: weko_admin/config.py:169 weko_admin/config.py:174
+#: weko_admin/config.py:183 weko_admin/config.py:188
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:25
msgid "Number Of Searches"
msgstr "検索数"
-#: weko_admin/config.py:170
+#: weko_admin/config.py:184
msgid "Host"
msgstr "ホスト"
-#: weko_admin/config.py:170
+#: weko_admin/config.py:184
msgid "IP Address"
msgstr "IPアドレス"
-#: weko_admin/config.py:171 weko_admin/config.py:173
+#: weko_admin/config.py:185 weko_admin/config.py:187
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:24
msgid "WEKO Top Page Access Count"
msgstr "WEKOトップページアクセス数"
-#: weko_admin/config.py:172
+#: weko_admin/config.py:186
msgid "Role"
msgstr "ロール"
-#: weko_admin/config.py:172
+#: weko_admin/config.py:186
msgid "Number Of Users"
msgstr "利用者数"
-#: weko_admin/config.py:174
+#: weko_admin/config.py:188
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:26
msgid "Number Of Views"
msgstr "ビュー数"
-#: weko_admin/config.py:175
+#: weko_admin/config.py:189
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:27
msgid "Number Of File download"
msgstr "ファイルダウンロード数"
-#: weko_admin/config.py:176
+#: weko_admin/config.py:190
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:28
msgid "Number Of File Regeneration"
msgstr "ファイル再生回数"
-#: weko_admin/config.py:181
+#: weko_admin/config.py:195
msgid "FileDownload_"
msgstr "ファイルダウンロード"
-#: weko_admin/config.py:182
+#: weko_admin/config.py:196
msgid "FilePreview_"
msgstr "ファイルプレビュー"
-#: weko_admin/config.py:183
+#: weko_admin/config.py:197
#, fuzzy
msgid "PayFileDownload_"
msgstr "ファイルダウンロード"
-#: weko_admin/config.py:184
+#: weko_admin/config.py:198
#, fuzzy
msgid "PayFilePreview_"
msgstr "ファイルプレビュー"
-#: weko_admin/config.py:185
+#: weko_admin/config.py:199
msgid "IndexAccess_"
msgstr "索引アクセス"
-#: weko_admin/config.py:186
+#: weko_admin/config.py:200
msgid "DetailView_"
msgstr "詳細ビュー"
-#: weko_admin/config.py:187
+#: weko_admin/config.py:201
msgid "FileUsingPerUser_"
msgstr "ユーザー毎のファイル使用"
-#: weko_admin/config.py:188
+#: weko_admin/config.py:202
msgid "SearchCount_"
msgstr "検索回数"
-#: weko_admin/config.py:189
+#: weko_admin/config.py:203
msgid "UserAffiliate_"
msgstr "加入ユーザー"
-#: weko_admin/config.py:190
+#: weko_admin/config.py:204
msgid "SiteAccess_"
msgstr "サイトアクセス"
-#: weko_admin/config.py:191
+#: weko_admin/config.py:205
msgid "TopPageAccess_"
msgstr "トップページへのアクセス"
-#: weko_admin/ext.py:74
+#: weko_admin/ext.py:75
msgid "A translation string"
msgstr "翻訳文字列"
-#: weko_admin/utils.py:235
+#: weko_admin/utils.py:234
msgid "Input type is invalid. Please check again."
msgstr "入力タイプが無効です。再度確認してください"
-#: weko_admin/utils.py:238 weko_admin/views.py:284 weko_admin/views.py:289
+#: weko_admin/utils.py:237 weko_admin/views.py:326 weko_admin/views.py:331
msgid "Account information is invalid. Please check again."
msgstr "アカウント情報が無効です。再度確認してください"
-#: weko_admin/utils.py:331
+#: weko_admin/utils.py:328
#, fuzzy
msgid "Registered Users"
msgstr "登録ユーザー"
-#: weko_admin/utils.py:373
+#: weko_admin/utils.py:372
msgid "Aggregation Month"
msgstr "月別集計"
-#: weko_admin/utils.py:388
+#: weko_admin/utils.py:389
msgid "Total Detail Views"
msgstr "詳細ビュー合計"
-#: weko_admin/utils.py:396
+#: weko_admin/utils.py:398
msgid "Site license member"
msgstr "サイトライセンスメンバー"
-#: weko_admin/utils.py:400
+#: weko_admin/utils.py:402
msgid "Other than site license"
msgstr "サイトライセンス外"
-#: weko_admin/utils.py:411
+#: weko_admin/utils.py:413
#, fuzzy
msgid "Institution Name"
msgstr "機関名"
-#: weko_admin/utils.py:1198
+#: weko_admin/utils.py:1219
msgid "Cannot update Feedback email settings."
msgstr ""
-#: weko_admin/utils.py:1225
+#: weko_admin/utils.py:1246
msgid "Author is duplicated."
msgstr " 著者が重複しています。"
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:48
-#: weko_admin/utils.py:1232
+#: weko_admin/utils.py:1253
msgid "Duplicate Email Addresses."
msgstr "メールアドレスが重複しています。"
-#: weko_admin/views.py:102
+#: weko_admin/views.py:116
#, python-format
msgid "%(icon)s Session"
msgstr "%(icon)s セッション"
-#: weko_admin/views.py:108
+#: weko_admin/views.py:122
msgid "Session"
msgstr "セッション"
-#: weko_admin/views.py:132
+#: weko_admin/views.py:147
msgid "Session lifetime was updated."
msgstr "セッションライフタイムは更新されました"
-#: weko_admin/views.py:137
-msgid "15 mins"
-msgstr "15分"
-
-#: weko_admin/views.py:138
-msgid "30 mins"
-msgstr "30分"
-
-#: weko_admin/views.py:139
-msgid "45 mins"
-msgstr "45分"
-
-#: weko_admin/views.py:140
-msgid "60 mins"
-msgstr "1時間"
-
-#: weko_admin/views.py:141
-msgid "180 mins"
-msgstr "3時間"
-
-#: weko_admin/views.py:142
-msgid "360 mins"
-msgstr "6時間"
-
-#: weko_admin/views.py:143
-msgid "720 mins"
-msgstr "12時間"
-
-#: weko_admin/views.py:144
-msgid "1440 mins"
-msgstr "1日"
-
-#: weko_admin/views.py:277
+#: weko_admin/views.py:319
msgid "Header Error"
msgstr "ヘッダエラー"
-#: weko_admin/views.py:559
+#: weko_admin/views.py:660
msgid "Restricted Access was successfully updated."
msgstr "制限公開の設定を変更しました。"
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:54
-#: weko_admin/views.py:618 weko_admin/views.py:651
+#: weko_admin/views.py:725 weko_admin/views.py:760
msgid "Success"
msgstr "成功"
-#: weko_admin/views.py:627
+#: weko_admin/views.py:734
msgid "Failed to update due to server error."
msgstr "サーバーエラーのため、更新に失敗しました。"
-#: weko_admin/views.py:632
+#: weko_admin/views.py:739
msgid "Failed to create due to server error."
msgstr "サーバーエラーのため、作成に失敗しました。"
-#: weko_admin/views.py:635
+#: weko_admin/views.py:742
msgid ""
"The item name/mapping is already exists. Please input other faceted "
"item/mapping."
msgstr "既に存在する項目名・マッピングです。別のファセット項目名・マッピングを入力してください。"
-#: weko_admin/views.py:658 weko_admin/views.py:661
+#: weko_admin/views.py:767 weko_admin/views.py:770
msgid "Failed to delete due to server error."
msgstr "サーバーエラーのため、削除に失敗しました。"
@@ -644,21 +654,21 @@ msgstr "サーバーエラーのため、削除に失敗しました。"
msgid "Welcome to"
msgstr "ようこそ"
-#: weko_admin/templates/weko_admin/admin/block_style.html:87
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:67
+#: weko_admin/templates/weko_admin/admin/block_style.html:89
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:74
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:44
#: weko_admin/templates/weko_admin/admin/file_preview_settings.html:62
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:94
#: weko_admin/templates/weko_admin/admin/lang_settings.html:86
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:169
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:191
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:145
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:170
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:192
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:147
#: weko_admin/templates/weko_admin/admin/report.html:224
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:52
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:422
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:459
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:562
-#: weko_admin/templates/weko_admin/admin/site_info.html:49
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:60
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:442
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:479
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:582
+#: weko_admin/templates/weko_admin/admin/site_info.html:51
#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:174
#: weko_admin/templates/weko_admin/admin/site_license_settings.html:204
#: weko_admin/templates/weko_admin/admin/stats_settings.html:71
@@ -667,11 +677,11 @@ msgstr "ようこそ"
msgid "Save"
msgstr "保存"
-#: weko_admin/templates/weko_admin/admin/block_style.html:91
+#: weko_admin/templates/weko_admin/admin/block_style.html:93
msgid "Color Setting"
msgstr "カラー設定"
-#: weko_admin/templates/weko_admin/admin/block_style.html:97
+#: weko_admin/templates/weko_admin/admin/block_style.html:99
msgid "Background1"
msgstr "背景1"
@@ -700,58 +710,95 @@ msgid "_Display"
msgstr "表示"
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:59
+msgid "UiType"
+msgstr "UI"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:60
+msgid "DisplayNumber"
+msgstr "表示件数"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:61
+msgid "OpenClose"
+msgstr "開閉状態"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:62
+msgid "OpenClose Open"
+msgstr "開"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:63
+msgid "OpenClose Close"
+msgstr "閉"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:64
+msgid "DisplayNumber Validation1"
+msgstr "表示件数は1以上99以下の整数値で入力する必要があります。"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:65
+msgid "DisplayNumber Validation2"
+msgstr "CheckboxListを選択した場合は表示件数を入力する必要があります。"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:66
msgid "_Hide"
msgstr "非表示"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:61
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:68
msgid "List"
msgstr "一覧"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:62
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:69
msgid "Create"
msgstr "作成"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:63
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:70
#: weko_admin/templates/weko_admin/admin/search_management_settings.html:230
msgid "Edit"
msgstr "編集"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:64
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:71
#: weko_admin/templates/weko_admin/partials/email_schedule.html:23
msgid "Details"
msgstr "詳細"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:66
-#: weko_admin/templates/weko_admin/settings/lifetime.html:55
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:73
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:48
+#: weko_admin/templates/weko_admin/settings/lifetime.html:56
msgid "Cancel"
msgstr "キャンセル"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:68
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:75
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:45
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:149
-#: weko_admin/templates/weko_admin/admin/site_info.html:57
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:151
+#: weko_admin/templates/weko_admin/admin/site_info.html:59
#: weko_admin/templates/weko_admin/admin/site_license_settings.html:70
msgid "Delete"
msgstr "削除"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:69
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:64
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:541
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:76
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:73
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:561
msgid "Add"
msgstr "追加"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:70
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:78
msgid "Please input all required item."
msgstr "必須項目は全て入力して下さい。"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:77
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:183
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:79
+msgid "Please select one aggregation mapping."
+msgstr "集計マッピングを1つ選択してください。"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:80
+msgid "Already exists."
+msgstr "既に存在しています。"
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:87
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:184
#: weko_admin/templates/weko_admin/admin/report.html:247
#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:197
msgid "Confirmation"
msgstr "確認"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:78
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:88
msgid "Are you sure you want to delete it?"
msgstr "削除してよろしいですか?"
@@ -822,9 +869,9 @@ msgid "Resend"
msgstr "再送信"
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:59
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:195
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:196
#: weko_admin/templates/weko_admin/admin/report.html:273
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:75
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:84
msgid "Close"
msgstr "閉じる"
@@ -863,7 +910,7 @@ msgstr ""
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:59
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:78
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:47
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:48
#: weko_admin/templates/weko_admin/admin/stats_settings.html:59
#: weko_admin/templates/weko_admin/partials/email_schedule.html:75
msgid "On"
@@ -871,7 +918,7 @@ msgstr "オン"
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:65
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:84
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:52
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:53
#: weko_admin/templates/weko_admin/admin/stats_settings.html:64
#: weko_admin/templates/weko_admin/partials/email_schedule.html:80
msgid "Off"
@@ -889,70 +936,105 @@ msgstr "対象言語"
msgid "Registered language"
msgstr "登録言語"
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:56
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:57
msgid "Addresses to Filter"
msgstr "フィルタリングするアドレス"
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:64
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:65
msgid "Enter the IP Addresses to Filter"
msgstr "フィルタリングするIPアドレスの入力"
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:128
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:129
msgid "Shared Crawler Lists"
msgstr "共有クローラーリスト"
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:186
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:187
msgid "Are you sure you want to block the given addresses?"
msgstr "与えられたアドレスをブロックしてもよろしいですか?"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:41
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:42
msgid "Show/Hide Ranking"
msgstr "ランキングの表示/非表示"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:58
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:59
msgid "Period To Judge As New Item"
msgstr "新着アイテムとして判断する期間"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:64
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:65
msgid "Day (Range : 1~30)"
msgstr "日(範囲:1-30)"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:68
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:69
msgid "Statistical Period"
msgstr "統計期間"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:73
-msgid "Day"
-msgstr "日"
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:74
+#, fuzzy
+msgid "Day (Range : 1~3650)"
+msgstr "日(範囲:1-30)"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:77
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:78
msgid "Display Rank"
msgstr "表示する順位"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:85
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:83
+#, fuzzy
+msgid "(Range : 1~100)"
+msgstr "日(範囲:1-30)"
+
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:87
msgid "Rankings"
msgstr "ランキング"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:91
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:93
msgid "Most Viewed Items"
msgstr "最も閲覧されたアイテム"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:102
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:104
msgid "Most Downloaded Items"
msgstr "最もダウンロードされたアイテム"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:113
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:115
msgid "User Who Created The Most Items"
msgstr "最もアイテムを作成したユーザー"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:124
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:126
msgid "Most Searched Keywords"
msgstr "最も検索されたキーワード"
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:135
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:137
msgid "New Items"
msgstr "新着アイテム"
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:38
+msgid "reindex item_index"
+msgstr "アイテムインデックスの再作成"
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:39
+msgid "reindex item"
+msgstr "アイテムの再インデックス"
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:40
+msgid "execute"
+msgstr "実行"
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:41
+msgid "waiting..."
+msgstr "実行可能"
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:47
+#, fuzzy
+msgid "Execute"
+msgstr "実行"
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:49
+msgid "validationMsg1"
+msgstr "実行モードが選ばれていません。"
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:50
+msgid "confirmMessage"
+msgstr "本処理の実行にはかなりの時間がかかることが予想されます。インデックスの再作成処理を実行してよいですか?"
+
#: weko_admin/templates/weko_admin/admin/report.html:54
msgid "Number of items registered"
msgstr "登録件数"
@@ -1074,7 +1156,7 @@ msgid "Are you sure you want to save changes?"
msgstr "変更してもよろしいですか?"
#: weko_admin/templates/weko_admin/admin/report.html:255
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:76
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:85
msgid "Send Mail"
msgstr "メール送信"
@@ -1094,99 +1176,117 @@ msgstr "ダウンロード回数"
msgid "Expiration Date"
msgstr "有効期限日数"
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:47
+msgid "Max Download Limit"
+msgstr "ダウンロード回数上限"
+
#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:48
+msgid "Max Expiration Date"
+msgstr "有効期限日数上限"
+
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:49
+msgid "Expiration Date Initial Value"
+msgstr "ダウンロード回数初期値"
+
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:50
+msgid "Download Limit Initial Value"
+msgstr "有効期限日数初期値"
+
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:52
msgid "Content File Download"
msgstr "コンテンツファイルのダウンロード"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:51
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:59
msgid "Unlimited"
msgstr "無制限"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:53
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:61
msgid "Usage Report Workflow Access"
msgstr "利用報告ワークフローへのアクセス"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:55
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:57
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:63
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:65
#, python-format
-msgid "Must set a positive integer for %(name)s."
-msgstr "%(name)sは1以上の整数を設定する必要があります。"
+msgid "Must set a positive integer and less than %(name1)s for %(name2)s."
+msgstr "%(name2)sは1以上の整数かつ%(name1)s以下の値を設定する必要があります。"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:58
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:59
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:66
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:67
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:68
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:69
#, python-format
msgid "Please set %(name)s."
msgstr "%(name)sを設定してください。"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:61
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:444
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:451
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:70
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:464
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:471
msgid "English"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:62
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:445
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:452
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:71
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:465
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:472
msgid "Japanese"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:63
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:72
msgid "Terms and Conditions"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:65
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:74
msgid "Please input the Terms and Conditions in English."
msgstr "英語の利用規約を入力してください。"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:68
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:77
msgid "Activity"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:69
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:78
#, fuzzy
msgid "Item"
msgstr "タイトル"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:70
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:79
msgid "WorkFlow"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:71
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:80
#, fuzzy
msgid "Status"
msgstr "統計"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:72
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:81
#, fuzzy
msgid "User"
msgstr "ユーザー"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:73
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:82
msgid "Usage Report Reminder Email"
msgstr "利用報告督促メール"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:74
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:83
msgid "Confirm Usage Mail"
msgstr "確認"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:77
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:86
#, fuzzy
msgid "Email is sent successfully."
msgstr "サイト情報が正常に保存されました。"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:78
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:87
msgid "Failed to send mail."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:79
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:88
msgid "action_doing"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:80
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:89
msgid "Secret URL Download"
msgstr "シークレットURLダウンロード"
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:81
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:90
msgid "SecretURL Enabled"
msgstr "機能有効化"
@@ -1311,7 +1411,6 @@ msgstr "座標"
msgid "Search item setting"
msgstr "検索項目設定"
-#: weko_admin/template/weko_admin/admin/search_management_setting.html
#: weko_admin/templates/weko_admin/admin/search_management_settings.html:279
msgid "Index Tree/Facet Display Setting"
msgstr "インデックスツリー/ファセット表示設定"
@@ -1322,6 +1421,7 @@ msgstr "インデックスツリー"
#: weko_admin/templates/weko_admin/admin/search_management_settings.html:295
#: weko_admin/templates/weko_admin/admin/search_management_settings.html:336
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:356
#, fuzzy
msgid "Display"
msgstr "表示"
@@ -1338,32 +1438,36 @@ msgstr ""
msgid "Facet"
msgstr "ファセット"
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:356
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:349
+msgid "Community"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:376
msgid "Main Screen Initial Display Setting"
msgstr "初期表示設定"
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:366
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:386
msgid "Default Contents to Display"
msgstr "初期表示画面設定"
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:380
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:400
msgid "Default Index to Display"
msgstr "初期表示インデックス表示方法"
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:397
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:417
msgid "Initial Display Index"
msgstr "初期表示インデックス"
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:400
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:420
msgid "An index which is not open in public cannot be selected"
msgstr "非公開インデックス以下は選択できません"
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:484
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:504
msgid "Item Type List"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:524
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:531
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:544
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:551
msgid "Enter Input Value"
msgstr ""
@@ -1392,78 +1496,93 @@ msgid "Selected icon"
msgstr ""
#: weko_admin/templates/weko_admin/admin/site_info.html:45
-msgid "Select icon file"
+#, fuzzy
+msgid "Select File"
msgstr "アイコンファイルの選択"
#: weko_admin/templates/weko_admin/admin/site_info.html:46
+msgid "Select icon file"
+msgstr "アイコンファイルの選択"
+
+#: weko_admin/templates/weko_admin/admin/site_info.html:47
+msgid "Selected file name"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/site_info.html:48
msgid "Add site name"
msgstr "サイト名の追加"
-#: weko_admin/templates/weko_admin/admin/site_info.html:47
+#: weko_admin/templates/weko_admin/admin/site_info.html:49
msgid "Site name is not set"
msgstr "サイト名未設定"
-#: weko_admin/templates/weko_admin/admin/site_info.html:50
+#: weko_admin/templates/weko_admin/admin/site_info.html:52
msgid "Must set at least 1 site name."
msgstr "サイト名は少くとも1つ設定する必要があります。"
-#: weko_admin/templates/weko_admin/admin/site_info.html:51
+#: weko_admin/templates/weko_admin/admin/site_info.html:53
msgid "Please input site information for empty field."
msgstr "サイト情報を空のフィールドに入力してください。"
-#: weko_admin/templates/weko_admin/admin/site_info.html:52
+#: weko_admin/templates/weko_admin/admin/site_info.html:54
msgid "The same language is set for many site names."
msgstr "サイト名が重複しています"
-#: weko_admin/templates/weko_admin/admin/site_info.html:53
+#: weko_admin/templates/weko_admin/admin/site_info.html:55
#, fuzzy
msgid "Site name is required."
msgstr "サイト名未設定"
-#: weko_admin/templates/weko_admin/admin/site_info.html:54
+#: weko_admin/templates/weko_admin/admin/site_info.html:56
msgid "Error when get languages."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:55
+#: weko_admin/templates/weko_admin/admin/site_info.html:57
msgid "Error when get site infomation."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:56
+#: weko_admin/templates/weko_admin/admin/site_info.html:58
msgid "Language is deleted from Registered Language of system."
msgstr "削除された言語は利用できません"
-#: weko_admin/templates/weko_admin/admin/site_info.html:58
+#: weko_admin/templates/weko_admin/admin/site_info.html:60
msgid "Site info is saved successfully."
msgstr "サイト情報が正常に保存されました。"
-#: weko_admin/templates/weko_admin/admin/site_info.html:59
+#: weko_admin/templates/weko_admin/admin/site_info.html:61
msgid "Log in Instructions"
msgstr "ログインの注意書き"
-#: weko_admin/templates/weko_admin/admin/site_info.html:60
+#: weko_admin/templates/weko_admin/admin/site_info.html:62
msgid "Add Instructions"
msgstr "注意書きの追加"
-#: weko_admin/templates/weko_admin/admin/site_info.html:61
+#: weko_admin/templates/weko_admin/admin/site_info.html:63
msgid "The same language is set for many instructions."
msgstr " 同一言語を複数の注意書きに設定されています。"
-#: weko_admin/templates/weko_admin/admin/site_info.html:62
+#: weko_admin/templates/weko_admin/admin/site_info.html:64
msgid "Maximum length of instruction is 1000 characters. "
msgstr "注意書きの字数上限は1000字です。"
-#: weko_admin/template/weko_admin/admin/site_info.html:64
+#: weko_admin/templates/weko_admin/admin/site_info.html:66
msgid "Tracking ID"
msgstr "トラッキングID"
-#: weko_admin/template/weko_admin/admin/site_info.html:65
+#: weko_admin/templates/weko_admin/admin/site_info.html:67
msgid "AddThis ID"
msgstr "AddThis ID"
-#: weko_admin/template/weko_admin/admin/site_info.html:66
+#: weko_admin/templates/weko_admin/admin/site_info.html:68
msgid "OGP Image"
msgstr "OGPイメージ"
+#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:37
+msgid ""
+"Please classify a check into the organization send a use of site license "
+"statistics email."
+msgstr ""
+
#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:42
#, fuzzy
msgid "Organization"
@@ -1586,71 +1705,19 @@ msgstr "頻度"
msgid "Life Time"
msgstr "有効期間"
-#: weko_admin/templates/weko_admin/settings/lifetime.html:42
-#: weko_admin/templates/weko_admin/settings/lifetime.html:49
+#: weko_admin/templates/weko_admin/settings/lifetime.html:43
+#: weko_admin/templates/weko_admin/settings/lifetime.html:50
msgid "Set lifetime for"
msgstr "有効期間を設定"
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html
-msgid "Please select one aggregation mapping."
-msgstr "集計マッピングを1つ選択してください。"
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html
-msgid "Already exists."
-msgstr "既に存在しています。"
-
-#: weko_admin/templates/weko_admin/settings/lifetime.html:42
+#: weko_admin/templates/weko_admin/settings/lifetime.html:43
msgid "Current"
msgstr "現行"
-#: weko_admin/templates/weko_admin/settings/lifetime.html:58
+#: weko_admin/templates/weko_admin/settings/lifetime.html:59
msgid "Update"
msgstr "更新"
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "reindex item_index"
-msgstr "アイテムインデックスの再作成"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "reindex item"
-msgstr "アイテムの再インデックス"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "execute"
-msgstr "実行"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "Maintenance"
-msgstr "メンテナンス"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "ElasticSearch Index"
-msgstr "インデックス再作成"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "waiting..."
-msgstr "実行可能"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "executing..."
-msgstr "実行中..."
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "haserror"
-msgstr "エラー発生中につき実行できません。"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "validationMsg1"
-msgstr "実行モードが選ばれていません。"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "confirmMessage"
-msgstr "本処理の実行にはかなりの時間がかかることが予想されます。インデックスの再作成処理を実行してよいですか?"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "completed"
-msgstr "処理が完了しました。"
-
#~ msgid "Title_Asc"
#~ msgstr "タイトル(昇順)"
@@ -1780,3 +1847,6 @@ msgstr "処理が完了しました。"
#~ msgid "Facet Search List"
#~ msgstr "ファセット検索一覧"
+#~ msgid "Day"
+#~ msgstr "日"
+
diff --git a/modules/weko-admin/weko_admin/translations/messages.pot b/modules/weko-admin/weko_admin/translations/messages.pot
index 1bbbdcf65b..d496f3c7af 100644
--- a/modules/weko-admin/weko_admin/translations/messages.pot
+++ b/modules/weko-admin/weko_admin/translations/messages.pot
@@ -1,623 +1,633 @@
# Translations template for weko-admin.
-# Copyright (C) 2021 National Institute of Informatics
+# Copyright (C) 2025 National Institute of Informatics
# This file is distributed under the same license as the weko-admin project.
-# FIRST AUTHOR , 2021.
+# FIRST AUTHOR , 2025.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: weko-admin 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2021-07-29 21:12+0900\n"
+"POT-Creation-Date: 2025-02-25 09:34+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.9.1\n"
+"Generated-By: Babel 2.5.1\n"
-#: weko_admin/admin.py:105
+#: tests/test_admin.py:1669 tests/test_admin.py:1675 tests/test_admin.py:1677
+#: tests/test_admin.py:1694 tests/test_admin.py:1702 tests/test_admin.py:1710
+#: tests/test_admin.py:1718 weko_admin/admin.py:134
+msgid "completed"
+msgstr ""
+
+#: tests/test_admin.py:1727 weko_admin/admin.py:127
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:43
+msgid "executing..."
+msgstr ""
+
+#: tests/test_admin.py:1737 weko_admin/admin.py:125
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:42
+msgid "haserror"
+msgstr ""
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:152
+msgid "15 mins"
+msgstr ""
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:153
+msgid "30 mins"
+msgstr ""
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:154
+msgid "45 mins"
+msgstr ""
+
+#: tests/test_views.py:97 tests/test_views.py:110 tests/test_views.py:124
+#: weko_admin/views.py:155
+msgid "60 mins"
+msgstr ""
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:156
+msgid "180 mins"
+msgstr ""
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:157
+msgid "360 mins"
+msgstr ""
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:158
+msgid "720 mins"
+msgstr ""
+
+#: tests/test_views.py:98 tests/test_views.py:111 tests/test_views.py:125
+#: weko_admin/views.py:159
+msgid "1440 mins"
+msgstr ""
+
+#: weko_admin/admin.py:220
msgid "deny access"
msgstr ""
-#: weko_admin/admin.py:124
+#: weko_admin/admin.py:239
msgid "Successfully update color."
msgstr ""
-#: weko_admin/admin.py:310
+#: weko_admin/admin.py:438
msgid "Monday"
msgstr ""
-#: weko_admin/admin.py:310
+#: weko_admin/admin.py:438
msgid "Tuesday"
msgstr ""
-#: weko_admin/admin.py:310
+#: weko_admin/admin.py:438
msgid "Wednesday"
msgstr ""
-#: weko_admin/admin.py:311
+#: weko_admin/admin.py:439
msgid "Thursday"
msgstr ""
-#: weko_admin/admin.py:311
+#: weko_admin/admin.py:439
msgid "Friday"
msgstr ""
-#: weko_admin/admin.py:311
+#: weko_admin/admin.py:439
msgid "Saturday"
msgstr ""
-#: weko_admin/admin.py:312
+#: weko_admin/admin.py:440
msgid "Sunday"
msgstr ""
-#: weko_admin/admin.py:342 weko_admin/tasks.py:92
+#: weko_admin/admin.py:469 weko_admin/tasks.py:161
msgid " Log report."
msgstr ""
-#: weko_admin/admin.py:353
+#: weko_admin/admin.py:480
msgid "Successfully sent the reports to the recepients."
msgstr ""
-#: weko_admin/admin.py:363
+#: weko_admin/admin.py:490
msgid "Unexpected error occurred."
msgstr ""
-#: weko_admin/admin.py:397
+#: weko_admin/admin.py:521
msgid "Successfully Changed Schedule."
msgstr ""
-#: weko_admin/admin.py:399
+#: weko_admin/admin.py:523
msgid "Could Not Save Changes."
msgstr ""
-#: weko_admin/admin.py:464 weko_admin/admin.py:572 weko_admin/admin.py:806
+#: weko_admin/admin.py:578 weko_admin/admin.py:604 weko_admin/admin.py:705
+#: weko_admin/admin.py:957
msgid "Successfully Changed Settings."
msgstr ""
-#: weko_admin/admin.py:485 weko_admin/views.py:564
+#: weko_admin/admin.py:608 weko_admin/views.py:665
msgid "Could not save data."
msgstr ""
-#: weko_admin/admin.py:496
-msgid "Could not get restricted data: "
+#: weko_admin/admin.py:619
+#, python-format
+msgid "Could not get restricted data: %s"
msgstr ""
-#: weko_admin/admin.py:497
+#: weko_admin/admin.py:620
msgid "Could not get restricted data."
msgstr ""
-#: weko_admin/admin.py:576 weko_admin/admin.py:809 weko_admin/admin.py:812
+#: weko_admin/admin.py:709 weko_admin/admin.py:960 weko_admin/admin.py:963
msgid "Failurely Changed Settings."
msgstr ""
-#: weko_admin/admin.py:849
+#: weko_admin/admin.py:1000
msgid "Successfully Changed Settings"
msgstr ""
-#: weko_admin/admin.py:853
+#: weko_admin/admin.py:1004
msgid "Failed To Change Settings"
msgstr ""
-#: weko_admin/admin.py:913
+#: weko_admin/admin.py:1066
msgid "Prefix"
msgstr ""
-#: weko_admin/admin.py:919
+#: weko_admin/admin.py:1072
msgid "Suffix"
msgstr ""
-#: weko_admin/admin.py:921
+#: weko_admin/admin.py:1074
msgid "Enable/Disable"
msgstr ""
-#: weko_admin/admin.py:931
+#: weko_admin/admin.py:1084
msgid "Repository"
msgstr ""
-#: weko_admin/admin.py:931
+#: weko_admin/admin.py:1084
msgid "JaLC DOI"
msgstr ""
-#: weko_admin/admin.py:932
+#: weko_admin/admin.py:1085
msgid "JaLC CrossRef DOI"
msgstr ""
-#: weko_admin/admin.py:933
+#: weko_admin/admin.py:1086
msgid "JaLC DataCite DOI"
msgstr ""
-#: weko_admin/admin.py:934
+#: weko_admin/admin.py:1087
msgid "NDL JaLC DOI"
msgstr ""
-#: weko_admin/admin.py:935
+#: weko_admin/admin.py:1088
msgid "Semi-automatic Suffix"
msgstr ""
-#: weko_admin/admin.py:952
+#: weko_admin/admin.py:1105
msgid "Only allow half with 1-bytes character in input"
msgstr ""
-#: weko_admin/admin.py:1017
+#: weko_admin/admin.py:1170
msgid "Specified repository is already registered."
msgstr ""
-#: weko_admin/admin.py:1137
+#: weko_admin/admin.py:1298
msgid "ID"
msgstr ""
-#: weko_admin/admin.py:1138
+#: weko_admin/admin.py:1299
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:50
msgid "Item Name(EN)"
msgstr ""
-#: weko_admin/admin.py:1139
+#: weko_admin/admin.py:1300
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:51
msgid "Item Name(JP)"
msgstr ""
-#: weko_admin/admin.py:1140
+#: weko_admin/admin.py:1301
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:52
msgid "Mapping"
msgstr ""
-#: weko_admin/admin.py:1141
-msgid "Active"
-msgstr ""
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:59
-msgid "UiType"
+#: weko_admin/admin.py:1302
+msgid "UI"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:60
-msgid "DisplayNumber"
-msgstr ""
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:61
-msgid "OpenClose"
-msgstr ""
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:62
-msgid "OpenClose Open"
-msgstr ""
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:63
-msgid "OpenClose Close"
-msgstr ""
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:64
-msgid "DisplayNumber Validation1"
-msgstr ""
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:65
-msgid "DisplayNumber Validation2"
+#: weko_admin/admin.py:1303
+msgid "Active"
msgstr ""
-#: weko_admin/admin.py:1210 weko_admin/admin.py:1237 weko_admin/admin.py:1246
-#: weko_admin/admin.py:1255 weko_admin/admin.py:1264 weko_admin/admin.py:1273
-#: weko_admin/admin.py:1282 weko_admin/admin.py:1291 weko_admin/admin.py:1309
-#: weko_admin/admin.py:1318 weko_admin/admin.py:1327 weko_admin/admin.py:1336
-#: weko_admin/admin.py:1344 weko_admin/admin.py:1352
+#: weko_admin/admin.py:1372 weko_admin/admin.py:1399 weko_admin/admin.py:1408
+#: weko_admin/admin.py:1417 weko_admin/admin.py:1426 weko_admin/admin.py:1435
+#: weko_admin/admin.py:1444 weko_admin/admin.py:1453 weko_admin/admin.py:1471
+#: weko_admin/admin.py:1480 weko_admin/admin.py:1489 weko_admin/admin.py:1498
+#: weko_admin/admin.py:1506 weko_admin/admin.py:1514
msgid "Setting"
msgstr ""
-#: weko_admin/admin.py:1211
+#: weko_admin/admin.py:1373
msgid "Style"
msgstr ""
-#: weko_admin/admin.py:1219 weko_admin/admin.py:1228 weko_admin/admin.py:1300
+#: weko_admin/admin.py:1381 weko_admin/admin.py:1390 weko_admin/admin.py:1462
msgid "Statistics"
msgstr ""
-#: weko_admin/admin.py:1220
+#: weko_admin/admin.py:1382
msgid "Report"
msgstr ""
-#: weko_admin/admin.py:1229
+#: weko_admin/admin.py:1391
msgid "Feedback Mail"
msgstr ""
-#: weko_admin/admin.py:1238
+#: weko_admin/admin.py:1400
msgid "Stats"
msgstr ""
-#: weko_admin/admin.py:1247
+#: weko_admin/admin.py:1409
#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:45
msgid "Log Analysis"
msgstr ""
-#: weko_admin/admin.py:1256
-#: weko_admin/templates/weko_admin/admin/site_info.html:48
+#: weko_admin/admin.py:1418
+#: weko_admin/templates/weko_admin/admin/site_info.html:50
msgid "Language"
msgstr ""
-#: weko_admin/admin.py:1265
+#: weko_admin/admin.py:1427
msgid "WebAPI Account"
msgstr ""
-#: weko_admin/admin.py:1274
+#: weko_admin/admin.py:1436
msgid "Ranking"
msgstr ""
-#: weko_admin/admin.py:1283
+#: weko_admin/admin.py:1445
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:61
msgid "Search"
msgstr ""
-#: weko_admin/admin.py:1292 weko_admin/admin.py:1301 weko_admin/config.py:154
-#: weko_admin/config.py:159
+#: weko_admin/admin.py:1454 weko_admin/admin.py:1463 weko_admin/config.py:168
+#: weko_admin/config.py:173
msgid "Site License"
msgstr ""
-#: weko_admin/admin.py:1310
+#: weko_admin/admin.py:1472
msgid "File Preview"
msgstr ""
-#: weko_admin/admin.py:1319
+#: weko_admin/admin.py:1481
msgid "Item Export"
msgstr ""
-#: weko_admin/admin.py:1328
+#: weko_admin/admin.py:1490
msgid "Site Info"
msgstr ""
-#: weko_admin/admin.py:1337
+#: weko_admin/admin.py:1499
msgid "Restricted Access"
msgstr ""
-#: weko_admin/admin.py:1345
+#: weko_admin/admin.py:1507
msgid "Identifier"
msgstr ""
-#: weko_admin/admin.py:1353
+#: weko_admin/admin.py:1515
msgid "Faceted Search"
msgstr ""
-#: weko_admin/api.py:82
+#: weko_admin/admin.py:1522
+msgid "Maintenance"
+msgstr ""
+
+#: weko_admin/admin.py:1523
+msgid "ElasticSearch Index"
+msgstr ""
+
+#: weko_admin/api.py:127
msgid "statistics report"
msgstr ""
-#: weko_admin/config.py:129
+#: weko_admin/config.py:143
msgid "No. Of File Downloads"
msgstr ""
-#: weko_admin/config.py:130
+#: weko_admin/config.py:144
msgid "No. Of File Previews"
msgstr ""
-#: weko_admin/config.py:131
+#: weko_admin/config.py:145
msgid "No. Of Paid File Downloads"
msgstr ""
-#: weko_admin/config.py:132
+#: weko_admin/config.py:146
msgid "No. Of Paid File Previews"
msgstr ""
-#: weko_admin/config.py:133
+#: weko_admin/config.py:147
msgid "Detail Views Per Index"
msgstr ""
-#: weko_admin/config.py:134
+#: weko_admin/config.py:148
msgid "Detail Views Count"
msgstr ""
-#: weko_admin/config.py:135
+#: weko_admin/config.py:149
msgid "Usage Count By User"
msgstr ""
-#: weko_admin/config.py:136
+#: weko_admin/config.py:150
msgid "Search Keyword Ranking"
msgstr ""
-#: weko_admin/config.py:137
+#: weko_admin/config.py:151
msgid "Number Of Access By Host"
msgstr ""
-#: weko_admin/config.py:138
+#: weko_admin/config.py:152
msgid "User Affiliation Information"
msgstr ""
-#: weko_admin/config.py:139
+#: weko_admin/config.py:153
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:21
msgid "Access Count By Site License"
msgstr ""
-#: weko_admin/config.py:144
+#: weko_admin/config.py:158
msgid "Open-Access No. Of File Downloads"
msgstr ""
-#: weko_admin/config.py:145
+#: weko_admin/config.py:159
msgid "Open-Access No. Of File Previews"
msgstr ""
-#: weko_admin/config.py:146
+#: weko_admin/config.py:160
msgid "Access Number Breakdown By Site License"
msgstr ""
-#: weko_admin/config.py:152 weko_admin/config.py:157
+#: weko_admin/config.py:166 weko_admin/config.py:171
msgid "File Name"
msgstr ""
-#: weko_admin/config.py:152 weko_admin/config.py:157 weko_admin/config.py:163
+#: weko_admin/config.py:166 weko_admin/config.py:171 weko_admin/config.py:177
msgid "Registered Index Name"
msgstr ""
-#: weko_admin/config.py:153
+#: weko_admin/config.py:167
msgid "No. Of Times Downloaded"
msgstr ""
-#: weko_admin/config.py:153 weko_admin/config.py:158
+#: weko_admin/config.py:167 weko_admin/config.py:172
msgid "Non-Logged In User"
msgstr ""
-#: weko_admin/config.py:154 weko_admin/config.py:159
+#: weko_admin/config.py:168 weko_admin/config.py:173
msgid "Logged In User"
msgstr ""
-#: weko_admin/config.py:154 weko_admin/config.py:159
+#: weko_admin/config.py:168 weko_admin/config.py:173
msgid "Admin"
msgstr ""
-#: weko_admin/config.py:155 weko_admin/config.py:160
+#: weko_admin/config.py:169 weko_admin/config.py:174
msgid "Registrar"
msgstr ""
-#: weko_admin/config.py:158
+#: weko_admin/config.py:172
msgid "No. Of Times Viewed"
msgstr ""
-#: weko_admin/config.py:161
+#: weko_admin/config.py:175
msgid "Index"
msgstr ""
-#: weko_admin/config.py:161
+#: weko_admin/config.py:175
msgid "No. Of Views"
msgstr ""
-#: weko_admin/config.py:163
+#: weko_admin/config.py:177
msgid "Title"
msgstr ""
-#: weko_admin/config.py:163
+#: weko_admin/config.py:177
msgid "View Count"
msgstr ""
-#: weko_admin/config.py:164
+#: weko_admin/config.py:178
msgid "Non-logged-in User"
msgstr ""
-#: weko_admin/config.py:165
+#: weko_admin/config.py:179
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:49
msgid "Mail address"
msgstr ""
-#: weko_admin/config.py:166
+#: weko_admin/config.py:180
msgid "Username"
msgstr ""
-#: weko_admin/config.py:167
+#: weko_admin/config.py:181
msgid "File download count"
msgstr ""
-#: weko_admin/config.py:168
+#: weko_admin/config.py:182
msgid "File playing count"
msgstr ""
-#: weko_admin/config.py:169
+#: weko_admin/config.py:183
#: weko_admin/templates/weko_admin/admin/report.html:116
msgid "Search Keyword"
msgstr ""
-#: weko_admin/config.py:169 weko_admin/config.py:174
+#: weko_admin/config.py:183 weko_admin/config.py:188
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:25
msgid "Number Of Searches"
msgstr ""
-#: weko_admin/config.py:170
+#: weko_admin/config.py:184
msgid "Host"
msgstr ""
-#: weko_admin/config.py:170
+#: weko_admin/config.py:184
msgid "IP Address"
msgstr ""
-#: weko_admin/config.py:171 weko_admin/config.py:173
+#: weko_admin/config.py:185 weko_admin/config.py:187
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:24
msgid "WEKO Top Page Access Count"
msgstr ""
-#: weko_admin/config.py:172
+#: weko_admin/config.py:186
msgid "Role"
msgstr ""
-#: weko_admin/config.py:172
+#: weko_admin/config.py:186
msgid "Number Of Users"
msgstr ""
-#: weko_admin/config.py:174
+#: weko_admin/config.py:188
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:26
msgid "Number Of Views"
msgstr ""
-#: weko_admin/config.py:175
+#: weko_admin/config.py:189
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:27
msgid "Number Of File download"
msgstr ""
-#: weko_admin/config.py:176
+#: weko_admin/config.py:190
#: weko_admin/templates/weko_admin/email_templates/site_license_report.html:28
msgid "Number Of File Regeneration"
msgstr ""
-#: weko_admin/config.py:181
+#: weko_admin/config.py:195
msgid "FileDownload_"
msgstr ""
-#: weko_admin/config.py:182
+#: weko_admin/config.py:196
msgid "FilePreview_"
msgstr ""
-#: weko_admin/config.py:183
+#: weko_admin/config.py:197
msgid "PayFileDownload_"
msgstr ""
-#: weko_admin/config.py:184
+#: weko_admin/config.py:198
msgid "PayFilePreview_"
msgstr ""
-#: weko_admin/config.py:185
+#: weko_admin/config.py:199
msgid "IndexAccess_"
msgstr ""
-#: weko_admin/config.py:186
+#: weko_admin/config.py:200
msgid "DetailView_"
msgstr ""
-#: weko_admin/config.py:187
+#: weko_admin/config.py:201
msgid "FileUsingPerUser_"
msgstr ""
-#: weko_admin/config.py:188
+#: weko_admin/config.py:202
msgid "SearchCount_"
msgstr ""
-#: weko_admin/config.py:189
+#: weko_admin/config.py:203
msgid "UserAffiliate_"
msgstr ""
-#: weko_admin/config.py:190
+#: weko_admin/config.py:204
msgid "SiteAccess_"
msgstr ""
-#: weko_admin/config.py:191
+#: weko_admin/config.py:205
msgid "TopPageAccess_"
msgstr ""
-#: weko_admin/ext.py:74
+#: weko_admin/ext.py:75
msgid "A translation string"
msgstr ""
-#: weko_admin/utils.py:235
+#: weko_admin/utils.py:234
msgid "Input type is invalid. Please check again."
msgstr ""
-#: weko_admin/utils.py:238 weko_admin/views.py:284 weko_admin/views.py:289
+#: weko_admin/utils.py:237 weko_admin/views.py:326 weko_admin/views.py:331
msgid "Account information is invalid. Please check again."
msgstr ""
-#: weko_admin/utils.py:331
+#: weko_admin/utils.py:328
msgid "Registered Users"
msgstr ""
-#: weko_admin/utils.py:373
+#: weko_admin/utils.py:372
msgid "Aggregation Month"
msgstr ""
-#: weko_admin/utils.py:388
+#: weko_admin/utils.py:389
msgid "Total Detail Views"
msgstr ""
-#: weko_admin/utils.py:396
+#: weko_admin/utils.py:398
msgid "Site license member"
msgstr ""
-#: weko_admin/utils.py:400
+#: weko_admin/utils.py:402
msgid "Other than site license"
msgstr ""
-#: weko_admin/utils.py:411
+#: weko_admin/utils.py:413
msgid "Institution Name"
msgstr ""
-#: weko_admin/utils.py:1198
+#: weko_admin/utils.py:1219
msgid "Cannot update Feedback email settings."
msgstr ""
-#: weko_admin/utils.py:1225
+#: weko_admin/utils.py:1246
msgid "Author is duplicated."
msgstr ""
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:48
-#: weko_admin/utils.py:1232
+#: weko_admin/utils.py:1253
msgid "Duplicate Email Addresses."
msgstr ""
-#: weko_admin/views.py:102
+#: weko_admin/views.py:116
#, python-format
msgid "%(icon)s Session"
msgstr ""
-#: weko_admin/views.py:108
+#: weko_admin/views.py:122
msgid "Session"
msgstr ""
-#: weko_admin/views.py:132
+#: weko_admin/views.py:147
msgid "Session lifetime was updated."
msgstr ""
-#: weko_admin/views.py:137
-msgid "15 mins"
-msgstr ""
-
-#: weko_admin/views.py:138
-msgid "30 mins"
-msgstr ""
-
-#: weko_admin/views.py:139
-msgid "45 mins"
-msgstr ""
-
-#: weko_admin/views.py:140
-msgid "60 mins"
-msgstr ""
-
-#: weko_admin/views.py:141
-msgid "180 mins"
-msgstr ""
-
-#: weko_admin/views.py:142
-msgid "360 mins"
-msgstr ""
-
-#: weko_admin/views.py:143
-msgid "720 mins"
-msgstr ""
-
-#: weko_admin/views.py:144
-msgid "1440 mins"
-msgstr ""
-
-#: weko_admin/views.py:277
+#: weko_admin/views.py:319
msgid "Header Error"
msgstr ""
-#: weko_admin/views.py:559
+#: weko_admin/views.py:660
msgid "Restricted Access was successfully updated."
msgstr ""
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:54
-#: weko_admin/views.py:618 weko_admin/views.py:651
+#: weko_admin/views.py:725 weko_admin/views.py:760
msgid "Success"
msgstr ""
-#: weko_admin/views.py:627
+#: weko_admin/views.py:734
msgid "Failed to update due to server error."
msgstr ""
-#: weko_admin/views.py:632
+#: weko_admin/views.py:739
msgid "Failed to create due to server error."
msgstr ""
-#: weko_admin/views.py:635
+#: weko_admin/views.py:742
msgid ""
"The item name/mapping is already exists. Please input other faceted "
"item/mapping."
msgstr ""
-#: weko_admin/views.py:658 weko_admin/views.py:661
+#: weko_admin/views.py:767 weko_admin/views.py:770
msgid "Failed to delete due to server error."
msgstr ""
@@ -625,21 +635,21 @@ msgstr ""
msgid "Welcome to"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/block_style.html:87
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:67
+#: weko_admin/templates/weko_admin/admin/block_style.html:89
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:74
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:44
#: weko_admin/templates/weko_admin/admin/file_preview_settings.html:62
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:94
#: weko_admin/templates/weko_admin/admin/lang_settings.html:86
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:169
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:191
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:145
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:170
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:192
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:147
#: weko_admin/templates/weko_admin/admin/report.html:224
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:52
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:422
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:459
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:562
-#: weko_admin/templates/weko_admin/admin/site_info.html:49
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:60
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:442
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:479
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:582
+#: weko_admin/templates/weko_admin/admin/site_info.html:51
#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:174
#: weko_admin/templates/weko_admin/admin/site_license_settings.html:204
#: weko_admin/templates/weko_admin/admin/stats_settings.html:71
@@ -648,11 +658,11 @@ msgstr ""
msgid "Save"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/block_style.html:91
+#: weko_admin/templates/weko_admin/admin/block_style.html:93
msgid "Color Setting"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/block_style.html:97
+#: weko_admin/templates/weko_admin/admin/block_style.html:99
msgid "Background1"
msgstr ""
@@ -681,58 +691,95 @@ msgid "_Display"
msgstr ""
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:59
-msgid "_Hide"
+msgid "UiType"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:60
+msgid "DisplayNumber"
msgstr ""
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:61
-msgid "List"
+msgid "OpenClose"
msgstr ""
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:62
-msgid "Create"
+msgid "OpenClose Open"
msgstr ""
#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:63
+msgid "OpenClose Close"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:64
+msgid "DisplayNumber Validation1"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:65
+msgid "DisplayNumber Validation2"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:66
+msgid "_Hide"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:68
+msgid "List"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:69
+msgid "Create"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:70
#: weko_admin/templates/weko_admin/admin/search_management_settings.html:230
msgid "Edit"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:64
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:71
#: weko_admin/templates/weko_admin/partials/email_schedule.html:23
msgid "Details"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:66
-#: weko_admin/templates/weko_admin/settings/lifetime.html:55
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:73
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:48
+#: weko_admin/templates/weko_admin/settings/lifetime.html:56
msgid "Cancel"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:68
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:75
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:45
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:149
-#: weko_admin/templates/weko_admin/admin/site_info.html:57
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:151
+#: weko_admin/templates/weko_admin/admin/site_info.html:59
#: weko_admin/templates/weko_admin/admin/site_license_settings.html:70
msgid "Delete"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:69
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:64
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:541
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:76
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:73
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:561
msgid "Add"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:70
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:78
msgid "Please input all required item."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:77
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:183
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:79
+msgid "Please select one aggregation mapping."
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:80
+msgid "Already exists."
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:87
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:184
#: weko_admin/templates/weko_admin/admin/report.html:247
#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:197
msgid "Confirmation"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:78
+#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:88
msgid "Are you sure you want to delete it?"
msgstr ""
@@ -803,9 +850,9 @@ msgid "Resend"
msgstr ""
#: weko_admin/templates/weko_admin/admin/feedback_mail.html:59
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:195
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:196
#: weko_admin/templates/weko_admin/admin/report.html:273
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:75
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:84
msgid "Close"
msgstr ""
@@ -843,7 +890,7 @@ msgstr ""
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:59
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:78
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:47
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:48
#: weko_admin/templates/weko_admin/admin/stats_settings.html:59
#: weko_admin/templates/weko_admin/partials/email_schedule.html:75
msgid "On"
@@ -851,7 +898,7 @@ msgstr ""
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:65
#: weko_admin/templates/weko_admin/admin/item_export_settings.html:84
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:52
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:53
#: weko_admin/templates/weko_admin/admin/stats_settings.html:64
#: weko_admin/templates/weko_admin/partials/email_schedule.html:80
msgid "Off"
@@ -869,70 +916,102 @@ msgstr ""
msgid "Registered language"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:56
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:57
msgid "Addresses to Filter"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:64
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:65
msgid "Enter the IP Addresses to Filter"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:128
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:129
msgid "Shared Crawler Lists"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:186
+#: weko_admin/templates/weko_admin/admin/log_analysis_settings.html:187
msgid "Are you sure you want to block the given addresses?"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:41
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:42
msgid "Show/Hide Ranking"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:58
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:59
msgid "Period To Judge As New Item"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:64
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:65
msgid "Day (Range : 1~30)"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:68
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:69
msgid "Statistical Period"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:73
-msgid "Day"
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:74
+msgid "Day (Range : 1~3650)"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:77
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:78
msgid "Display Rank"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:85
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:83
+msgid "(Range : 1~100)"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:87
msgid "Rankings"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:91
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:93
msgid "Most Viewed Items"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:102
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:104
msgid "Most Downloaded Items"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:113
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:115
msgid "User Who Created The Most Items"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:124
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:126
msgid "Most Searched Keywords"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/ranking_settings.html:135
+#: weko_admin/templates/weko_admin/admin/ranking_settings.html:137
msgid "New Items"
msgstr ""
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:38
+msgid "reindex item_index"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:39
+msgid "reindex item"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:40
+msgid "execute"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:41
+msgid "waiting..."
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:47
+msgid "Execute"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:49
+msgid "validationMsg1"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/reindex_elasticsearch.html:50
+msgid "confirmMessage"
+msgstr ""
+
#: weko_admin/templates/weko_admin/admin/report.html:54
msgid "Number of items registered"
msgstr ""
@@ -1052,7 +1131,7 @@ msgid "Are you sure you want to save changes?"
msgstr ""
#: weko_admin/templates/weko_admin/admin/report.html:255
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:76
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:85
msgid "Send Mail"
msgstr ""
@@ -1072,95 +1151,113 @@ msgstr ""
msgid "Expiration Date"
msgstr ""
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:47
+msgid "Max Download Limit"
+msgstr ""
+
#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:48
+msgid "Max Expiration Date"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:49
+msgid "Expiration Date Initial Value"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:50
+msgid "Download Limit Initial Value"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:52
msgid "Content File Download"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:51
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:59
msgid "Unlimited"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:53
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:61
msgid "Usage Report Workflow Access"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:55
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:57
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:63
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:65
#, python-format
-msgid "Must set a positive integer for %(name)s."
+msgid "Must set a positive integer and less than %(name1)s for %(name2)s."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:58
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:59
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:66
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:67
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:68
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:69
#, python-format
msgid "Please set %(name)s."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:61
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:444
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:451
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:70
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:464
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:471
msgid "English"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:62
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:445
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:452
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:71
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:465
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:472
msgid "Japanese"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:63
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:72
msgid "Terms and Conditions"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:65
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:74
msgid "Please input the Terms and Conditions in English."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:68
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:77
msgid "Activity"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:69
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:78
msgid "Item"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:70
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:79
msgid "WorkFlow"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:71
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:80
msgid "Status"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:72
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:81
msgid "User"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:73
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:82
msgid "Usage Report Reminder Email"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:74
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:83
msgid "Confirm Usage Mail"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:77
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:86
msgid "Email is sent successfully."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:78
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:87
msgid "Failed to send mail."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:79
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:88
msgid "action_doing"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:80
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:89
msgid "Secret URL Download"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:81
+#: weko_admin/templates/weko_admin/admin/restricted_access_settings.html:90
msgid "SecretURL Enabled"
msgstr ""
@@ -1293,6 +1390,7 @@ msgstr ""
#: weko_admin/templates/weko_admin/admin/search_management_settings.html:295
#: weko_admin/templates/weko_admin/admin/search_management_settings.html:336
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:356
msgid "Display"
msgstr ""
@@ -1308,32 +1406,36 @@ msgstr ""
msgid "Facet"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:356
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:349
+msgid "Community"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:376
msgid "Main Screen Initial Display Setting"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:366
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:386
msgid "Default Contents to Display"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:380
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:400
msgid "Default Index to Display"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:397
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:417
msgid "Initial Display Index"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:400
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:420
msgid "An index which is not open in public cannot be selected"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:484
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:504
msgid "Item Type List"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:524
-#: weko_admin/templates/weko_admin/admin/search_management_settings.html:531
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:544
+#: weko_admin/templates/weko_admin/admin/search_management_settings.html:551
msgid "Enter Input Value"
msgstr ""
@@ -1362,79 +1464,89 @@ msgid "Selected icon"
msgstr ""
#: weko_admin/templates/weko_admin/admin/site_info.html:45
-msgid "Select icon file"
+msgid "Select File"
msgstr ""
#: weko_admin/templates/weko_admin/admin/site_info.html:46
-msgid "Add site name"
+msgid "Select icon file"
msgstr ""
#: weko_admin/templates/weko_admin/admin/site_info.html:47
+msgid "Selected file name"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/site_info.html:48
+msgid "Add site name"
+msgstr ""
+
+#: weko_admin/templates/weko_admin/admin/site_info.html:49
msgid "Site name is not set"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:50
+#: weko_admin/templates/weko_admin/admin/site_info.html:52
msgid "Must set at least 1 site name."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:51
+#: weko_admin/templates/weko_admin/admin/site_info.html:53
msgid "Please input site information for empty field."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:52
+#: weko_admin/templates/weko_admin/admin/site_info.html:54
msgid "The same language is set for many site names."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:53
+#: weko_admin/templates/weko_admin/admin/site_info.html:55
msgid "Site name is required."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:54
+#: weko_admin/templates/weko_admin/admin/site_info.html:56
msgid "Error when get languages."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:55
+#: weko_admin/templates/weko_admin/admin/site_info.html:57
msgid "Error when get site infomation."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:56
+#: weko_admin/templates/weko_admin/admin/site_info.html:58
msgid "Language is deleted from Registered Language of system."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:58
+#: weko_admin/templates/weko_admin/admin/site_info.html:60
msgid "Site info is saved successfully."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:59
+#: weko_admin/templates/weko_admin/admin/site_info.html:61
msgid "Log in Instructions"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:60
+#: weko_admin/templates/weko_admin/admin/site_info.html:62
msgid "Add Instructions"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:61
+#: weko_admin/templates/weko_admin/admin/site_info.html:63
msgid "The same language is set for many instructions."
msgstr ""
-#: weko_admin/templates/weko_admin/admin/site_info.html:62
+#: weko_admin/templates/weko_admin/admin/site_info.html:64
msgid "Maximum length of instruction is 1000 characters. "
msgstr ""
-#: weko_admin/template/weko_admin/admin/site_info.html:64
+#: weko_admin/templates/weko_admin/admin/site_info.html:66
msgid "Tracking ID"
msgstr ""
-#: weko_admin/template/weko_admin/admin/site_info.html:65
+#: weko_admin/templates/weko_admin/admin/site_info.html:67
msgid "AddThis ID"
msgstr ""
-#: weko_admin/template/weko_admin/admin/site_info.html:66
+#: weko_admin/templates/weko_admin/admin/site_info.html:68
msgid "OGP Image"
msgstr ""
-#: weko_admin/template/weko_admin/admin/search_management_setting.html
-msgid "Index Tree/Facet Display Setting"
+#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:37
+msgid ""
+"Please classify a check into the organization send a use of site license "
+"statistics email."
msgstr ""
#: weko_admin/templates/weko_admin/admin/site_license_send_mail_settings.html:42
@@ -1555,71 +1667,16 @@ msgstr ""
msgid "Life Time"
msgstr ""
-#: weko_admin/templates/weko_admin/settings/lifetime.html:42
-#: weko_admin/templates/weko_admin/settings/lifetime.html:49
+#: weko_admin/templates/weko_admin/settings/lifetime.html:43
+#: weko_admin/templates/weko_admin/settings/lifetime.html:50
msgid "Set lifetime for"
msgstr ""
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html
-msgid "Please select one aggregation mapping."
-msgstr "Please select one aggregation mapping."
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html
-msgid "Already exists."
-msgstr "Already exists."
-
-#: weko_admin/templates/weko_admin/admin/facet_search_setting.html:
-msgid "Failed to create due to server error."
-msgstr "Failed to create due to server error."
-
-#: weko_admin/templates/weko_admin/settings/lifetime.html:42
+#: weko_admin/templates/weko_admin/settings/lifetime.html:43
msgid "Current"
msgstr ""
-#: weko_admin/templates/weko_admin/settings/lifetime.html:58
+#: weko_admin/templates/weko_admin/settings/lifetime.html:59
msgid "Update"
msgstr ""
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "reindex item_index"
-msgstr "アイテムインデックスの再作成"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "reindex item"
-msgstr "アイテムの再インデックス"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "execute"
-msgstr "実行"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "Maintenance"
-msgstr "メンテナンス"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "ElasticSearch Index"
-msgstr "インデックス再作成"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "waiting..."
-msgstr "実行可能"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "executing..."
-msgstr "実行中..."
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "haserror"
-msgstr "エラー発生中につき実行できません"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "validationMsg1"
-msgstr "実行モードが選ばれていません。"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "confirmMessage"
-msgstr "本処理の実行にはかなりの時間がかかることが予想されます。インデックスの再作成処理を実行してよいですか?"
-
-#: weko_admin/admin/reindex_elasticsearch.html
-msgid "completed"
-msgstr "処理が完了しました。"
\ No newline at end of file
diff --git a/modules/weko-records-ui/tests/conftest.py b/modules/weko-records-ui/tests/conftest.py
index d90d5fd8f1..08dbbf7041 100644
--- a/modules/weko-records-ui/tests/conftest.py
+++ b/modules/weko-records-ui/tests/conftest.py
@@ -25,11 +25,12 @@
from os.path import dirname, exists, join
import mimetypes
import os
+import re
import shutil
import tempfile
import time
import uuid
-from datetime import datetime
+from datetime import datetime, timezone
from collections import OrderedDict
from unittest.mock import patch
from datetime import timedelta
@@ -108,7 +109,8 @@
from weko_records.models import ItemType, ItemTypeMapping, ItemTypeName, SiteLicenseInfo, FeedbackMailList,SiteLicenseIpAddress
from weko_records.utils import get_options_and_order_list
from weko_records_ui.config import WEKO_ADMIN_PDFCOVERPAGE_TEMPLATE,RECORDS_UI_ENDPOINTS,WEKO_RECORDS_UI_SECRET_KEY,WEKO_RECORDS_UI_ONETIME_DOWNLOAD_PATTERN
-from weko_records_ui.models import PDFCoverPageSettings,FileOnetimeDownload, FilePermission #RocrateMapping
+from weko_records_ui.models import FileSecretDownload, PDFCoverPageSettings,FileOnetimeDownload, FilePermission #RocrateMapping
+from weko_records_ui.utils import create_download_url
from weko_schema_ui.config import (
WEKO_SCHEMA_DDI_SCHEMA_NAME,
WEKO_SCHEMA_JPCOAR_V1_SCHEMA_NAME,
@@ -4330,15 +4332,16 @@ def site_license_ipaddr(app, db,site_license_info):
return record1
@pytest.fixture()
-def db_fileonetimedownload(app, db):
- record = FileOnetimeDownload(
+def db_fileonetimedownload(app, users):
+ record = FileOnetimeDownload.create(
+ approver_id=1,
+ record_id='1',
file_name="helloworld.pdf",
+ expiration_date=datetime.now(timezone.utc) + timedelta(days=30),
+ download_limit=10,
user_mail="wekosoftware@nii.ac.jp",
- record_id='1',
- download_count=10,
- expiration_date=0)
- with db.session.begin_nested():
- db.session.add(record)
+ is_guest=False,
+ extra_info={})
return record
@@ -4483,3 +4486,59 @@ def db_rocrate_mapping(db):
with db.session.begin_nested():
db.session.add(rocrate_mapping)
db.session.commit()
+
+
+@pytest.fixture
+def secret_url(users, params=None):
+ """Fixture that creates secret URL object and provides the token of it.
+
+ Args:
+ params (dict, optional): Custom parameters for the secret object.
+ """
+ params = params or {}
+ ex_date = datetime.now(timezone.utc) + timedelta(days=30)
+ secret_obj = FileSecretDownload.create(
+ creator_id =params.get('creator_id' , 1 ),
+ record_id =params.get('record_id' , '1' ),
+ file_name =params.get('file_name' , 'test.txt'),
+ label_name =params.get('label_name' , 'test_url'),
+ expiration_date =params.get('expiration_date', ex_date ),
+ download_limit =params.get('download_limit' , 10 )
+ )
+ secret_url = create_download_url(secret_obj)
+ match = re.search(r'[?&]token=([^&]+)', secret_url)
+ secret_token = match.group(1)
+ return {
+ 'secret_obj' : secret_obj,
+ 'secret_token': secret_token,
+ 'secret_url' : secret_url
+ }
+
+
+@pytest.fixture
+def onetime_url(users, params=None):
+ """Fixture that creates onetime URL object and provides the token of it.
+
+ Args:
+ params (dict, optional): Custom parameters for the onetime object.
+ """
+ params = params or {}
+ ex_date = datetime.now(timezone.utc) + timedelta(days=30)
+ onetime_obj = FileOnetimeDownload.create(
+ approver_id = params.get('approver_id' , 1 ),
+ record_id = params.get('record_id' , '1' ),
+ file_name = params.get('file_name' , 'test.txt' ),
+ expiration_date = params.get('expiration_date', ex_date ),
+ download_limit = params.get('download_limit' , 10 ),
+ user_mail = params.get('user_mail' , 'test@example.org'),
+ is_guest = params.get('is_guest' , False ),
+ extra_info = params.get('extra_info' , {'activity_id': 1})
+ )
+ onetime_url = create_download_url(onetime_obj)
+ match = re.search(r'[?&]token=([^&]+)', onetime_url)
+ onetime_token = match.group(1)
+ return {
+ 'onetime_obj' : onetime_obj,
+ 'onetime_token': onetime_token,
+ 'onetime_url' : onetime_url
+ }
diff --git a/modules/weko-records-ui/tests/test_fd.py b/modules/weko-records-ui/tests/test_fd.py
index ba45e32d74..f8cdc99b18 100644
--- a/modules/weko-records-ui/tests/test_fd.py
+++ b/modules/weko-records-ui/tests/test_fd.py
@@ -5,7 +5,7 @@
from requests import Response
from weko_deposit.api import WekoFileObject
#from weko_records_ui.errors import AvailableFilesNotFoundRESTError
-from weko_records_ui.fd import _is_terms_of_use_only, file_download_secret, prepare_response,file_download_onetime,_download_file,add_signals_info,weko_view_method,file_ui,file_preview_ui,file_download_ui # ,file_list_ui
+from weko_records_ui.fd import _is_terms_of_use_only, error_response, file_download_secret, prepare_response,file_download_onetime,_download_file,add_signals_info,weko_view_method,file_ui,file_preview_ui,file_download_ui # ,file_list_ui
from weko_records_ui.config import WEKO_RECORDS_UI_DETAIL_TEMPLATE
from unittest.mock import MagicMock
from invenio_theme.config import THEME_ERROR_TEMPLATE
@@ -19,9 +19,10 @@
from invenio_accounts.testutils import login_user_via_session
from mock import patch
from invenio_records_files.utils import record_file_factory
+from weko_schema_ui.models import PublishStatus
from werkzeug.exceptions import NotFound ,Forbidden
-from weko_records_ui.models import FileSecretDownload
+from weko_records_ui.models import AccessStatus, FileSecretDownload
from sqlalchemy.exc import SQLAlchemyError
# def weko_view_method(pid, record, template=None, **kwargs):
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_fd.py::test_weko_view_method -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
@@ -260,46 +261,84 @@ def all_func():
add_signals_info(record,obj)
-# def file_download_onetime(pid, record, _record_file_factory=None, **kwargs):
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_fd.py::test_error_response -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.fd.render_template')
+def test_error_response(mock_render):
+ mock_render.return_value = 'Error Test'
+ error_template = 'weko_theme/error.html'
+ render, status_code = error_response('Error Test', 500)
+ assert render == 'Error Test'
+ assert status_code == 500
+ mock_render.assert_called_once_with(error_template, error='Error Test')
+
+
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_fd.py::test_file_download_onetime -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_file_download_onetime(app, records, itemtypes, users, db_fileonetimedownload):
- indexer, results = records
- recid = results[0]["recid"]
- record = results[0]["record"]
- app.config["THEME_ERROR_TEMPLATE"]=THEME_ERROR_TEMPLATE
- with app.test_request_context('?token=MSB1c2VyQGV4YW1wbGUub3JnIDIwMjItMDktMjcgNDBDRkNGODFGM0FFRUI0Ng=='):
- with patch("flask_login.utils._get_user", return_value=users[1]["obj"]):
- with patch("flask.templating._render", return_value=""):
- with patch("weko_records_ui.fd.get_onetime_download", return_value=db_fileonetimedownload):
- with patch("weko_records_ui.fd.parse_one_time_download_token", return_value=(True, [1])):
- assert file_download_onetime(recid,record,record_file_factory)==""
-
- with patch("weko_records_ui.fd.parse_one_time_download_token", return_value=(False, ("","","",""))):
-
- with patch("weko_records_ui.fd.validate_onetime_download_token", return_value=(False, [1])):
- assert file_download_onetime(recid,record,record_file_factory)==""
-
- _rv = (True, "")
- with patch("weko_records_ui.fd.validate_onetime_download_token", return_value=_rv):
- assert file_download_onetime(recid,record,record_file_factory)==""
-
- with patch("weko_records_ui.fd.record_file_factory", return_value=False):
- assert file_download_onetime(recid,record,None)==""
-
- file_object = MagicMock()
- file_object.obj = {"foo" : "hoge"}
- file_object.get = lambda x : 'open_restricted'
- with patch("weko_records_ui.fd.record_file_factory", return_value=file_object):
- with patch('weko_records_ui.fd.check_and_send_usage_report',return_value ="error"):
- assert file_download_onetime(recid,record,None)==""
- with patch('weko_records_ui.fd.check_and_send_usage_report',side_effect = BaseException ):
- assert file_download_onetime(recid,record,None)==""
- with patch('weko_records_ui.fd.check_and_send_usage_report',side_effect =SQLAlchemyError):
- assert file_download_onetime(recid,record,None)==""
- with patch('weko_records_ui.fd.check_and_send_usage_report',return_value =""):
- with patch('weko_records_ui.fd.update_onetime_download',return_value =True):
- with patch('weko_records_ui.fd._download_file',return_value ="downloaded"):
- assert file_download_onetime(recid,record,None)=="downloaded"
+@patch('weko_records_ui.fd.request.args.get')
+@patch('weko_records_ui.fd.validate_url_download')
+@patch('weko_records_ui.fd.error_response')
+@patch('weko_records_ui.fd.check_and_send_usage_report')
+@patch('weko_records_ui.fd.save_download_log')
+@patch('weko_records_ui.fd._download_file')
+def test_file_download_onetime(dl_file, save_log, chk_and_send, err_res,
+ val_url, token, onetime_url):
+ # Setup arguments of sut
+ pid = None
+ record = {}
+ filename = 'test.txt'
+ _record_file_factory = MagicMock()
+ _record_file_factory.return_value = file_obj = MagicMock()
+ file_obj.obj = {'filename': filename}
+ file_obj.get.return_value = 'open_restricted'
+
+ # Setup default return values of mock objects
+ token.return_value = onetime_url['onetime_token']
+ val_url.return_value = (True, '')
+ chk_and_send.return_value = None
+ dl_file.return_value = 'SUCCESS'
+ err_res.return_value = 'ERROR'
+
+ # Happy path
+ assert file_download_onetime(
+ pid, record, filename, _record_file_factory) == 'SUCCESS'
+ save_log.assert_called_once_with(
+ record, filename, token.return_value, is_secret_url=False)
+
+ # Invalid token
+ with patch('weko_records_ui.fd.validate_url_download',
+ return_value=(False, 'Invalid token')):
+ assert file_download_onetime(
+ pid, record, filename, _record_file_factory) == 'ERROR'
+
+ # File object is not found
+ with patch('weko_records_ui.fd.record_file_factory',
+ return_value=None):
+ assert file_download_onetime(
+ pid, record, filename) == 'ERROR'
+
+ # check_and_send_usage_report() returns an error
+ with patch('weko_records_ui.fd.check_and_send_usage_report',
+ return_value='ERROR'):
+ assert file_download_onetime(
+ pid, record, filename, _record_file_factory) == 'ERROR'
+
+ # check_and_send_usage_report() raises an exception
+ with patch('weko_records_ui.fd.check_and_send_usage_report',
+ side_effect=BaseException):
+ assert file_download_onetime(
+ pid, record, filename, _record_file_factory) == 'ERROR'
+
+ # update_extra_info() raises an SQLAlchemyError
+ with patch('weko_records_ui.models.FileOnetimeDownload.update_extra_info',
+ side_effect=SQLAlchemyError):
+ assert file_download_onetime(
+ pid, record, filename, _record_file_factory) == 'ERROR'
+
+ # save_download_log() raises an exception
+ with patch('weko_records_ui.fd.save_download_log',
+ side_effect=Exception):
+ assert file_download_onetime(
+ pid, record, filename, _record_file_factory) == 'ERROR'
+
# def _is_terms_of_use_only(file_obj:dict , req :dict) -> bool:
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_fd.py::test__is_terms_of_use_only -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
@@ -358,53 +397,69 @@ def test__is_terms_of_use_only(app, records_restricted, users, db_file_permissio
with patch("flask_login.utils._get_user", return_value=users[0]["obj"]):
assert not _is_terms_of_use_only(provide_not,{'terms_of_use_only': True})
-# def file_download_secret(pid, record, _record_file_factory=None, **kwargs):
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_fd.py::test_file_download_secret -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_file_download_secret(app,db, itemtypes, users, records):
- indexer, results = records
- recid = results[1]["recid"]
- record = results[1]["record"]
-
- # token:str = re.sub("^.+?token=" ,"" , urls[0])
- with app.test_request_context("?token=MSA1IDIwMjMtMDMtMDggMDA6NTI6MTkuNjI0NTUyIDZGQTdEMzIxQTk0OTU1MEQ="):
- p = FileSecretDownload.create(file_name="helloworld.docx", record_id=recid.pid_value, user_mail=users[0]["email"] ,download_count = 1)
- factory = MagicMock()
- factory.obj = {"":""}
- with patch("flask_login.utils._get_user", return_value=users[1]["obj"]):
- with patch("weko_records_ui.fd.render_template", side_effect=lambda x,error: (x,error)): #return param
- with patch("weko_records_ui.fd._download_file", return_value="_download_file"):
- with patch("weko_records_ui.fd.parse_secret_download_token", return_value=( "parse_secret_download_token",("token"))):
- #28
- assert file_download_secret(recid,record,record_file_factory) == ('weko_theme/error.html', "parse_secret_download_token")
- with patch("weko_records_ui.fd.parse_secret_download_token", return_value=(False , (results[1]["recid"].pid_value,1,p.created,""))):
- with patch("weko_records_ui.fd.validate_download_record", return_value=None):
- with patch("weko_records_ui.fd.validate_secret_download_token", return_value=(False , "validate_secret_download_token")):
- # 29
- assert file_download_secret(recid,record,record_file_factory,filename="helloworld.docx")==('weko_theme/error.html' , "validate_secret_download_token")
- with patch("weko_records_ui.fd.validate_secret_download_token", return_value=(True , "")):
- with patch("weko_records_ui.fd.record_file_factory", return_value=""):
- # 30
- assert file_download_secret(recid,record,record_file_factory=lambda x ,y ,z: "",filename="helloworld.docx")==('weko_theme/error.html' , "{} does not exist.".format(results[1]["filename"]))
- with patch("weko_records_ui.fd.record_file_factory", return_value=factory):
- with patch("weko_records_ui.fd.get_secret_download", return_value=p):
- with patch("weko_records_ui.fd.update_secret_download", return_value=None):
- assert file_download_secret(results[0]["recid"],results[0]["record"],record_file_factory=None,filename="helloworld.docx")==('weko_theme/error.html' , "Unexpected error occurred.")
- #31
- assert file_download_secret(recid,record,record_file_factory,filename="helloworld.docx")=="_download_file"
- assert db.session.query(FileSecretDownload).one_or_none().download_count == 0
- with patch("weko_records_ui.fd.get_secret_download", return_value=None):
- with pytest.raises(Forbidden):
- file_download_secret(recid,record,record_file_factory,filename="helloworld.docx")
- with patch("weko_records_ui.fd.render_template", side_effect=lambda x,error: (x,error)): #return param
- with patch("weko_records_ui.fd.parse_secret_download_token", return_value=(False , (results[1]["recid"].pid_value,1,p.created,""))):
- with patch("weko_records_ui.fd.validate_secret_download_token", return_value=(True , "")):
- with patch("weko_records_ui.fd._download_file", return_value="_download_file"):
- with patch("weko_records_ui.fd.record_file_factory", return_value=factory):
- with patch("weko_records_ui.fd.get_secret_download", return_value=p):
- assert file_download_secret(recid,record,record_file_factory,filename="helloworld.docx")=="_download_file"
-
- with patch("weko_records_ui.fd.record_file_factory", return_value=False):
- assert file_download_onetime(recid,record,record_file_factory)==('weko_theme/error.html', 'Token is invalid.')
+@patch('weko_records_ui.fd.request.args.get')
+@patch('weko_records_ui.fd.validate_url_download')
+@patch('weko_records_ui.fd.error_response')
+@patch('weko_records_ui.fd.current_user')
+@patch('weko_records_ui.fd.save_download_log')
+@patch('weko_records_ui.fd._download_file')
+def test_file_download_secret(dl_file, save_log, current_user, err_res,
+ val_url, token, secret_url):
+ # Setup arguments
+ pid = None
+ record = {}
+ filename = 'test.txt'
+ _record_file_factory = MagicMock()
+ _record_file_factory.return_value = file_obj = MagicMock()
+ file_obj.obj = {'filename': filename}
+ file_obj.get.return_value = 'open_no'
+
+ # Setup default return values of mock objects
+ token.return_value = secret_url['secret_token']
+ val_url.return_value = (True, '')
+ current_user.is_authenticated = False
+ err_res.return_value = 'ERROR'
+ dl_file.return_value = 'SUCCESS'
+
+ # Happy path
+ assert file_download_secret(
+ pid, record, filename, _record_file_factory) == 'SUCCESS'
+ save_log.assert_called_once_with(
+ record, filename, token.return_value, is_secret_url=True)
+ dl_file.assert_called_once_with(
+ file_obj, False, 'en', file_obj.obj, pid, record)
+
+ # Happy path with authenticated user
+ mock_user = MagicMock()
+ mock_user.language = 'ja'
+ with patch('weko_user_profiles.models.UserProfile.get_by_userid',
+ return_value=mock_user):
+ with patch('weko_records_ui.fd.current_user.is_authenticated', True):
+ assert file_download_secret(
+ pid, record, filename, _record_file_factory) == 'SUCCESS'
+ save_log.assert_called_with(
+ record, filename, token.return_value, is_secret_url=True)
+ dl_file.assert_called_with(
+ file_obj, False, 'ja', file_obj.obj, pid, record)
+
+ # Invalid token
+ with patch('weko_records_ui.fd.validate_url_download',
+ return_value=(False, 'Invalid token')):
+ assert file_download_secret(
+ pid, record, filename, _record_file_factory) == 'ERROR'
+
+ # File object is not found
+ with patch('weko_records_ui.fd.record_file_factory',
+ return_value=None):
+ assert file_download_secret(
+ pid, record, filename) == 'ERROR'
+
+ # save_download_log() raises an exception
+ with patch('weko_records_ui.fd.save_download_log',
+ side_effect=Exception):
+ assert file_download_secret(
+ pid, record, filename, _record_file_factory) == 'ERROR'
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_fd.py::test_file_list_ui -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
diff --git a/modules/weko-records-ui/tests/test_models.py b/modules/weko-records-ui/tests/test_models.py
index c8b72a5140..b58b743035 100644
--- a/modules/weko-records-ui/tests/test_models.py
+++ b/modules/weko-records-ui/tests/test_models.py
@@ -1,4 +1,5 @@
import io
+import time
from datetime import datetime, timedelta, timezone
from unittest import mock # python3
#from unittest.mock import MagicMock
@@ -13,14 +14,12 @@
from invenio_accounts.models import Role, User
from invenio_accounts.testutils import create_test_user, login_user_via_session
from mock import patch
+from sqlalchemy.exc import IntegrityError
+
+from weko_records_ui.models import (AccessStatus, FileUrlDownloadLog,
+ InstitutionName, FileSecretDownload, FilePermission ,FileOnetimeDownload,
+ UrlType)
-from weko_records_ui.models import (
- InstitutionName
- ,FileSecretDownload
- ,FilePermission
- ,FileOnetimeDownload
-)
-
institution_name = InstitutionName(
name="test"
@@ -106,17 +105,6 @@ def test_FilePermission_delete_object(app, db, db_FilePermission):
assert db.session.query(FilePermission).count() == 0
-def test_FileOnetimeDownload_update_download(app, db, db_FileOneTimeDownload):
- data1 = {
- "file_name": db_FileOneTimeDownload.file_name,
- "user_mail": db_FileOneTimeDownload.user_mail,
- "record_id": db_FileOneTimeDownload.record_id,
- }
-
- db_FileOneTimeDownload.update_download(
- data=data1
- )
-
# def find_list_permission_approved(record_id, file_name):
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::test_find_list_permission_approved -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
def test_find_list_permission_approved(app, records_restricted, users,db_file_permission):
@@ -135,6 +123,285 @@ def test_find_by_activity(db_file_permission):
sorted_list = sorted(listpermission, key= lambda x: x.id ,reverse=True)
assert listpermission == sorted_list
+
+class TestFileOnetimeDownload:
+ expiration_date = datetime.now(timezone.utc) + timedelta(hours=24)
+ no_tz = expiration_date.replace(tzinfo=None)
+ base_data = {
+ 'approver_id': 1,
+ 'record_id': '1',
+ 'file_name': 'test file',
+ 'expiration_date': expiration_date,
+ 'download_limit': 1,
+ 'user_mail': 'test@example.org',
+ 'is_guest': False,
+ 'extra_info': {'info': 'value'}
+ }
+ expected_data = {
+ **base_data,
+ 'expiration_date': no_tz
+ }
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_init -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_init(self, db):
+ obj = FileOnetimeDownload(**self.base_data)
+ for key, value in self.base_data.items():
+ assert getattr(obj, key) == value
+ for key in self.base_data.keys():
+ bad_data = self.base_data.copy()
+ bad_data.pop(key)
+ with pytest.raises(TypeError):
+ FileOnetimeDownload(**bad_data)
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_create -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_create(self, users):
+ assert FileOnetimeDownload.query.count() == 0
+ obj = FileOnetimeDownload.create(**self.base_data)
+ assert isinstance(obj, FileOnetimeDownload)
+ assert FileOnetimeDownload.query.count() == 1
+ rec = FileOnetimeDownload.query.first()
+ for key, value in self.expected_data.items():
+ assert getattr(rec, key) == value
+
+ bad_data1 = self.base_data.copy()
+ bad_data1['expiration_date'] = (datetime.now(timezone.utc)
+ - timedelta(hours=24))
+ with pytest.raises(Exception):
+ FileOnetimeDownload.create(**bad_data1)
+ assert FileOnetimeDownload.query.count() == 1
+
+ bad_data2 = self.base_data.copy()
+ bad_data2['download_limit'] = -1
+ with pytest.raises(Exception):
+ FileOnetimeDownload.create(**bad_data2)
+ assert FileOnetimeDownload.query.count() == 1
+
+ with patch('weko_records_ui.models.db.session.commit') as mock_commit:
+ mock_commit.side_effect = Exception('DB error test')
+ with pytest.raises(Exception):
+ FileOnetimeDownload.create(**self.base_data)
+ mock_commit.assert_called_once()
+ assert FileOnetimeDownload.query.count() == 1
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_get_by_id -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_get_by_id(self, users):
+ FileOnetimeDownload.create(**self.base_data)
+ record = FileOnetimeDownload.get_by_id(1)
+ assert isinstance(record, FileOnetimeDownload)
+ not_found = FileOnetimeDownload.get_by_id(100)
+ assert not_found is None
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_find_downloadable_only -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_find_downloadable_only(self, db, users):
+ # Setups
+ expiring = datetime.now(timezone.utc)+timedelta(seconds=3)
+ ex_data = {**self.base_data, 'expiration_date': expiring}
+ FileOnetimeDownload.create(**ex_data)
+ for _ in range(2):
+ FileOnetimeDownload.create(**self.base_data)
+ query = {'file_name': self.base_data['file_name'],
+ 'record_id': self.base_data['record_id'],
+ 'user_mail': self.base_data['user_mail']}
+
+ # Test
+ recs = FileOnetimeDownload.find_downloadable_only(**query)
+ assert len(recs) == 3
+ recs[0].increment_download_count()
+ recs = FileOnetimeDownload.find_downloadable_only(**query)
+ assert len(recs) == 2
+ recs[0].delete_logically()
+ recs = FileOnetimeDownload.find_downloadable_only(**query)
+ assert len(recs) == 1
+ time.sleep(3)
+ recs = FileOnetimeDownload.find_downloadable_only(**query)
+ assert len(recs) == 0
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_update_extra_info -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_update_extra_info(self, users):
+ obj = FileOnetimeDownload.create(**self.base_data)
+ obj.update_extra_info({'new': 'value'})
+ assert obj.extra_info == {'new': 'value'}
+
+ with pytest.raises(ValueError):
+ obj.update_extra_info('invalid')
+ assert obj.extra_info == {'new': 'value'}
+
+ with patch('weko_records_ui.models.db.session.commit') as mock_commit:
+ mock_commit.side_effect = Exception('DB error test')
+ with pytest.raises(Exception):
+ obj.update_extra_info({'new': 'value2'})
+ mock_commit.assert_called_once()
+ assert obj.extra_info == {'new': 'value'}
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_increment_download_count -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_increment_download_count(self, users):
+ rec = FileOnetimeDownload.create(**self.base_data)
+ assert rec.download_count == 0
+ rec.increment_download_count()
+ assert rec.download_count == 1
+
+ with pytest.raises(ValueError):
+ rec.increment_download_count()
+ assert rec.download_count == 1
+
+ rec2 = FileOnetimeDownload.create(**self.base_data)
+ with patch('weko_records_ui.models.db.session.commit') as mock_commit:
+ mock_commit.side_effect = Exception('DB error test')
+ with pytest.raises(Exception):
+ rec2.increment_download_count()
+ mock_commit.assert_called_once()
+ assert rec2.download_count == 0
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_delete_logically -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_delete_logically(self, users):
+ rec = FileOnetimeDownload.create(**self.base_data)
+ assert rec.is_deleted is False
+ rec.delete_logically()
+ assert rec.is_deleted is True
+
+ rec.delete_logically()
+ assert rec.is_deleted is True
+
+ rec2 = FileOnetimeDownload.create(**self.base_data)
+ with patch('weko_records_ui.models.db.session.commit') as mock_commit:
+ mock_commit.side_effect = Exception('DB error test')
+ with pytest.raises(Exception):
+ rec2.delete_logically()
+ mock_commit.assert_called_once()
+ assert rec2.is_deleted is False
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileOnetimeDownload::test_fetch_active_urls -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_fetch_active_urls(self, users):
+ recid = self.base_data['record_id']
+ filename = self.base_data['file_name']
+ assert FileOnetimeDownload.fetch_active_urls(recid, filename) == []
+ FileOnetimeDownload.create(**self.base_data)
+ assert len(FileOnetimeDownload.fetch_active_urls(recid, filename)) == 1
+ FileOnetimeDownload.create(**self.base_data)
+ assert len(FileOnetimeDownload.fetch_active_urls(recid, filename)) == 2
+ assert FileOnetimeDownload.fetch_active_urls(
+ recid, filename, ascending=True)[0].id == 1
+ assert FileOnetimeDownload.fetch_active_urls(
+ recid, filename, ascending=False)[0].id == 2
+
+
+class TestFileSecretDownload:
+ expiration_date = datetime.now(timezone.utc) + timedelta(hours=24)
+ no_tz = expiration_date.replace(tzinfo=None)
+ base_data = {
+ 'creator_id': 1,
+ 'record_id': '1',
+ 'file_name': 'test file',
+ 'label_name': 'test label',
+ 'expiration_date': expiration_date,
+ 'download_limit': 1
+ }
+ expected_data = {
+ **base_data,
+ 'expiration_date': no_tz
+ }
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileSecretDownload::test_init -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_init(self, db):
+ obj = FileSecretDownload(**self.base_data)
+ for key, value in self.base_data.items():
+ assert getattr(obj, key) == value
+ for key in self.base_data.keys():
+ bad_data = self.base_data.copy()
+ bad_data.pop(key)
+ with pytest.raises(TypeError):
+ FileSecretDownload(**bad_data)
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileSecretDownload::test_create -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_create(self, users):
+ assert FileSecretDownload.query.count() == 0
+ obj = FileSecretDownload.create(**self.base_data)
+ assert isinstance(obj, FileSecretDownload)
+ assert FileSecretDownload.query.count() == 1
+ rec = FileSecretDownload.query.first()
+ for key, value in self.expected_data.items():
+ assert getattr(rec, key) == value
+
+ bad_data1 = self.base_data.copy()
+ bad_data1['expiration_date'] = (datetime.now(timezone.utc)
+ - timedelta(hours=24))
+ with pytest.raises(Exception):
+ FileSecretDownload.create(**bad_data1)
+ assert FileSecretDownload.query.count() == 1
+
+ bad_data2 = self.base_data.copy()
+ bad_data2['download_limit'] = -1
+ with pytest.raises(Exception):
+ FileSecretDownload.create(**bad_data2)
+ assert FileSecretDownload.query.count() == 1
+
+ with patch('weko_records_ui.models.db.session.commit') as mock_commit:
+ mock_commit.side_effect = Exception('DB error test')
+ with pytest.raises(Exception):
+ FileSecretDownload.create(**self.base_data)
+ mock_commit.assert_called_once()
+ assert FileSecretDownload.query.count() == 1
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileSecretDownload::test_get_by_id -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_get_by_id(self, users):
+ FileSecretDownload.create(**self.base_data)
+ record = FileSecretDownload.get_by_id(1)
+ assert isinstance(record, FileSecretDownload)
+ not_found = FileSecretDownload.get_by_id(100)
+ assert not_found is None
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileSecretDownload::test_increment_download_count -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_increment_download_count(self, users):
+ rec = FileSecretDownload.create(**self.base_data)
+ assert rec.download_count == 0
+ rec.increment_download_count()
+ assert rec.download_count == 1
+
+ with pytest.raises(ValueError):
+ rec.increment_download_count()
+ assert rec.download_count == 1
+
+ rec2 = FileSecretDownload.create(**self.base_data)
+ with patch('weko_records_ui.models.db.session.commit') as mock_commit:
+ mock_commit.side_effect = Exception('DB error test')
+ with pytest.raises(Exception):
+ rec2.increment_download_count()
+ mock_commit.assert_called_once()
+ assert rec2.download_count == 0
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileSecretDownload::test_delete_logically -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_delete_logically(self, users):
+ rec = FileSecretDownload.create(**self.base_data)
+ assert rec.is_deleted is False
+ rec.delete_logically()
+ assert rec.is_deleted is True
+
+ rec.delete_logically()
+ assert rec.is_deleted is True
+
+ rec2 = FileSecretDownload.create(**self.base_data)
+ with patch('weko_records_ui.models.db.session.commit') as mock_commit:
+ mock_commit.side_effect = Exception('DB error test')
+ with pytest.raises(Exception):
+ rec2.delete_logically()
+ mock_commit.assert_called_once()
+ assert rec2.is_deleted is False
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileSecretDownload::test_fetch_active_urls -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_fetch_active_urls(self, users):
+ recid = self.base_data['record_id']
+ filename = self.base_data['file_name']
+ assert FileSecretDownload.fetch_active_urls(recid, filename) == []
+ FileSecretDownload.create(**self.base_data)
+ assert len(FileSecretDownload.fetch_active_urls(recid, filename)) == 1
+ FileSecretDownload.create(**self.base_data)
+ assert len(FileSecretDownload.fetch_active_urls(recid, filename)) == 2
+ assert FileSecretDownload.fetch_active_urls(
+ recid, filename, ascending=True)[0].id == 1
+ assert FileSecretDownload.fetch_active_urls(
+ recid, filename, ascending=False)[0].id == 2
+
+
# def find_downloadable_only(cls, **obj) -> list:
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::test_find_downloadable_only -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
@pytest.mark.skip(reason="'from sqlalchemy.dialects.postgresql import INTERVAL' can't tests on SQLite.")
@@ -155,114 +422,146 @@ def test_find_downloadable_only(app,db):
assert len(recs) == 2
-# def find_by_activity:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::test_find_by_activity -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_init():
- # 36
- dl = FileSecretDownload("a","b","c",1,2)
- assert dl.file_name == "a"
- assert dl.user_mail == "b"
- assert dl.record_id == "c"
- assert dl.download_count == 1
- assert dl.expiration_date == 2
-
-# def create(cls, **data):
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::test_create -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_create(app,db):
- # 37 42
- with app.test_request_context():
- dl = FileSecretDownload.create(
- file_name = "a"
- ,user_mail ="b"
- ,record_id = "c"
- ,download_count = 1
- ,expiration_date= 2
- )
- assert dl.id
- assert dl.created
- rec = FileSecretDownload.find(
- id = dl.id
- ,file_name = "a"
- ,record_id = "c"
- ,created = dl.created
- )
- assert len(rec) == 1
- rec = rec[0]
- assert rec.file_name == "a"
- assert rec.user_mail == "b"
- assert rec.record_id == "c"
- assert rec.download_count == 1
- assert rec.expiration_date == 2
-
- # 38
- with app.test_request_context():
- with patch("weko_records_ui.models.db.session.add", side_effect=Exception("test_error")):
- defaultlength = len(FileSecretDownload.query.filter_by().all())
- with pytest.raises(Exception):
- dl = FileSecretDownload.create(
- file_name = "a"
- ,user_mail ="b"
- ,record_id = "c"
- )
- assert defaultlength == len(FileSecretDownload.query.filter_by().all())
-
-# def update_download(cls, **data):
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::test_update_download -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_update_download(app,db):
- with app.test_request_context():
- # 39
- dl = FileSecretDownload.create(
- file_name = "a"
- ,user_mail ="b"
- ,record_id = "c"
- ,download_count = 1
- ,expiration_date= 2
- )
- result = FileSecretDownload.update_download(
- id = dl.id
- ,file_name = "a"
- ,record_id = "c"
- ,created = dl.created
- ,download_count = 100
- )
- if result:
- assert result[0].download_count == 100
- else:
- assert False
-
- # 40
- assert FileSecretDownload.update_download(
- id = dl.id + 1
- ,file_name = "a"
- ,record_id = "c"
- ,created = dl.created
- ) == None
- assert FileSecretDownload.update_download(
- id = dl.id
- ,file_name = "a"
- ,record_id = "c"
- ,created = dl.created
- )
-def test_update_download2(app,db):
- with app.test_request_context():
- # 41
- dl = FileSecretDownload.create(
- file_name = "a"
- ,user_mail ="b"
- ,record_id = "c"
- ,download_count = 1
- ,expiration_date= 2
- )
- with patch("weko_records_ui.models.db.session.merge", side_effect=Exception("test_error")):
- before = FileSecretDownload.query.filter_by().one_or_none().download_count
- try:
- dl = FileSecretDownload.update_download(
- id = dl.id
- ,file_name = "a"
- ,record_id = "c"
- ,created = dl.created
- ,download_count = 200
- )
- assert False
- except:
- assert before == FileSecretDownload.query.filter_by().one_or_none().download_count
+class TestFileUrlDownloadLog:
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileUrlDownloadLog::test_init -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_init(self):
+ secret_dl_data = {
+ 'url_type': UrlType.SECRET,
+ 'secret_url_id': 1,
+ 'onetime_url_id': None,
+ 'ip_address': '192.168.56.1',
+ 'access_status': AccessStatus.OPEN_NO,
+ 'used_token': 'test token'
+ }
+ # When each key is present
+ log_obj = FileUrlDownloadLog(**secret_dl_data)
+ for key, value in secret_dl_data.items():
+ assert getattr(log_obj, key) == value
+ # When each key is missing
+ for key in secret_dl_data.keys():
+ bad_data = secret_dl_data.copy()
+ bad_data.pop(key)
+ with pytest.raises(TypeError):
+ FileUrlDownloadLog(**bad_data)
+
+ onetime_dl_data = {
+ 'url_type': UrlType.ONETIME,
+ 'secret_url_id': None,
+ 'onetime_url_id': 1,
+ 'ip_address': None,
+ 'access_status': AccessStatus.OPEN_RESTRICTED,
+ 'used_token': 'test token'
+ }
+ # When each key is present
+ log_obj = FileUrlDownloadLog(**onetime_dl_data)
+ for key, value in onetime_dl_data.items():
+ assert getattr(log_obj, key) == value
+ # When each key is missing
+ for key in onetime_dl_data.keys():
+ bad_data = onetime_dl_data.copy()
+ bad_data.pop(key)
+ with pytest.raises(TypeError):
+ FileUrlDownloadLog(**bad_data)
+
+ # .tox/c1/bin/pytest --cov=weko_records_ui tests/test_models.py::TestFileUrlDownloadLog::test_create -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+ def test_create(self, secret_url, onetime_url):
+ # Happy path with secret URL(open_no)
+ open_no = {
+ 'url_type': UrlType.SECRET,
+ 'secret_url_id': secret_url['secret_obj'].id,
+ 'onetime_url_id': None,
+ 'ip_address': '192.168.56.1',
+ 'access_status': AccessStatus.OPEN_NO,
+ 'used_token': secret_url['secret_token']
+ }
+ assert FileUrlDownloadLog.query.count() == 0
+ log_obj = FileUrlDownloadLog.create(**open_no)
+ assert isinstance(log_obj, FileUrlDownloadLog)
+ assert FileUrlDownloadLog.query.count() == 1
+ log_rec = FileUrlDownloadLog.query.filter_by(id=1).first()
+ for key, value in open_no.items():
+ assert getattr(log_rec, key) == value
+
+ # Happy path with secret URL(open_date)
+ open_date = {
+ 'url_type': UrlType.SECRET,
+ 'secret_url_id': secret_url['secret_obj'].id,
+ 'onetime_url_id': None,
+ 'ip_address': '192.168.56.1',
+ 'access_status': AccessStatus.OPEN_DATE,
+ 'used_token': secret_url['secret_token']
+ }
+ assert FileUrlDownloadLog.query.count() == 1
+ log_obj = FileUrlDownloadLog.create(**open_date)
+ assert isinstance(log_obj, FileUrlDownloadLog)
+ assert FileUrlDownloadLog.query.count() == 2
+ log_rec = FileUrlDownloadLog.query.filter_by(id=2).first()
+ for key, value in open_date.items():
+ assert getattr(log_rec, key) == value
+
+ # Happy path with onetime URL(open_restricted)
+ open_restricted = {
+ 'url_type': UrlType.ONETIME,
+ 'secret_url_id': None,
+ 'onetime_url_id': onetime_url['onetime_obj'].id,
+ 'ip_address': None,
+ 'access_status': AccessStatus.OPEN_RESTRICTED,
+ 'used_token': onetime_url['onetime_token']
+ }
+ assert FileUrlDownloadLog.query.count() == 2
+ log_obj = FileUrlDownloadLog.create(**open_restricted)
+ assert isinstance(log_obj, FileUrlDownloadLog)
+ assert FileUrlDownloadLog.query.count() == 3
+ log_rec = FileUrlDownloadLog.query.filter_by(id=3).first()
+ for key, value in open_restricted.items():
+ assert getattr(log_rec, key) == value
+
+ # Either secret_url_id or onetime_url_id must be null
+ secret_id_err = open_no.copy()
+ secret_id_err['onetime_url_id'] = onetime_url['onetime_obj'].id
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**secret_id_err)
+ onetime_id_err = open_restricted.copy()
+ onetime_id_err['secret_url_id'] = secret_url['secret_obj'].id
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**onetime_id_err)
+
+ # Either secret_url_id or onetime_url_id must be present
+ no_id_err = open_no.copy()
+ no_id_err['secret_url_id'] = None
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**no_id_err)
+ no_id_err = open_restricted.copy()
+ no_id_err['onetime_url_id'] = None
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**no_id_err)
+
+ # ip_address must be present if url_type is secret
+ secret_ip_err = open_no.copy()
+ secret_ip_err['ip_address'] = None
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**secret_ip_err)
+
+ # ip_address must be null if url_type is onetime
+ onetime_ip_err = open_restricted.copy()
+ onetime_ip_err['ip_address'] = open_no['ip_address']
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**onetime_ip_err)
+
+ # access_status must be 'open_no' or 'open_date' if url_type is secret
+ secret_access_err = open_no.copy()
+ secret_access_err['access_status'] = AccessStatus.OPEN_RESTRICTED
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**secret_access_err)
+
+ # access_status must be 'open_restricted' if url_type is onetime
+ onetime_access_err = open_restricted.copy()
+ onetime_access_err['access_status'] = AccessStatus.OPEN_NO
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**onetime_access_err)
+
+ # used_token must be present
+ token_err = open_no.copy()
+ token_err['used_token'] = None
+ with pytest.raises(IntegrityError):
+ FileUrlDownloadLog.create(**token_err)
diff --git a/modules/weko-records-ui/tests/test_utils.py b/modules/weko-records-ui/tests/test_utils.py
index 579ecfb0be..e2e1dbefee 100644
--- a/modules/weko-records-ui/tests/test_utils.py
+++ b/modules/weko-records-ui/tests/test_utils.py
@@ -1,20 +1,27 @@
+import re
import pytest
from weko_records_ui.utils import (
+ can_manage_onetime_url,
+ convert_token_into_obj,
+ has_permission_to_manage_onetime_url,
+ is_onetime_file,
+ save_download_log,
+ to_utc_datetime,
+ create_download_url,
+ create_onetime_url_record,
+ create_secret_url_record,
+ generate_sha256_hash,
is_future,
create_usage_report_for_user,
get_data_usage_application_data,
+ send_secret_url_mail,
send_usage_report_mail_for_user,
check_and_send_usage_report,
- update_onetime_download,
- create_onetime_download_url,
get_onetime_download,
- validate_onetime_download_token,
get_license_pdf,
hide_item_metadata,
get_pair_value,
get_min_price_billing_file_download,
- parse_one_time_download_token,
- generate_one_time_download_url,
validate_download_record,
is_private_index,
get_file_info_list,
@@ -33,25 +40,29 @@
get_record_permalink,
get_google_detaset_meta,
get_google_scholar_meta,
- create_secret_url,
- parse_secret_download_token,
- validate_secret_download_token,
- get_secret_download,
- update_secret_download,
get_valid_onetime_download,
display_oaiset_path,
get_terms,
get_roles,
check_items_settings,
+ validate_expiration_date,
+ validate_file_access,
+ validate_secret_url_generation_request,
#RoCrateConverter,
#create_tsv
+ is_secret_url_feature_enabled,
+ has_permission_to_manage_secret_url,
+ is_secret_file,
+ can_manage_secret_url,
+ validate_token,
+ validate_url_download,
)
import base64
from unittest.mock import MagicMock
import copy
import pytest
import io
-from datetime import datetime as dt
+from datetime import date, datetime as dt, time, timezone
from datetime import timedelta
from lxml import etree
from fpdf import FPDF
@@ -62,7 +73,8 @@
from invenio_pidstore.models import PersistentIdentifier, PIDStatus
from mock import patch
from weko_deposit.api import WekoRecord
-from weko_records_ui.models import FileOnetimeDownload, FileSecretDownload
+from weko_records_ui.models import (AccessStatus, FileOnetimeDownload,
+ FileSecretDownload, FileUrlDownloadLog, UrlType)
from weko_records.api import ItemTypes,Mapping
from werkzeug.exceptions import NotFound
from weko_admin.models import AdminSettings
@@ -71,6 +83,8 @@
from flask_babelex import gettext as _
from datetime import datetime ,timedelta
+from weko_schema_ui.models import PublishStatus
+
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
# def is_future(settings=None):
@@ -544,55 +558,6 @@ def send_reminder_mail_2(x, y, z):
with patch("weko_records_ui.utils.check_create_usage_report",return_value=None):
check_and_send_usage_report({"is_guest": False, "send_usage_report": True, "usage_application_activity_id": "A-20230101-00001"},users[7]['email'],data1, data2)
-# def generate_one_time_download_url(
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_generate_one_time_download_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_generate_one_time_download_url(app):
- file_name = "003.jpg"
- record_id = "1"
- guest_mail= "user@example.org"
- with app.test_request_context():
- ret = generate_one_time_download_url(file_name,record_id,guest_mail)
- rets = ret.split('token=')
- token_str =base64.b64decode(rets[1])
- token = (token_str.decode('utf-8')).split(' ')
- assert token[0] == record_id
- assert token[1] == guest_mail
-
-
-# def parse_one_time_download_token(token: str) -> Tuple[str, Tuple]:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_parse_one_time_download_token -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_parse_one_time_download_token(app):
- token = "MSB1c2VyQGV4YW1wbGUub3JnIDIwMjItMDktMjcgNDBDRkNGODFGM0FFRUI0Ng=="
- with app.test_request_context():
- assert parse_one_time_download_token(token)==('', ('1', 'user@example.org', '2022-09-27', '40CFCF81F3AEEB46'))
- assert parse_one_time_download_token("test") != None
- assert parse_one_time_download_token(None) != None
-
-
-# def validate_onetime_download_token(
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_onetime_download_token -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_validate_onetime_download_token(app,db_fileonetimedownload):
- file_name='helloworld.pdf'
- record_id='1'
- user_email='wekosoftware@nii.ac.jp'
- token = "9948A41F46456DF5"
- date = "2022-09-28"
- with app.test_request_context():
- file_downloads = FileOnetimeDownload.find(
- file_name=file_name, record_id=record_id, user_mail=user_email
- )
- assert validate_onetime_download_token(file_downloads[0],file_name,record_id,user_email,date,token)== (True, '')
-
- data1 = MagicMock()
- data1.download_count = 0
-
- with patch('passlib.handlers.oracle.oracle10.verify', return_value=False):
- assert validate_onetime_download_token(file_downloads[0],file_name,record_id,user_email,date,token)== (False, 'Token is invalid.')
-
- assert validate_onetime_download_token(False,file_name,record_id,user_email,date,token)== (False, 'Token is invalid.')
-
- assert validate_onetime_download_token(data1,file_name,record_id,user_email,date,token)== (False, 'Token is invalid.')
-
# def is_private_index(record):
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_is_private_index -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
@@ -624,25 +589,204 @@ def test_is_private_index(app,records):
# def validate_download_record(record: dict):
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_download_record -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_validate_download_record(app, records):
- indexer, results = records
- record = results[0]["record"]
- assert validate_download_record(record)==None
-
- data1 = {
- "publish_status": 1
- }
+def test_validate_download_record():
+ record = {'publish_status': PublishStatus.PUBLIC.value}
+ with patch('weko_records_ui.utils.is_private_index', return_value=False):
+ assert validate_download_record(record) is True
+ record['publish_status'] = None
+ assert validate_download_record(record) is False
+ record['publish_status'] = PublishStatus.PUBLIC.value
+ with patch('weko_records_ui.utils.is_private_index', return_value=True):
+ assert validate_download_record(record) is False
+ record['publish_status'] = None
+ assert validate_download_record(record) is False
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_is_secret_url_feature_enabled -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_is_secret_url_feature_enabled(app):
+ with app.app_context():
+ # Case 1: secret_enableがTrueを返す
+ with patch('weko_records_ui.utils.AdminSettings.get') as mock_get:
+ mock_get.return_value = {
+ 'secret_URL_file_download': {
+ 'secret_enable': True,
+ }
+ }
+ assert is_secret_url_feature_enabled() is True
- try:
- validate_download_record(data1)
- except:
- pass
+ # Case 2: secret_enableがFalseを返す
+ with patch('weko_records_ui.utils.AdminSettings.get') as mock_get:
+ mock_get.return_value = {
+ 'secret_URL_file_download': {
+ 'secret_enable': False,
+ }
+ }
+ assert is_secret_url_feature_enabled() is False
- with patch("weko_records_ui.utils.is_private_index", return_value=True):
- try:
- validate_download_record(record)
- except:
- pass
+ # Case 3: AdminSettingsがNoneでcurrent_app.configが存在し、期待するデフォルト設定がある場合
+ with patch('weko_records_ui.utils.AdminSettings.get', return_value=None):
+ with patch('weko_records_ui.utils.current_app.config', {
+ 'WEKO_ADMIN_RESTRICTED_ACCESS_SETTINGS': {
+ 'secret_URL_file_download': {}
+ }
+ }):
+ # secret_enable は存在しないのでデフォルト値の False を返すことを検証
+ assert is_secret_url_feature_enabled() is False
+
+ # Case 4: AdminSettingsがNoneでcurrent_app.configが存在しない場合
+ with patch('weko_records_ui.utils.AdminSettings.get', return_value=None):
+ with patch('weko_records_ui.utils.current_app.config', {'WEKO_ADMIN_RESTRICTED_ACCESS_SETTINGS': {}}):
+ # 設定がない場合も False を返すことを検証
+ assert is_secret_url_feature_enabled() is False
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_has_permission_to_manage_secret_url -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@pytest.mark.parametrize(
+ "user_id, expected",
+ [
+ (0, True), # Owner
+ (4, True), # Shared user
+ (1, True), # Superuser
+ (2, True), # Superuser
+ (3, False), # No permission
+ (5, False), # No superuser role
+ ],
+)
+def test_has_permission_to_manage_secret_url(user_id, expected, app, users):
+ # レコードに必要なデータを設定
+ # 'owner'と'weko_shared_id'は、usersリストから取り出した値を使用
+ record = {'owner': str(users[0]["id"]), 'weko_shared_id': users[4]["id"]}
+
+ # アプリケーションコンテキスト内でテスト実行
+ with app.app_context():
+ # has_permission_to_manage_secret_url関数を実行し、
+ # 結果が期待される値 (expected) と一致するかを検証
+ assert has_permission_to_manage_secret_url(record, users[user_id]["id"]) == expected
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_has_permission_to_manage_onetime_url -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@pytest.mark.parametrize(
+ "user_id, expected",
+ [
+ (0, True), # Owner
+ (4, False), # Shared user
+ (1, True), # Superuser
+ (2, True), # Superuser
+ (3, False), # No permission
+ (5, False), # No superuser role
+ ],
+)
+def test_has_permission_to_manage_onetime_url(user_id, expected, app, users):
+ record = {'owner': str(users[0]["id"]), 'weko_shared_id': users[4]["id"]}
+ with app.app_context():
+ assert has_permission_to_manage_onetime_url(
+ record, users[user_id]["id"]) is expected
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_is_secret_file -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@pytest.mark.parametrize(
+ "file_data, filename, expected",
+ [
+ # ケース1: accessroleが 'open_no' の場合
+ ([{'filename': 'testfile.txt', 'accessrole': 'open_no', 'date': [{'dateValue': '2999-12-31'}]}], 'testfile.txt', True),
+ # ケース2: accessroleが 'open_date' で公開日が未来の場合
+ ([{'filename': 'testfile.txt', 'accessrole': 'open_date', 'date': [{'dateValue': '2999-12-31'}]}], 'testfile.txt', True),
+ # ケース3: accessroleが 'open_date' で公開日が過去の場合
+ ([{'filename': 'testfile.txt', 'accessrole': 'open_date', 'date': [{'dateValue': '2000-01-01'}]}], 'testfile.txt', False),
+ # ケース4: accessroleが 'open_no' や 'open_date' でない場合
+ ([{'filename': 'testfile.txt', 'accessrole': 'open_test', 'date': [{'dateValue': '2999-12-31'}]}], 'testfile.txt', False),
+ # ケース5: ファイル名が一致しない場合
+ ([{'filename': 'otherfile.txt', 'accessrole': 'open_no', 'date': [{'dateValue': '2999-12-31'}]}], 'testfile.txt', False),
+ # ケース6: file_dataが空の場合
+ ([], 'testfile.txt', False),
+ ],
+)
+def test_is_secret_file(file_data, filename, expected):
+ # WekoRecordのモックを作成し、get_file_dataメソッドをファイルデータでモックする
+ mock_record = MagicMock(spec=WekoRecord)
+ mock_record.get_file_data.return_value = file_data # モックのget_file_dataメソッドが返す値を設定
+
+ # dt(日時関連)をモックして、現在の日付や日付文字列の変換を制御する
+ with patch('weko_records_ui.utils.dt') as mock_dt:
+ mock_dt.utcnow.return_value = dt(2024, 1, 1) # 現在の日付を2024年1月1日に設定
+ mock_dt.strptime.side_effect = lambda *args, **kwargs: dt.strptime(*args, **kwargs) # strptimeの動作をモック
+
+ # is_secret_file関数を実行して、結果が期待される値と一致するかを確認
+ result = is_secret_file(mock_record, filename)
+
+ # 実際の結果が期待値と一致することを確認
+ assert result == expected
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_is_onetime_file -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_is_onetime_file():
+ mock_record = MagicMock()
+ mock_record.get_file_data.return_value = [
+ {"filename": "file1.txt", "accessrole": "open_restricted"},
+ {"filename": "file2.txt", "accessrole": "public"}
+ ]
+ assert is_onetime_file(mock_record, "file1.txt") is True
+ assert is_onetime_file(mock_record, "file2.txt") is False
+ assert is_onetime_file(mock_record, "file3.txt") is False
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_can_manage_secret_url -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@pytest.mark.parametrize(
+ "is_authenticated, feature_enabled, has_permission, is_secret, expected",
+ [
+ # Case 1: ユーザーが認証されていない場合
+ (False, True, True, True, False),
+ # Case 2: 機能が有効でない場合
+ (True, False, True, True, False),
+ # Case 3: ユーザーに権限がない場合
+ (True, True, False, True, False),
+ # Case 4: ファイルが秘密でない場合
+ (True, True, True, False, False),
+ # Case 5: すべての条件を満たす場合
+ (True, True, True, True, True),
+ ],
+)
+def test_can_manage_secret_url(is_authenticated, feature_enabled, has_permission, is_secret, expected):
+ # WekoRecordのモックを作成
+ mock_record = MagicMock(spec=WekoRecord)
+
+ # ユーザーのモックを作成
+ mock_user = MagicMock()
+ mock_user.is_authenticated = is_authenticated # ユーザーが認証されているかどうかを設定
+
+ # current_userのモックを作成して、`mock_user`を返すように設定
+ with patch('weko_records_ui.utils.current_user', mock_user):
+ # is_secret_url_feature_enabledのモックを作成して、`feature_enabled`を返すように設定
+ with patch('weko_records_ui.utils.is_secret_url_feature_enabled', return_value=feature_enabled):
+ # has_permission_to_manage_secret_urlのモックを作成して、`has_permission`を返すように設定
+ with patch('weko_records_ui.utils.has_permission_to_manage_secret_url', return_value=has_permission):
+ # is_secret_fileのモックを作成して、`is_secret`を返すように設定
+ with patch('weko_records_ui.utils.is_secret_file', return_value=is_secret):
+ # can_manage_secret_url関数を実行し、結果が期待される値と一致するかを確認
+ assert can_manage_secret_url(mock_record, 'testfile.txt') == expected
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_can_manage_onetime_url -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@pytest.mark.parametrize(
+ "is_authenticated, has_permission, is_onetime, expected",
+ [
+ # Case 1: ユーザーが認証されていない場合
+ (False, True, True, False),
+ # Case 2: ユーザーに権限がない場合
+ (True, False, True, False),
+ # Case 3: ファイルが制限公開アイテムでない場合
+ (True, True, False, False),
+ # Case 4: すべての条件を満たす場合
+ (True, True, True, True),
+ ],
+)
+def test_can_manage_onetime_url(is_authenticated, has_permission, is_onetime, expected):
+ mock_record = MagicMock(spec=WekoRecord)
+ mock_user = MagicMock()
+ mock_user.is_authenticated = is_authenticated
+ with patch('weko_records_ui.utils.current_user', mock_user):
+ with patch('weko_records_ui.utils.has_permission_to_manage_onetime_url', return_value=has_permission):
+ with patch('weko_records_ui.utils.is_onetime_file', return_value=is_onetime):
+ assert can_manage_onetime_url(mock_record, 'testfile.txt') == expected
# def get_onetime_download(file_name: str, record_id: str,
@@ -665,24 +809,6 @@ def test_get_valid_onetime_download():
with patch("weko_records_ui.models.FileOnetimeDownload.find_downloadable_only",return_value=["a","b"]):
assert "a" == get_valid_onetime_download(file_name= "str", record_id= "str",user_mail= "str")
-# def create_onetime_download_url(
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_create_onetime_download_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_create_onetime_download_url(app):
- with app.test_request_context():
- assert create_onetime_download_url('ACT','helloworld.pdf','1','wekosoftware@nii.ac.jp') == None
-
- data1 = []
-
- with patch('weko_records_ui.utils.get_restricted_access', return_value=data1):
- assert create_onetime_download_url('ACT','helloworld.pdf','1','wekosoftware@nii.ac.jp') == False
-
-
-# def update_onetime_download(**kwargs) -> NoReturn:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_update_onetime_download -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_update_onetime_download(app):
- with app.test_request_context():
- assert update_onetime_download(file_name="helloworld.pdf", user_mail="wekosoftware@nii.ac.jp", record_id="1", download_count=0)==None
-
# def get_workflows():
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_get_workflows -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
@@ -765,178 +891,603 @@ def test_get_google_detaset_meta(app, records, itemtypes, oaischema, oaiidentify
with patch("lxml.etree", return_value=data1):
assert get_google_detaset_meta(record) == None
-#def create_secret_url(record_id:str ,file_name:str ,user_mail:str ,restricted_fullname='',restricted_data_name='') -> dict:
-# def _generate_secret_download_url(file_name: str, record_id: str, id: str ,created :dt) -> str:
-# _create_secret_download_url(file_name: str, record_id: str, user_mail: str)
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_create_secret_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_create_secret_url(app,db,users,records):
- url , results = records
- file_name= results[1]["filename"]
- record_id=results[1]["recid"].pid_value
- user_mail = users[0]["email"]
-
- db.session.add(AdminSettings(id=6,name='restricted_access',settings={"secret_URL_file_download":
- {"secret_enable": True,
- "secret_download_limit": 1,
- "secret_expiration_date": 9999999,
- "secret_download_limit_unlimited_chk": False,
- "secret_expiration_date_unlimited_chk": False}}))
-
- with app.test_request_context():
-
- #60
- #76
- # with db.session.begin_nested():
- return_dict = create_secret_url(file_name= file_name, record_id=record_id, user_mail=user_mail)
-
- assert return_dict["restricted_download_count"] == '1'
- assert return_dict["restricted_download_count_ja"] == ""
- assert return_dict["restricted_download_count_en"] == ""
- assert return_dict['restricted_expiration_date'] == ""
- assert return_dict['restricted_expiration_date_ja'] == "無制限"
- assert return_dict['restricted_expiration_date_en'] == "Unlimited"
-
- #61
- # with db.session.begin_nested():
- db.session.merge(AdminSettings(id=6,name='restricted_access',settings={"secret_URL_file_download":
- {"secret_enable": True,
- "secret_download_limit": 9999999,
- "secret_expiration_date": 1,
- "secret_download_limit_unlimited_chk": False,
- "secret_expiration_date_unlimited_chk": False}}))
- return_dict = create_secret_url(file_name= file_name
- , record_id=record_id
- , user_mail=user_mail)
- assert return_dict["restricted_download_count"] == ""
- assert return_dict["restricted_download_count_ja"] == "無制限"
- assert return_dict["restricted_download_count_en"] == "Unlimited"
- assert return_dict['restricted_expiration_date'] == (datetime.today() + timedelta(1)).strftime("%Y-%m-%d")
- assert return_dict['restricted_expiration_date_ja'] == ""
- assert return_dict['restricted_expiration_date_en'] == ""
-
- #62
- #63
- from re import match
- assert match("^.+record\/" + record_id + "\/file\/secret\/"+file_name+"\?token=.+=$",return_dict["restricted_download_link"])
- assert return_dict["restricted_download_link"] != ""
- assert return_dict["mail_recipient"] == user_mail
-
-# def parse_secret_download_token(token: str) -> Tuple[str, Tuple]:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_parse_secret_download_token -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_parse_secret_download_token(app ,db):
- #64
- assert parse_secret_download_token(None) == (_("Token is invalid."),())
- assert parse_secret_download_token("") == (_("Token is invalid."),())
- #65
- assert parse_secret_download_token("random_string sajfosijdfasodfjv") == (_("Token is invalid."),())
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_to_utc_datetime -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_to_utc_datetime(app):
+ assert to_utc_datetime('2025-1-1') == datetime(
+ 2025, 1, 1, 0, 0, tzinfo=timezone.utc)
+ assert to_utc_datetime('2025-01-01') == datetime(
+ 2025, 1, 1, 0, 0, tzinfo=timezone.utc)
+ assert to_utc_datetime('2025-1-1', 720) == datetime(
+ 2025, 1, 1, 12, 0, tzinfo=timezone.utc)
+ assert to_utc_datetime('2025-1-1', -720) == datetime(
+ 2024, 12, 31, 12, 0, tzinfo=timezone.utc)
+ assert to_utc_datetime('2025-1-1', -540) == datetime(
+ 2024, 12, 31, 15, 0, tzinfo=timezone.utc)
+ assert to_utc_datetime('2025/01/01') is None
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_secret_url_generation_request -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.utils.validate_expiration_date')
+def test_validate_secret_url_generation_request(mock_date, app):
+ mock_date.return_value = True
+ base_case = {'link_name' : '',
+ 'expiration_date' : 'mocked',
+ 'download_limit' : 1,
+ 'send_email' : False,
+ 'timezone_offset_minutes': 0}
+ test_cases = [
+ (None,
+ False),
+ # When all fields are valid
+ ({'link_name' : '123',
+ 'expiration_date' : 'mocked',
+ 'download_limit' : 1,
+ 'send_email' : False,
+ 'timezone_offset_minutes': 0},
+ True),
+ # When all fields are invalid
+ ({'link_name' : 123,
+ 'expiration_date' : 123,
+ 'download_limit' : 0,
+ 'send_email' : None,
+ 'timezone_offset_minutes': '0'},
+ False),
+ # When each keys do not exist
+ ({key: value for key, value in base_case.items()
+ if key != 'link_name'}, False),
+ ({key: value for key, value in base_case.items()
+ if key != 'expiration_date'}, False),
+ ({key: value for key, value in base_case.items()
+ if key != 'download_limit'}, False),
+ ({key: value for key, value in base_case.items()
+ if key != 'send_email'}, False),
+ ({key: value for key, value in base_case.items()
+ if key != 'timezone_offset_minutes'}, False),
+ # For link_name
+ ({**base_case, 'link_name': '123' }, True),
+ ({**base_case, 'link_name': 123 }, False),
+ ({**base_case, 'link_name': 'a' * 256}, False),
+ # For expiration_date
+ ({**base_case, 'expiration_date': '2025-01-00'}, True),
+ ({**base_case, 'expiration_date': 20250101}, False),
+ # For download_limit
+ ({**base_case, 'download_limit': 1 }, True),
+ ({**base_case, 'download_limit': 0 }, False),
+ ({**base_case, 'download_limit': -1 }, False),
+ ({**base_case, 'download_limit': 1.1 }, False),
+ ({**base_case, 'download_limit': 'abc'}, False),
+ # For send_email
+ ({**base_case, 'send_email': False}, True),
+ ({**base_case, 'send_email': True }, True),
+ ({**base_case, 'send_email': None }, False),
+ # For timezone_offset_minutes
+ ({**base_case, 'timezone_offset_minutes': 0 }, True),
+ ({**base_case, 'timezone_offset_minutes': 720 }, True),
+ ({**base_case, 'timezone_offset_minutes': -720 }, True),
+ ({**base_case, 'timezone_offset_minutes': 800 }, False),
+ ({**base_case, 'timezone_offset_minutes': -800 }, False),
+ ({**base_case, 'timezone_offset_minutes': '100'}, False),
+ ]
+ for request_data, expected in test_cases:
+ assert validate_secret_url_generation_request(request_data) is expected
+
+ # if validate_expiration_date is False
+ mock_date.return_value = False
+ assert validate_secret_url_generation_request(base_case) is False
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_expiration_date -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_validate_expiration_date(app):
+ assert validate_expiration_date('1999-12-31', 0) is False
+
+ yesterday = (datetime.now() - timedelta(1)).strftime("%Y-%m-%d")
+ assert validate_expiration_date(yesterday, 0) is False
+
+ tomorrow = (datetime.now() + timedelta(1)).strftime("%Y-%m-%d")
+ with patch('weko_records_ui.utils.get_restricted_access') as mock_settings:
+ mock_settings.return_value = None
+ assert validate_expiration_date(tomorrow, 0) is False
+
+ in_a_week = (datetime.now() + timedelta(7)).strftime("%Y-%m-%d")
+ with patch('weko_records_ui.utils.get_restricted_access') as mock_settings:
+ mock_settings.return_value = {'secret_expiration_date': 1}
+ assert validate_expiration_date(in_a_week, 0) is False
+
+ in_an_year = (datetime.now() + timedelta(365)).strftime("%Y-%m-%d")
+ with patch('weko_records_ui.utils.get_restricted_access') as mock_settings:
+ mock_settings.return_value = {}
+ assert validate_expiration_date(in_an_year, 0) is False
+
+ invalid_date = '2025-01-00'
+ assert validate_expiration_date(invalid_date, 0) is False
+
+ assert validate_expiration_date(tomorrow, 0) is True
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_create_secret_url_record -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.utils.get_restricted_access')
+@patch('weko_records_ui.utils.current_user')
+def test_create_secret_url_record(mock_user, mock_settings, users):
+ mock_settings.return_value = {'expiration_date': 30, 'download_limit': 10}
+ mock_user.id = 1
+ record_id = 1
+ file_name = 'test.txt'
+
+ # Test request data
+ request = {'link_name': '', 'expiration_date': '', 'download_limit': None,
+ 'timezone_offset_minutes': 0}
+ url_obj = create_secret_url_record(record_id, file_name, request)
+ assert isinstance(url_obj, FileSecretDownload)
+ assert url_obj.creator_id == 1
+ assert url_obj.record_id == str(record_id)
+ assert url_obj.file_name == file_name
+ expected_name = 'test.txt_' + datetime.now(timezone.utc).strftime('%Y-%m-%d')
+ assert url_obj.label_name == expected_name
+ expected_date = datetime.combine((datetime.now(timezone.utc).date()+timedelta(days=31)), time(0, 0, 0))
+ assert url_obj.expiration_date == expected_date
+ assert url_obj.download_limit == 10
+
+ # If request is valid
+ request = {
+ 'link_name': 'test',
+ 'expiration_date': (datetime.now(timezone.utc).date()).strftime('%Y-%m-%d'),
+ 'download_limit': 5,
+ 'timezone_offset_minutes': 720
+ }
+ url_obj2 = create_secret_url_record(record_id, file_name, request)
+ assert url_obj2.creator_id == 1
+ assert url_obj2.record_id == str(record_id)
+ assert url_obj2.file_name == file_name
+ assert url_obj2.label_name == 'test'
+ expected_date2 = datetime.combine((datetime.now(timezone.utc).date()+timedelta(days=1)), time(12,0,0))
+ assert url_obj2.expiration_date == expected_date2
+ assert url_obj2.download_limit == 5
+ request = {'link_name': '',
+ 'expiration_date': '2022-10-10',
+ 'download_limit': '',
+ 'timezone_offset_minutes': 0}
+ with pytest.raises(ValueError):
+ create_secret_url_record(record_id, file_name, request)
+ request = {'link_name': '',
+ 'expiration_date': '',
+ 'download_limit': 0,
+ 'timezone_offset_minutes': 0}
+ with pytest.raises(ValueError):
+ create_secret_url_record(record_id, file_name, request)
+
+ # If settings is invalid
+ mock_settings.return_value = {}
+ assert create_secret_url_record(record_id, file_name, request) is None
+ mock_settings.return_value = 'invalid data'
+ assert create_secret_url_record(record_id, file_name, request) is None
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_create_onetime_download_record -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.utils.get_restricted_access')
+@patch('weko_records_ui.utils.current_user')
+def test_create_onetime_download_record(mock_user, mock_get, users):
+ mock_get.return_value = {'expiration_date': 30}
+ mock_user.id = 1
+ activity_id = 1
+ record_id = 1
+ file_name = 'test.txt'
+ user_mail = 'test@example.org'
+
+ assert FileOnetimeDownload.query.count() == 0
+ url_obj = create_onetime_url_record(
+ activity_id, record_id, file_name, user_mail)
+ assert FileOnetimeDownload.query.count() == 1
+ assert isinstance(url_obj, FileOnetimeDownload)
+ assert url_obj.approver_id == 1
+ assert url_obj.record_id == str(record_id)
+ assert url_obj.file_name == file_name
+ now = (dt.now(timezone.utc) + timedelta(days=31)).replace(tzinfo=None)
+ tolerance = timedelta(seconds=1)
+ assert now - url_obj.expiration_date <= tolerance
+ assert url_obj.download_limit == 10
+ assert url_obj.user_mail == user_mail
+ assert url_obj.is_guest is False
+
+ mock_get.return_value = {}
+ assert create_onetime_url_record(
+ activity_id, record_id, file_name, user_mail) is None
+ mock_get.return_value = 'invalid data'
+ assert create_onetime_url_record(
+ activity_id, record_id, file_name, user_mail) is None
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_create_download_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_create_download_url(app):
+ with patch('weko_records_ui.utils.base64.urlsafe_b64encode') as encoded:
+ encoded.return_value = b'test'
+ with app.test_request_context():
+ secret_obj = FileSecretDownload(
+ creator_id=1,
+ record_id=1,
+ file_name='test.txt',
+ label_name='test_url',
+ expiration_date=dt.now() + timedelta(days=30),
+ download_limit=10)
+ url = create_download_url(secret_obj)
+ assert url == (f'http://TEST_SERVER/record/1/file/secret/test.txt'
+ f'?token={b"test".decode()}')
+ with app.test_request_context():
+ onetime_obj = FileOnetimeDownload(
+ approver_id=1,
+ record_id=1,
+ file_name='test.txt',
+ expiration_date=dt.now() + timedelta(days=30),
+ download_limit=10,
+ user_mail='test@example.org',
+ is_guest=False,
+ extra_info={'activity_id': 1})
+ url = create_download_url(onetime_obj)
+ assert url == (f'http://TEST_SERVER/record/1/file/onetime/test.txt'
+ f'?token={b"test".decode()}')
+ with app.test_request_context():
+ invalid_obj = MagicMock()
+ url = create_download_url(invalid_obj)
+ assert url is None
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_generate_sha256_hash -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_generate_sha256_hash(app):
+ app.config['WEKO_RECORDS_UI_SECRET_KEY'] = 'secret'
+ secret_ubj = FileSecretDownload(
+ creator_id=1,
+ record_id=1,
+ file_name='test.txt',
+ label_name='test_url',
+ expiration_date=dt.now().date() + timedelta(days=30),
+ download_limit=10)
+ secret_url = generate_sha256_hash(secret_ubj)
+ assert len(secret_url) == 32
+ secret_obj2 = FileSecretDownload(
+ creator_id=2,
+ record_id=2,
+ file_name='test2.txt',
+ label_name='test_url2',
+ expiration_date=dt.now().date() + timedelta(days=10),
+ download_limit=5)
+ secret_url2 = generate_sha256_hash(secret_obj2)
+ assert len(secret_url2) == 32
+ assert secret_url != secret_url2
+ same_url = generate_sha256_hash(secret_ubj)
+ assert secret_url == same_url
+
+ onetime_obj = FileOnetimeDownload(
+ approver_id=1,
+ record_id=1,
+ file_name='test.txt',
+ expiration_date=dt.now().date() + timedelta(days=30),
+ download_limit=10,
+ user_mail='test@example.org',
+ is_guest=False,
+ extra_info={'activity_id': 1})
+ onetime_url = generate_sha256_hash(onetime_obj)
+ assert len(onetime_url) == 32
+ onetime_obj2 = FileOnetimeDownload(
+ approver_id=2,
+ record_id=2,
+ file_name='test2.txt',
+ expiration_date=dt.now().date() + timedelta(days=10),
+ download_limit=5,
+ user_mail='test2@example.org',
+ is_guest=True,
+ extra_info={'activity_id': 2})
+ onetime_url2 = generate_sha256_hash(onetime_obj2)
+ assert len(onetime_url2) == 32
+ assert onetime_url != onetime_url2
+ same_url = generate_sha256_hash(onetime_obj)
+ assert onetime_url == same_url
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_send_secret_url_mail -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.utils.UserProfile.get_by_userid')
+@patch('weko_records_ui.utils.current_user')
+@patch('weko_records_ui.utils.set_mail_info', return_value={})
+@patch('weko_records_ui.utils.process_send_mail', return_value=True)
+def test_send_secret_url_mail(mock_send, mock_set_info, mock_user,
+ mock_profile, app):
+ app.config['WEKO_RECORDS_UI_MAIL_TEMPLATE_SECRET_URL'] = 'test_template'
+ mock_profile_obj = MagicMock()
+ mock_profile_obj._displayname = 'test_user'
+ mock_profile.return_value = mock_profile_obj
+ mock_user.id = 1
+ mock_user.email = 'test@example.org'
+
+ uuid = 'test_uuid'
+ url_obj = FileSecretDownload(
+ creator_id=1,
+ record_id=1,
+ file_name='test.txt',
+ label_name='test_url',
+ expiration_date=datetime(2125, 1, 1, 0, 0),
+ download_limit=10)
+ item_title = 'test_title'
+ mock_user.id = 1
+ expected_info = {
+ 'restricted_download_link' : create_download_url(url_obj),
+ 'mail_recipient' : 'test@example.org',
+ 'file_name' : url_obj.file_name,
+ 'restricted_expiration_date': '2125-01-01 23:59:59(JST)',
+ 'restricted_download_count' : str(url_obj.download_limit),
+ 'restricted_fullname' : 'test_user',
+ 'restricted_data_name' : item_title,
+ }
+ expected_pattern = 'test_template'
+ with app.test_request_context():
+ assert send_secret_url_mail(uuid, url_obj, item_title) is True
+ mock_send.assert_called_once_with(expected_info, expected_pattern)
+ mock_send.reset_mock()
- # 66
- # onetime_download pattern
- assert parse_secret_download_token("MSB1c2VyQGV4YW1wbGUub3JnIDIwMjItMDktMjcgNDBDRkNGODFGM0FFRUI0Ng==") == ('', ('1', 'user@example.org', '2022-09-27', '40CFCF81F3AEEB46'))
+ mock_profile.return_value = None
+ with app.test_request_context():
+ assert send_secret_url_mail(uuid, url_obj, item_title) is True
+ expected_info['restricted_fullname'] = ''
+ mock_send.assert_called_once_with(expected_info, expected_pattern)
- # 67
- # secret_download pattern
- error , res = parse_secret_download_token("MSA1IDIwMjMtMDMtMDggMDA6NTI6MTkuNjI0NTUyIDZGQTdEMzIxQTk0OTU1MEQ=")
- assert error == 'Token is invalid.'
- assert res == ()
+ mock_send.return_value = False
+ with app.test_request_context():
+ assert send_secret_url_mail(uuid, url_obj, item_title) is False
-# def validate_secret_download_token(
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_secret_download_token -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_validate_secret_download_token(app):
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_token -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_validate_token(app, users):
with app.test_request_context():
- secret_download=FileSecretDownload(
- file_name= "eee.txt", record_id= '1',user_mail="repoadmin@example.org",expiration_date=999999,download_count=10
- )
- secret_download.created = datetime(2023,3,8,0,52,19,624552)
- secret_download.id = 5
- # 68
- res = validate_secret_download_token(secret_download=None , file_name= "eee.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("Token is invalid."))
-
- #69
- res = validate_secret_download_token(secret_download=secret_download , file_name= "aaa.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("Token is invalid."))
- res = validate_secret_download_token(secret_download=secret_download , file_name= "eee.txt", record_id= '5', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("Token is invalid."))
- res = validate_secret_download_token(secret_download=secret_download , file_name= "eee.txt", record_id= '1', id= '1', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("Token is invalid."))
- res = validate_secret_download_token(secret_download=secret_download , file_name= "eee.txt", record_id= '1', id= '5', date= '2099-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("Token is invalid."))
- res = validate_secret_download_token(secret_download=secret_download , file_name= "eee.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '7FA7D321A949550D')
- assert res == (False , _("Token is invalid."))
-
- # 70
- secret_download2=FileSecretDownload(
- file_name= "eee.txt", record_id= '5',user_mail="repoadmin@example.org",expiration_date=-1,download_count=10
- )
- secret_download2.created = datetime(2023,3,8,0,52,19,624552)
- secret_download2.id = 5
- res = validate_secret_download_token(secret_download=secret_download2 , file_name= "eee.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("The expiration date for download has been exceeded."))
-
- #71
- secret_download2.expiration_date = 99999999
- res = validate_secret_download_token(secret_download=secret_download2 , file_name= "eee.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (True ,"")
-
- # 72
- secret_download2.expiration_date = 9999999
- secret_download2.download_count = 0
- res = validate_secret_download_token(secret_download=secret_download2 , file_name= "eee.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("The download limit has been exceeded."))
-
- # 73
- res = validate_secret_download_token(secret_download=secret_download , file_name= "eee.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (True ,"")
-
- secret_download2.expiration_date = "hoge"
- res = validate_secret_download_token(secret_download=secret_download2 , file_name= "eee.txt", record_id= '1', id= '5', date= '2023-03-08 00:52:19.624552', token= '6FA7D321A949550D')
- assert res == (False , _("Token is invalid."))
-
-# def get_secret_download(file_name: str, record_id: str,
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_get_secret_download -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_get_secret_download(app ,db ):
+ secret_obj = FileSecretDownload.create(
+ creator_id=1,
+ record_id=1,
+ file_name='test.txt',
+ label_name='test_url',
+ expiration_date=dt.now(timezone.utc) + timedelta(days=30),
+ download_limit=10)
+ url = create_download_url(secret_obj)
+ match = re.search(r'[?&]token=([^&]+)', url)
+ secret_token = match.group(1)
+ assert validate_token(secret_token, is_secret_url=True) is True
with app.test_request_context():
- with db.session.begin_nested():
- secret_download=FileSecretDownload(
- file_name= "eee.txt", record_id= '1',user_mail="repoadmin@example.org",expiration_date=999999,download_count=10
- )
- db.session.add(secret_download)
-
+ onetime_obj = FileOnetimeDownload.create(
+ approver_id=1,
+ record_id=1,
+ file_name='test.txt',
+ expiration_date=dt.now(timezone.utc) + timedelta(days=30),
+ download_limit=10,
+ user_mail='test@example.org',
+ is_guest=False,
+ extra_info={'activity_id': 1})
+ url = create_download_url(onetime_obj)
+ match = re.search(r'[?&]token=([^&]+)', url)
+ onetime_token = match.group(1)
+ assert validate_token(onetime_token, is_secret_url=False) is True
+ invalid_bytes = b'\xb2q\xff\x19\xaf\xfc\xc6T\x8bt\xd6\xf6\xc6 \
+ \x08D\xe7\xf3G;cN\x1bn|\xa2\x88\x01v\xed\x1cA_1'
+ with app.test_request_context():
+ secret_token = base64.urlsafe_b64decode(secret_token.encode())
+ assert secret_token.split(b'_')[-1] == invalid_bytes.split(b'_')[-1]
+ invalid_token = base64.urlsafe_b64encode(invalid_bytes).decode()
+ assert validate_token(invalid_token, is_secret_url=True) is False
+ with app.test_request_context():
+ onetime_token = base64.urlsafe_b64decode(onetime_token.encode())
+ assert onetime_token.split(b'_')[-1] == invalid_bytes.split(b'_')[-1]
+ invalid_token = base64.urlsafe_b64encode(invalid_bytes).decode()
+ assert validate_token(invalid_token, is_secret_url=False) is False
+ with app.test_request_context():
+ assert validate_token('', is_secret_url=True) is False
+ assert validate_token(123, is_secret_url=True) is False
-
- assert get_secret_download(file_name= secret_download.file_name
- , record_id= secret_download.record_id
- , id= secret_download.id
- , created =secret_download.created)
-
- assert not get_secret_download(file_name= secret_download.file_name
- , record_id= secret_download.record_id
- , id= secret_download.id + 1
- , created =secret_download.created)
-# def update_secret_download(**kwargs) -> Optional[List[FileSecretDownload]]:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_get_data_usage_application_data -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_get_data_usage_application_data(app ,db):
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_convert_token_into_obj -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.utils.validate_token')
+def test_convert_token_into_obj(vldt_token, app, users):
+ vldt_token.return_value = True
+ created_at = dt.now(timezone.utc)
with app.test_request_context():
- with db.session.begin_nested():
- secret_download=FileSecretDownload(
- file_name= "eee.txt", record_id= '1',user_mail="repoadmin@example.org",expiration_date=999999,download_count=10
- )
- db.session.add(secret_download)
- update_data = dict(
- file_name = secret_download.file_name
- , record_id = secret_download.record_id
- , download_count = 100
- , created = secret_download.created
- , id = secret_download.id
- )
- res = update_secret_download(**update_data)
- assert len(res) == 1
- assert res[0].download_count == 100
+ secret_obj = FileSecretDownload.create(
+ creator_id=1,
+ record_id=1,
+ file_name='test.txt',
+ label_name='test_url',
+ expiration_date=created_at + timedelta(days=30),
+ download_limit=10)
+ assert FileSecretDownload.query.count() == 1
+ url = create_download_url(secret_obj)
+ match = re.search(r'[?&]token=([^&]+)', url)
+ secret_token = match.group(1)
+ secret_obj = convert_token_into_obj(secret_token, is_secret_url=True)
+ assert isinstance(secret_obj, FileSecretDownload)
+ assert secret_obj.id == 1
+ assert secret_obj.creator_id == 1
+ assert secret_obj.record_id == '1'
+ assert secret_obj.file_name == 'test.txt'
+ assert secret_obj.label_name == 'test_url'
+ expected_date = (created_at + timedelta(days=30)).replace(tzinfo=None)
+ assert secret_obj.expiration_date == expected_date
+ assert secret_obj.download_limit == 10
+ vldt_token.assert_called_once_with(secret_token, True)
+ vldt_token.reset_mock()
+ with app.test_request_context():
+ onetime_obj = FileOnetimeDownload.create(
+ approver_id=1,
+ record_id=1,
+ file_name='test.txt',
+ expiration_date=created_at + timedelta(days=30),
+ download_limit=10,
+ user_mail='test@example.org',
+ is_guest=False,
+ extra_info={'activity_id': 1})
+ assert FileOnetimeDownload.query.count() == 1
+ url = create_download_url(onetime_obj)
+ match = re.search(r'[?&]token=([^&]+)', url)
+ onetime_token = match.group(1)
+ onetime_obj = convert_token_into_obj(onetime_token, is_secret_url=False)
+ assert isinstance(onetime_obj, FileOnetimeDownload)
+ assert onetime_obj.id == 1
+ assert onetime_obj.approver_id == 1
+ assert onetime_obj.record_id == '1'
+ assert onetime_obj.file_name == 'test.txt'
+ expected_date = (created_at + timedelta(days=30)).replace(tzinfo=None)
+ assert onetime_obj.expiration_date == expected_date
+ assert onetime_obj.download_limit == 10
+ assert onetime_obj.is_guest == False
+ assert onetime_obj.extra_info == {'activity_id': 1}
+ vldt_token.assert_called_once_with(onetime_token, False)
+ vldt_token.return_value = False
+ with app.test_request_context():
+ assert convert_token_into_obj(secret_token, True) is None
+ assert convert_token_into_obj(onetime_token, False) is None
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_url_download -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.utils.validate_token')
+@patch('weko_records_ui.utils.is_secret_url_feature_enabled')
+@patch('weko_records_ui.utils.validate_file_access')
+@patch('weko_records_ui.utils.validate_download_record')
+def test_validate_url_download(vldt_record, vldt_file, is_enabled, vldt_token,
+ app, db, users):
+ with app.test_request_context():
+ secret_obj = FileSecretDownload.create(
+ creator_id=1,
+ record_id=1,
+ file_name='test.txt',
+ label_name='test_url',
+ expiration_date=dt.now(timezone.utc) + timedelta(days=30),
+ download_limit=10)
+ db.session.flush()
+ match = re.search(r'[?&]token=([^&]+)', create_download_url(secret_obj))
+ secret_token = match.group(1)
+ vldt_token.return_value = True
+ is_enabled.return_value = True
+ vldt_file.return_value = True
+ vldt_record.return_value = True
+ assert validate_url_download('', '', secret_token, True) == (True, '')
+
+ with app.test_request_context():
+ onetime_obj = FileOnetimeDownload.create(
+ approver_id=1,
+ record_id=1,
+ file_name='test.txt',
+ expiration_date=dt.now(timezone.utc) + timedelta(days=30),
+ download_limit=10,
+ user_mail='test@example.org',
+ is_guest=False,
+ extra_info={'activity_id': 1})
+ db.session.flush()
+ match = re.search(r'[?&]token=([^&]+)', create_download_url(onetime_obj))
+ onetime_token = match.group(1)
+ assert validate_url_download('', '', onetime_token, False) == (True, '')
+
+ with patch('weko_records_ui.utils.validate_token',
+ return_value=False):
+ assert validate_url_download('', '', secret_token, True) == (
+ False, 'The provided token is invalid.')
+ with patch('weko_records_ui.utils.is_secret_url_feature_enabled',
+ return_value=False):
+ assert validate_url_download('', '', secret_token, True) == (
+ False, 'This feature is currently disabled.')
+ with patch('weko_records_ui.utils.validate_file_access',
+ return_value=False):
+ assert validate_url_download('', '', secret_token, True) == (
+ False, 'This file is currently not available for this feature.')
+ with patch('weko_records_ui.utils.validate_download_record',
+ return_value=False):
+ assert validate_url_download('', '', secret_token, True) == (
+ False, 'This file is currently not available for this feature.')
+
+ secret_obj.is_deleted = True
+ db.session.commit()
+ assert validate_url_download('', '', secret_token, True) == (
+ False, 'This URL has been deactivated.')
+ secret_obj.is_deleted = False
+ secret_obj.download_count = 10
+ db.session.commit()
+ assert validate_url_download('', '', secret_token, True) == (
+ False, 'The download limit has been exceeded.')
+ secret_obj.download_count = 0
+ db.session.commit()
+ with patch('weko_records_ui.utils.dt') as mock_dt:
+ mock_dt.now.return_value = dt.now(timezone.utc) + timedelta(days=31)
+ assert validate_url_download('', '', secret_token, True) == (
+ False, 'The expiration date for download has been exceeded.')
+
+ onetime_obj.is_deleted = True
+ db.session.commit()
+ assert validate_url_download('', '', onetime_token, False) == (
+ False, 'This URL has been deactivated.')
+ onetime_obj.is_deleted = False
+ onetime_obj.download_count = 10
+ db.session.commit()
+ assert validate_url_download('', '', onetime_token, False) == (
+ False, 'The download limit has been exceeded.')
+ onetime_obj.download_count = 0
+ db.session.commit()
+ with patch('weko_records_ui.utils.dt') as mock_dt:
+ mock_dt.now.return_value = dt.now(timezone.utc) + timedelta(days=31)
+ assert validate_url_download('', '', onetime_token, False) == (
+ False, 'The expiration date for download has been exceeded.')
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_validate_file_access -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_validate_file_access():
+ with patch('weko_records_ui.utils.is_secret_file', return_value=True):
+ assert validate_file_access('', '', is_secret_url=True) is True
+ with patch('weko_records_ui.utils.is_secret_file', return_value=False):
+ assert validate_file_access('', '', is_secret_url=True) is False
+ with patch('weko_records_ui.utils.is_onetime_file', return_value=True):
+ assert validate_file_access('', '', is_secret_url=False) is True
+ with patch('weko_records_ui.utils.is_onetime_file', return_value=False):
+ assert validate_file_access('', '', is_secret_url=False) is False
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_save_download_log -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.utils.request')
+def test_save_download_log(request, secret_url, onetime_url):
+ file_name = 'test.txt'
+ record = MagicMock()
+ request.remote_addr = '192.168.56.1'
+ secret_token = secret_url['secret_token']
+
+ # When accessrole is open_no
+ record.get_file_data.return_value = [
+ {'filename': 'other_file', 'accessrole': 'open_yes'},
+ {'filename': file_name, 'accessrole': 'open_no'}
+ ]
+ open_no_dl = save_download_log(
+ record, file_name, secret_token, is_secret_url=True)
+ assert isinstance(open_no_dl, FileUrlDownloadLog)
+ assert open_no_dl.url_type is UrlType.SECRET
+ assert open_no_dl.secret_url_id == 1
+ assert open_no_dl.onetime_url_id is None
+ assert open_no_dl.ip_address == '192.168.56.1'
+ assert open_no_dl.access_status is AccessStatus.OPEN_NO
+ assert open_no_dl.used_token == secret_token
+
+ # When accessrole is open_date
+ record.get_file_data.return_value = [
+ {'filename': file_name, 'accessrole': 'open_date'}
+ ]
+ open_date_dl = save_download_log(
+ record, file_name, secret_token, is_secret_url=True)
+ assert isinstance(open_date_dl, FileUrlDownloadLog)
+ assert open_date_dl.url_type is UrlType.SECRET
+ assert open_date_dl.secret_url_id == 1
+ assert open_date_dl.onetime_url_id is None
+ assert open_date_dl.ip_address == '192.168.56.1'
+ assert open_date_dl.access_status is AccessStatus.OPEN_DATE
+ assert open_date_dl.used_token == secret_token
+
+ # When accessrole is open_restricted
+ onetime_token = onetime_url['onetime_token']
+ open_restricted = save_download_log(
+ record, file_name, onetime_token, is_secret_url=False)
+ assert isinstance(open_restricted, FileUrlDownloadLog)
+ assert open_restricted.url_type is UrlType.ONETIME
+ assert open_restricted.secret_url_id is None
+ assert open_restricted.onetime_url_id == 1
+ assert open_restricted.ip_address is None
+ assert open_restricted.access_status is AccessStatus.OPEN_RESTRICTED
+ assert open_restricted.used_token == onetime_token
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_utils.py::test_RoCrateConverter_convert -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
@@ -1034,3 +1585,4 @@ def test_create_tsv(app, records):
res_tsv = create_tsv(record.files)
for field in WEKO_RECORDS_UI_TSV_FIELD_NAMES_DEFAULT:
assert field in res_tsv.getvalue()
+
diff --git a/modules/weko-records-ui/tests/test_views.py b/modules/weko-records-ui/tests/test_views.py
index e51f6488a6..3d463e2ba3 100644
--- a/modules/weko-records-ui/tests/test_views.py
+++ b/modules/weko-records-ui/tests/test_views.py
@@ -1,8 +1,9 @@
+from datetime import datetime, timedelta, timezone
from unittest.mock import MagicMock
import uuid
import pytest
import io
-from flask import Flask, json, jsonify, session, url_for ,make_response
+from flask import Flask, json, jsonify, session, url_for ,make_response, current_app
from flask_security.utils import login_user
from invenio_accounts.testutils import login_user_via_session
from invenio_files_rest.models import ObjectVersion
@@ -22,9 +23,10 @@
FlowDefine,
WorkFlow,
)
-from weko_records_ui.models import PDFCoverPageSettings, FilePermission
+from weko_records_ui.models import (
+ FileOnetimeDownload, FileSecretDownload, PDFCoverPageSettings,
+ FilePermission)
from weko_records_ui.views import (
- _get_show_secret_url_button,
check_permission,
citation,
escape_newline,
@@ -53,7 +55,7 @@
preview_able,
get_uri,
)
-
+from weko_records_ui.utils import create_download_url
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
# def record_from_pid(pid_value):
@@ -446,7 +448,7 @@ def test_get_workflow_detail(app,workflows):
# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test_default_view_method -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
# """Display default view.
# def _get_rights_title(result, rights_key, rights_values, current_lang, meta_options):
-def test_default_view_method(app, records, itemtypes, indexstyle ,users):
+def test_default_view_method(app, records, itemtypes, indexstyle, users):
indexer, results = records
record = results[0]["record"]
recid = results[0]["recid"]
@@ -456,16 +458,41 @@ def test_default_view_method(app, records, itemtypes, indexstyle ,users):
with patch("weko_records_ui.views.get_index_link_list", return_value=[]):
with patch("weko_records_ui.views.render_template", return_value=make_response()):
assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
- # # need to fix
- # with pytest.raises(Exception) as e:
- # res = default_view_method(recid, record, 'helloworld.pdf')
- # assert e.type==TemplatesNotFound
- default_view_method(recid, record )
- with pytest.raises(NotFound) : #404
- default_view_method(recid, record ,'notfound.pdf')
- with pytest.raises(NotFound) : #404
- default_view_method(recid, record ,'[No FileName]')
+ #メソッド_get_show_secret_url_buttonからcan_manage_secret_urlに変更に伴うケース追加: show_secret_URLのテスト
+ with patch('weko_records_ui.views.can_manage_secret_url', return_value=True):
+ response = default_view_method(recid, record, 'helloworld.pdf')
+ assert response.status_code == 200
+ # show_secret_URLがTrueの場合の動作確認
+ with patch('weko_records_ui.views.render_template') as mock_render_template:
+ default_view_method(recid, record, 'helloworld.pdf')
+ args, kwargs = mock_render_template.call_args
+ assert kwargs['show_secret_URL'] is True
+
+ with patch('weko_records_ui.views.can_manage_secret_url', return_value=False):
+ response = default_view_method(recid, record, 'helloworld.pdf')
+ assert response.status_code == 200
+ # show_secret_URLがFalseの場合の動作確認
+ with patch('weko_records_ui.views.render_template') as mock_render_template:
+ default_view_method(recid, record, 'helloworld.pdf')
+ args, kwargs = mock_render_template.call_args
+ assert kwargs['show_secret_URL'] is False
+
+ with patch('weko_records_ui.views.can_manage_secret_url', return_value=None):
+ response = default_view_method(recid, record, 'helloworld.pdf')
+ assert response.status_code == 200
+ # show_secret_URLがNoneの場合の動作確認
+ with patch('weko_records_ui.views.render_template') as mock_render_template:
+ default_view_method(recid, record, 'helloworld.pdf')
+ args, kwargs = mock_render_template.call_args
+ assert kwargs['show_secret_URL'] is None
+
+ # 既存のテストケース
+ default_view_method(recid, record)
+ with pytest.raises(NotFound): # 404
+ default_view_method(recid, record, 'notfound.pdf')
+ with pytest.raises(NotFound): # 404
+ default_view_method(recid, record, '[No FileName]')
def cannnot():
return False
@@ -473,38 +500,35 @@ def cannnot():
file_permission_factory.can = cannnot
with patch('weko_records_ui.views.file_permission_factory', return_value=file_permission_factory):
with patch('weko_records_ui.views._redirect_method', return_value="redirect"):
- assert default_view_method(recid, record ,'helloworld.pdf') == "redirect"
+ assert default_view_method(recid, record, 'helloworld.pdf') == "redirect"
with patch("flask_login.utils._get_user", return_value=users[3]["obj"]):
- with pytest.raises(Forbidden) : #404
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
- with patch('weko_records_ui.views.AdminSettings.get'
- , side_effect=lambda name , dict_to_object : {'display_stats' : False} if name == 'display_stats_settings' else None):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
- with patch('weko_records_ui.views.AdminSettings.get'
- , side_effect=lambda name , dict_to_object : {'items_search_author' : "author"} if name == 'items_display_settings' else None):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
- with patch('weko_search_ui.utils.get_data_by_property', return_value=(False,False)):
- with patch('weko_records_ui.views.selected_value_by_language' ,return_value="helloworld.pdf"):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
+ with pytest.raises(Forbidden): # 404
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+ with patch('weko_records_ui.views.AdminSettings.get',
+ side_effect=lambda name, dict_to_object: {'display_stats': False} if name == 'display_stats_settings' else None):
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+ with patch('weko_records_ui.views.AdminSettings.get',
+ side_effect=lambda name, dict_to_object: {'items_search_author': "author"} if name == 'items_display_settings' else None):
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+ with patch('weko_search_ui.utils.get_data_by_property', return_value=(False, False)):
+ with patch('weko_records_ui.views.selected_value_by_language', return_value="helloworld.pdf"):
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
with patch('weko_records_ui.views.get_record_permalink', return_value=False):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
-
- record.update(
- {'system_identifier_doi' :
- {"attribute_value_mlt" :[{'subitem_systemidt_identifier':"permalink_uri"}]}})
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+ record.update(
+ {'system_identifier_doi':
+ {"attribute_value_mlt": [{'subitem_systemidt_identifier': "permalink_uri"}]}})
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
def side_effect(arg):
values = ['a', 'b']
return values[arg]
- # with patch('weko_search_ui.utils.get_sub_item_value', side_effect=side_effect):
- # default_view_method(recid, record ,'helloworld.pdf')
pid_ver = MagicMock
pid_ver.exists = False
- with patch('weko_records_ui.views.PIDVersioning',return_value=pid_ver):
- with pytest.raises(NotFound) : #404
- assert default_view_method(recid, record ,'helloworld.pdf')
+ with patch('weko_records_ui.views.PIDVersioning', return_value=pid_ver):
+ with pytest.raises(NotFound): # 404
+ assert default_view_method(recid, record, 'helloworld.pdf')
pid_ver = MagicMock
pid_ver.exists = True
@@ -512,22 +536,257 @@ def side_effect(arg):
mock = MagicMock
mock.object_uuid = uuid.uuid4()
pid_ver.children = [mock]
- pid_ver.get_children = lambda ordered,pid_status : [mock]
- with patch('weko_records_ui.views.PIDVersioning',return_value=pid_ver):
- with patch('weko_records_ui.views.WekoRecord.get_record',return_value={'_deposit':{'status':'draft'}}):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
-
- with patch('weko_records_ui.views.WekoRecord.get_record',side_effect=Exception):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
- with patch('weko_records_ui.views.ItemLink.get_item_link_info',return_value={"relation":"res"}):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
-
+ pid_ver.get_children = lambda ordered, pid_status: [mock]
+ with patch('weko_records_ui.views.PIDVersioning', return_value=pid_ver):
+ with patch('weko_records_ui.views.WekoRecord.get_record', return_value={'_deposit': {'status': 'draft'}}):
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+
+ with patch('weko_records_ui.views.WekoRecord.get_record', side_effect=Exception):
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+ with patch('weko_records_ui.views.ItemLink.get_item_link_info', return_value={"relation": "res"}):
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+
index = MagicMock()
index.index_name = ""
- index.index_name_english ="index"
- with patch('weko_records_ui.views.Indexes.get_index',return_value=index):
- assert default_view_method(recid, record ,'helloworld.pdf').status_code == 200
-
+ index.index_name_english = "index"
+ with patch('weko_records_ui.views.Indexes.get_index', return_value=index):
+ assert default_view_method(recid, record, 'helloworld.pdf').status_code == 200
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test_create_secret_url_and_send_mail -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+@patch('weko_records_ui.views.validate_secret_url_generation_request')
+@patch('weko_records_ui.views.can_manage_secret_url')
+@patch('weko_records_ui.utils.current_user')
+@patch('weko_records_ui.views.send_secret_url_mail')
+def test_create_secret_url_and_send_mail(send_mail, login_user, can_manage,
+ vldt_req, client, users, records):
+ vldt_req.return_value = True
+ can_manage.return_value = True
+ login_user.id = 1
+ tmp, results = records
+ url = url_for('invenio_records_ui.recid_secret_url',
+ pid_value=results[1]["recid"].pid_value,
+ filename=results[1]["filename"])
+ base_data = {
+ 'link_name': '',
+ 'expiration_date': '',
+ 'download_limit': None,
+ 'send_email': False,
+ 'timezone_offset_minutes': 0
+ }
+
+ # Success
+ res = client.post(url, data=json.dumps(base_data),
+ content_type='application/json')
+ assert res.status_code == 200
+ assert 'Secret URL generated successfully' in res.get_data(as_text=True)
+ send_mail.return_value = True
+ data = {**base_data, 'send_email': True}
+ res = client.post(url, data=json.dumps(data),
+ content_type='application/json')
+ assert res.status_code == 200
+ assert 'Secret URL generated successfully' in res.get_data(as_text=True)
+ assert 'please check your email inbox' in res.get_data(as_text=True)
+ send_mail.return_value = False
+ res = client.post(url, data=json.dumps(data),
+ content_type='application/json')
+ assert res.status_code == 200
+ assert 'Secret URL generated successfully' in res.get_data(as_text=True)
+ assert 'there was an error' in res.get_data(as_text=True)
+
+ # Fail
+ with patch('weko_records_ui.views.create_secret_url_record',
+ side_effect=Exception('Test DB Error')):
+ with pytest.raises(Exception):
+ res = client.post(url, data=json.dumps(data),
+ content_type='application/json')
+ assert res.status_code == 500
+ can_manage.return_value = False
+ with pytest.raises(Exception):
+ res = client.post(url, data=json.dumps(data),
+ content_type='application/json')
+ assert res.status_code == 403
+ vldt_req.return_value = False
+ res = client.post(url, data=json.dumps(data),
+ content_type='application/json')
+ assert res.status_code == 400
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test_copy_secret_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_copy_secret_url(client, records):
+ _, records = records
+ url = url_for('invenio_records_ui.recid_copy_secret_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ secret_url_id=1)
+ secret_obj = FileSecretDownload.create(
+ creator_id=1,
+ record_id=records[1]['recid'].pid_value,
+ file_name=records[1]['filename'],
+ label_name='test link',
+ expiration_date=datetime.now(timezone.utc) + timedelta(days=1),
+ download_limit=1,
+ )
+ expected_secret_url = create_download_url(secret_obj)
+ with patch('weko_records_ui.views.can_manage_secret_url',
+ return_value=True):
+ res = client.get(url)
+ assert res.status_code == 200
+ assert ('The secret URL copied to your clipboard.'
+ in res.get_data(as_text=True))
+ assert res.json['url'] == expected_secret_url
+ with patch('weko_records_ui.views.can_manage_secret_url',
+ return_value=False):
+ with pytest.raises(Exception):
+ res = client.get(url)
+ assert res.status_code == 403
+ with patch('weko_records_ui.views.create_download_url',
+ side_effect=Exception('Test Error')):
+ with pytest.raises(Exception):
+ res = client.get(url)
+ assert res.status_code == 500
+ with patch('weko_records_ui.views.can_manage_secret_url',
+ return_value=True):
+ url = url_for('invenio_records_ui.recid_copy_secret_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ secret_url_id=99) # invalid secret_url_id
+ res = client.get(url)
+ assert res.json['url'] is None
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test_copy_onetime_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_copy_onetime_url(client, records):
+ _, records = records
+ url = url_for('invenio_records_ui.recid_copy_onetime_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ onetime_url_id=1)
+ onetime_obj = FileOnetimeDownload.create(
+ approver_id=1,
+ record_id=records[1]['recid'].pid_value,
+ file_name=records[1]['filename'],
+ expiration_date=datetime.now(timezone.utc) + timedelta(days=1),
+ download_limit=1,
+ user_mail='test@example.org',
+ is_guest=False,
+ extra_info={}
+ )
+ expected_onetime_url = create_download_url(onetime_obj)
+ with patch('weko_records_ui.views.can_manage_onetime_url',
+ return_value=True):
+ res = client.get(url)
+ assert res.status_code == 200
+ assert ('The onetime URL copied to your clipboard.'
+ in res.get_data(as_text=True))
+ assert res.json['url'] == expected_onetime_url
+ with patch('weko_records_ui.views.can_manage_onetime_url',
+ return_value=False):
+ with pytest.raises(Exception):
+ res = client.get(url)
+ assert res.status_code == 403
+ with patch('weko_records_ui.views.create_download_url',
+ side_effect=Exception('Test Error')):
+ with pytest.raises(Exception):
+ res = client.get(url)
+ assert res.status_code == 500
+ with patch('weko_records_ui.views.can_manage_onetime_url',
+ return_value=True):
+ url = url_for('invenio_records_ui.recid_copy_onetime_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ onetime_url_id=99) # invalid onetime_url_id
+ res = client.get(url)
+ assert res.json['url'] is None
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test_delete_secret_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_delete_secret_url(client, records):
+ _, records = records
+ url = url_for('invenio_records_ui.recid_delete_secret_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ secret_url_id=1)
+ secret_obj = FileSecretDownload.create(
+ creator_id=1,
+ record_id=records[1]['recid'].pid_value,
+ file_name=records[1]['filename'],
+ label_name='test link',
+ expiration_date=datetime.now(timezone.utc) + timedelta(days=1),
+ download_limit=1,
+ )
+ assert secret_obj.is_deleted == False
+ with patch('weko_records_ui.views.can_manage_secret_url',
+ return_value=True):
+ res = client.delete(url)
+ assert res.status_code == 200
+ assert ('The secret URL has been successfully deleted.'
+ in res.get_data(as_text=True))
+ assert secret_obj.is_deleted == True
+ with patch('weko_records_ui.views.can_manage_secret_url',
+ return_value=False):
+ with pytest.raises(Exception):
+ res = client.delete(url)
+ assert res.status_code == 403
+ with patch('weko_records_ui.models.FileSecretDownload.delete_logically',
+ side_effect=Exception('Test Error')):
+ with pytest.raises(Exception):
+ res = client.delete(url)
+ assert res.status_code == 500
+ with patch('weko_records_ui.views.can_manage_secret_url',
+ return_value=True):
+ url = url_for('invenio_records_ui.recid_delete_secret_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ secret_url_id=99) # invalid secret_url_id
+ with pytest.raises(Exception):
+ res = client.delete(url)
+ assert res.status_code == 404
+
+
+# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test_delete_onetime_url -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
+def test_delete_onetime_url(client, records):
+ _, records = records
+ url = url_for('invenio_records_ui.recid_delete_onetime_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ onetime_url_id=1)
+ onetime_obj = FileOnetimeDownload.create(
+ approver_id=1,
+ record_id=records[1]['recid'].pid_value,
+ file_name=records[1]['filename'],
+ expiration_date=datetime.now(timezone.utc) + timedelta(days=1),
+ download_limit=1,
+ user_mail='test@example.org',
+ is_guest=False,
+ extra_info={}
+ )
+ assert onetime_obj.is_deleted == False
+ with patch('weko_records_ui.views.can_manage_onetime_url',
+ return_value=True):
+ res = client.delete(url)
+ assert res.status_code == 200
+ assert ('The one-time URL has been successfully deleted.'
+ in res.get_data(as_text=True))
+ assert onetime_obj.is_deleted == True
+ with patch('weko_records_ui.views.can_manage_onetime_url',
+ return_value=False):
+ with pytest.raises(Exception):
+ res = client.delete(url)
+ assert res.status_code == 403
+ with patch('weko_records_ui.models.FileOnetimeDownload.delete_logically',
+ side_effect=Exception('Test Error')):
+ with pytest.raises(Exception):
+ res = client.delete(url)
+ assert res.status_code == 500
+ with patch('weko_records_ui.views.can_manage_onetime_url',
+ return_value=True):
+ url = url_for('invenio_records_ui.recid_delete_onetime_url',
+ pid_value=records[1]['recid'].pid_value,
+ filename=records[1]['filename'],
+ onetime_url_id=99)
+ with pytest.raises(Exception):
+ res = client.delete(url)
+ assert res.status_code == 404
# def doi_ish_view_method(parent_pid_value=0, version=0):
@@ -968,135 +1227,3 @@ def test_default_view_method_fix35133(app, records, itemtypes, indexstyle,mocker
{'name': 'citation_abstract_html_url','data': 'http://TEST_SERVER/records/1'},
]
assert kwargs["google_dataset_meta"] == '{"@context": "https://schema.org/", "@type": "Dataset", "citation": ["http://hdl.handle.net/2261/0002005680", "https://repository.dl.itc.u-tokyo.ac.jp/records/2005680"], "creator": [{"@type": "Person", "alternateName": "creator alternative name", "familyName": "creator family name", "givenName": "creator given name", "identifier": "123", "name": "creator name"}], "description": "『史料編纂掛備用寫眞畫像圖畫類目録』(1905年)の「画像」(肖像画模本)の部に著録する資料の架番号の新旧対照表。史料編纂所所蔵肖像画模本データベースおよび『目録』版面画像へのリンク付き。『画像史料解析センター通信』98(2022年10月)に解説記事あり。", "distribution": [{"@type": "DataDownload", "contentUrl": "https://repository.dl.itc.u-tokyo.ac.jp/record/2005680/files/comparison_table_of_preparation_image_catalog.xlsx", "encodingFormat": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, {"@type": "DataDownload", "contentUrl": "https://raw.githubusercontent.com/RCOSDP/JDCat-base/main/apt.txt", "encodingFormat": "text/plain"}, {"@type": "DataDownload", "contentUrl": "https://raw.githubusercontent.com/RCOSDP/JDCat-base/main/environment.yml", "encodingFormat": "application/x-yaml"}, {"@type": "DataDownload", "contentUrl": "https://raw.githubusercontent.com/RCOSDP/JDCat-base/main/postBuild", "encodingFormat": "text/x-shellscript"}], "includedInDataCatalog": {"@type": "DataCatalog", "name": "https://localhost"}, "license": ["CC BY"], "name": "『史料編纂掛備用写真画像図画類目録』画像の部:新旧架番号対照表", "spatialCoverage": [{"@type": "Place", "geo": {"@type": "GeoCoordinates", "latitude": "point latitude test", "longitude": "point longitude test"}}, {"@type": "Place", "geo": {"@type": "GeoShape", "box": "1 3 2 4"}}, "geo location place test"]}'
-# def create_secret_url_and_send_mail(pid:PersistentIdentifier, record:WekoRecord, filename:str, **kwargs) -> str:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test_create_secret_url_and_send_mail -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-def test_create_secret_url_and_send_mail(app,client,db,users,records):
- app.config['WEKO_WORKFLOW_DATE_FORMAT'] = "%Y-%m-%d"
- indexer, results = records
- record = results[1]
-
- # 79
- id = 1 #repoadmin
- secret_file_url = url_for("invenio_records_ui.recid_secret_url"
- ,pid_value=results[1]["recid"].pid_value
- ,filename=results[1]["filename"])
- login_user_via_session(client=client, user=users[id]["obj"] ,email=users[id]["email"])
- with patch('weko_records_ui.views._get_show_secret_url_button',return_value = True):
- with patch('weko_records_ui.views.process_send_mail',return_value = True):
- # with app.test_request_context():
- res = client.get(secret_file_url)
- assert res.status_code == 405
-
- res = client.post(secret_file_url ,data=json.dumps({}), content_type='application/json')
- assert res.status_code == 200
- with patch('weko_records_ui.views.process_send_mail',return_value = False):
- with patch("flask.templating._render", return_value=""):
- res = client.post(secret_file_url ,data=json.dumps({}), content_type='application/json')
- assert res.status_code == 500
- with patch('weko_records_ui.views._get_show_secret_url_button',return_value = False):
- with patch('weko_records_ui.views.process_send_mail',return_value = True):
- with patch("flask.templating._render", return_value=""):
- res = client.post(secret_file_url ,data=json.dumps({}), content_type='application/json')
- assert res.status_code == 403
-
-# def create_secret_url_and_send_mail(pid:PersistentIdentifier, record:WekoRecord, filename:str, **kwargs) -> str:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test__get_show_secret_url_button -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-@pytest.mark.parametrize(
- "id, is_show",
- [
- (0, False), #contributor
- (1, False), #repoadmin
- (2, False), #sysadmin
- (3, False), #comadmin
- (4, False), #generaluser
- (5, False), #originalroleuser (owner)
- (6, False), #originalroleuser2 (repoadmin)
- (7, False), #user (weko_shared owner)
- ],
-)
-def test__get_show_secret_url_button(users,records,id ,is_show):
- indexer, results = records
- # 80
- i = 0
- role = ["open_access" , "open_no" ,"open_date"]
- for record in results:
- record["record"]['owner'] = users[5]["id"]
- record["record"]['weko_shared_id'] = users[7]["id"]
- file_data = record["record"].get_file_data()
- if len(file_data) > 0:
- file_data[0].update({'accessrole':role[i%3]})
- file_data[0].update({'date':[{"dateValue" :'2999-12-31'}]})
- i = i + 1
-
- with patch("flask_login.utils._get_user", return_value=users[id]["obj"]):
- res = []
- for record in results:
- if 'filename' in record:
- res.append( _get_show_secret_url_button(record["record"] , record["filename"]) )
-
- assert not res[0]
- assert res[1] == is_show
- assert res[2] == is_show
-
-# def create_secret_url_and_send_mail(pid:PersistentIdentifier, record:WekoRecord, filename:str, **kwargs) -> str:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test__get_show_secret_url_button2 -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-@pytest.mark.parametrize(
- "id, is_show",
- [
- (1, True), #repoadmin
- ],
-)
-def test__get_show_secret_url_button2(users,records ,id,is_show):
- indexer, results = records
- # 80
- # pattern of not db_restricted_access_secret
- i = 0
- role = ["open_access" , "open_no" ,"open_date"]
- for record in results:
- record["record"]['owner'] = users[5]["id"]
- record["record"]['weko_shared_id'] = users[7]["id"]
- file_data = record["record"].get_file_data()
- if len(file_data) > 0:
- file_data[0].update({'accessrole':role[i%3]})
- file_data[0].update({'date':[{"dateValue" :'2999-12-31'}]})
- i = i + 1
- with patch("flask_login.utils._get_user", return_value=users[id]["obj"]):
- res = []
- for record in results:
- if 'filename' in record:
- res.append( _get_show_secret_url_button(record["record"] , record["filename"]) )
-
- assert res[0] == False
- assert res[1] == False
- assert res[2] == False
-
-# def create_secret_url_and_send_mail(pid:PersistentIdentifier, record:WekoRecord, filename:str, **kwargs) -> str:
-# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_views.py::test__get_show_secret_url_button3 -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp
-@pytest.mark.parametrize(
- "id, is_show",
- [
- (1, False), #repoadmin
- ],
-)
-def test__get_show_secret_url_button3(users,records,id,is_show):
- indexer, results = records
- # 80
- i = 0
- role = ["open_access" , "open_no" ,"open_date"]
- for record in results:
- record["record"]['owner'] = users[5]["id"]
- record["record"]['weko_shared_id'] = users[7]["id"]
- file_data = record["record"].get_file_data()
- if len(file_data) > 0:
- file_data[0].update({'accessrole':role[i%3]})
- file_data[0].update({'date':[{"dateValue" :'2999-12-31'}]})
- i = i + 1
- with patch("flask_login.utils._get_user", return_value=users[id]["obj"]):
- res = []
- for record in results:
- if 'filename' in record:
- res.append( _get_show_secret_url_button(record["record"] , record["filename"]) )
-
- assert res[0] == False
- assert res[1] == is_show
- assert res[2] == False
diff --git a/modules/weko-records-ui/weko_records_ui/alembic/2750aa1ddc76_create_weko_records_ui_branch.py b/modules/weko-records-ui/weko_records_ui/alembic/2750aa1ddc76_create_weko_records_ui_branch.py
new file mode 100644
index 0000000000..2622bdff59
--- /dev/null
+++ b/modules/weko-records-ui/weko_records_ui/alembic/2750aa1ddc76_create_weko_records_ui_branch.py
@@ -0,0 +1,28 @@
+#
+# This file is part of Invenio.
+# Copyright (C) 2016-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.
+
+"""Create weko-records-ui branch."""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '2750aa1ddc76'
+down_revision = None
+branch_labels = ('weko_records_ui',)
+depends_on = 'invenio_accounts'
+
+
+def upgrade():
+ """Upgrade database."""
+ pass
+
+
+def downgrade():
+ """Downgrade database."""
+ pass
diff --git a/modules/weko-records-ui/weko_records_ui/alembic/e0b1ef08d08c_create_file_url_download_log_table.py b/modules/weko-records-ui/weko_records_ui/alembic/e0b1ef08d08c_create_file_url_download_log_table.py
new file mode 100644
index 0000000000..5fc43128b4
--- /dev/null
+++ b/modules/weko-records-ui/weko_records_ui/alembic/e0b1ef08d08c_create_file_url_download_log_table.py
@@ -0,0 +1,138 @@
+#
+# This file is part of Invenio.
+# Copyright (C) 2016-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.
+
+"""Create file_url_download_log table."""
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import INET
+from sqlalchemy.orm import Session
+
+
+# revision identifiers, used by Alembic.
+revision = 'e0b1ef08d08c'
+down_revision = '2750aa1ddc76'
+branch_labels = ()
+depends_on = 'invenio_accounts'
+
+
+def upgrade():
+ """Upgrade database."""
+
+ # Recreate 'file_onetime_download' table
+ op.drop_table('file_onetime_download')
+ op.create_table(
+ 'file_onetime_download',
+ sa.Column('created', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('updated', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
+ sa.Column('approver_id', sa.Integer(), nullable=False),
+ sa.Column('record_id', sa.String(255), nullable=False),
+ sa.Column('file_name', sa.String(255), nullable=False),
+ sa.Column('expiration_date', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('download_limit', sa.Integer(), nullable=False),
+ sa.Column('download_count', sa.Integer(), nullable=False, server_default=sa.text('0')),
+ sa.Column('user_mail', sa.String(255), nullable=False),
+ sa.Column('is_guest', sa.Boolean(), nullable=False),
+ sa.Column('is_deleted', sa.Boolean(), nullable=False, server_default=sa.text('FALSE')),
+ sa.Column('extra_info', sa.JSON(), nullable=False, server_default=sa.text("'{}'")),
+ sa.ForeignKeyConstraint(['approver_id'], ['accounts_user.id'], name='fk_file_onetime_download_approver_id'),
+ sa.CheckConstraint('created < expiration_date', name='check_expiration_date'),
+ sa.CheckConstraint('download_limit > 0', name='check_download_limit_positive'),
+ sa.CheckConstraint('download_count <= download_limit', name='check_download_count_limit')
+ )
+
+ # Recreate 'file_secret_download' table
+ op.drop_table('file_secret_download')
+ op.create_table(
+ 'file_secret_download',
+ sa.Column('created', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('updated', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
+ sa.Column('creator_id', sa.Integer(), nullable=False),
+ sa.Column('record_id', sa.String(255), nullable=False),
+ sa.Column('file_name', sa.String(255), nullable=False),
+ sa.Column('label_name', sa.String(255), nullable=False),
+ sa.Column('expiration_date', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('download_limit', sa.Integer(), nullable=False),
+ sa.Column('download_count', sa.Integer(), nullable=False, server_default=sa.text('0')),
+ sa.Column('is_deleted', sa.Boolean(), nullable=False, server_default=sa.text('FALSE')),
+ sa.ForeignKeyConstraint(['creator_id'], ['accounts_user.id'], name='fk_file_secret_download_creator_id'),
+ sa.CheckConstraint('created < expiration_date', name='check_expiration_date'),
+ sa.CheckConstraint('download_limit > 0', name='check_download_limit_positive'),
+ sa.CheckConstraint('download_count <= download_limit', name='check_download_count_limit')
+ )
+
+ # Add 'file_url_download_log' table
+ op.create_table(
+ 'file_url_download_log',
+ sa.Column('created', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('updated', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
+ sa.Column('url_type', sa.Enum('SECRET', 'ONETIME', name='urltype'), nullable=False),
+ sa.Column('secret_url_id', sa.Integer(), sa.ForeignKey('file_secret_download.id'), nullable=True),
+ sa.Column('onetime_url_id', sa.Integer(), sa.ForeignKey('file_onetime_download.id'), nullable=True),
+ sa.Column('ip_address', INET().with_variant(sa.String(255), 'sqlite').with_variant(sa.String(255), 'mysql'), nullable=True),
+ sa.Column('access_status', sa.Enum('OPEN_NO', 'OPEN_DATE', 'OPEN_RESTRICTED', name='accessstatus'), nullable=False),
+ sa.Column('used_token', sa.String(255), nullable=False),
+ sa.CheckConstraint(
+ """
+ (url_type = 'SECRET' AND secret_url_id IS NOT NULL AND onetime_url_id IS NULL)
+ OR
+ (url_type = 'ONETIME' AND onetime_url_id IS NOT NULL AND secret_url_id IS NULL)
+ """,
+ name="chk_url_id"
+ ),
+ sa.CheckConstraint(
+ """
+ (url_type = 'SECRET' AND ip_address IS NOT NULL)
+ OR
+ (url_type = 'ONETIME' AND ip_address IS NULL)
+ """,
+ name="chk_ip_address"
+ ),
+ sa.CheckConstraint(
+ """
+ (url_type = 'SECRET' AND (access_status = 'OPEN_NO' OR access_status = 'OPEN_DATE'))
+ OR
+ (url_type = 'ONETIME' AND access_status = 'OPEN_RESTRICTED')
+ """,
+ name="chk_access_status"
+ )
+ )
+
+def downgrade():
+ """Downgrade database."""
+
+ op.drop_table('file_url_download_log')
+ op.execute("DROP TYPE IF EXISTS urltype;")
+ op.execute("DROP TYPE IF EXISTS accessstatus;")
+ op.drop_table('file_onetime_download')
+ op.create_table(
+ 'file_onetime_download',
+ sa.Column('created', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('updated', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
+ sa.Column('file_name', sa.String(255), nullable=False),
+ sa.Column('user_mail', sa.String(255), nullable=False),
+ sa.Column('record_id', sa.String(255), nullable=False),
+ sa.Column('download_count', sa.Integer(), nullable=False, server_default=sa.text('0')),
+ sa.Column('expiration_date', sa.Integer(), nullable=False, server_default=sa.text('0')),
+ sa.Column('extra_info', sa.JSON(), nullable=True, server_default=sa.text("'{}'")),
+ )
+ op.drop_table('file_secret_download')
+ op.create_table(
+ 'file_secret_download',
+ sa.Column('created', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('updated', sa.TIMESTAMP(timezone=False), nullable=False),
+ sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
+ sa.Column('file_name', sa.String(255), nullable=False),
+ sa.Column('user_mail', sa.String(255), nullable=False),
+ sa.Column('record_id', sa.String(255), nullable=False),
+ sa.Column('download_count', sa.Integer(), nullable=False, server_default=sa.text('0')),
+ sa.Column('expiration_date', sa.Integer(), nullable=False, server_default=sa.text('0')),
+ )
diff --git a/modules/weko-records-ui/weko_records_ui/config.py b/modules/weko-records-ui/weko_records_ui/config.py
index 3f0e997164..369892fb19 100644
--- a/modules/weko-records-ui/weko_records_ui/config.py
+++ b/modules/weko-records-ui/weko_records_ui/config.py
@@ -178,6 +178,42 @@
':page_permission_factory',
methods=['POST'],
),
+ recid_copy_secret_url=dict(
+ pid_type='recid',
+ route='/records//secret//',
+ view_imp='weko_records_ui.views.copy_secret_url',
+ record_class='weko_deposit.api:WekoRecord',
+ permission_factory_imp='weko_records_ui.permissions'
+ ':page_permission_factory',
+ methods=['GET'],
+ ),
+ recid_copy_onetime_url=dict(
+ pid_type='recid',
+ route='/records//onetime//',
+ view_imp='weko_records_ui.views.copy_onetime_url',
+ record_class='weko_deposit.api:WekoRecord',
+ permission_factory_imp='weko_records_ui.permissions'
+ ':page_permission_factory',
+ methods=['GET'],
+ ),
+ recid_delete_secret_url=dict(
+ pid_type='recid',
+ route='/records//secret//',
+ view_imp='weko_records_ui.views.delete_secret_url',
+ record_class='weko_deposit.api:WekoRecord',
+ permission_factory_imp='weko_records_ui.permissions'
+ ':page_permission_factory',
+ methods=['DELETE'],
+ ),
+ recid_delete_onetime_url=dict(
+ pid_type='recid',
+ route='/records//onetime//',
+ view_imp='weko_records_ui.views.delete_onetime_url',
+ record_class='weko_deposit.api:WekoRecord',
+ permission_factory_imp='weko_records_ui.permissions'
+ ':page_permission_factory',
+ methods=['DELETE'],
+ ),
recid_secret_file_download=dict(
pid_type='recid',
route='/record//file/secret/',
@@ -193,10 +229,6 @@
"filename={} record_id={} user_mail={} date={}"
"""Onetime download pattern."""
-WEKO_RECORDS_UI_SECRET_DOWNLOAD_PATTERN = \
- "filename={} record_id={} id={} date={}"
-"""Secret URL download pattern."""
-
WEKO_RECORDS_UI_MAIL_TEMPLATE_SECRET_URL = "email_pattern_send_secret_url.tpl"
RECORDS_UI_EXPORT_FORMATS = {
diff --git a/modules/weko-records-ui/weko_records_ui/fd.py b/modules/weko-records-ui/weko_records_ui/fd.py
index 5a66280464..2f59e403b7 100644
--- a/modules/weko-records-ui/weko_records_ui/fd.py
+++ b/modules/weko-records-ui/weko_records_ui/fd.py
@@ -20,11 +20,12 @@
"""Utilities for download file."""
+import base64
import json
import mimetypes
import traceback
import unicodedata
-from datetime import datetime
+from datetime import datetime, timezone
from flask import abort, current_app, render_template, request ,redirect ,url_for
from flask_babelex import gettext as _
@@ -40,21 +41,21 @@
from weko_deposit.api import WekoRecord
from weko_groups.api import Group
from weko_records.api import FilesMetadata, ItemTypes
-from weko_records_ui.utils import generate_one_time_download_url
from weko_user_profiles.models import UserProfile
from weko_workflow.utils import is_terms_of_use_only
from werkzeug.datastructures import Headers
from werkzeug.urls import url_quote
-from .models import FileOnetimeDownload, FileSecretDownload, PDFCoverPageSettings
+from .models import FileOnetimeDownload, FileSecretDownload, \
+ PDFCoverPageSettings
from .pdf import make_combined_pdf
from .permissions import check_original_pdf_download_permission, \
file_permission_factory, is_owners_or_superusers
-from .utils import check_and_send_usage_report, get_billing_file_download_permission, \
+from .utils import check_and_send_usage_report, convert_token_into_obj, \
+ create_download_url, get_billing_file_download_permission, \
get_groups_price, get_min_price_billing_file_download, \
- get_onetime_download, get_secret_download, is_billing_item, parse_one_time_download_token, parse_secret_download_token, \
- update_onetime_download, update_secret_download, validate_download_record, \
- validate_onetime_download_token, validate_secret_download_token
+ get_onetime_download, is_billing_item, save_download_log, \
+ validate_url_download
def weko_view_method(pid, record, template=None, **kwargs):
@@ -248,8 +249,7 @@ def file_ui(
current_app.logger.info('onetime_download is None')
abort(403)
- onetime_file_url = generate_one_time_download_url(
- file_name, record_id, user_mail )
+ onetime_file_url = create_download_url(onetime_download)
return redirect(onetime_file_url) #redirect to file_download_onetime()
# #Check permissions
@@ -408,80 +408,68 @@ def add_signals_info(record, obj):
obj.item_id = record['_deposit']['id']
-def file_download_onetime(pid, record, _record_file_factory=None, **kwargs):
- """File download onetime.
+def error_response(error_message, status_code=400):
+ error_template = "weko_theme/error.html"
+ return render_template(error_template, error=error_message), status_code
- :param pid:
- :param record: Record json
- :param _record_file_factory:
- :param kwargs:
- :return:
+
+def file_download_onetime(pid, record, filename, _record_file_factory=None,
+ **kwargs):
+ """Download a file using a one-time download URL.
+
+ Args:
+ pid (PersistentIdentifier): The identifier for the item.
+ record (WekoRecord): The record metadata of the item.
+ filename (str): The name of the file to download.
+
+ Returns:
+ Response: The Flask wrapper object for the file download
"""
+ # Validate the download request
token = request.args.get('token', type=str)
- filename = kwargs.get("filename")
- error_template = "weko_theme/error.html"
- # Parse token
- error, token_data = \
- parse_one_time_download_token(token)
- if error:
- return render_template(error_template, error=error)
- record_id, user_mail, date, secret_token = token_data
-
- # Validate record status
- validate_download_record(record)
-
- # Get one time download record.
- onetime_download = get_onetime_download(
- file_name=filename, record_id=record_id, user_mail=user_mail
- )
-
- # Validate token
- is_valid, error = validate_onetime_download_token(
- onetime_download, filename, record_id, user_mail, date, secret_token)
- if not is_valid:
- return render_template(error_template, error=error)
+ is_validated, error_msg = validate_url_download(
+ record, filename, token, is_secret_url=False)
+ if not is_validated:
+ return error_response(error_msg, 403)
+ # Locate the file object
_record_file_factory = _record_file_factory or record_file_factory
-
- # Get file object
file_object = _record_file_factory(pid, record, filename)
if not file_object or not file_object.obj:
- return render_template(error_template,
- error="{} does not exist.".format(filename))
-
- # Create updated data
- update_data = dict(
- file_name=filename, record_id=record_id, user_mail=user_mail,
- download_count=onetime_download.download_count - 1,
- )
+ return error_response(_('The file "%s" does not exist.') % filename, 404)
- # Check and send usage report for Guest User.
- if onetime_download.extra_info and 'open_restricted' == file_object.get(
- 'accessrole'):
- extra_info = onetime_download.extra_info
+ # Update 'extra_info' of the one-time URL object
+ url_obj = convert_token_into_obj(token, is_secret_url=False)
+ extra_info = url_obj.extra_info
+ if extra_info:
try:
- error_msg = check_and_send_usage_report(extra_info, user_mail ,record, file_object)
- if error_msg:
- return render_template(error_template, error=error_msg)
+ # 'extra_info' can be changed by this method
+ error = check_and_send_usage_report(
+ extra_info, url_obj.user_mail ,record, file_object)
+ if error:
+ return error_response(error, 403)
+ url_obj.update_extra_info(extra_info)
db.session.commit()
except SQLAlchemyError as ex:
- current_app.logger.error("sqlalchemy error: {}".format(ex))
+ current_app.logger.error(f'SQLAlchemy error: {ex}')
db.session.rollback()
- return render_template(error_template, error=_("Unexpected error occurred."))
+ return error_response('Unexpected error occurred.', 500)
except BaseException as ex:
- current_app.logger.error("Unexpected error: {}".format(ex))
+ current_app.logger.error(f'Unexpected error: {ex}')
db.session.rollback()
- return render_template(error_template, error=_("Unexpected error occurred."))
+ return error_response('Unexpected error occurred.', 500)
- update_data['extra_info'] = extra_info
+ # Increase the download count and save the download log
+ try:
+ save_download_log(record, filename, token, is_secret_url=False)
+ url_obj.increment_download_count()
+ except Exception as e:
+ current_app.logger.error(e)
+ return error_response(_('Unexpected error occurred.'), 500)
- # Update download data
- if not update_onetime_download(**update_data):
- return render_template(error_template,
- error=_("Unexpected error occurred."))
+ return _download_file(
+ file_object, False, 'en', file_object.obj, pid, record)
- return _download_file(file_object, False, 'en', file_object.obj, pid,
- record)
def _is_terms_of_use_only(file_obj:dict , req :dict) -> bool:
"""
@@ -516,70 +504,46 @@ def _is_terms_of_use_only(file_obj:dict , req :dict) -> bool:
return is_terms_of_use_only(workflow_id) if workflow_id != "" else False
-def file_download_secret(pid, record, _record_file_factory=None, **kwargs):
- """File download secret.
- :param pid:
- :param record: Record json
- :param _record_file_factory:
- :param kwargs:
- :return:
- """
- token = request.args.get('token', type=str)
- filename:str = str(kwargs.get("filename"))
- error_template = "weko_theme/error.html"
- # Parse token
- error, token_data = \
- parse_secret_download_token(token)
- if error:
- return render_template(error_template, error=error)
- record_id, id, date, secret_token = token_data
-
- # Validate record status
- validate_download_record(record)
-
- if isinstance(date,str):
- date = datetime.strptime(date, "%Y-%m-%dT%H:%M:%S.%f")
-
- # Get secret download record.
- secret_download :FileSecretDownload = get_secret_download(
- file_name=filename, record_id=pid.pid_value, id=id , created=date
- )
+def file_download_secret(pid, record, filename, _record_file_factory=None,
+ **kwargs):
+ """Download a file using a secret URL.
- if not secret_download:
- abort(403)
+ Args:
+ pid (PersistentIdentifier): The identifier for the item.
+ record (WekoRecord): The record metadata of the item.
+ filename (str): The name of the file to download.
- # Validate token
- is_valid, error = validate_secret_download_token(
- secret_download, filename, pid.pid_value, id, date.isoformat(), secret_token)
- current_app.logger.debug("is_valid: {}, error: {}".format(is_valid,error))
-
- if not is_valid:
- return render_template(error_template, error=error)
+ Returns:
+ Response: The Flask wrapper object for the file download.
+ """
+ # Validate the download request
+ token = request.args.get('token', type=str)
+ is_validated, error_msg = (
+ validate_url_download(record, filename, token, is_secret_url=True))
+ if not is_validated:
+ return error_response(error_msg, 403)
+ # Locate the file object
_record_file_factory = _record_file_factory or record_file_factory
-
- # Get file object
file_object = _record_file_factory(pid, record, filename)
if not file_object or not file_object.obj:
- return render_template(error_template,
- error="{} does not exist.".format(filename))
-
- # Create updated data
- update_data = dict(
- file_name=filename, record_id=record_id, id=id,
- download_count=secret_download.download_count - 1,created=str(date)
- )
+ return error_response(_('The file "%s" does not exist.') % filename, 404)
- # Update download data
- if not update_secret_download(**update_data):
- return render_template(error_template,
- error=_("Unexpected error occurred."))
-
- # Get user's language and defautl language for PDF coverpage.
+ # Set language for PDF cover page
lang = 'en'
if current_user.is_authenticated :
user_profile = UserProfile.get_by_userid(current_user.get_id())
- lang = user_profile.language if user_profile and user_profile.language \
- else 'en'
- return _download_file(file_object, False, lang, file_object.obj, pid, record)
\ No newline at end of file
+ lang = user_profile.language if user_profile else 'en'
+
+ # Increase the download count and save the download log
+ url_obj = convert_token_into_obj(token, is_secret_url=True)
+ try:
+ save_download_log(record, filename, token, is_secret_url=True)
+ url_obj.increment_download_count()
+ except Exception as e:
+ current_app.logger.error(e)
+ return error_response(_('Unexpected error occurred.'), 500)
+
+ return _download_file(
+ file_object, False, lang, file_object.obj, pid, record)
diff --git a/modules/weko-records-ui/weko_records_ui/models.py b/modules/weko-records-ui/weko_records_ui/models.py
index 2343c5712c..ce9da6adbb 100644
--- a/modules/weko-records-ui/weko_records_ui/models.py
+++ b/modules/weko-records-ui/weko_records_ui/models.py
@@ -21,16 +21,15 @@
"""Database models for weko-admin."""
-from datetime import datetime
-from datetime import timedelta
-import traceback
+from datetime import datetime, timezone
+import enum
from typing import List
from flask import current_app
from invenio_db import db
-from sqlalchemy import desc, or_ ,func
+from sqlalchemy import CheckConstraint, desc, func, asc
from sqlalchemy.dialects import postgresql
-from sqlalchemy.dialects.postgresql import INTERVAL
+from sqlalchemy.dialects.postgresql import INET
from sqlalchemy.sql.functions import concat ,now
from sqlalchemy_utils.models import Timestamp
from sqlalchemy_utils.types import JSONType
@@ -289,66 +288,181 @@ def delete_object(cls, permission):
db.session.delete(permission)
-class FileOnetimeDownload(db.Model, Timestamp):
- """File onetime download."""
+class DownloadMixin:
+ """A mixin class that provides common methods for managing download-related
+ functionality.
- __tablename__ = 'file_onetime_download'
+ This mixin class is specifically designed for managing URL-related
+ downloads, particularly one-time URLs and secret URLs.
- id = db.Column(db.Integer, primary_key=True, autoincrement=True)
- """Identifier"""
+ Note:
+ To use this mixin, the model class must have the following attributes:
+ - download_limit (int): The maximum number of downloads allowed.
+ - download_count (int): The number the URL has been downloaded.
+ - is_deleted (bool): Indicates whether the record is deleted.
+ """
- file_name = db.Column(db.String(255), nullable=False)
- """File name"""
+ def increment_download_count(self):
+ """Increment the 'download_count' attribute by 1 and commit the change.
- user_mail = db.Column(db.String(255), nullable=False)
- """User mail"""
+ This method increases the download count for the instance by one
+ and persists the change to the database.
- record_id = db.Column(db.String(255), nullable=False)
- """Record identifier."""
-
- download_count = db.Column(db.Integer, nullable=False, default=0)
- """Download count"""
-
- expiration_date = db.Column(db.Integer, nullable=False, default=0)
- """Expiration Date"""
-
- extra_info = db.Column(
- db.JSON().with_variant(
- postgresql.JSONB(none_as_null=True),
- 'postgresql',
- ).with_variant(
- JSONType(),
- 'sqlite',
- ).with_variant(
- JSONType(),
- 'mysql',
- ),
+ Raises:
+ ValueError: If the download limit has been reached.
+ Exception: If an unexpected error occurs during the update.
+ """
+ if self.download_count >= self.download_limit:
+ raise ValueError('Download limit has been reached.')
+ try:
+ self.download_count += 1
+ db.session.commit()
+ except Exception as ex:
+ db.session.rollback()
+ current_app.logger.error(ex)
+ raise ex
+
+ def delete_logically(self):
+ """Execute logical deletion by setting the 'is_deleted' flag to True.
+
+ This marks the record as deleted without removing it from the database.
+
+ Raises:
+ Exception: If an unexpected error occurs during the deletion.
+ """
+ try:
+ self.is_deleted = True
+ db.session.commit()
+ except Exception as ex:
+ db.session.rollback()
+ current_app.logger.error(ex)
+ raise ex
+
+ @classmethod
+ def fetch_active_urls(cls, record_id, file_name, ascending=False):
+ """Fetch the active URLs for a specified file from the database.
+
+ Args:
+ record_id (str): The ID of the record to which the file belongs.
+ file_name (str): The name of the file.
+ ascending (bool): A flag indicating how the results are ordered.
+
+ Returns:
+ List[cls]: A list of active URLs.
+ """
+ query = cls.query.filter(
+ cls.record_id == record_id,
+ cls.file_name == file_name,
+ cls.expiration_date > datetime.utcnow(),
+ cls.download_count < cls.download_limit,
+ cls.is_deleted == False
+ )
+ if ascending:
+ return query.order_by(asc(cls.id)).all()
+ else:
+ return query.order_by(desc(cls.id)).all()
+
+
+class FileOnetimeDownload(db.Model, Timestamp, DownloadMixin):
+ """A model class for the 'file_onetime_download' table.
+
+ This class stores information about one-time URLs used for file access.
+
+ Note:
+ Despite being called 'one-time', the download limit can be set to more
+ than once.
+
+ Attributes:
+ id (int): The unique identifier of the record.
+ approver_id (int): The ID of the user who approved the application.
+ record_id (str): The ID of the associated file record.
+ file_name (str): The name of the file.
+ expiration_date (datetime): The date and time when the URL expires.
+ download_limit (int): The maximum number of downloads allowed.
+ download_count (int): The number of times the URL has been downloaded.
+ user_mail (str): The email address of the user who applied.
+ is_guest (bool): Indicates whether the user is a guest.
+ is_deleted (bool): Indicates whether the record is deleted.
+ extra_info (dict): Additional information stored in JSON format.
+ """
+ __tablename__ = 'file_onetime_download'
+ id = db.Column(db.Integer,primary_key=True,autoincrement=True)
+ approver_id = db.Column(
+ db.Integer,
+ db.ForeignKey(
+ 'accounts_user.id',
+ name='fk_file_onetime_download_approver_id'),
+ nullable=False)
+ record_id = db.Column(db.String(255), nullable=False)
+ file_name = db.Column(db.String(255), nullable=False)
+ expiration_date = db.Column(db.DateTime, nullable=False)
+ download_limit = db.Column(db.Integer, nullable=False)
+ download_count = db.Column(db.Integer, nullable=False, default=0)
+ user_mail = db.Column(db.String(255), nullable=False)
+ is_guest = db.Column(db.Boolean, nullable=False, default=False)
+ is_deleted = db.Column(db.Boolean, nullable=False, default=False)
+ extra_info = db.Column(db.JSON()
+ .with_variant(postgresql.JSONB(none_as_null=True), 'postgresql')
+ .with_variant(JSONType(), 'sqlite')
+ .with_variant(JSONType(), 'mysql'),
default=lambda: dict(),
- nullable=True
+ nullable=True,)
+ __table_args__ = (
+ CheckConstraint('created < expiration_date',
+ name='check_expiration_date'),
+ CheckConstraint('download_limit > 0',
+ name='check_download_limit_positive'),
+ CheckConstraint('download_count <= download_limit',
+ name='check_download_count_limit'),
)
- """Extra info."""
-
- def __init__(self, file_name, user_mail, record_id, download_count=0,
- expiration_date=0, extra_info=None):
- """Init.
-
- :param file_name: File name
- :param user_mail: User mail
- :param record_id: Record identifier
- :param download_count: Download count
- :param expiration_date: Expiration date
- :param extra_info: Extra info want to store
+
+ def __init__(
+ self, approver_id, record_id, file_name, expiration_date,
+ download_limit, user_mail, is_guest, extra_info
+ ):
+ """Initialize the instance.
+
+ Note:
+ The 'id', 'download_count', and 'is_deleted' fields are not part of
+ the initialization.
+
+ Args:
+ approver_id (int): The ID of the user who approved the application.
+ record_id (str): The ID of the file's associated record.
+ file_name (str): The name of the file.
+ expiration_date (datetime): The date and time when the URL expires.
+ download_limit (int): The download limit of the URL.
+ user_mail (str): The email address of the user who applied.
+ is_guest (bool): A flag indicating whether the user is a guest.
+ extra_info (dict): Additional information stored in JSON format.
"""
- self.file_name = file_name
- self.user_mail = user_mail
- self.record_id = record_id
- self.download_count = download_count
+ self.approver_id = approver_id
+ self.record_id = record_id
+ self.file_name = file_name
self.expiration_date = expiration_date
- self.extra_info = extra_info
+ self.download_limit = download_limit
+ self.user_mail = user_mail
+ self.is_guest = is_guest
+ self.extra_info = extra_info
@classmethod
def create(cls, **data):
- """Create data."""
+ """Create a new instance and save it to the database.
+
+ Args:
+ **data: The attributes for the new instance.
+
+ Returns:
+ FileOnetimeDownload: The created instance.
+
+ Raises:
+ ValueError: If the arguments are invalid.
+ Exception: If an unexpected error occurs during the creation.
+ """
+ if data['expiration_date'] < datetime.now(tz=timezone.utc):
+ raise ValueError('The expiration date must be in the future.')
+ if data['download_limit'] <= 0:
+ raise ValueError('The download limit must be greater than 0.')
try:
file_download = cls(**data)
db.session.add(file_download)
@@ -357,37 +471,19 @@ def create(cls, **data):
except Exception as ex:
db.session.rollback()
current_app.logger.error(ex)
- return None
+ raise ex
@classmethod
- def update_download(cls, **data):
- """Update download count.
+ def get_by_id(cls, id):
+ """Get a record by its ID.
- :param data:
- :return:
+ Args:
+ id (int): The ID of the record to retrieve.
+
+ Returns:
+ FileOnetimeDownload: The record instance, or None if not found.
"""
- try:
- file_name = data.get("file_name")
- user_mail = data.get("user_mail")
- record_id = data.get("record_id")
- file_permission = cls.find(file_name=file_name, user_mail=user_mail,
- record_id=record_id)
- if file_permission and len(file_permission) > 0:
- for file in file_permission:
- if data.get("download_count") is not None:
- file.download_count = data.get("download_count")
- if data.get("expiration_date") is not None:
- file.expiration_date = data.get("expiration_date")
- if data.get("extra_info"):
- file.extra_info = data.get("extra_info")
- db.session.merge(file)
- db.session.commit()
- return file_permission
- return None
- except Exception as ex:
- db.session.rollback()
- current_app.logger.error(ex)
- return None
+ return cls.query.get(id)
@classmethod
def find(cls, **obj) -> list:
@@ -402,7 +498,7 @@ def find(cls, **obj) -> list:
cls.user_mail == obj.get("user_mail"),
)
return query.order_by(desc(cls.id)).all()
-
+
@classmethod
def find_downloadable_only(cls, **obj) -> list:
"""If the user can download ,find file onetime download.
@@ -414,59 +510,118 @@ def find_downloadable_only(cls, **obj) -> list:
cls.file_name == obj.get("file_name"),
cls.record_id == obj.get("record_id"),
cls.user_mail == obj.get("user_mail"),
- cls.download_count > 0 ,
- now() < cls.created + func.cast( concat( cls.expiration_date , ' days' ) , INTERVAL)
+ cls.download_count < cls.download_limit,
+ cls.expiration_date > datetime.now(timezone.utc),
+ cls.is_deleted == False
)
return query.order_by(desc(cls.id)).all()
-
-class FileSecretDownload(db.Model, Timestamp):
- """File secret download."""
+ def update_extra_info(self, new_info: dict):
+ """Update the 'extra_info' field with the provided new data.
- __tablename__ = 'file_secret_download'
+ Args:
+ new_info (dict): A dictionary containing the new info to update.
- id = db.Column(db.Integer, primary_key=True, autoincrement=True)
- """Identifier"""
+ Raises:
+ ValueError: If the new info is not a dictionary.
+ Exception: If an unexpected error occurs during the update.
+ """
+ if not isinstance(new_info, dict):
+ raise ValueError('The new info must be a dictionary.')
+ try:
+ self.extra_info = new_info
+ db.session.commit()
+ except Exception as ex:
+ db.session.rollback()
+ current_app.logger.error(ex)
+ raise ex
- file_name = db.Column(db.String(255), nullable=False)
- """File name"""
- user_mail = db.Column(db.String(255), nullable=False)
- """User mail"""
+class FileSecretDownload(db.Model, Timestamp, DownloadMixin):
+ """A model class for 'file_secret_download' table.
- record_id = db.Column(db.String(255), nullable=False)
- """Record identifier."""
+ This class stores information about secret URLs, which used for private
+ file access.
- download_count = db.Column(db.Integer, nullable=False, default=0)
- """Download count"""
+ Attributes:
+ id (int): The identifier of the record.
+ creator_id (int): The ID of the user who issued the secret URL.
+ record_id (str): The ID of the record that has the file.
+ file_name (str): The name of the file.
+ label_name (str): The label of the secret URL.
+ expiration_date (datetime): The date and time when the URL expires.
+ download_limit (int): The download limit of the URL.
+ download_count (int): The number of times the URL has been downloaded.
+ is_deleted (bool): A flag indicating whether the record is deleted.
+ """
+ __tablename__ = 'file_secret_download'
+ id = db.Column(db.Integer,primary_key=True,autoincrement=True)
+ creator_id = db.Column(db.Integer,
+ db.ForeignKey(
+ 'accounts_user.id',
+ name='fk_file_secret_download_creator_id'),
+ nullable=False)
+ record_id = db.Column(db.String(255), nullable=False)
+ file_name = db.Column(db.String(255), nullable=False)
+ label_name = db.Column(db.String(255), nullable=False)
+ expiration_date = db.Column(db.DateTime, nullable=False)
+ download_limit = db.Column(db.Integer, nullable=False)
+ download_count = db.Column(db.Integer, nullable=False, default=0)
+ is_deleted = db.Column(db.Boolean, nullable=False, default=False)
+ __table_args__ = (
+ CheckConstraint('created < expiration_date',
+ name='check_expiration_date'),
+ CheckConstraint('download_limit > 0',
+ name='check_download_limit_positive'),
+ CheckConstraint('download_count <= download_limit',
+ name='check_download_count_limit'),
+ )
- expiration_date = db.Column(db.Integer, nullable=False, default=0)
- """Expiration Date"""
+ def __init__(self, creator_id, record_id, file_name, label_name,
+ expiration_date, download_limit):
+ """Initialize the instance.
- def __init__(self, file_name, user_mail, record_id, download_count=0,
- expiration_date=0):
- """Init.
+ Note:
+ The 'id', 'download_count', and 'is_deleted' fields are not part of
+ the initialization.
- :param file_name: File name
- :param user_mail: User mail
- :param record_id: Record identifier
- :param download_count: Download count
- :param expiration_date: Expiration date
+ Args:
+ creator_id (int): The ID of the user who issued the secret URL.
+ record_id (str): The ID of the record that has the file.
+ file_name (str): The name of the file.
+ label_name (str): The label of the secret URL.
+ expiration_date (date): The date when the URL expires.
+ download_limit (int): The download limit of the URL.
"""
- self.file_name = file_name
- self.user_mail = user_mail
- self.record_id = record_id
- self.download_count = download_count
+ self.creator_id = creator_id
+ self.record_id = record_id
+ self.file_name = file_name
+ self.label_name = label_name
self.expiration_date = expiration_date
+ self.download_limit = download_limit
@classmethod
def create(cls, **data):
- """Create data."""
+ """Create a new instance and save it to the database.
+
+ Args:
+ **data: The attributes for the new instance.
+
+ Returns:
+ FileSecretDownload: The created instance.
+
+ Raises:
+ ValueError: If the arguments are invalid.
+ Exception: If an unexpected error occurs during the creation.
+ """
+ if data['expiration_date'] < datetime.now(tz=timezone.utc):
+ raise ValueError('The expiration date must be in the future.')
+ if data['download_limit'] <= 0:
+ raise ValueError('The download limit must be greater than 0.')
try:
file_download = cls(**data)
db.session.add(file_download)
db.session.commit()
- db.session.flush()
return file_download
except Exception as ex:
db.session.rollback()
@@ -474,34 +629,16 @@ def create(cls, **data):
raise ex
@classmethod
- def update_download(cls, **data):
- """Update download count.
+ def get_by_id(cls, id):
+ """Get a record by its ID.
- :param data:
- :return:
+ Args:
+ id (int): The ID of the record to retrieve.
+
+ Returns:
+ FileSecretDownload: The record instance, or None if not found.
"""
- try:
- file_name = data.get("file_name")
- id = data.get("id")
- record_id = data.get("record_id")
- created = data.get("created")
- current_app.logger.debug("data: {}".format(data))
- file_permission = cls.find(file_name=file_name, id=id,
- record_id=record_id,created=created)
- current_app.logger.debug("file_permission: {}".format(file_permission))
- if len(file_permission) == 1:
- file = file_permission[0]
- if data.get("download_count") is not None:
- file.download_count = data.get("download_count")
- db.session.merge(file)
- db.session.commit()
- return file_permission
- else:
- return None
- except Exception as ex:
- db.session.rollback()
- current_app.logger.error(traceback.format_exc())
- raise ex
+ return cls.query.get(id)
@classmethod
def find(cls, **obj) -> list:
@@ -518,4 +655,121 @@ def find(cls, **obj) -> list:
)
return query.order_by(desc(cls.id)).all()
-__all__ = ('PDFCoverPageSettings', 'FilePermission', 'FileOnetimeDownload' ,'FileSecretDownload')
+
+class UrlType(enum.Enum):
+ """An ENUM data type for the used URL."""
+ SECRET = 'SECRET'
+ ONETIME = 'ONETIME'
+
+
+class AccessStatus(enum.Enum):
+ """An ENUM data type for the access status of the downloaded file."""
+ OPEN_NO = 'OPEN_NO'
+ OPEN_DATE = 'OPEN_DATE'
+ OPEN_RESTRICTED = 'OPEN_RESTRICTED'
+
+
+class FileUrlDownloadLog(db.Model, Timestamp):
+ """Stores information of the executed download by download-URLs.
+
+ This class(table) is used to store information of the executed download of
+ a file using either secret URL or onetime URL.
+
+ Attributes:
+ id (int): The identifier of each download information.
+ url_type (UrlType): The used URL type('SECRET' or 'ONETIME').
+ secret_url_id (int): The secret URL record ID.
+ onetime_url_id (int): The onetime URL record ID.
+ ip_address (str): The IP address of the downloader.
+ access_status (AccessStatus): The access status of the downloaded file.
+ used_token (str): The URL token used to access the file.
+ """
+ __tablename__ = 'file_url_download_log'
+ id = db.Column(db.Integer(),
+ primary_key=True,
+ autoincrement=True)
+ url_type = db.Column(db.Enum(UrlType), nullable=False)
+ secret_url_id = db.Column(db.Integer(),
+ db.ForeignKey(FileSecretDownload.id))
+ onetime_url_id = db.Column(db.Integer(),
+ db.ForeignKey(FileOnetimeDownload.id))
+ ip_address = db.Column(INET()
+ .with_variant(db.String(255), 'sqlite')
+ .with_variant(db.String(255), 'mysql'))
+ access_status = db.Column(db.Enum(AccessStatus), nullable=False)
+ used_token = db.Column(db.String(255), nullable=False)
+ __table_args__ = (
+ CheckConstraint(
+ """
+ (url_type = 'SECRET' AND secret_url_id IS NOT NULL AND
+ onetime_url_id IS NULL)
+ OR
+ (url_type = 'ONETIME' AND onetime_url_id IS NOT NULL AND
+ secret_url_id IS NULL)
+ """,
+ name="chk_url_id"),
+ CheckConstraint(
+ """
+ (url_type = 'SECRET' AND ip_address IS NOT NULL)
+ OR
+ (url_type = 'ONETIME' AND ip_address IS NULL)
+ """,
+ name="chk_ip_address"),
+ CheckConstraint(
+ """
+ (url_type = 'SECRET' AND
+ (access_status = 'OPEN_NO' OR access_status = 'OPEN_DATE'))
+ OR
+ (url_type = 'ONETIME' AND access_status = 'OPEN_RESTRICTED')
+ """,
+ name="chk_access_status")
+ )
+
+ def __init__(self, url_type, secret_url_id, onetime_url_id, ip_address,
+ access_status, used_token):
+ """Initializes the FileUrlDownloadLog instance.
+
+ Args:
+ url_type (UrlType): The used URL type.
+ secret_url_id (int): The secret URL record ID.
+ onetime_url_id (int): The onetime URL record ID.
+ ip_address (str): The IP address of the downloader.
+ access_status (AccessStatus): The status of the downloaded file.
+ used_token (str): The URL token used to access the file.
+ """
+ self.url_type = url_type
+ self.secret_url_id = secret_url_id
+ self.onetime_url_id = onetime_url_id
+ self.ip_address = ip_address
+ self.access_status = access_status
+ self.used_token = used_token
+
+ @classmethod
+ def create(cls, **data):
+ """Create a new instance and save it to the database.
+
+ Args:
+ **data: The attributes for the new instance.
+
+ Returns:
+ FileUrlDownloadLog: The created instance.
+
+ Raises:
+ Exception: If an unexpected error occurs during the creation.
+ """
+ try:
+ file_download = cls(**data)
+ db.session.add(file_download)
+ db.session.commit()
+ return file_download
+ except Exception as ex:
+ db.session.rollback()
+ current_app.logger.error(ex)
+ raise ex
+
+
+__all__ = ('PDFCoverPageSettings',
+ 'FilePermission',
+ 'FileOnetimeDownload',
+ 'FileSecretDownload',
+ 'FileUrlDownloadLog',)
diff --git a/modules/weko-records-ui/weko_records_ui/static/css/weko_records_ui/style.css b/modules/weko-records-ui/weko_records_ui/static/css/weko_records_ui/style.css
index 6635439bd9..d0b5d325d6 100644
--- a/modules/weko-records-ui/weko_records_ui/static/css/weko_records_ui/style.css
+++ b/modules/weko-records-ui/weko_records_ui/static/css/weko_records_ui/style.css
@@ -76,12 +76,12 @@
.action-button {
margin-top: 5px;
margin-bottom: 5px;
-// display: block;
+/* display: block;*/
margin-right: auto;
margin-left: auto;
font-size: 13px;
line-height: 12px;
-// background-color: #D3D3D3;
+/* background-color: #D3D3D3;*/
height: 27px;
}
@@ -100,3 +100,146 @@
background-color: #f7f7f7 !important;
border: 1px solid #ebebeb;
}
+
+.icon-space {
+ padding-right: 8px;
+}
+#secret_url_form {
+ display: flex; /* フォーム全体を横一列に配置 */
+ flex-direction: row;
+ gap: 20px; /* 各要素間のスペース */
+ align-items: flex-start; /* 上揃え */
+}
+
+#secret_url_form #link_name,
+#secret_url_form #expiration_date,
+#secret_url_form #download_limit {
+ display: flex; /* ラベルとフィールドを縦並びに */
+ flex-direction: column; /* ラベルを上に配置 */
+ align-items: flex-start; /* 左揃え */
+}
+
+#secret_url_form #link_name label,
+#secret_url_form #expiration_date label,
+#secret_url_form #download_limit label {
+ margin-bottom: 5px; /* ラベルとフィールドの間のスペース */
+ font-weight: bold;
+}
+
+#secret_url_form input[type="text"],
+#secret_url_form input[type="date"],
+#secret_url_form input[type="number"] {
+ width: 150px; /* 各入力フィールドの幅を調整 */
+ padding: 10px;
+ border: 1px solid #ccc;
+ border-radius: 5px;
+ box-sizing: border-box;
+}
+
+#secret_url_form button {
+ align-self: center; /* ボタンを中央揃え */
+ padding: 10px;
+ background-color: #007bff;
+ color: #fff;
+ border: none;
+ border-radius: 5px;
+ cursor: pointer;
+ font-size: 16px;
+}
+
+#secret_url_form button:hover {
+ background-color: #0056b3;
+}
+
+#secret_url_section {
+ border: 1px solid #ccc;
+ margin-bottom: 20px;
+ padding: 15px 5px;
+}
+
+#max_date_display,
+#max_download_display {
+ font-size: 14px;
+ color: #555;
+ margin-top: 5px; /* フィールドとテキストの間にスペース */
+}
+
+#secret_url_form #checkbox-container {
+ display: flex;
+ flex-direction: row-reverse; /* 順番を逆にする */
+ align-items: center;
+}
+
+#secret_url_form #checkbox-container label {
+ margin-left: 5px; /* チェックボックスとラベルの間にスペース */
+ font-weight: normal; /* チェックボックスラベルのフォントを通常に */
+}
+
+.error-message {
+ color: red;
+}
+
+/* 削除ボタンのスタイル */
+.delete_secret_url {
+ background-color: #dc3545;
+ width: 130px;
+ color: white;
+}
+
+/* コピーボタンのスタイル */
+.copy_secret_url {
+ background-color: #F0F8FF;
+ width: 130px;
+ color: black;
+}
+
+.secret-url-area table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+.secret-url-area th, .secret-url-area td {
+ padding: 10px;
+ text-align: left;
+ border: 1px solid #ddd;
+ vertical-align: middle; /* 縦方向の中央揃え */
+}
+
+.secret-url-area th {
+ background-color: #f2f2f2;
+}
+
+/* 削除ボタンのスタイル */
+.delete_onetime_url {
+ background-color: #dc3545;
+ width: 130px;
+ color: white;
+}
+
+/* コピーボタンのスタイル */
+.copy_onetime_url {
+ background-color: #F0F8FF;
+ width: 130px;
+ color: black;
+}
+
+.onetime-url-area table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+.onetime-url-area th, .onetime-url-area td {
+ padding: 10px;
+ text-align: left;
+ border: 1px solid #ddd;
+ vertical-align: middle; /* 縦方向の中央揃え */
+}
+
+.onetime-url-area th {
+ background-color: #f2f2f2;
+}
+
+.button-group {
+ margin-right: 5px;
+ display: inline-block; /* ボタンを横並びにする */
+}
\ No newline at end of file
diff --git a/modules/weko-records-ui/weko_records_ui/static/js/weko_records_ui/detail.js b/modules/weko-records-ui/weko_records_ui/static/js/weko_records_ui/detail.js
index 64087b48d8..ec6d93f14f 100644
--- a/modules/weko-records-ui/weko_records_ui/static/js/weko_records_ui/detail.js
+++ b/modules/weko-records-ui/weko_records_ui/static/js/weko_records_ui/detail.js
@@ -272,25 +272,303 @@ require([
}
});
- $('#secret_url')?.on('click', function(){
- const webelement = $('#secret_url');
- if (webelement){
+ // シークレットURL作成フォーム
+ // link_name フィールドの入力を検証
+ const MAX_LENGTH=50;
+ const linkNameInput = document.querySelector('#link_name');
+ if (linkNameInput) {
+ linkNameInput.maxLength = MAX_LENGTH;
+ }
+
+ // APIエンドポイントから設定を取得
+ fetch('/get-secret-settings')
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`Network response was not ok: ${response.statusText}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ // APIからのデータをフォームに反映
+ const secretDownloadLimit = data.secret_download_limit;
+ const secretExpirationDate = data.secret_expiration_date;
+ const maxSecretExpirationDate = data.max_secret_expiration_date;
+ const maxSecretDownloadLimit = data.max_secret_download_limit;
+
+ // 今日の日付を取得
+ const today = new Date();
+ const todayFormatted = today.toISOString().split('T')[0];
+
+ // secret_expiration_date を使用して日付を計算
+ const expirationDate = new Date();
+ expirationDate.setDate(today.getDate() + parseInt(secretExpirationDate, 10));
+ const formattedDate = expirationDate.toISOString().split('T')[0];
+
+ // maxSecretExpirationDate を適切な日付形式に変換
+ const maxDate = new Date();
+ maxDate.setDate(maxDate.getDate() + parseInt(maxSecretExpirationDate, 10));
+ const maxFormattedDate = maxDate.toISOString().split('T')[0];
+
+ // 要素に設定
+ const expirationDateInput = document.querySelector('#expiration_date');
+ if (expirationDateInput) {
+ expirationDateInput.value = formattedDate;
+ expirationDateInput.max = maxFormattedDate;
+ expirationDateInput.min = todayFormatted;
+ }
+ // フォームのフィールドに値を設定
+ const downloadLimitInput = document.querySelector('#download_limit');
+ if (downloadLimitInput) {
+ downloadLimitInput.value = secretDownloadLimit;
+ // maxSecretDownloadLimit 以上の入力を制御
+ downloadLimitInput.addEventListener('input', function () {
+ if (parseInt(downloadLimitInput.value, 10) > maxSecretDownloadLimit) {
+ downloadLimitInput.value = maxSecretDownloadLimit;
+ }
+ });
+ }
+ // 有効期限の下に表示するメッセージを設定
+ const maxExpirationData = document.querySelector('#max_date_display');
+ if (maxExpirationData) {
+ const translationDate = maxExpirationData.dataset.expirationDate;
+ maxExpirationData.textContent = ` ※${translationDate} ${maxFormattedDate}`;
+ }
+ // ダウンロード制限の下に表示するメッセージを設定
+ const maxDownloadDisplay = document.querySelector('#max_download_display');
+ if (maxDownloadDisplay) {
+ const downloadcount = maxDownloadDisplay.dataset.downloadCount;
+ maxDownloadDisplay.textContent = ` ※${downloadcount} ${maxSecretDownloadLimit}`;
+ }
+ })
+ .catch(error => {
+ console.error('Error fetching secret settings:', error);
+ });
+ });
+
+
+ $("#secret_url").click(function() {
+ $("#secret_url_section").toggle();
+ });
+
+ $('#create_secret_url')?.on('click', function(event) {
+ event.preventDefault();
+ const webelement = $('#create_secret_url');
+ if (webelement) {
const url = webelement.attr('url');
- webelement.prop('disabled' ,true);
+ const linkName = $('#link_name').val();
+ const expirationDate = $('#expiration_date').val();
+ const downloadLimit = $('#download_limit').val();
+ const sendEmail = $('#send_email').is(':checked');
+ const timezoneOffsetMinutes = new Date().getTimezoneOffset();
+ const linkNameError = $('#link_name_error');
+ const expirationDateError = $('#expiration_date_error');
+ const downloadLimitError = $('#download_limit_error');
+
+ let hasError = false;
+
+ // エラーチェック関数
+ function checkError(input, errorElement) {
+ if (!input) {
+ errorElement.css('display', 'block'); // エラーメッセージを表示
+ hasError = true;
+ } else {
+ errorElement.css('display', 'none'); // エラーメッセージを非表示
+ }
+ }
+
+ // 各項目のエラーチェック
+ checkError(linkName, linkNameError);
+ checkError(expirationDate, expirationDateError);
+ checkError(downloadLimit, downloadLimitError);
+
+ // エラーがある場合は処理を停止
+ if (hasError) {
+ return;
+ }
+
$.ajax({
url: url,
method: 'POST',
contentType: 'application/json',
- data: null,
- success: function (responce) {
- webelement.prop('disabled',false);
- alert(responce);
+ dataType: 'json',
+ data: JSON.stringify({
+ link_name: linkName,
+ expiration_date: expirationDate,
+ download_limit: parseInt(downloadLimit),
+ send_email: sendEmail,
+ timezone_offset_minutes: timezoneOffsetMinutes,
+ }),
+ success: function(response) {
+ webelement.prop('disabled', false);
+ alert(response.message || "Success!");
+ location.reload();
},
- error: function (jqXHE, status ,msg) {
- webelement.prop('disabled',false);
- alert(msg);
+ error: function(jqXHR, status, msg) {
+ webelement.prop('disabled', false);
+ alert("Error: " + (jqXHR.responseJSON?.message || msg));
}
});
}
});
+
+ $('#print-btn')?.on('click',() => {
+ const iframe = document.createElement('iframe');
+ iframe.srcdoc = ""
+ document.body.appendChild(iframe);
+ iframe.onload = () => {
+ iframe.contentDocument.body.appendChild(document.getElementById('terms').cloneNode(true));
+ iframe.contentWindow.print();
+ }
+ })
+
+
+$('#close_btn, #modal_close_btn').on('click', function () {
+ document.location.href = location.pathname;
+ })
+$('#mailcheck_download_modal').on('hidden.bs.modal', function () {
+ document.location.href = location.pathname;
+})
+$('#mailaddress_confirm_download').click(function () {
+ let mailaddress = document.getElementById('mail_form').value;
+ let password_checkflag = document.getElementById("password_checkflag").value;
+ var input_password;
+ var post_data = {};
+ if(password_checkflag == "True"){
+ input_password = document.getElementById('input_password').value;
+ post_data = {'input_password': input_password};
+}
+ let input_error = document.getElementById('input_error_messsge').value;
+ let url_element = document.getElementById('url_element');
+ let onetime_file_url = url_element.dataset.onetime_file_url;
+ const get_uri = onetime_file_url + '&mailaddress='+ mailaddress + '&isajax=true';
+ let item_detailes_url = location.pathname;
+ if(mailaddress == null || mailaddress == ""){
+ alert(input_error);
+ document.location.href = onetime_file_url;
+ }else{
+ $.ajax({
+ url: get_uri,
+ method: 'POST',
+ async: true,
+ data: JSON.stringify(post_data),
+ contentType: 'application/json',
+ success: function (response) {
+ let link = document.createElement("a");
+ link.download = "";
+ if (!!response.guest_token) {
+ link.href = get_uri + "&guest-token=" + response.guest_token;
+ } else {
+ link.href = get_uri;
+ }
+ link.click();
+ $('#mailcheck_download_modal').modal('hide');
+ document.location.href = item_detailes_url;
+ },
+ error: function (error) {
+ response_text = error['responseText'];
+ alert(response_text);
+ $('#mailcheck_download_modal').modal('hide');
+ document.location.href = item_detailes_url;
+ }
+ })
+ }
+});
+
+
+document.addEventListener('DOMContentLoaded', function() {
+ // 日付をフォーマットする関数
+ function formatDate(dateString) {
+ // Dateオブジェクトを作成
+ const date = new Date(dateString);
+ const year = date.getFullYear();
+ const month = ('0' + (date.getMonth() + 1)).slice(-2);
+ const day = ('0' + date.getDate()).slice(-2);
+ return `${year}-${month}-${day}`;
+ }
+
+ // .date-format クラスを持つすべての要素を取得
+ const dateElements = document.querySelectorAll('.date-format');
+
+ // 各要素の日付をフォーマット
+ dateElements.forEach(function(element) {
+ const originalDate = element.textContent;
+ element.textContent = formatDate(originalDate);
+ });
+});
+
+// 確認メッセージを取得
+const deleteConfirmationMessage = $('#delete-confirmation-message').data('message');
+const deleteSuccssesMessage = $('#delete-success-message').data('message');
+const copyMessage = $('#copy-message').data('message');
+
+$(document).ready(function() {
+ // 共通のAJAXリクエスト関数
+ function handleAjaxRequest($button, url, method, successMessage, clipboardText, finalMessage) {
+ $button.prop('disabled', true);
+ $.ajax({
+ url: url,
+ method: method,
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function(response) {
+ $button.prop('disabled', false);
+ if (clipboardText) {
+ navigator.clipboard.writeText(response.url)
+ .catch(function(err) {
+ alert('Could not copy URL: ', err);
+ });
+ } else {
+ location.reload(); // 画面をリロード
+ }
+ if (finalMessage) {
+ alert(finalMessage);
+ }
+ },
+ error: function(jqXHR, status, msg) {
+ $button.prop('disabled', false);
+ alert("Error: " + (jqXHR.responseJSON?.message || msg));
+ }
+ });
+ }
+
+ // シークレットURLの削除
+ $('.delete_secret_url').on('click', function(event) {
+ event.preventDefault();
+ const $button = $(this);
+ const url = $button.attr('url');
+
+ // 確認ポップアップを表示
+ if (confirm(deleteConfirmationMessage)) {
+ handleAjaxRequest($button, url, 'DELETE', "Success!", false, deleteSuccssesMessage);
+ }
+ });
+
+ // シークレットURLのコピー
+ $('.copy_secret_url').on('click', function(event) {
+ event.preventDefault();
+ const $button = $(this);
+ const url = $button.attr('url');
+ handleAjaxRequest($button, url, 'GET', "Success!", true, copyMessage);
+ });
+
+ // ワンタイムURLの削除
+ $('.delete_onetime_url').on('click', function(event) {
+ event.preventDefault();
+ const $button = $(this);
+ const url = $button.attr('url');
+
+ // 確認ポップアップを表示
+ if (confirm(deleteConfirmationMessage)) {
+ handleAjaxRequest($button, url, 'DELETE', "Success!", false, deleteSuccssesMessage);
+ }
+ });
+
+ // ワンタイムURLのコピー
+ $('.copy_onetime_url').on('click', function(event) {
+ event.preventDefault();
+ const $button = $(this);
+ const url = $button.attr('url');
+ handleAjaxRequest($button, url, 'GET', "Success!", true, copyMessage);
+ });
});
+
diff --git a/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/file_details_contents.html b/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/file_details_contents.html
index 129c88d50e..5d2de3323b 100644
--- a/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/file_details_contents.html
+++ b/modules/weko-records-ui/weko_records_ui/templates/weko_records_ui/file_details_contents.html
@@ -167,6 +167,51 @@ {{ filename.
+ {%- if show_secret_URL -%}
+
+ {%- for file in files | sort(attribute='key') if file.key == filename -%}
+ {%- set is_billing_file = False -%}
+ {%- set billing_file_data = "" -%}
+ {%- set billing_file_url = "" -%}
+ {%- set billing_file_class = "" -%}
+ {%- if billing_files_permission -%}
+ {%- set billing_file_permission = billing_files_permission.get(file.filename) -%}
+ {%- set is_billing_file = True -%}
+ {%- set billing_file_class = " billing-file" -%}
+ {%- set file_url = "javascript:void(0);" -%}
+ {%- set access_permission = record | check_file_permission(file.info()) -%}
+ {%- endif %}
+
+ {%- endfor -%}
+
+ {%- endif -%}
{% from "weko_records_ui/output_detail_data.html" import output_attribute_value_mlt %}
{%- set display_file_info = record.display_file_info -%}
@@ -179,7 +224,100 @@ {{ filename.
{%- endfor -%}
-
+ {%- if show_secret_URL -%}
+ {%- if active_secret_URLs -%}
+
+
+
+
+ | {{_('Secret URL')}} |
+
+
+ | {{_('Label Name')}} |
+ {{_('Create Date')}} |
+ {{_('Expiration Date')}} |
+ {{_('Download Count')}} |
+ {{_('Action')}} |
+
+
+
+ {%- for url in active_secret_URLs -%}
+
+ | {{ url.label_name }} |
+ {{ url.created }} |
+ {{ url.expiration_date }} |
+ {{ url.download_count }}/{{url.download_limit}} |
+
+
+
+
+
+ |
+
+ {%- endfor -%}
+
+
+
+
+
+
+ {%- endif -%}
+ {%- endif -%}
+ {%- if show_onetime_URL -%}
+ {%- if active_onetime_URLs -%}
+
+
+
+
+ | {{_('Onetime URL')}} |
+
+
+ | {{_('User Name')}} |
+ {{_('Create Date')}} |
+ {{_('Expiration Date')}} |
+ {{_('Download Count')}} |
+ {{_('Action')}} |
+
+
+
+ {%- for url in active_onetime_URLs -%}
+
+ | {{ url.user_mail }} |
+ {{ url.created }} |
+ {{ url.expiration_date }} |
+ {{ url.download_count }}/{{url.download_limit}} |
+
+
+
+
+
+ |
+
+ {%- endfor -%}
+
+
+
+
+
+
+ {%- endif -%}
+ {%- endif -%}
- {{_('Version')}}
diff --git a/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.mo b/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.mo
index 77e8ab730f..64569bd093 100644
Binary files a/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.mo and b/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.mo differ
diff --git a/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.po b/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.po
index 6561112995..8e462f94c8 100644
--- a/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.po
+++ b/modules/weko-records-ui/weko_records_ui/translations/en/LC_MESSAGES/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: weko-records-ui 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2019-04-25 18:57+0900\n"
+"POT-Creation-Date: 2025-02-10 15:07+0900\n"
"PO-Revision-Date: 2018-04-12 18:06+0900\n"
"Last-Translator: FULL NAME \n"
"Language: en\n"
@@ -19,548 +19,706 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
-#: weko_records_ui/admin.py:73
+#: tests/test_utils.py:541 weko_records_ui/fd.py:468 weko_records_ui/fd.py:546
+#: weko_records_ui/utils.py:1109
+msgid "Unexpected error occurred."
+msgstr ""
+
+#: tests/test_utils.py:545 weko_records_ui/utils.py:1111
+msgid "Failed to send mail."
+msgstr ""
+
+#: weko_records_ui/admin.py:89
msgid "Author flag was updated."
msgstr "Updated Author flag"
-#: weko_records_ui/admin.py:137 weko_records_ui/admin.py:146
-#: weko_records_ui/admin.py:155 weko_records_ui/admin.py:353
+#: weko_records_ui/admin.py:165
+#, fuzzy
+msgid "Institution Name was updated."
+msgstr "Updated Author flag"
+
+#: weko_records_ui/admin.py:228 weko_records_ui/admin.py:237
+#: weko_records_ui/admin.py:246
msgid "Setting"
msgstr ""
-#: weko_records_ui/admin.py:138
+#: weko_records_ui/admin.py:229
msgid "Others"
msgstr ""
-#: weko_records_ui/admin.py:147
+#: weko_records_ui/admin.py:238 weko_records_ui/admin.py:255
msgid "Items"
msgstr ""
-#: weko_records_ui/admin.py:156
+#: weko_records_ui/admin.py:247
#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:98
msgid "PDF Cover Page"
msgstr ""
-#: weko_records_ui/admin.py:196
-msgid "Prefix"
+#: weko_records_ui/admin.py:256
+msgid "Bulk Update"
+msgstr ""
+
+#: weko_records_ui/config.py:394
+msgid "write your own license"
+msgstr ""
+
+#: weko_records_ui/config.py:399
+msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
+msgstr ""
+
+#: weko_records_ui/config.py:414
+msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
+msgstr ""
+
+#: weko_records_ui/config.py:426
+msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
+msgstr ""
+
+#: weko_records_ui/config.py:440
+msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
msgstr ""
-#: weko_records_ui/admin.py:202
-msgid "Suffix"
+#: weko_records_ui/config.py:454
+msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
msgstr ""
-#: weko_records_ui/admin.py:204
-msgid "Enable/Disable"
+#: weko_records_ui/config.py:468
+msgid ""
+"Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC "
+"BY-NC-SA 3.0)"
msgstr ""
-#: weko_records_ui/admin.py:214
-msgid "Repository"
+#: weko_records_ui/config.py:482
+msgid ""
+"Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-"
+"NC-ND 3.0)"
msgstr ""
-#: weko_records_ui/admin.py:214
-msgid "JaLC DOI"
+#: weko_records_ui/config.py:497
+msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
msgstr ""
-#: weko_records_ui/admin.py:215
-msgid "JaLC CrossRef DOI"
+#: weko_records_ui/config.py:509
+msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
msgstr ""
-#: weko_records_ui/admin.py:216
-msgid "JaLC DataCite DOI"
+#: weko_records_ui/config.py:523
+msgid ""
+"Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND "
+"4.0)"
msgstr ""
-#: weko_records_ui/admin.py:829
-msgid "NDL JaLC DOI"
+#: weko_records_ui/config.py:537
+msgid ""
+"Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC "
+"4.0)"
msgstr ""
-#: weko_records_ui/admin.py:217
-msgid "CNRI"
+#: weko_records_ui/config.py:551
+msgid ""
+"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
+"(CC BY-NC-SA 4.0)"
msgstr ""
-#: weko_records_ui/admin.py:218
-msgid "Semi-automatic Suffix"
-msgstr "Formatted Suffix"
+#: weko_records_ui/config.py:565
+msgid ""
+"Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 "
+"International (CC BY-NC-ND 4.0)"
+msgstr ""
-#: weko_records_ui/admin.py:235
-msgid "Only allow halfwith 1-bytes character in input"
+#: weko_records_ui/fd.py:439 weko_records_ui/fd.py:531
+#, python-format
+msgid "The file \"%s\" does not exist."
msgstr ""
-#: weko_records_ui/admin.py:354
-msgid "Identifier"
+#: weko_records_ui/pdf.py:662
+msgid "The storage path is incorrect."
msgstr ""
-#: weko_records_ui/config.py:46
-msgid "write your own license"
+#: weko_records_ui/pdf.py:664 weko_records_ui/pdf.py:677
+#: weko_records_ui/pdf.py:690
+msgid "Please contact the administrator."
msgstr ""
-#: weko_records_ui/config.py:47 weko_records_ui/views.py:178
-msgid "Creative Commons : Attribution"
+#: weko_records_ui/pdf.py:675
+msgid "The storage location cannot be accessed."
msgstr ""
-#: weko_records_ui/config.py:48 weko_records_ui/views.py:179
-msgid "Creative Commons : Attribution - ShareAlike"
+#: weko_records_ui/pdf.py:689
+msgid "There is not enough storage space."
msgstr ""
-#: weko_records_ui/config.py:49 weko_records_ui/views.py:180
-msgid "Creative Commons : Attribution - NoDerivatives"
+#: weko_records_ui/utils.py:436
+msgid "Item cannot be deleted because the import is in progress."
msgstr ""
-#: weko_records_ui/config.py:50 weko_records_ui/views.py:181
-msgid "Creative Commons : Attribution - NonCommercial"
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:147
+#: weko_records_ui/utils.py:889
+msgid "Restricted Access"
+msgstr ""
+
+#: weko_records_ui/utils.py:1373
+msgid "Guest"
+msgstr ""
+
+#: weko_records_ui/utils.py:1384
+msgid "Free Input"
+msgstr ""
+
+#: weko_records_ui/utils.py:2080
+msgid "The provided token is invalid."
+msgstr ""
+
+#: weko_records_ui/utils.py:2084
+msgid "This feature is currently disabled."
+msgstr ""
+
+#: weko_records_ui/utils.py:2089
+msgid "This file is currently not available for this feature."
+msgstr ""
+
+#: weko_records_ui/utils.py:2094
+msgid "This URL has been deactivated."
+msgstr ""
+
+#: weko_records_ui/utils.py:2096
+msgid "The download limit has been exceeded."
msgstr ""
-#: weko_records_ui/config.py:51 weko_records_ui/views.py:182
-msgid "Creative Commons : Attribution - NonCommercial - ShareAlike"
+#: weko_records_ui/utils.py:2099
+msgid "The expiration date for download has been exceeded."
+msgstr ""
+
+#: weko_records_ui/views.py:769
+msgid "Secret URL generated successfully"
+msgstr ""
+
+#: weko_records_ui/views.py:774
+msgid ", please check your email inbox"
+msgstr ""
+
+#: weko_records_ui/views.py:776
+msgid ""
+", but there was an error while sending the email. To use the URL, please "
+"refresh the page and copy it from the issued URL list"
msgstr ""
-#: weko_records_ui/config.py:52 weko_records_ui/views.py:183
-msgid "Creative Commons : Attribution - NonCommercial - NoDerivatives"
+#: weko_records_ui/views.py:779
+msgid "."
msgstr ""
-#: weko_records_ui/views.py:479
+#: weko_records_ui/views.py:1008
msgid "PDF cover page settings have been updated."
msgstr "Updated PDF cover settings"
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:34
-msgid "Index"
+#: weko_records_ui/templates/weko_records_ui/_macros.html:23
+msgid "This data is not available for this user."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:60
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:29
-msgid "Item"
+#: weko_records_ui/templates/weko_records_ui/_macros.html:45
+#: weko_records_ui/templates/weko_records_ui/_macros.html:58
+#: weko_records_ui/templates/weko_records_ui/_macros.html:70
+#: weko_records_ui/templates/weko_records_ui/_macros.html:83
+#: weko_records_ui/templates/weko_records_ui/_macros.html:101
+#: weko_records_ui/templates/weko_records_ui/_macros.html:130
+#: weko_records_ui/templates/weko_records_ui/_macros.html:144
+#: weko_records_ui/templates/weko_records_ui/_macros.html:159
+#: weko_records_ui/templates/weko_records_ui/_macros.html:175
+#: weko_records_ui/templates/weko_records_ui/_macros.html:193
+msgid "Apply JGSS"
+msgstr "Apply"
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:210
+msgid "Terms and Conditions"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:63
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:32
-msgid "No title"
+#: weko_records_ui/templates/weko_records_ui/_macros.html:232
+msgid "I have read and agreed to the Terms and Conditions"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:85
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:48
-msgid "Name"
+#: weko_records_ui/templates/weko_records_ui/_macros.html:242
+#: weko_records_ui/templates/weko_records_ui/box/analysis.html:79
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:55
+msgid "Next"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:110
+#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:115
+msgid "Search repository"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/box/export.html:26
+#: weko_records_ui/templates/weko_records_ui/export_well.html:24
+msgid "OAI-PMH"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/box/export.html:23
+#: weko_records_ui/templates/weko_records_ui/export_well.html:38
+msgid "Export"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details.html:116
+msgid "Confirm"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:85
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:53
+#: weko_records_ui/templates/weko_records_ui/file_details.html:119
+msgid "This file is a Billing file. (Price: XXXXX). Do you want to download it?"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details.html:123
+msgid "Yes"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details.html:124
+msgid "No"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:33
+msgid "Item"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/box/head.html:80
+#: weko_records_ui/templates/weko_records_ui/box/head.html:83
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:36
+msgid "No title"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:64
msgid "File"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:86
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:54
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:65
msgid "License"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:98
-msgid "Detail"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:67
+msgid "Action"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:127
-msgid "Restricted Access"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:100
+msgid ""
+"The file cannot be downloaded because you do not have permission to view "
+"this file."
msgstr ""
+"The file cannot be downloaded because you do not have permission to view "
+"it."
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:136
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:77
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:120
msgid "Original"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:147
-msgid "Plagiarism Check"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:143
+msgid "Secret URL"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:161
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:188
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:34
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:114
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:139
-msgid "Preview"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:156
+msgid "Plagarism Check"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:226
-msgid "item type"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:266
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:289
+msgid "Version"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:289
-msgid "Link"
+#: weko_records_ui/templates/weko_records_ui/box/stats.html:5
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:267
+msgid "Stats"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:299
-msgid "Publish Status"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:275
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:295
+msgid "Show"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:312
-msgid "Public"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:276
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:295
+msgid "Hide"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:314
-msgid "Change to Private"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:290
+msgid "Date Modified"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:317
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:323
-msgid "Private"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:291
+msgid "Object File Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:319
-msgid "Change to Public"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:292
+msgid "File Size"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:323
-msgid "Publish"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:293
+msgid "File Hash Value"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:343
-msgid "Back"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:294
+msgid "Contributor Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:347
-msgid "Edit"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:316
+msgid "Downloads"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:352
-msgid "Delete"
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:324
+msgid "Plays"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:359
-msgid "Confirm"
+#: weko_records_ui/templates/weko_records_ui/box/stats.html:29
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:334
+msgid "See details"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:38
+msgid "Item type"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:104
+msgid "Thumbnail"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:136
+msgid "Link"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:148
+msgid "Publish Status"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:162
+msgid "Public"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:167
+msgid "Change to Private"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:349
-msgid "The workflow is being edited."
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:170
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:180
+msgid "Private"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:175
+msgid "Change to Public"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:362
-msgid "Are you sure you want to delete this item?"
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:179
+msgid "Publish"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:365
-msgid "OK"
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:131
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:172
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:227
+msgid "Language:"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/body_contents.html:366
-msgid "Cancel"
+#: weko_records_ui/templates/weko_records_ui/tombstone.html:13
+msgid "This item has been deleted."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:34
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:25
msgid "Fields For Update"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:65
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:58
msgid "Open Access"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:68
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:61
msgid "Open Access Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:72
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:65
msgid "Login User Only"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:83
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:76
msgid "Add Field"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:91
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:84
msgid "Search"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:119
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:110
msgid "Item list"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:132
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:123
msgid "Export Checked Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:133
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:124
msgid "Export All Displayed Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:134
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:125
msgid "Export All Items Of This Index"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:135
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:126
msgid "Print Checked Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:136
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:127
msgid "Print All Displayed Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:137
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:128
msgid "Print All Items Of This Index"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:139
-msgid "Execution"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:142
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:169
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:132
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:159
msgid "Display order"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:144
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:134
msgid "Title(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:145
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:135
msgid "Title(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:146
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:136
msgid "Registrant(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:147
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:137
msgid "Registrant(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:148
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:138
msgid "Item Types(Asending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:149
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:139
msgid "Item Types(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:150
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:140
msgid "ID(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:151
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:141
msgid "ID(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:152
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:142
msgid "Modified Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:153
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:143
msgid "Modified Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:154
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:144
msgid "Created Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:155
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:145
msgid "Created Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:156
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:146
msgid "Review Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:157
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:147
msgid "Review Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:158
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:148
msgid "Published Year(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:159
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:149
msgid "Published Year(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:160
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:150
msgid "Custom(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:161
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:151
msgid "Custom(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:188
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:178
msgid "The number of display"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:204
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:194
msgid "Select All"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:208
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:198
msgid "Search failed."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:214
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:204
msgid "Loading..."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:57
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:89
-#: weko_records_ui/templates/weko_records_ui/bulk_update_display.html:243
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:233
msgid "Update"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/export.html:25
-#: weko_records_ui/templates/weko_records_ui/export_well.html:24
-msgid "OAI-PMH"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/box/export.html:39
-#: weko_records_ui/templates/weko_records_ui/export_well.html:38
-msgid "Export"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:101
-msgid "Plagarism Check"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:177
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:194
-msgid "Version"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/box/stats.html:4
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:178
-msgid "Stats"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:186
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:200
-msgid "Show"
+#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:43
+msgid "Institution Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:187
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:200
-msgid "Hide"
+#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:56
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:90
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:241
+msgid "Save"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:195
-msgid "Date Modified"
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:35
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:41
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:50
+msgid "Display Email"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:196
-msgid "Object File Name"
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:45
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:54
+msgid "Hide Email"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:197
-msgid "File Size"
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:61
+msgid "Open Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:198
-msgid "File Hash Value"
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:67
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:76
+msgid "Display"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:199
-msgid "Contributor Name"
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:71
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:80
+msgid "Hide Open Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:220
-msgid "Downloads"
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:137
+msgid "Header Settings"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:228
-msgid "Plays"
+#: weko_records_ui/templates/weko_records_ui/box/analysis.html:27
+#: weko_records_ui/templates/weko_records_ui/box/analysis.html:31
+msgid "Online Analysis"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/stats.html:22
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:238
-msgid "See details"
+#: weko_records_ui/templates/weko_records_ui/box/analysis.html:42
+msgid "Terms of Use"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:29
-msgid "Life Time"
+#: weko_records_ui/templates/weko_records_ui/box/analysis.html:70
+msgid "I have read and agreed to the Terms of Use"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:46
-msgid "Institution Name"
+#: weko_records_ui/templates/weko_records_ui/box/export.html:40
+msgid "Other Formats"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:34
-msgid "Search Author"
+#: weko_records_ui/templates/weko_records_ui/box/head.html:26
+msgid "There is a"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:40
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:49
-msgid "Search by Author Name"
+#: weko_records_ui/templates/weko_records_ui/box/head.html:27
+msgid "newer version"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:44
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:53
-msgid "Search by Author ID"
+#: weko_records_ui/templates/weko_records_ui/box/head.html:27
+msgid "of this record available."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:60
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:66
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:75
-msgid "Display Email"
+#: weko_records_ui/templates/weko_records_ui/box/meta.html:42
+msgid "Publication date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:70
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:79
-msgid "Hide Email"
+#: weko_records_ui/templates/weko_records_ui/box/meta.html:48
+msgid "Schema"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:137
-msgid "Header Settings"
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:34
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:34
+msgid "Preview"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:241
-msgid " Update"
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:48
+msgid "Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/analysis.html:27
-#: weko_records_ui/templates/weko_records_ui/box/analysis.html:31
-msgid "Online Analysis"
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:49
+msgid "Size"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/analysis.html:42
-msgid "Terms of Use"
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:58
+msgid ""
+"This is the file fingerprint (MD5 checksum), which can be used to verify "
+"the file integrity."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/analysis.html:70
-msgid "I have read and agreed to the Terms of Use"
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
+msgid "Download"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/analysis.html:79
-msgid "Next"
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:47
+msgid "First"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/meta.html:42
-msgid "Publication date"
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:51
+msgid "Previous"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/meta.html:48
-msgid "Schema"
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:59
+msgid "Last"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:49
-msgid "Size"
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:119
+msgid "Cannot preview because the file size is too large."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:58
-msgid ""
-"This is the file fingerprint (MD5 checksum), which can be used to verify "
-"the file integrity."
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:138
+msgid "No preview available."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
-msgid "Download"
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:155
+msgid "Unable to load preview."
msgstr ""
#: weko_records_ui/templates/weko_records_ui/box/share.html:23
msgid "Share"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/share.html:41
+#: weko_records_ui/templates/weko_records_ui/box/share.html:55
msgid "Your record could not be processed by the citation formatter"
msgstr "Could not show by the citation formatter"
-#: weko_records_ui/templates/weko_records_ui/box/stats.html:29
+#: weko_records_ui/templates/weko_records_ui/box/stats.html:21
+msgid "Choose stats period"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/box/stats.html:36
msgid "Views"
msgstr ""
+#: weko_records_ui/templates/weko_records_ui/box/tools.html:23
+msgid "Tools"
+msgstr ""
+
#: weko_records_ui/templates/weko_records_ui/box/versions.html:2
msgid "Versions"
msgstr ""
-#: weko_workflow/templates/weko_workflow/modal_withdraw_confirmation.html:44
-msgid "Are you sure you want to withdraw DOI?"
+#: weko_records_ui/templates/weko_records_ui/box/versions.html:5
+msgid "Ver."
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/box/versions.html:37
+msgid "Show All versions"
msgstr ""
#~ msgid "Privating"
@@ -584,778 +742,793 @@ msgstr ""
#~ msgid "Period"
#~ msgstr ""
-#: weko-records-ui/weko_records_ui/templates/weko_records_ui/body_contents.html:146
-#: weko-records-ui/weko_records_ui/templates/weko_records_ui/file_details_contents.html:86
-msgid "The file cannot be downloaded because you do not have permission to view this file."
-msgstr "The file cannot be downloaded because you do not have permission to view it."
+#~ msgid "Prefix"
+#~ msgstr ""
-#: weko-records-ui/weko_records_ui/templates/weko_records_ui/body_contents.html:436
-#: weko-records-ui/weko_records_ui/templates/weko_records_ui/file_details.html:112
-msgid "This file is a Billing file. (Price: XXXXX). Do you want to download it?"
-msgstr ""
+#~ msgid "Suffix"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "There is a"
-msgstr ""
+#~ msgid "Enable/Disable"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "newer version"
-msgstr ""
+#~ msgid "Repository"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "of this record available."
-msgstr ""
+#~ msgid "JaLC DOI"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "User Name"
-msgstr ""
+#~ msgid "JaLC CrossRef DOI"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Corresponding Usage Application ID"
-msgstr ""
+#~ msgid "JaLC DataCite DOI"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Annual Report"
-msgstr ""
+#~ msgid "NDL JaLC DOI"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Corresponding Output ID"
-msgstr ""
+#~ msgid "CNRI"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Data Type"
-msgstr ""
+#~ msgid "Semi-automatic Suffix"
+#~ msgstr "Formatted Suffix"
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Content File"
-msgstr ""
+#~ msgid "Only allow halfwith 1-bytes character in input"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Affiliated Institution"
-msgstr ""
+#~ msgid "Identifier"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "User Information"
-msgstr ""
+#~ msgid "Creative Commons : Attribution"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "FullName"
-msgstr ""
+#~ msgid "Creative Commons : Attribution - ShareAlike"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Usage location"
-msgstr ""
+#~ msgid "Creative Commons : Attribution - NoDerivatives"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Advisor Name"
-msgstr ""
+#~ msgid "Creative Commons : Attribution - NonCommercial"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Advisor Affiliation"
-msgstr ""
+#~ msgid "Creative Commons : Attribution - NonCommercial - ShareAlike"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Advisor Mail Address"
-msgstr ""
+#~ msgid "Creative Commons : Attribution - NonCommercial - NoDerivatives"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Advisor Phone Number"
-msgstr ""
+#~ msgid "Index"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Research Title"
-msgstr ""
+#~ msgid "Detail"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Research Plan"
-msgstr ""
+#~ msgid "Plagiarism Check"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Guarantor Name"
-msgstr ""
+#~ msgid "item type"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Guarantor Affiliation"
-msgstr ""
+#~ msgid "Back"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Guarantor Mail Address"
-msgstr ""
+#~ msgid "Edit"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Item Title"
-msgstr ""
+#~ msgid "Delete"
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Position(Other)"
-msgstr ""
+#~ msgid "The workflow is being edited."
+#~ msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:6
-msgid "Affiliation"
-msgstr ""
+#~ msgid "Are you sure you want to delete this item?"
+#~ msgstr ""
-msgid "PubDate"
-msgstr ""
+#~ msgid "OK"
+#~ msgstr ""
-msgid "life"
-msgstr ""
+#~ msgid "Cancel"
+#~ msgstr ""
-msgid "accumulation"
-msgstr ""
+#~ msgid "Execution"
+#~ msgstr ""
-msgid "combinational_analysis"
-msgstr ""
+#~ msgid "Life Time"
+#~ msgstr ""
-msgid "perfectures"
-msgstr ""
+#~ msgid "Search Author"
+#~ msgstr ""
-msgid "location_information"
-msgstr ""
+#~ msgid "Search by Author Name"
+#~ msgstr ""
-msgid "Output Type"
-msgstr ""
+#~ msgid "Search by Author ID"
+#~ msgstr ""
-msgid "Published Media Name"
-msgstr ""
+#~ msgid " Update"
+#~ msgstr ""
-msgid "Published URL (DOI)"
-msgstr ""
+#~ msgid "Are you sure you want to withdraw DOI?"
+#~ msgstr ""
-msgid "Published Date"
-msgstr ""
+#~ msgid "User Name"
+#~ msgstr ""
-msgid "Field"
-msgstr ""
+#~ msgid "Corresponding Usage Application ID"
+#~ msgstr ""
-msgid "Member"
-msgstr ""
+#~ msgid "Annual Report"
+#~ msgstr ""
-msgid "Dataset Usage"
-msgstr ""
+#~ msgid "Corresponding Output ID"
+#~ msgstr ""
-msgid "Stop"
-msgstr ""
+#~ msgid "Data Type"
+#~ msgstr ""
-msgid "Position(Others)"
-msgstr ""
+#~ msgid "Content File"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "write your own license"
-msgstr ""
+#~ msgid "Affiliated Institution"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
-msgstr ""
+#~ msgid "User Information"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
-msgstr ""
+#~ msgid "FullName"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
-msgstr ""
+#~ msgid "Usage location"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
-msgstr ""
+#~ msgid "Advisor Name"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)"
-msgstr ""
+#~ msgid "Advisor Affiliation"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-NC-ND 3.0)"
-msgstr ""
+#~ msgid "Advisor Mail Address"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
-msgstr ""
+#~ msgid "Advisor Phone Number"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
-msgstr ""
+#~ msgid "Research Title"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0)"
-msgstr ""
+#~ msgid "Research Plan"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)"
-msgstr ""
+#~ msgid "Guarantor Name"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)"
-msgstr ""
+#~ msgid "Guarantor Affiliation"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)"
-msgstr ""
+#~ msgid "Guarantor Mail Address"
+#~ msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
-msgstr ""
+#~ msgid "Item Title"
+#~ msgstr ""
+
+#~ msgid "Position(Other)"
+#~ msgstr ""
+
+#~ msgid "Affiliation"
+#~ msgstr ""
+
+#~ msgid "PubDate"
+#~ msgstr ""
+
+#~ msgid "life"
+#~ msgstr ""
+
+#~ msgid "accumulation"
+#~ msgstr ""
+
+#~ msgid "combinational_analysis"
+#~ msgstr ""
+
+#~ msgid "perfectures"
+#~ msgstr ""
+
+#~ msgid "location_information"
+#~ msgstr ""
+
+#~ msgid "Output Type"
+#~ msgstr ""
+
+#~ msgid "Published Media Name"
+#~ msgstr ""
+
+#~ msgid "Published URL (DOI)"
+#~ msgstr ""
+
+#~ msgid "Published Date"
+#~ msgstr ""
+
+#~ msgid "Field"
+#~ msgstr ""
+
+#~ msgid "Member"
+#~ msgstr ""
+
+#~ msgid "Dataset Usage"
+#~ msgstr ""
+
+#~ msgid "Stop"
+#~ msgstr ""
+
+#~ msgid "Position(Others)"
+#~ msgstr ""
# WEKO_RECORDS_UI_ITEM_DETAIL
-msgid "Date (ISO-8601)"
-msgstr ""
+#~ msgid "Date (ISO-8601)"
+#~ msgstr ""
-msgid "Subject"
-msgstr ""
+#~ msgid "Subject"
+#~ msgstr ""
-msgid "Subject Scheme"
-msgstr ""
+#~ msgid "Subject Scheme"
+#~ msgstr ""
-msgid "Subject URI"
-msgstr ""
+#~ msgid "Subject URI"
+#~ msgstr ""
-msgid "Alternative Title"
-msgstr ""
+#~ msgid "Alternative Title"
+#~ msgstr ""
-msgid "Creator"
-msgstr ""
+#~ msgid "Creator"
+#~ msgstr ""
-msgid "Creator Name Identifier"
-msgstr ""
+#~ msgid "Creator Name Identifier"
+#~ msgstr ""
-msgid "Creator Name Identifier Scheme"
-msgstr ""
+#~ msgid "Creator Name Identifier Scheme"
+#~ msgstr ""
-msgid "Creator Name Identifier URI"
-msgstr ""
+#~ msgid "Creator Name Identifier URI"
+#~ msgstr ""
-msgid "Creator Name"
-msgstr ""
+#~ msgid "Creator Name"
+#~ msgstr ""
-msgid "Name_"
-msgstr "Name"
+#~ msgid "Name_"
+#~ msgstr "Name"
-msgid "Creator Family Name"
-msgstr ""
+#~ msgid "Creator Family Name"
+#~ msgstr ""
-msgid "Family Name"
-msgstr ""
+#~ msgid "Family Name"
+#~ msgstr ""
-msgid "Creator Given Name"
-msgstr ""
+#~ msgid "Creator Given Name"
+#~ msgstr ""
-msgid "Given Name"
-msgstr ""
+#~ msgid "Given Name"
+#~ msgstr ""
-msgid "Creator Alternative Name"
-msgstr ""
+#~ msgid "Creator Alternative Name"
+#~ msgstr ""
-msgid "Alternative Name"
-msgstr ""
+#~ msgid "Alternative Name"
+#~ msgstr ""
-msgid "Affiliation Name Identifier"
-msgstr ""
+#~ msgid "Affiliation Name Identifier"
+#~ msgstr ""
-msgid "Affiliation Name Identifier Scheme"
-msgstr ""
+#~ msgid "Affiliation Name Identifier Scheme"
+#~ msgstr ""
-msgid "Affiliation Name Identifier URI"
-msgstr ""
+#~ msgid "Affiliation Name Identifier URI"
+#~ msgstr ""
-msgid "Affiliation Name"
-msgstr ""
+#~ msgid "Affiliation Name"
+#~ msgstr ""
-msgid "Creator Email Address"
-msgstr ""
+#~ msgid "Creator Email Address"
+#~ msgstr ""
-msgid "Description Type"
-msgstr ""
+#~ msgid "Description Type"
+#~ msgstr ""
-msgid "Bibliographic Information"
-msgstr ""
+#~ msgid "Bibliographic Information"
+#~ msgstr ""
-msgid "Journal Title"
-msgstr ""
+#~ msgid "Journal Title"
+#~ msgstr ""
-msgid "Volume Number"
-msgstr ""
+#~ msgid "Volume Number"
+#~ msgstr ""
-msgid "Issue Number"
-msgstr ""
+#~ msgid "Issue Number"
+#~ msgstr ""
-msgid "Page Start"
-msgstr ""
+#~ msgid "Page Start"
+#~ msgstr ""
-msgid "Page End"
-msgstr ""
+#~ msgid "Page End"
+#~ msgstr ""
-msgid "Publication year"
-msgstr ""
+#~ msgid "Publication year"
+#~ msgstr ""
-msgid "Date Type"
-msgstr ""
+#~ msgid "Date Type"
+#~ msgstr ""
-msgid "Publisher"
-msgstr ""
+#~ msgid "Publisher"
+#~ msgstr ""
-msgid "Source Identifier"
-msgstr ""
+#~ msgid "Source Identifier"
+#~ msgstr ""
-msgid "Source Identifier Type"
-msgstr ""
+#~ msgid "Source Identifier Type"
+#~ msgstr ""
-msgid "Source Identifier"
-msgstr ""
+#~ msgid "Relation"
+#~ msgstr ""
-msgid "Relation"
-msgstr ""
+#~ msgid "RelationType"
+#~ msgstr ""
-msgid "RelationType"
-msgstr ""
+#~ msgid "Related Identifier"
+#~ msgstr ""
-msgid "Related Identifier"
-msgstr ""
+#~ msgid "Related Identifier Type"
+#~ msgstr ""
-msgid "Related Identifier Type"
-msgstr ""
+#~ msgid "Identifier Type"
+#~ msgstr ""
-msgid "Identifier Type"
-msgstr ""
+#~ msgid "Related Title"
+#~ msgstr ""
-msgid "Related Title"
-msgstr ""
+#~ msgid "Rights"
+#~ msgstr ""
-msgid "Rights"
-msgstr ""
+#~ msgid "Resource"
+#~ msgstr ""
-msgid "Resource"
-msgstr ""
+#~ msgid "Fileinfo"
+#~ msgstr ""
-msgid "Fileinfo"
-msgstr ""
+#~ msgid "Text"
+#~ msgstr ""
-msgid "Text"
-msgstr ""
+#~ msgid "Version Type"
+#~ msgstr ""
-msgid "Version Type"
-msgstr ""
+#~ msgid "URI"
+#~ msgstr ""
-msgid "URI"
-msgstr ""
+#~ msgid "Label"
+#~ msgstr ""
-msgid "Label"
-msgstr ""
+#~ msgid "Mime Type"
+#~ msgstr ""
-msgid "Mime Type"
-msgstr ""
+#~ msgid "Heading"
+#~ msgstr ""
-msgid "Heading"
-msgstr ""
+#~ msgid "Headline"
+#~ msgstr ""
-msgid "Headline"
-msgstr ""
+#~ msgid "Subheading"
+#~ msgstr ""
-msgid "Subheading"
-msgstr ""
+#~ msgid "Access Right"
+#~ msgstr ""
-msgid "Access Right"
-msgstr ""
+#~ msgid "Access Rights URI"
+#~ msgstr ""
-msgid "Access Rights URI"
-msgstr ""
+#~ msgid "Contributor"
+#~ msgstr ""
-msgid "Contributor"
-msgstr ""
+#~ msgid "Contributor Type"
+#~ msgstr ""
-msgid "Contributor Type"
-msgstr ""
+#~ msgid "Contributor Name Identifier"
+#~ msgstr ""
-msgid "Contributor Name Identifier"
-msgstr ""
+#~ msgid "Contributor Name Identifier Scheme"
+#~ msgstr ""
-msgid "Contributor Name Identifier Scheme"
-msgstr ""
+#~ msgid "Contributor Name Identifier URI"
+#~ msgstr ""
-msgid "Contributor Name Identifier URI"
-msgstr ""
+#~ msgid "Contributor_Name"
+#~ msgstr "Contributor Name"
-msgid "Contributor_Name"
-msgstr "Contributor Name"
+#~ msgid "Contributor Family Name"
+#~ msgstr ""
-msgid "Contributor Family Name"
-msgstr ""
+#~ msgid "Contributor Given Name"
+#~ msgstr ""
-msgid "Contributor Given Name"
-msgstr ""
+#~ msgid "Contributor Alternative Name"
+#~ msgstr ""
-msgid "Contributor Alternative Name"
-msgstr ""
+#~ msgid "Contributor Alternative"
+#~ msgstr ""
-msgid "Contributor Alternative"
-msgstr ""
+#~ msgid "Contributor Email Address"
+#~ msgstr ""
-msgid "Contributor Email Address"
-msgstr ""
+#~ msgid "Degree Name"
+#~ msgstr ""
-msgid "Degree Name"
-msgstr ""
+#~ msgid "Degree Grantor"
+#~ msgstr ""
-msgid "Degree Grantor"
-msgstr ""
+#~ msgid "Degree Grantor Name Identifier"
+#~ msgstr ""
-msgid "Degree Grantor Name Identifier"
-msgstr ""
+#~ msgid "Degree Grantor Name"
+#~ msgstr ""
-msgid "Degree Grantor Name"
-msgstr ""
+#~ msgid "Date Granted"
+#~ msgstr ""
-msgid "Date Granted"
-msgstr ""
+#~ msgid "Dissertation Number"
+#~ msgstr ""
-msgid "Dissertation Number"
-msgstr ""
+#~ msgid "Contributor ID"
+#~ msgstr ""
-msgid "Contributor ID"
-msgstr ""
+#~ msgid "Funding Reference"
+#~ msgstr ""
-msgid "Funding Reference"
-msgstr ""
+#~ msgid "Funder Name"
+#~ msgstr ""
-msgid "Funder Name"
-msgstr ""
+#~ msgid "Award Number"
+#~ msgstr ""
-msgid "Award Number"
-msgstr ""
+#~ msgid "Book Name"
+#~ msgstr ""
-msgid "Book Name"
-msgstr ""
+#~ msgid "Date Reported"
+#~ msgstr ""
-msgid "Date Reported"
-msgstr ""
+#~ msgid "Name Identifier"
+#~ msgstr ""
-msgid "Name Identifier"
-msgstr ""
+#~ msgid "Name Identifier Scheme"
+#~ msgstr ""
-msgid "Name Identifier Scheme"
-msgstr ""
+#~ msgid "Description_"
+#~ msgstr "Description"
-msgid "Description_"
-msgstr "Description"
+#~ msgid "Rights Resource"
+#~ msgstr ""
-msgid "Rights Resource"
-msgstr ""
+#~ msgid "Rights Holder"
+#~ msgstr ""
-msgid "Rights Holder"
-msgstr ""
+#~ msgid "Rights Holder Name Identifier"
+#~ msgstr ""
-msgid "Rights Holder Name Identifier"
-msgstr ""
+#~ msgid "Rights Holder Name Identifier Scheme"
+#~ msgstr ""
-msgid "Rights Holder Name Identifier Scheme"
-msgstr ""
+#~ msgid "Rights Holder Name Identifier URI"
+#~ msgstr ""
-msgid "Rights Holder Name Identifier URI"
-msgstr ""
+#~ msgid "Rights Holder Name"
+#~ msgstr ""
-msgid "Rights Holder Name"
-msgstr ""
+#~ msgid "Resource Type"
+#~ msgstr ""
-msgid "Resource Type"
-msgstr ""
+#~ msgid "Temporal"
+#~ msgstr ""
-msgid "Temporal"
-msgstr ""
+#~ msgid "Geo Location"
+#~ msgstr ""
-msgid "Geo Location"
-msgstr ""
+#~ msgid "Geo Location Point"
+#~ msgstr ""
-msgid "Geo Location Point"
-msgstr ""
+#~ msgid "Point Longitude"
+#~ msgstr ""
-msgid "Point Longitude"
-msgstr ""
+#~ msgid "Point Latitude"
+#~ msgstr ""
-msgid "Point Latitude"
-msgstr ""
+#~ msgid "Geo Location Box"
+#~ msgstr ""
-msgid "Geo Location Box"
-msgstr ""
+#~ msgid "West Bound Longitude"
+#~ msgstr ""
-msgid "West Bound Longitude"
-msgstr ""
+#~ msgid "East Bound Longitude"
+#~ msgstr ""
-msgid "East Bound Longitude"
-msgstr ""
+#~ msgid "South Bound Latitude"
+#~ msgstr ""
-msgid "South Bound Latitude"
-msgstr ""
+#~ msgid "North Bound Latitude"
+#~ msgstr ""
-msgid "North Bound Latitude"
-msgstr ""
+#~ msgid "Geo Location Place"
+#~ msgstr ""
-msgid "Geo Location Place"
-msgstr ""
+#~ msgid "funder Identifier"
+#~ msgstr ""
-msgid "funder Identifier"
-msgstr ""
+#~ msgid "Funder Identifier Type"
+#~ msgstr ""
-msgid "Funder Identifier Type"
-msgstr ""
+#~ msgid "Award Number URI"
+#~ msgstr ""
-msgid "Award Number URI"
-msgstr ""
+#~ msgid "AwardTitle"
+#~ msgstr ""
-msgid "AwardTitle"
-msgstr ""
+#~ msgid "Source Title"
+#~ msgstr ""
-msgid "Source Title"
-msgstr ""
+#~ msgid "Number of Pages"
+#~ msgstr ""
-msgid "Number of Pages"
-msgstr ""
+#~ msgid "Degree Grantor Name Identifier Scheme"
+#~ msgstr ""
-msgid "Degree Grantor Name Identifier Scheme"
-msgstr ""
+#~ msgid "Conference"
+#~ msgstr ""
-msgid "Conference"
-msgstr ""
+#~ msgid "Conference Name"
+#~ msgstr ""
-msgid "Conference Name"
-msgstr ""
+#~ msgid "Conference Sequence"
+#~ msgstr ""
-msgid "Conference Sequence"
-msgstr ""
+#~ msgid "Conference Place"
+#~ msgstr ""
-msgid "Conference Place"
-msgstr ""
+#~ msgid "Conference Country"
+#~ msgstr ""
-msgid "Conference Country"
-msgstr ""
+#~ msgid "URI Object Type"
+#~ msgstr ""
-msgid "URI Object Type"
-msgstr ""
+#~ msgid "URI Label"
+#~ msgstr ""
-msgid "URI Label"
-msgstr ""
+#~ msgid "Format"
+#~ msgstr ""
-msgid "Format"
-msgstr ""
+#~ msgid "Extent"
+#~ msgstr ""
-msgid "Extent"
-msgstr ""
+#~ msgid "Issued Date"
+#~ msgstr ""
-msgid "Issued Date"
-msgstr ""
+#~ msgid "Issue"
+#~ msgstr ""
-msgid "Issue"
-msgstr ""
+#~ msgid "Volume"
+#~ msgstr ""
-msgid "Volume"
-msgstr ""
+#~ msgid "Billing File"
+#~ msgstr ""
-msgid "Search repository"
-msgstr ""
+#~ msgid "ID Agency"
+#~ msgstr ""
-msgid "Content File"
-msgstr ""
+#~ msgid "Series"
+#~ msgstr ""
-msgid "Billing File"
-msgstr ""
+#~ msgid "Version Date"
+#~ msgstr ""
-msgid "ID Agency"
-msgstr ""
+#~ msgid "DateType"
+#~ msgstr ""
-msgid "Series"
-msgstr ""
+#~ msgid "Bibliographic Citation"
+#~ msgstr ""
-msgid "Version Date"
-msgstr ""
+#~ msgid "Topic"
+#~ msgstr ""
-msgid "DateType"
-msgstr ""
+#~ msgid "topic vocabURI"
+#~ msgstr ""
-msgid "Bibliographic Citation"
-msgstr ""
+#~ msgid "subjectScheme"
+#~ msgstr ""
-msgid "Topic"
-msgstr ""
+#~ msgid "Topic J"
+#~ msgstr ""
-msgid "Topic"
-msgstr ""
+#~ msgid "Topic E"
+#~ msgstr ""
-msgid "topic vocabURI"
-msgstr ""
+#~ msgid "Time Period"
+#~ msgstr ""
-msgid "subjectScheme"
-msgstr ""
+#~ msgid "Time Period Event"
+#~ msgstr ""
-msgid "Topic J"
-msgstr ""
+#~ msgid "Date Of Collection Event"
+#~ msgstr ""
-msgid "Topic E"
-msgstr ""
+#~ msgid "Geographic Coverage"
+#~ msgstr ""
-msgid "Time Period"
-msgstr ""
+#~ msgid "Unit of Analysis"
+#~ msgstr ""
-msgid "Time Period Event"
-msgstr ""
+#~ msgid "Unit of Analysis J"
+#~ msgstr ""
-msgid "Date Of Collection Event"
-msgstr ""
+#~ msgid "Unit of Analysis E"
+#~ msgstr ""
-msgid "Geographic Coverage"
-msgstr ""
+#~ msgid "Sampling Procedure E"
+#~ msgstr ""
-msgid "Unit of Analysis"
-msgstr ""
+#~ msgid "Sampling Procedure J"
+#~ msgstr ""
-msgid "Unit of Analysis J"
-msgstr ""
+#~ msgid "Collection Method"
+#~ msgstr ""
-msgid "Unit of Analysis E"
-msgstr ""
+#~ msgid "Collection Method J"
+#~ msgstr ""
-msgid "Sampling Procedure E"
-msgstr ""
+#~ msgid "Collection Method E"
+#~ msgstr ""
-msgid "Sampling Procedure J"
-msgstr ""
+#~ msgid "Sampling Rate"
+#~ msgstr ""
-msgid "Collection Method"
-msgstr ""
+#~ msgid "Access"
+#~ msgstr ""
-msgid "Collection Method J"
-msgstr ""
+#~ msgid "Rdf:Resource"
+#~ msgstr ""
-msgid "Collection Method E"
-msgstr ""
+#~ msgid "Access E"
+#~ msgstr ""
-msgid "Sampling Rate"
-msgstr ""
+#~ msgid "Access J"
+#~ msgstr ""
-msgid "Access"
-msgstr ""
+#~ msgid "Study ID"
+#~ msgstr ""
-msgid "Access"
-msgstr ""
+#~ msgid "Copyright"
+#~ msgstr ""
-msgid "Rdf:Resource"
-msgstr ""
+#~ msgid "Topic Vocab"
+#~ msgstr ""
-msgid "Access E"
-msgstr ""
+#~ msgid "Topic Vocab URI"
+#~ msgstr ""
-msgid "Access J"
-msgstr ""
+#~ msgid "Date Of Collection"
+#~ msgstr ""
-msgid "Study ID"
-msgstr ""
+#~ msgid "Event"
+#~ msgstr ""
-msgid "Copyright"
-msgstr ""
+#~ msgid "Universe"
+#~ msgstr ""
-msgid "Topic Vocab"
-msgstr ""
+#~ msgid "Data Type J"
+#~ msgstr ""
-msgid "Topic Vocab URI"
-msgstr ""
+#~ msgid "Data Type E"
+#~ msgstr ""
-msgid "Date Of Collection"
-msgstr ""
+#~ msgid "Sampling Procedure"
+#~ msgstr ""
-msgid "Event"
-msgstr ""
+#~ msgid "Identifier Registration Type"
+#~ msgstr ""
-msgid "Universe"
-msgstr ""
+#~ msgid "Identifier Registration"
+#~ msgstr ""
-msgid "Data Type J"
-msgstr ""
+#~ msgid "Related Study"
+#~ msgstr ""
-msgid "Data Type E"
-msgstr ""
+#~ msgid "Related Study DOI"
+#~ msgstr ""
-msgid "Sampling Procedure"
-msgstr ""
+#~ msgid "Related Publications"
+#~ msgstr ""
-msgid "Identifier Registration Type"
-msgstr ""
+#~ msgid "Related Publications DOI"
+#~ msgstr ""
-msgid "Identifier Registration"
-msgstr ""
+#~ msgid "Fund Agency"
+#~ msgstr ""
-msgid "Related Study"
-msgstr ""
+#~ msgid "Fund Agency ID"
+#~ msgstr ""
-msgid "Related Study DOI"
-msgstr ""
+#~ msgid "GrantNo"
+#~ msgstr ""
-msgid "Related Publications"
-msgstr ""
+#~ msgid "Distributor Abbreviation"
+#~ msgstr ""
-msgid "Related Publications DOI"
-msgstr ""
+#~ msgid "Distributor Affiliation"
+#~ msgstr ""
-msgid "Fund Agency"
-msgstr ""
+#~ msgid "Distributor URI"
+#~ msgstr ""
-msgid "Fund Agency ID"
-msgstr ""
+#~ msgid "Contributor IdentifierType"
+#~ msgstr ""
-msgid "Funder Identifier Type"
-msgstr ""
+#~ msgid "Distributor Name"
+#~ msgstr ""
-msgid "GrantNo"
-msgstr ""
+#~ msgid "Award Title"
+#~ msgstr ""
-msgid "Distributor Abbreviation"
-msgstr ""
+#~ msgid "Related Study Title"
+#~ msgstr ""
-msgid "Distributor Affiliation"
-msgstr ""
+#~ msgid "Related Study Identifier"
+#~ msgstr ""
-msgid "Distributor URI"
-msgstr ""
+#~ msgid "Related Publications Title"
+#~ msgstr ""
-msgid "Contributor IdentifierType"
-msgstr ""
+#~ msgid "Related Publications Identifier"
+#~ msgstr ""
-msgid "Distributor Name"
-msgstr ""
+#~ msgid "Related Publications Identifier Type"
+#~ msgstr ""
-msgid "Award Title"
-msgstr ""
+#~ msgid "GrantURI"
+#~ msgstr ""
-msgid "Related Study Title"
-msgstr ""
+#~ msgid "Related Study Identifier Type"
+#~ msgstr ""
-msgid "Related Study Identifier"
-msgstr ""
+#~ msgid "Grant No"
+#~ msgstr ""
-msgid "Related Publications Title"
-msgstr ""
+#~ msgid "Summary DDI"
+#~ msgstr "Summary"
-msgid "Related Publications Identifier"
-msgstr ""
+#~ msgid "Download is available from {}/{}/{}."
+#~ msgstr "Download is available from {}/{}/{}."
-msgid "Related Publications Identifier Type"
-msgstr ""
+#~ msgid "Download / Preview is available from {}/{}/{}."
+#~ msgstr "Download / Preview is available from {}/{}/{}."
-msgid "GrantURI"
-msgstr ""
+#~ msgid ""
+#~ "This data is not available for "
+#~ "undergraduate students or those who do"
+#~ " not register their positions."
+#~ msgstr ""
-msgid "Related Study Identifier Type"
-msgstr ""
+#~ msgid "Please input email address."
+#~ msgstr ""
-msgid "Grant No"
-msgstr ""
+#~ msgid "Email address"
+#~ msgstr ""
-msgid "Summary DDI"
-msgstr "Summary"
+#~ msgid "Email address(reconfirmation)"
+#~ msgstr ""
-msgid "This item has been deleted."
-msgstr ""
+#~ msgid "Token is invalid."
+#~ msgstr ""
-msgid "Download is available from {}/{}/{}."
-msgstr "Download is available from {}/{}/{}."
+#~ msgid "Success Secret URL Generate"
+#~ msgstr ""
+#~ "Success: Secret URL Generate is succeed."
+#~ " Sent the URL to your email "
+#~ "adress."
msgid "Download / Preview is available from {}/{}/{}."
msgstr "Download / Preview is available from {}/{}/{}."
+
msgid "Apply JGSS"
msgstr "Apply"
@@ -1385,3 +1558,16 @@ msgstr ""
msgid "Success Secret URL Generate"
msgstr "Success: Secret URL Generate is succeed. Sent the URL to your email adress."
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html
+msgid "Max Download Count"
+msgstr "Max Download Limit"
+
+msgid "message_del_check"
+msgstr "If you delete this URL, it will no longer be available. Are you sure you want to delete it?"
+
+msgid "message_del_success"
+msgstr "URL has been removed"
+
+msgid "message_copy_success"
+msgstr "URL has been copied to the clipboard"
diff --git a/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.mo b/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.mo
index e4d42d46ae..0d4b76b585 100644
Binary files a/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.mo and b/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.mo differ
diff --git a/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.po b/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.po
index 4532b82131..55774890aa 100644
--- a/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.po
+++ b/modules/weko-records-ui/weko_records_ui/translations/ja/LC_MESSAGES/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: weko-records-ui 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2021-03-25 14:23+0900\n"
+"POT-Creation-Date: 2025-02-25 09:09+0900\n"
"PO-Revision-Date: 2021-02-02 03:25+0000\n"
"Last-Translator: FULL NAME \n"
"Language: ja\n"
@@ -17,494 +17,676 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.8.0\n"
+"Generated-By: Babel 2.5.1\n"
-#: weko_records_ui/admin.py:87
+#: tests/test_utils.py:542 weko_records_ui/fd.py:468 weko_records_ui/fd.py:546
+#: weko_records_ui/utils.py:1109
+msgid "Unexpected error occurred."
+msgstr "予期しないエラーが発生しました"
+
+#: tests/test_utils.py:546 weko_records_ui/utils.py:1111
+msgid "Failed to send mail."
+msgstr ""
+
+#: weko_records_ui/admin.py:89
msgid "Author flag was updated."
msgstr ""
-#: weko_records_ui/admin.py:148
+#: weko_records_ui/admin.py:165
msgid "Institution Name was updated."
msgstr ""
-#: weko_records_ui/admin.py:212 weko_records_ui/admin.py:221
-#: weko_records_ui/admin.py:230
+#: weko_records_ui/admin.py:228 weko_records_ui/admin.py:237
+#: weko_records_ui/admin.py:246
msgid "Setting"
msgstr ""
-#: weko_records_ui/admin.py:213
+#: weko_records_ui/admin.py:229
msgid "Others"
msgstr ""
-#: weko_records_ui/admin.py:222 weko_records_ui/admin.py:239
+#: weko_records_ui/admin.py:238 weko_records_ui/admin.py:255
msgid "Items"
msgstr ""
-#: weko_records_ui/admin.py:231
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:91
+#: weko_records_ui/admin.py:247
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:98
msgid "PDF Cover Page"
msgstr ""
-#: weko_records_ui/admin.py:240
+#: weko_records_ui/admin.py:256
msgid "Bulk Update"
msgstr ""
-#: weko_records_ui/config.py:296
+#: weko_records_ui/config.py:394
msgid "write your own license"
msgstr ""
-#: weko_records_ui/config.py:301
+#: weko_records_ui/config.py:399
msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
msgstr ""
-#: weko_records_ui/config.py:316
+#: weko_records_ui/config.py:414
msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
msgstr ""
-#: weko_records_ui/config.py:328
+#: weko_records_ui/config.py:426
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
msgstr ""
-#: weko_records_ui/config.py:342
+#: weko_records_ui/config.py:440
msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
msgstr ""
-#: weko_records_ui/config.py:356
+#: weko_records_ui/config.py:454
msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
msgstr ""
-#: weko_records_ui/config.py:370
+#: weko_records_ui/config.py:468
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC "
"BY-NC-SA 3.0)"
msgstr ""
-#: weko_records_ui/config.py:384
+#: weko_records_ui/config.py:482
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-"
"NC-ND 3.0)"
msgstr ""
-#: weko_records_ui/config.py:399
+#: weko_records_ui/config.py:497
msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
msgstr ""
-#: weko_records_ui/config.py:411
+#: weko_records_ui/config.py:509
msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
msgstr ""
-#: weko_records_ui/config.py:425
+#: weko_records_ui/config.py:523
msgid ""
"Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND "
"4.0)"
msgstr ""
-#: weko_records_ui/config.py:439
+#: weko_records_ui/config.py:537
msgid ""
"Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC "
"4.0)"
msgstr ""
-#: weko_records_ui/config.py:453
+#: weko_records_ui/config.py:551
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
"(CC BY-NC-SA 4.0)"
msgstr ""
-#: weko_records_ui/config.py:467
+#: weko_records_ui/config.py:565
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 "
"International (CC BY-NC-ND 4.0)"
msgstr ""
-#: weko_records_ui/pdf.py:556
+#: weko_records_ui/fd.py:439 weko_records_ui/fd.py:531
+#, python-format
+msgid "The file \"%s\" does not exist."
+msgstr "指定されたファイル「\"%s\"」が存在しません"
+
+#: weko_records_ui/pdf.py:662
msgid "The storage path is incorrect."
msgstr ""
-#: weko_records_ui/pdf.py:558 weko_records_ui/pdf.py:571
-#: weko_records_ui/pdf.py:584
+#: weko_records_ui/pdf.py:664 weko_records_ui/pdf.py:677
+#: weko_records_ui/pdf.py:690
msgid "Please contact the administrator."
msgstr ""
-#: weko_records_ui/pdf.py:569
+#: weko_records_ui/pdf.py:675
msgid "The storage location cannot be accessed."
msgstr ""
-#: weko_records_ui/pdf.py:583
+#: weko_records_ui/pdf.py:689
msgid "There is not enough storage space."
msgstr ""
-#: weko_records_ui/utils.py:185
+#: weko_records_ui/utils.py:436
msgid "Item cannot be deleted because the import is in progress."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:113
-#: weko_records_ui/utils.py:570
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:147
+#: weko_records_ui/utils.py:889
msgid "Restricted Access"
msgstr ""
-#: weko_records_ui/views.py:681
+#: weko_records_ui/utils.py:1373
+msgid "Guest"
+msgstr ""
+
+#: weko_records_ui/utils.py:1384
+msgid "Free Input"
+msgstr ""
+
+#: weko_records_ui/utils.py:2103
+msgid "The provided token is invalid."
+msgstr "トークンが無効です。"
+
+#: weko_records_ui/utils.py:2107
+msgid "This feature is currently disabled."
+msgstr "この機能は現在ご利用頂けません。"
+
+#: weko_records_ui/utils.py:2112
+msgid "This file is currently not available for this feature."
+msgstr "このファイルは現在ダウンロードできません。"
+
+#: weko_records_ui/utils.py:2117
+msgid "This URL has been deactivated."
+msgstr "このURLは削除されました。"
+
+#: weko_records_ui/utils.py:2119
+msgid "The download limit has been exceeded."
+msgstr "ダウンロード制限回数を超過しています。"
+
+#: weko_records_ui/utils.py:2122
+msgid "The expiration date for download has been exceeded."
+msgstr "ダウンロード有効期限を超過しています。"
+
+#: weko_records_ui/views.py:806
+msgid "Secret URL generated successfully"
+msgstr "シークレットURLの作成に成功しました"
+
+#: weko_records_ui/views.py:811
+msgid ", please check your email inbox"
+msgstr "。メールをご確認ください"
+
+#: weko_records_ui/views.py:813
+msgid ""
+", but there was an error while sending the email. To use the URL, please "
+"refresh the page and copy it from the issued URL list"
+msgstr "が、メール送信エラーが発生しました。ページを更新し、URL一覧表からご利用ください"
+
+#: weko_records_ui/views.py:816
+msgid "."
+msgstr "。"
+
+#: weko_records_ui/views.py:1045
msgid "PDF cover page settings have been updated."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/_macros.html:31
-#: weko_records_ui/templates/weko_records_ui/_macros.html:46
-#: weko_records_ui/templates/weko_records_ui/_macros.html:78
-#: weko_records_ui/templates/weko_records_ui/_macros.html:94
-#: weko_records_ui/templates/weko_records_ui/_macros.html:113
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:55
-msgid "Download"
-msgstr "ダウンロード"
+#: weko_records_ui/templates/weko_records_ui/_macros.html:23
+msgid "This data is not available for this user."
+msgstr "このデータは利用できません(権限がないため)。"
-#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:77
+#: weko_records_ui/templates/weko_records_ui/_macros.html:45
+#: weko_records_ui/templates/weko_records_ui/_macros.html:58
+#: weko_records_ui/templates/weko_records_ui/_macros.html:70
+#: weko_records_ui/templates/weko_records_ui/_macros.html:83
+#: weko_records_ui/templates/weko_records_ui/_macros.html:101
+#: weko_records_ui/templates/weko_records_ui/_macros.html:130
+#: weko_records_ui/templates/weko_records_ui/_macros.html:144
+#: weko_records_ui/templates/weko_records_ui/_macros.html:159
+#: weko_records_ui/templates/weko_records_ui/_macros.html:175
+#: weko_records_ui/templates/weko_records_ui/_macros.html:193
+msgid "Apply JGSS"
+msgstr "申請"
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:210
+msgid "Terms and Conditions"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:232
+msgid "I have read and agreed to the Terms and Conditions"
+msgstr "上記の条件に同意する"
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:242
+#: weko_records_ui/templates/weko_records_ui/box/analysis.html:79
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:55
+msgid "Next"
+msgstr "次へ"
+
+#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:110
+#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:115
msgid "Search repository"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/export.html:24
-#: weko_records_ui/templates/weko_records_ui/export_well.html:21
+#: weko_records_ui/templates/weko_records_ui/box/export.html:26
+#: weko_records_ui/templates/weko_records_ui/export_well.html:24
msgid "OAI-PMH"
msgstr ""
#: weko_records_ui/templates/weko_records_ui/box/export.html:23
-#: weko_records_ui/templates/weko_records_ui/export_well.html:31
+#: weko_records_ui/templates/weko_records_ui/export_well.html:38
msgid "Export"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:80
+#: weko_records_ui/templates/weko_records_ui/file_details.html:116
msgid "Confirm"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:83
+#: weko_records_ui/templates/weko_records_ui/file_details.html:119
msgid "This file is a Billing file. (Price: XXXXX). Do you want to download it?"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:87
+#: weko_records_ui/templates/weko_records_ui/file_details.html:123
msgid "Yes"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:88
+#: weko_records_ui/templates/weko_records_ui/file_details.html:124
msgid "No"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:30
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:33
msgid "Item"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:54
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:33
+#: weko_records_ui/templates/weko_records_ui/box/head.html:80
+#: weko_records_ui/templates/weko_records_ui/box/head.html:83
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:36
msgid "No title"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:58
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:64
msgid "File"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:59
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:65
msgid "License"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:86
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:67
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:240
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:287
+msgid "Action"
+msgstr "アクション"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:100
msgid ""
"The file cannot be downloaded because you do not have permission to view "
"this file."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:101
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:120
msgid "Original"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:119
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:143
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:233
+msgid "Secret URL"
+msgstr "シークレットURL"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:156
msgid "Plagarism Check"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:142
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:163
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:186
+msgid "Link Name"
+msgstr "リンク名"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:188
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:193
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:199
+msgid "Item has not been filled in."
+msgstr "項目が未入力です"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:191
+msgid "URL Expiry Date"
+msgstr "URL有効期限"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:194
+msgid "Max Expiry Date"
+msgstr "有効期限上限"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:197
+msgid "Download Limit"
+msgstr "ダウンロード回数"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:200
+msgid "Max Download Count"
+msgstr "ダウンロード回数上限"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:204
+msgid "Create Secret URL"
+msgstr "シークレットURL作成"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:207
+msgid "Send Email"
+msgstr "メール通知"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:236
+msgid "Label Name"
+msgstr "リンク名"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:237
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:284
+msgid "Create Date"
+msgstr "作成日時"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:238
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:285
+msgid "Expiration Date"
+msgstr "DL期限"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:239
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:286
+msgid "Download Count"
+msgstr "DL回数"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:255
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:302
+msgid "Delete"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:260
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:307
+msgid "Copy"
+msgstr "コピー"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:268
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:315
+msgid "message_del_check"
+msgstr "このURLを削除すると、利用できなくなります。本当に削除しますか?"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:269
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:316
+msgid "message_del_success"
+msgstr "URLが削除されました"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:270
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:317
+msgid "message_copy_success"
+msgstr "URLがクリップボードにコピーされました"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:280
+msgid "Onetime URL"
+msgstr "ワンタイムURL"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:283
+msgid "User Name"
+msgstr "ユーザー名"
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:323
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:346
msgid "Version"
msgstr ""
#: weko_records_ui/templates/weko_records_ui/box/stats.html:5
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:143
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:324
msgid "Stats"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:151
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:169
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:332
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:352
msgid "Show"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:152
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:169
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:333
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:352
msgid "Hide"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:164
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:347
msgid "Date Modified"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:165
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:348
msgid "Object File Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:166
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:349
msgid "File Size"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:167
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:350
msgid "File Hash Value"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:168
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:351
msgid "Contributor Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:190
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:373
msgid "Downloads"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:198
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:381
msgid "Plays"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:67
-msgid "Action"
-msgstr "アクション"
-
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:142
-msgid "Secret URL"
-msgstr "シークレットURL"
-
#: weko_records_ui/templates/weko_records_ui/box/stats.html:29
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:208
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:391
msgid "See details"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:29
-msgid "item type"
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:38
+msgid "Item type"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:79
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:104
msgid "Thumbnail"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:97
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:136
msgid "Link"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:108
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:148
msgid "Publish Status"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:119
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:162
msgid "Public"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:124
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:167
msgid "Change to Private"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:127
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:137
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:170
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:180
msgid "Private"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:132
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:175
msgid "Change to Public"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:136
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:179
msgid "Publish"
msgstr ""
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:131
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:172
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:227
+msgid "Language:"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/tombstone.html:13
+msgid "This item has been deleted."
+msgstr "このアイテムは削除されています。"
#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:25
msgid "Fields For Update"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:54
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:58
msgid "Open Access"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:57
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:61
msgid "Open Access Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:61
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:65
msgid "Login User Only"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:72
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:76
msgid "Add Field"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:80
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:84
msgid "Search"
msgstr "検索"
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:101
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:110
msgid "Item list"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:112
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:123
msgid "Export Checked Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:113
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:124
msgid "Export All Displayed Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:114
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:125
msgid "Export All Items Of This Index"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:115
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:126
msgid "Print Checked Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:116
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:127
msgid "Print All Displayed Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:117
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:128
msgid "Print All Items Of This Index"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:121
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:144
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:132
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:159
msgid "Display order"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:123
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:134
msgid "Title(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:124
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:135
msgid "Title(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:125
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:136
msgid "Registrant(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:126
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:137
msgid "Registrant(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:127
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:138
msgid "Item Types(Asending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:128
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:139
msgid "Item Types(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:129
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:140
msgid "ID(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:130
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:141
msgid "ID(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:131
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:142
msgid "Modified Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:132
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:143
msgid "Modified Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:133
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:144
msgid "Created Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:134
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:145
msgid "Created Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:135
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:146
msgid "Review Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:136
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:147
msgid "Review Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:137
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:148
msgid "Published Year(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:138
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:149
msgid "Published Year(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:139
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:150
msgid "Custom(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:140
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:151
msgid "Custom(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:158
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:178
msgid "The number of display"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:173
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:194
msgid "Select All"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:176
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:198
msgid "Search failed."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:180
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:204
msgid "Loading..."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:203
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:233
msgid "Update"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:27
-msgid "Life Time"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:40
+#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:43
msgid "Institution Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:51
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:78
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:234
+#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:56
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:90
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:241
msgid "Save"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:29
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:34
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:42
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:35
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:41
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:50
msgid "Display Email"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:38
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:46
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:45
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:54
msgid "Hide Email"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:52
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:61
msgid "Open Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:57
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:65
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:67
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:76
msgid "Display"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:61
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:69
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:71
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:80
msgid "Hide Open Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:130
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:137
msgid "Header Settings"
msgstr ""
@@ -521,79 +703,75 @@ msgstr "利用について"
msgid "I have read and agreed to the Terms of Use"
msgstr "上記の条件に同意する"
-#: weko_records_ui/templates/weko_records_ui/box/analysis.html:79
-msgid "Next"
-msgstr "次へ"
-
-#: weko_records_ui/templates/weko_records_ui/box/export.html:34
+#: weko_records_ui/templates/weko_records_ui/box/export.html:40
msgid "Other Formats"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:23
+#: weko_records_ui/templates/weko_records_ui/box/head.html:26
msgid "There is a"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:24
+#: weko_records_ui/templates/weko_records_ui/box/head.html:27
msgid "newer version"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:24
+#: weko_records_ui/templates/weko_records_ui/box/head.html:27
msgid "of this record available."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/meta.html:36
+#: weko_records_ui/templates/weko_records_ui/box/meta.html:42
msgid "Publication date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/meta.html:39
+#: weko_records_ui/templates/weko_records_ui/box/meta.html:48
msgid "Schema"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:32
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:55
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:27
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:34
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:34
msgid "Preview"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:43
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:48
msgid "Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:44
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:49
msgid "Size"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:52
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:58
msgid ""
"This is the file fingerprint (MD5 checksum), which can be used to verify "
"the file integrity."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:39
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
+msgid "Download"
+msgstr "ダウンロード"
+
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:47
msgid "First"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:43
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:51
msgid "Previous"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:47
-msgid "Next"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:51
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:59
msgid "Last"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:89
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:119
msgid "Cannot preview because the file size is too large."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:105
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:138
msgid "No preview available."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:120
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:155
msgid "Unable to load preview."
msgstr ""
@@ -601,7 +779,7 @@ msgstr ""
msgid "Share"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/share.html:39
+#: weko_records_ui/templates/weko_records_ui/box/share.html:55
msgid "Your record could not be processed by the citation formatter"
msgstr ""
@@ -613,47 +791,49 @@ msgstr "表示する統計期間を選択"
msgid "Views"
msgstr ""
+#: weko_records_ui/templates/weko_records_ui/box/tools.html:23
+msgid "Tools"
+msgstr ""
+
#: weko_records_ui/templates/weko_records_ui/box/versions.html:2
msgid "Versions"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/versions.html:2
+#: weko_records_ui/templates/weko_records_ui/box/versions.html:5
msgid "Ver."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/versions.html:21
+#: weko_records_ui/templates/weko_records_ui/box/versions.html:37
msgid "Show All versions"
msgstr ""
-msgid "This item has been deleted."
-msgstr "このアイテムは削除されています。"
-
-msgid "Apply JGSS"
-msgstr "申請"
+#~ msgid "item type"
+#~ msgstr ""
-msgid "This data is not available for undergraduate students or those who do not register their positions."
-msgstr "このデータは利用できません(学部生または役職が登録されていないため)"
+#~ msgid "Life Time"
+#~ msgstr ""
-msgid "Please input email address."
-msgstr "メールアドレスを入力してください。"
+#~ msgid ""
+#~ "This data is not available for "
+#~ "undergraduate students or those who do"
+#~ " not register their positions."
+#~ msgstr "このデータは利用できません(学部生または役職が登録されていないため)"
-msgid "Email address"
-msgstr "メールアドレス"
+#~ msgid "Please input email address."
+#~ msgstr "メールアドレスを入力してください。"
-msgid "Email address(reconfirmation)"
-msgstr "メールアドレス(確認用)"
+#~ msgid "Email address"
+#~ msgstr "メールアドレス"
-msgid "Token is invalid."
-msgstr "トークンが無効です。"
+#~ msgid "Email address(reconfirmation)"
+#~ msgstr "メールアドレス(確認用)"
-msgid "The expiration date for download has been exceeded."
-msgstr "ダウンロード有効期限を超過しています。"
+#~ msgid "Success Secret URL Generate"
+#~ msgstr "成功: シークレットURLを生成し、あなたのメールアドレス宛に送信しました。"
-msgid "The download limit has been exceeded."
-msgstr "ダウンロード制限回数を超過しています。"
+#~ msgid "Download Limit Initial Value"
+#~ msgstr "ダウンロード回数初期値"
-msgid "This data is not available for this user."
-msgstr "このデータは利用できません(権限がないため)。"
+#~ msgid "Expiration Date Initial Value"
+#~ msgstr "有効期限日数初期値"
-msgid "Success Secret URL Generate"
-msgstr "成功: シークレットURLを生成し、あなたのメールアドレス宛に送信しました。"
diff --git a/modules/weko-records-ui/weko_records_ui/translations/messages.pot b/modules/weko-records-ui/weko_records_ui/translations/messages.pot
index dc2230acab..ecdeac9987 100644
--- a/modules/weko-records-ui/weko_records_ui/translations/messages.pot
+++ b/modules/weko-records-ui/weko_records_ui/translations/messages.pot
@@ -1,319 +1,502 @@
# Translations template for weko-records-ui.
-# Copyright (C) 2021 National Institute of Informatics
+# Copyright (C) 2025 National Institute of Informatics
# This file is distributed under the same license as the weko-records-ui
# project.
-# FIRST AUTHOR , 2021.
+# FIRST AUTHOR , 2025.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: weko-records-ui 0.1.0.dev20170000\n"
"Report-Msgid-Bugs-To: wekosoftware@nii.ac.jp\n"
-"POT-Creation-Date: 2021-03-25 14:23+0900\n"
+"POT-Creation-Date: 2025-02-25 09:09+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.8.0\n"
+"Generated-By: Babel 2.5.1\n"
-#: weko_records_ui/admin.py:87
+#: tests/test_utils.py:542 weko_records_ui/fd.py:468 weko_records_ui/fd.py:546
+#: weko_records_ui/utils.py:1109
+msgid "Unexpected error occurred."
+msgstr ""
+
+#: tests/test_utils.py:546 weko_records_ui/utils.py:1111
+msgid "Failed to send mail."
+msgstr ""
+
+#: weko_records_ui/admin.py:89
msgid "Author flag was updated."
msgstr ""
-#: weko_records_ui/admin.py:148
+#: weko_records_ui/admin.py:165
msgid "Institution Name was updated."
msgstr ""
-#: weko_records_ui/admin.py:212 weko_records_ui/admin.py:221
-#: weko_records_ui/admin.py:230
+#: weko_records_ui/admin.py:228 weko_records_ui/admin.py:237
+#: weko_records_ui/admin.py:246
msgid "Setting"
msgstr ""
-#: weko_records_ui/admin.py:213
+#: weko_records_ui/admin.py:229
msgid "Others"
msgstr ""
-#: weko_records_ui/admin.py:222 weko_records_ui/admin.py:239
+#: weko_records_ui/admin.py:238 weko_records_ui/admin.py:255
msgid "Items"
msgstr ""
-#: weko_records_ui/admin.py:231
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:91
+#: weko_records_ui/admin.py:247
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:98
msgid "PDF Cover Page"
msgstr ""
-#: weko_records_ui/admin.py:240
+#: weko_records_ui/admin.py:256
msgid "Bulk Update"
msgstr ""
-#: weko_records_ui/config.py:296
+#: weko_records_ui/config.py:394
msgid "write your own license"
msgstr ""
-#: weko_records_ui/config.py:301
+#: weko_records_ui/config.py:399
msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
msgstr ""
-#: weko_records_ui/config.py:316
+#: weko_records_ui/config.py:414
msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
msgstr ""
-#: weko_records_ui/config.py:328
+#: weko_records_ui/config.py:426
msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
msgstr ""
-#: weko_records_ui/config.py:342
+#: weko_records_ui/config.py:440
msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
msgstr ""
-#: weko_records_ui/config.py:356
+#: weko_records_ui/config.py:454
msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
msgstr ""
-#: weko_records_ui/config.py:370
+#: weko_records_ui/config.py:468
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC "
"BY-NC-SA 3.0)"
msgstr ""
-#: weko_records_ui/config.py:384
+#: weko_records_ui/config.py:482
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-"
"NC-ND 3.0)"
msgstr ""
-#: weko_records_ui/config.py:399
+#: weko_records_ui/config.py:497
msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
msgstr ""
-#: weko_records_ui/config.py:411
+#: weko_records_ui/config.py:509
msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
msgstr ""
-#: weko_records_ui/config.py:425
+#: weko_records_ui/config.py:523
msgid ""
"Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND "
"4.0)"
msgstr ""
-#: weko_records_ui/config.py:439
+#: weko_records_ui/config.py:537
msgid ""
"Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC "
"4.0)"
msgstr ""
-#: weko_records_ui/config.py:453
+#: weko_records_ui/config.py:551
msgid ""
"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
"(CC BY-NC-SA 4.0)"
msgstr ""
-#: weko_records_ui/config.py:467
+#: weko_records_ui/config.py:565
msgid ""
"Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 "
"International (CC BY-NC-ND 4.0)"
msgstr ""
-#: weko_records_ui/pdf.py:556
+#: weko_records_ui/fd.py:439 weko_records_ui/fd.py:531
+#, python-format
+msgid "The file \"%s\" does not exist."
+msgstr ""
+
+#: weko_records_ui/pdf.py:662
msgid "The storage path is incorrect."
msgstr ""
-#: weko_records_ui/pdf.py:558 weko_records_ui/pdf.py:571
-#: weko_records_ui/pdf.py:584
+#: weko_records_ui/pdf.py:664 weko_records_ui/pdf.py:677
+#: weko_records_ui/pdf.py:690
msgid "Please contact the administrator."
msgstr ""
-#: weko_records_ui/pdf.py:569
+#: weko_records_ui/pdf.py:675
msgid "The storage location cannot be accessed."
msgstr ""
-#: weko_records_ui/pdf.py:583
+#: weko_records_ui/pdf.py:689
msgid "There is not enough storage space."
msgstr ""
-#: weko_records_ui/utils.py:185
+#: weko_records_ui/utils.py:436
msgid "Item cannot be deleted because the import is in progress."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:113
-#: weko_records_ui/utils.py:570
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:147
+#: weko_records_ui/utils.py:889
msgid "Restricted Access"
msgstr ""
-#: weko_records_ui/views.py:681
+#: weko_records_ui/utils.py:1373
+msgid "Guest"
+msgstr ""
+
+#: weko_records_ui/utils.py:1384
+msgid "Free Input"
+msgstr ""
+
+#: weko_records_ui/utils.py:2103
+msgid "The provided token is invalid."
+msgstr ""
+
+#: weko_records_ui/utils.py:2107
+msgid "This feature is currently disabled."
+msgstr ""
+
+#: weko_records_ui/utils.py:2112
+msgid "This file is currently not available for this feature."
+msgstr ""
+
+#: weko_records_ui/utils.py:2117
+msgid "This URL has been deactivated."
+msgstr ""
+
+#: weko_records_ui/utils.py:2119
+msgid "The download limit has been exceeded."
+msgstr ""
+
+#: weko_records_ui/utils.py:2122
+msgid "The expiration date for download has been exceeded."
+msgstr ""
+
+#: weko_records_ui/views.py:806
+msgid "Secret URL generated successfully"
+msgstr ""
+
+#: weko_records_ui/views.py:811
+msgid ", please check your email inbox"
+msgstr ""
+
+#: weko_records_ui/views.py:813
+msgid ""
+", but there was an error while sending the email. To use the URL, please "
+"refresh the page and copy it from the issued URL list"
+msgstr ""
+
+#: weko_records_ui/views.py:816
+msgid "."
+msgstr ""
+
+#: weko_records_ui/views.py:1045
msgid "PDF cover page settings have been updated."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/_macros.html:31
-#: weko_records_ui/templates/weko_records_ui/_macros.html:46
-#: weko_records_ui/templates/weko_records_ui/_macros.html:78
-#: weko_records_ui/templates/weko_records_ui/_macros.html:94
-#: weko_records_ui/templates/weko_records_ui/_macros.html:113
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:55
-msgid "Download"
+#: weko_records_ui/templates/weko_records_ui/_macros.html:23
+msgid "This data is not available for this user."
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:45
+#: weko_records_ui/templates/weko_records_ui/_macros.html:58
+#: weko_records_ui/templates/weko_records_ui/_macros.html:70
+#: weko_records_ui/templates/weko_records_ui/_macros.html:83
+#: weko_records_ui/templates/weko_records_ui/_macros.html:101
+#: weko_records_ui/templates/weko_records_ui/_macros.html:130
+#: weko_records_ui/templates/weko_records_ui/_macros.html:144
+#: weko_records_ui/templates/weko_records_ui/_macros.html:159
+#: weko_records_ui/templates/weko_records_ui/_macros.html:175
+#: weko_records_ui/templates/weko_records_ui/_macros.html:193
+msgid "Apply JGSS"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:210
+msgid "Terms and Conditions"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:232
+msgid "I have read and agreed to the Terms and Conditions"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/_macros.html:242
+#: weko_records_ui/templates/weko_records_ui/box/analysis.html:79
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:55
+msgid "Next"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:77
+#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:110
+#: weko_records_ui/templates/weko_records_ui/creator_detail_template.html:115
msgid "Search repository"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/export.html:24
-#: weko_records_ui/templates/weko_records_ui/export_well.html:21
+#: weko_records_ui/templates/weko_records_ui/box/export.html:26
+#: weko_records_ui/templates/weko_records_ui/export_well.html:24
msgid "OAI-PMH"
msgstr ""
#: weko_records_ui/templates/weko_records_ui/box/export.html:23
-#: weko_records_ui/templates/weko_records_ui/export_well.html:31
+#: weko_records_ui/templates/weko_records_ui/export_well.html:38
msgid "Export"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:80
+#: weko_records_ui/templates/weko_records_ui/file_details.html:116
msgid "Confirm"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:83
+#: weko_records_ui/templates/weko_records_ui/file_details.html:119
msgid "This file is a Billing file. (Price: XXXXX). Do you want to download it?"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:87
+#: weko_records_ui/templates/weko_records_ui/file_details.html:123
msgid "Yes"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details.html:88
+#: weko_records_ui/templates/weko_records_ui/file_details.html:124
msgid "No"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:30
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:33
msgid "Item"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:54
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:33
+#: weko_records_ui/templates/weko_records_ui/box/head.html:80
+#: weko_records_ui/templates/weko_records_ui/box/head.html:83
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:36
msgid "No title"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:58
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:64
msgid "File"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:59
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:65
msgid "License"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:86
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:67
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:240
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:287
+msgid "Action"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:100
msgid ""
"The file cannot be downloaded because you do not have permission to view "
"this file."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:101
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:120
msgid "Original"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:119
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:143
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:233
+msgid "Secret URL"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:156
msgid "Plagarism Check"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:142
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:163
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:186
+msgid "Link Name"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:188
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:193
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:199
+msgid "Item has not been filled in."
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:191
+msgid "URL Expiry Date"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:194
+msgid "Max Expiry Date"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:197
+msgid "Download Limit"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:200
+msgid "Max Download Count"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:204
+msgid "Create Secret URL"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:207
+msgid "Send Email"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:236
+msgid "Label Name"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:237
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:284
+msgid "Create Date"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:238
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:285
+msgid "Expiration Date"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:239
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:286
+msgid "Download Count"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:255
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:302
+msgid "Delete"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:260
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:307
+msgid "Copy"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:268
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:315
+msgid "message_del_check"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:269
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:316
+msgid "message_del_success"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:270
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:317
+msgid "message_copy_success"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:280
+msgid "Onetime URL"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:283
+msgid "User Name"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:323
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:346
msgid "Version"
msgstr ""
#: weko_records_ui/templates/weko_records_ui/box/stats.html:5
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:143
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:324
msgid "Stats"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:151
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:169
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:332
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:352
msgid "Show"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:152
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:169
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:333
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:352
msgid "Hide"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:164
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:347
msgid "Date Modified"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:165
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:348
msgid "Object File Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:166
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:349
msgid "File Size"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:167
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:350
msgid "File Hash Value"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:168
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:351
msgid "Contributor Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:190
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:373
msgid "Downloads"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:198
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:381
msgid "Plays"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:67
-msgid "Action"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:142
-msgid "Secret URL"
-msgstr ""
-
#: weko_records_ui/templates/weko_records_ui/box/stats.html:29
-#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:208
+#: weko_records_ui/templates/weko_records_ui/file_details_contents.html:391
msgid "See details"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:29
-msgid "item type"
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:38
+msgid "Item type"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:79
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:104
msgid "Thumbnail"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:97
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:136
msgid "Link"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:108
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:148
msgid "Publish Status"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:119
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:162
msgid "Public"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:124
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:167
msgid "Change to Private"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:127
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:137
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:170
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:180
msgid "Private"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:132
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:175
msgid "Change to Public"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/item_detail.html:136
+#: weko_records_ui/templates/weko_records_ui/item_detail.html:179
msgid "Publish"
msgstr ""
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:131
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:172
+#: weko_records_ui/templates/weko_records_ui/output_detail_data.html:227
+msgid "Language:"
+msgstr ""
+
#: weko_records_ui/templates/weko_records_ui/tombstone.html:13
msgid "This item has been deleted."
msgstr ""
@@ -322,191 +505,187 @@ msgstr ""
msgid "Fields For Update"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:54
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:58
msgid "Open Access"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:57
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:61
msgid "Open Access Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:61
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:65
msgid "Login User Only"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:72
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:76
msgid "Add Field"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:80
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:84
msgid "Search"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:101
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:110
msgid "Item list"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:112
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:123
msgid "Export Checked Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:113
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:124
msgid "Export All Displayed Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:114
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:125
msgid "Export All Items Of This Index"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:115
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:126
msgid "Print Checked Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:116
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:127
msgid "Print All Displayed Items"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:117
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:128
msgid "Print All Items Of This Index"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:121
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:144
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:132
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:159
msgid "Display order"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:123
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:134
msgid "Title(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:124
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:135
msgid "Title(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:125
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:136
msgid "Registrant(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:126
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:137
msgid "Registrant(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:127
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:138
msgid "Item Types(Asending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:128
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:139
msgid "Item Types(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:129
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:140
msgid "ID(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:130
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:141
msgid "ID(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:131
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:142
msgid "Modified Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:132
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:143
msgid "Modified Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:133
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:144
msgid "Created Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:134
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:145
msgid "Created Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:135
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:146
msgid "Review Date and Time(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:136
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:147
msgid "Review Date and Time(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:137
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:148
msgid "Published Year(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:138
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:149
msgid "Published Year(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:139
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:150
msgid "Custom(Ascending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:140
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:151
msgid "Custom(Descending)"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:158
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:178
msgid "The number of display"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:173
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:194
msgid "Select All"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:176
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:198
msgid "Search failed."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:180
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:204
msgid "Loading..."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:203
+#: weko_records_ui/templates/weko_records_ui/admin/bulk_update_display.html:233
msgid "Update"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:27
-msgid "Life Time"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:40
+#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:43
msgid "Institution Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:51
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:78
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:234
+#: weko_records_ui/templates/weko_records_ui/admin/institution_name_setting.html:56
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:90
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:241
msgid "Save"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:29
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:34
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:42
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:35
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:41
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:50
msgid "Display Email"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:38
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:46
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:45
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:54
msgid "Hide Email"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:52
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:61
msgid "Open Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:57
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:65
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:67
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:76
msgid "Display"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:61
-#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:69
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:71
+#: weko_records_ui/templates/weko_records_ui/admin/item_setting.html:80
msgid "Hide Open Date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:130
+#: weko_records_ui/templates/weko_records_ui/admin/pdfcoverpage.html:137
msgid "Header Settings"
msgstr ""
@@ -523,79 +702,75 @@ msgstr ""
msgid "I have read and agreed to the Terms of Use"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/analysis.html:79
-msgid "Next"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/box/export.html:34
+#: weko_records_ui/templates/weko_records_ui/box/export.html:40
msgid "Other Formats"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:23
+#: weko_records_ui/templates/weko_records_ui/box/head.html:26
msgid "There is a"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:24
+#: weko_records_ui/templates/weko_records_ui/box/head.html:27
msgid "newer version"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/head.html:24
+#: weko_records_ui/templates/weko_records_ui/box/head.html:27
msgid "of this record available."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/meta.html:36
+#: weko_records_ui/templates/weko_records_ui/box/meta.html:42
msgid "Publication date"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/meta.html:39
+#: weko_records_ui/templates/weko_records_ui/box/meta.html:48
msgid "Schema"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:32
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:55
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:27
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:34
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:34
msgid "Preview"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:43
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:48
msgid "Name"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:44
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:49
msgid "Size"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview.html:52
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:58
msgid ""
"This is the file fingerprint (MD5 checksum), which can be used to verify "
"the file integrity."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:39
-msgid "First"
-msgstr ""
-
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:43
-msgid "Previous"
+#: weko_records_ui/templates/weko_records_ui/box/preview.html:61
+msgid "Download"
msgstr ""
#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:47
-msgid "Next"
+msgid "First"
msgstr ""
#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:51
+msgid "Previous"
+msgstr ""
+
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:59
msgid "Last"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:89
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:119
msgid "Cannot preview because the file size is too large."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:105
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:138
msgid "No preview available."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:120
+#: weko_records_ui/templates/weko_records_ui/box/preview_carousel.html:155
msgid "Unable to load preview."
msgstr ""
@@ -603,7 +778,7 @@ msgstr ""
msgid "Share"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/share.html:39
+#: weko_records_ui/templates/weko_records_ui/box/share.html:55
msgid "Your record could not be processed by the citation formatter"
msgstr ""
@@ -615,648 +790,19 @@ msgstr ""
msgid "Views"
msgstr ""
+#: weko_records_ui/templates/weko_records_ui/box/tools.html:23
+msgid "Tools"
+msgstr ""
+
#: weko_records_ui/templates/weko_records_ui/box/versions.html:2
msgid "Versions"
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/versions.html:2
+#: weko_records_ui/templates/weko_records_ui/box/versions.html:5
msgid "Ver."
msgstr ""
-#: weko_records_ui/templates/weko_records_ui/box/versions.html:21
+#: weko_records_ui/templates/weko_records_ui/box/versions.html:37
msgid "Show All versions"
msgstr ""
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "write your own license"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution 3.0 Unported (CC BY 3.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NoDerivs 3.0 Unported (CC BY-ND 3.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-NC-ND 3.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution 4.0 International (CC BY 4.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)"
-msgstr ""
-
-# WEKO_RECORDS_UI_LICENSE_DICT
-msgid "Creative Commons CC0 1.0 Universal Public Domain Designation"
-msgstr ""
-
-# WEKO_RECORDS_UI_ITEM_DETAIL
-msgid "Date (ISO-8601)"
-msgstr ""
-
-msgid "Subject"
-msgstr ""
-
-msgid "Subject Scheme"
-msgstr ""
-
-msgid "Subject URI"
-msgstr ""
-
-msgid "Alternative Title"
-msgstr ""
-
-msgid "Creator"
-msgstr ""
-
-msgid "Creator Name Identifier"
-msgstr ""
-
-msgid "Creator Name Identifier Scheme"
-msgstr ""
-
-msgid "Creator Name Identifier URI"
-msgstr ""
-
-msgid "Creator Name"
-msgstr ""
-
-msgid "Name_"
-msgstr ""
-
-msgid "Creator Family Name"
-msgstr ""
-
-msgid "Family Name"
-msgstr ""
-
-msgid "Creator Given Name"
-msgstr ""
-
-msgid "Given Name"
-msgstr ""
-
-msgid "Creator Alternative Name"
-msgstr ""
-
-msgid "Alternative Name"
-msgstr ""
-
-msgid "Affiliation Name Identifier"
-msgstr ""
-
-msgid "Affiliation Name Identifier Scheme"
-msgstr ""
-
-msgid "Affiliation Name Identifier URI"
-msgstr ""
-
-msgid "Affiliation Name"
-msgstr ""
-
-msgid "Creator Email Address"
-msgstr ""
-
-msgid "Description Type"
-msgstr ""
-
-msgid "Bibliographic Information"
-msgstr ""
-
-msgid "Journal Title"
-msgstr ""
-
-msgid "Volume Number"
-msgstr ""
-
-msgid "Issue Number"
-msgstr ""
-
-msgid "Page Start"
-msgstr ""
-
-msgid "Page End"
-msgstr ""
-
-msgid "Publication year"
-msgstr ""
-
-msgid "Date Type"
-msgstr ""
-
-msgid "Publisher"
-msgstr ""
-
-msgid "Source Identifier"
-msgstr ""
-
-msgid "Source Identifier Type"
-msgstr ""
-
-msgid "Source Identifier"
-msgstr ""
-
-msgid "Relation"
-msgstr ""
-
-msgid "RelationType"
-msgstr ""
-
-msgid "Related Identifier"
-msgstr ""
-
-msgid "Related Identifier Type"
-msgstr ""
-
-msgid "Identifier Type"
-msgstr ""
-
-msgid "Related Title"
-msgstr ""
-
-msgid "Rights"
-msgstr ""
-
-msgid "Resource"
-msgstr ""
-
-msgid "Fileinfo"
-msgstr ""
-
-msgid "Text"
-msgstr ""
-
-msgid "Version Type"
-msgstr ""
-
-msgid "URI"
-msgstr ""
-
-msgid "Label"
-msgstr ""
-
-msgid "Mime Type"
-msgstr ""
-
-msgid "Heading"
-msgstr ""
-
-msgid "Headline"
-msgstr ""
-
-msgid "Subheading"
-msgstr ""
-
-msgid "Access Right"
-msgstr ""
-
-msgid "Access Rights URI"
-msgstr ""
-
-msgid "Contributor"
-msgstr ""
-
-msgid "Contributor Type"
-msgstr ""
-
-msgid "Contributor Name Identifier"
-msgstr ""
-
-msgid "Contributor Name Identifier Scheme"
-msgstr ""
-
-msgid "Contributor Name Identifier URI"
-msgstr ""
-
-msgid "Contributor_Name"
-msgstr ""
-
-msgid "Contributor Family Name"
-msgstr ""
-
-msgid "Contributor Given Name"
-msgstr ""
-
-msgid "Contributor Alternative Name"
-msgstr ""
-
-msgid "Contributor Alternative"
-msgstr ""
-
-msgid "Contributor Email Address"
-msgstr ""
-
-msgid "Degree Name"
-msgstr ""
-
-msgid "Degree Grantor"
-msgstr ""
-
-msgid "Degree Grantor Name Identifier"
-msgstr ""
-
-msgid "Degree Grantor Name"
-msgstr ""
-
-msgid "Date Granted"
-msgstr ""
-
-msgid "Dissertation Number"
-msgstr ""
-
-msgid "Contributor ID"
-msgstr ""
-
-msgid "Funding Reference"
-msgstr ""
-
-msgid "Funder Name"
-msgstr ""
-
-msgid "Award Number"
-msgstr ""
-
-msgid "Book Name"
-msgstr ""
-
-msgid "Date Reported"
-msgstr ""
-
-msgid "Name Identifier"
-msgstr ""
-
-msgid "Name Identifier Scheme"
-msgstr ""
-
-msgid "Description_"
-msgstr ""
-
-msgid "Rights Resource"
-msgstr ""
-
-msgid "Rights Holder"
-msgstr ""
-
-msgid "Rights Holder Name Identifier"
-msgstr ""
-
-msgid "Rights Holder Name Identifier Scheme"
-msgstr ""
-
-msgid "Rights Holder Name Identifier URI"
-msgstr ""
-
-msgid "Rights Holder Name"
-msgstr ""
-
-msgid "Resource Type"
-msgstr ""
-
-msgid "Temporal"
-msgstr ""
-
-msgid "Geo Location"
-msgstr ""
-
-msgid "Geo Location Point"
-msgstr ""
-
-msgid "Point Longitude"
-msgstr ""
-
-msgid "Point Latitude"
-msgstr ""
-
-msgid "Geo Location Box"
-msgstr ""
-
-msgid "West Bound Longitude"
-msgstr ""
-
-msgid "East Bound Longitude"
-msgstr ""
-
-msgid "South Bound Latitude"
-msgstr ""
-
-msgid "North Bound Latitude"
-msgstr ""
-
-msgid "Geo Location Place"
-msgstr ""
-
-msgid "funder Identifier"
-msgstr ""
-
-msgid "Funder Identifier Type"
-msgstr ""
-
-msgid "Award Number URI"
-msgstr ""
-
-msgid "Source Title"
-msgstr ""
-
-msgid "Number of Pages"
-msgstr ""
-
-msgid "Degree Grantor Name Identifier Scheme"
-msgstr ""
-
-msgid "Conference"
-msgstr ""
-
-msgid "Conference Name"
-msgstr ""
-
-msgid "Conference Sequence"
-msgstr ""
-
-msgid "Conference Place"
-msgstr ""
-
-msgid "Conference Country"
-msgstr ""
-
-msgid "URI Object Type"
-msgstr ""
-
-msgid "URI Label"
-msgstr ""
-
-msgid "Format"
-msgstr ""
-
-msgid "Extent"
-msgstr ""
-
-msgid "Issued Date"
-msgstr ""
-
-msgid "Issue"
-msgstr ""
-
-msgid "Volume"
-msgstr ""
-
-msgid "Search repository"
-msgstr ""
-
-msgid "Content File"
-msgstr ""
-
-msgid "Billing File"
-msgstr ""
-
-msgid "ID Agency"
-msgstr ""
-
-msgid "Series"
-msgstr ""
-
-msgid "Version Date"
-msgstr ""
-
-msgid "DateType"
-msgstr ""
-
-msgid "Bibliographic Citation"
-msgstr ""
-
-msgid "Topic"
-msgstr ""
-
-msgid "topic vocabURI"
-msgstr ""
-
-msgid "subjectScheme"
-msgstr ""
-
-msgid "Topic J"
-msgstr ""
-
-msgid "Topic E"
-msgstr ""
-
-msgid "Time Period"
-msgstr ""
-
-msgid "Time Period Event"
-msgstr ""
-
-msgid "Date Of Collection Event"
-msgstr ""
-
-msgid "Geographic Coverage"
-msgstr ""
-
-msgid "Unit of Analysis"
-msgstr ""
-
-msgid "Unit of Analysis J"
-msgstr ""
-
-msgid "Unit of Analysis E"
-msgstr ""
-
-msgid "Sampling Procedure E"
-msgstr ""
-
-msgid "Sampling Procedure J"
-msgstr ""
-
-msgid "Collection Method"
-msgstr ""
-
-msgid "Collection Method J"
-msgstr ""
-
-msgid "Collection Method E"
-msgstr ""
-
-msgid "Sampling Rate"
-msgstr ""
-
-msgid "Access"
-msgstr ""
-
-msgid "Rdf:Resource"
-msgstr ""
-
-msgid "Access E"
-msgstr ""
-
-msgid "Access J"
-msgstr ""
-
-msgid "Study ID"
-msgstr ""
-
-msgid "Copyright"
-msgstr ""
-
-msgid "Topic Vocab"
-msgstr ""
-
-msgid "Topic Vocab URI"
-msgstr ""
-
-msgid "Date Of Collection"
-msgstr ""
-
-msgid "Event"
-msgstr ""
-
-msgid "Universe"
-msgstr ""
-
-msgid "Data Type J"
-msgstr ""
-
-msgid "Data Type E"
-msgstr ""
-
-msgid "Sampling Procedure"
-msgstr ""
-
-msgid "Identifier Registration Type"
-msgstr ""
-
-msgid "Identifier Registration"
-msgstr ""
-
-msgid "Related Study"
-msgstr ""
-
-msgid "Related Study DOI"
-msgstr ""
-
-msgid "Related Publications"
-msgstr ""
-
-msgid "Related Publications DOI"
-msgstr ""
-
-msgid "Fund Agency"
-msgstr ""
-
-msgid "Fund Agency ID"
-msgstr ""
-
-msgid "Funder Identifier Type"
-msgstr ""
-
-msgid "GrantNo"
-msgstr ""
-
-msgid "Award Title"
-msgstr ""
-
-msgid "Distributor Abbreviation"
-msgstr ""
-
-msgid "Distributor Affiliation"
-msgstr ""
-
-msgid "Distributor URI"
-msgstr ""
-
-msgid "Contributor IdentifierType"
-msgstr ""
-
-msgid "Distributor Name"
-msgstr ""
-
-msgid "AwardTitle"
-msgstr ""
-
-msgid "Related Study Title"
-msgstr ""
-
-msgid "Related Study Identifier"
-msgstr ""
-
-msgid "Related Publications Title"
-msgstr ""
-
-msgid "Related Publications Identifier"
-msgstr ""
-
-msgid "Related Publications Identifier Type"
-msgstr ""
-
-msgid "GrantURI"
-msgstr ""
-
-msgid "Related Study Identifier Type"
-msgstr ""
-
-msgid "Grant No"
-msgstr ""
-
-msgid "Summary DDI"
-msgstr ""
-
-
-msgid "Apply JGSS"
-msgstr "Apply"
-
-msgid "This data is not available for undergraduate students or those who do not register their positions."
-msgstr ""
-
-msgid "Please input email address."
-msgstr ""
-
-msgid "Email address"
-msgstr ""
-
-msgid "Email address(reconfirmation)"
-msgstr ""
-
-msgid "Token is invalid."
-msgstr ""
-
-msgid "The expiration date for download has been exceeded."
-msgstr ""
-
-msgid "The download limit has been exceeded."
-msgstr ""
-
-msgid "This data is not available for this user."
-msgstr ""
-
-msgid "Success Secret URL Generate"
-msgstr "succeess:secret url generate is succeed. send to your mail adress."
diff --git a/modules/weko-records-ui/weko_records_ui/utils.py b/modules/weko-records-ui/weko_records_ui/utils.py
index e69bfd20c7..aa6710af5a 100644
--- a/modules/weko-records-ui/weko_records_ui/utils.py
+++ b/modules/weko-records-ui/weko_records_ui/utils.py
@@ -21,8 +21,9 @@
"""Module of weko-records-ui utils."""
import base64
+import hashlib
import os
-from datetime import datetime as dt
+from datetime import datetime as dt, timezone
from datetime import timedelta
from decimal import Decimal
from typing import List, NoReturn, Optional, Tuple
@@ -52,13 +53,15 @@
from weko_records.utils import replace_fqdn
from weko_records.models import ItemReference
from weko_schema_ui.models import PublishStatus
+from weko_user_profiles.models import UserProfile
from weko_workflow.api import WorkActivity, WorkFlow, UpdateItem
from weko_workflow.models import ActivityStatusPolicy
from weko_records_ui.models import InstitutionName
from weko_workflow.models import Activity
+from weko_workflow.utils import get_item_info, process_send_mail, set_mail_info
-from .models import FileOnetimeDownload, FilePermission, FileSecretDownload
+from .models import AccessStatus, FileOnetimeDownload, FilePermission, FileSecretDownload, FileUrlDownloadLog, UrlType
from .permissions import check_create_usage_report, \
check_file_download_permission, check_user_group_permission, \
is_open_restricted
@@ -1115,110 +1118,6 @@ def check_and_send_usage_report(extra_info:dict, user_mail:str ,record:dict, fil
FilePermission.update_usage_report_activity_id(permission,activity_id)
-def generate_one_time_download_url(
- file_name: str, record_id: str, guest_mail: str
-) -> str:
- """Generate one time download URL.
-
- :param file_name: File name
- :param record_id: File Version ID
- :param guest_mail: guest email
- :return:
- """
- secret_key = current_app.config['WEKO_RECORDS_UI_SECRET_KEY']
- download_pattern = current_app.config[
- 'WEKO_RECORDS_UI_ONETIME_DOWNLOAD_PATTERN']
- current_date = dt.utcnow().strftime("%Y-%m-%d")
- hash_value = download_pattern.format(file_name, record_id, guest_mail,
- current_date)
- secret_token = oracle10.hash(secret_key, hash_value)
-
- token_pattern = "{} {} {} {}"
- token = token_pattern.format(record_id, guest_mail, current_date,
- secret_token)
- token_value = base64.b64encode(token.encode()).decode()
- host_name = request.host_url
- url = "{}record/{}/file/onetime/{}?token={}" \
- .format(host_name, record_id, file_name, token_value)
- return url
-
-
-def parse_one_time_download_token(token: str) -> Tuple[str, Tuple]:
- """Parse onetime download token.
-
- @param token:
- @return:
- """
- # current_app.logger.debug("token:{}".format(token))
- error = _("Token is invalid.")
- if token is None:
- return error, ()
- try:
- decode_token = base64.b64decode(token.encode()).decode()
- param = decode_token.split(" ")
- if not param or len(param) != 4:
- return error, ()
-
- return "", (param[0], param[1], param[2], param[3])
- except Exception as err:
- current_app.logger.error(err)
- return error, ()
-
-
-def validate_onetime_download_token(
- onetime_download: FileOnetimeDownload, file_name: str, record_id: str,
- guest_mail: str, date: str, token: str
-) -> Tuple[bool, str]:
- """Validate onetime download token.
-
- @param onetime_download:
- @param file_name:
- @param record_id:
- @param guest_mail:
- @param date:
- @param token:
- @return:
- """
- # current_app.logger.debug("onetime_download:{}".format(onetime_download))
- # current_app.logger.debug("file_name:{}".format(file_name))
- # current_app.logger.debug("record_id:{}".format(record_id))
- # current_app.logger.debug("guest_mail:{}".format(guest_mail))
- # current_app.logger.debug("date:{}".format(date))
- # current_app.logger.debug("token:{}".format(token))
-
- token_invalid = _("Token is invalid.")
- secret_key = current_app.config['WEKO_RECORDS_UI_SECRET_KEY']
- download_pattern = current_app.config[
- 'WEKO_RECORDS_UI_ONETIME_DOWNLOAD_PATTERN']
- hash_value = download_pattern.format(
- file_name, record_id, guest_mail, date)
-
- if not oracle10.verify(secret_key, token, hash_value):
- current_app.logger.debug('Validate token error: {}'.format(hash_value))
- return False, token_invalid
- try:
- if not onetime_download:
- return False, token_invalid
- try:
- expiration_date = timedelta(onetime_download.expiration_date)
- download_date = onetime_download.created.date() + expiration_date
- current_date = dt.utcnow().date()
- if current_date > download_date:
- return False, _(
- "The expiration date for download has been exceeded.")
- except OverflowError:
- current_app.logger.error('date value out of range:',
- onetime_download.expiration_date)
-
- if onetime_download.download_count <= 0:
- return False, _("The download limit has been exceeded.")
- return True, ""
- except Exception as err:
- current_app.logger.error('Validate onetime download token error:')
- current_app.logger.error(err)
- return False, token_invalid
-
-
def is_private_index(record):
"""Check index of workflow is private.
@@ -1239,15 +1138,174 @@ def is_private_index(record):
return False
-def validate_download_record(record: dict):
- """Validate record.
+def validate_download_record(record):
+ """Validate the record(item) if it is downloadable.
- :param record:
+ Args:
+ record (dict): Record meta data.
+
+ Returns:
+ bool: True if record is downloadable, False otherwise.
"""
if record['publish_status'] != PublishStatus.PUBLIC.value:
- abort(403)
+ return False
if is_private_index(record):
- abort(403)
+ return False
+ return True
+
+
+def is_secret_url_feature_enabled():
+ """Check if the feature is enabled.
+
+ Returns:
+ bool: True if the feature is enabled, False otherwise.
+ """
+ settings = AdminSettings.get(name='restricted_access',dict_to_object=False)
+ if not settings:
+ settings = current_app.config['WEKO_ADMIN_RESTRICTED_ACCESS_SETTINGS']
+ secret_url_settings = settings.get('secret_URL_file_download', {})
+ is_enabled = secret_url_settings.get('secret_enable', False)
+ return is_enabled
+
+
+def has_permission_to_manage_secret_url(record, user_id):
+ """Check if the user has permission to manage a secret URL.
+
+ Following users have the permission.
+ - The administrators.
+ - The user who registered the item(record).
+ - The user who registered the item on behalf of other users.
+
+ Returns:
+ bool: True if the user has permission, False otherwise.
+ """
+ super_roles = current_app.config['WEKO_PERMISSION_SUPER_ROLE_USER']
+ user = User.query.filter_by(id=user_id).first()
+ # Need to change the 'weko_shared_id' to 'weko_shared_ids' in the future.
+ has_permission = (
+ user_id == int(record['owner']) or
+ user_id in [record['weko_shared_id']] or
+ any(role.name in super_roles for role in user.roles or [])
+ )
+ return has_permission
+
+
+def has_permission_to_manage_onetime_url(record, user_id):
+ """Check if the user has permission to manage a onetime URL.
+
+ The current difference in required permissions between a secret URL and a
+ one-time URL is that users who registered the item on behalf of others do
+ not have permission to manage the one-time URL (though they can manage
+ secret URLs).
+
+ Following users have the permission.
+ - The administrators.
+ - The user who registered the item(record).
+
+ Returns:
+ bool: True if the user has permission, False otherwise.
+ """
+ super_roles = current_app.config['WEKO_PERMISSION_SUPER_ROLE_USER']
+ user = User.query.filter_by(id=user_id).first()
+ has_permission = (
+ user_id == int(record['owner']) or
+ any(role.name in super_roles for role in user.roles or [])
+ )
+ return has_permission
+
+
+def is_secret_file(record, file_name):
+ """Check if the target file meets the requirements for secret URL use.
+
+ Args:
+ record (WekoRecord): The record object to which the file belongs.
+ filename (str): The target file name.
+
+ Returns:
+ bool: True if the file is for secret URL use, False otherwise.
+ """
+ target_data = {}
+ for file_data in record.get_file_data():
+ if file_data.get('filename') == file_name:
+ target_data = file_data
+ break
+ if not target_data:
+ return False
+
+ publish_date = dt.strptime(
+ target_data.get('date')[0].get('dateValue'), '%Y-%m-%d')
+ is_secret_file = (
+ target_data.get('accessrole') == 'open_no' or (
+ target_data.get('accessrole') == 'open_date' and
+ dt.utcnow() < publish_date
+ ))
+ return is_secret_file
+
+
+def is_onetime_file(record, file_name):
+ """Check if the target file meets the requirements for onetime URL use.
+
+ Args:
+ record (WekoRecord): The record object to which the file belongs.
+ filename (str): The target file name.
+
+ Returns:
+ bool: True if the file is for onetime URL use, False otherwise.
+ """
+ for file_data in record.get_file_data():
+ if file_data.get('filename') == file_name:
+ return file_data.get('accessrole') == 'open_restricted'
+ return False
+
+
+def can_manage_secret_url(record, filename):
+ """Determine if the user can manage a secret URL.
+
+ This function checks whether the secret URL feature can be used for a given
+ file in a record by evaluating the following conditions:
+ 1. The secret URL feature is enabled system-wide.
+ 2. The logged-in user has the necessary permissions.
+ 3. The specified file qualifies for secret URL use.
+
+ Args:
+ record (WekoRecord): The record object containing the file.
+ filename (str): The name of the target file.
+
+ Returns:
+ bool: True if all conditions are met, False otherwise.
+ """
+ if not current_user or not current_user.is_authenticated:
+ return False
+ else:
+ return (
+ is_secret_url_feature_enabled() and
+ has_permission_to_manage_secret_url(record, current_user.id) and
+ is_secret_file(record, filename)
+ )
+
+
+def can_manage_onetime_url(record, filename):
+ """Determine if the user can manage a onetime URL.
+
+ This function checks whether the onetime URL feature can be used for a
+ given file in a record by evaluating the following conditions:
+ 1. The logged-in user has the necessary permissions.
+ 2. The specified file qualifies for onetime URL use.
+
+ Args:
+ record (WekoRecord): The record object containing the file.
+ filename (str): The name of the target file.
+
+ Returns:
+ bool: True if all conditions are met, False otherwise.
+ """
+ if not current_user or not current_user.is_authenticated:
+ return False
+ else:
+ return (
+ has_permission_to_manage_onetime_url(record, current_user.id) and
+ is_onetime_file(record, filename)
+ )
def get_onetime_download(file_name: str, record_id: str,
@@ -1291,49 +1349,6 @@ def get_valid_onetime_download(file_name: str, record_id: str,user_mail: str) ->
return None
-def create_onetime_download_url(
- activity_id: str, file_name: str, record_id: str, user_mail: str,
- is_guest: bool = False
-):
- """Create onetime download.
-
- :param activity_id:
- :param file_name:
- :param record_id:
- :param user_mail:
- :param is_guest:
- :return:
- """
- content_file_download = get_restricted_access('content_file_download')
- if content_file_download and isinstance(content_file_download, dict):
- expiration_date = content_file_download.get("expiration_date", 30)
- download_limit = content_file_download.get("download_limit", 10)
- extra_info = dict(
- usage_application_activity_id=activity_id,
- send_usage_report=True,
- is_guest=is_guest
- )
- file_onetime = FileOnetimeDownload.create(**{
- "file_name": file_name,
- "record_id": record_id,
- "user_mail": user_mail,
- "expiration_date": expiration_date,
- "download_count": download_limit,
- "extra_info": extra_info,
- })
- return file_onetime
- return False
-
-
-def update_onetime_download(**kwargs) -> Optional[List[FileOnetimeDownload]]:
- """Update onetime download.
-
- @param kwargs:
- @return:
- """
- return FileOnetimeDownload.update_download(**kwargs)
-
-
def get_workflows():
"""Get workflow.
@@ -1719,225 +1734,445 @@ def get_google_detaset_meta(record,record_tree=None):
return json.dumps(res_data, ensure_ascii=False)
-def create_secret_url(record_id:str ,file_name:str ,user_mail:str ,restricted_fullname='',restricted_data_name='') -> dict:
+
+def to_utc_datetime(str_date, offset_minutes=0):
+ """Parse string date info into datetime object in UTC timezone.
+
+ Args:
+ str_date (str): The date string as 'YYYY-MM-DD'.
+ offset_minutes (int): The timezone offset in minutes.
+
+ Returns:
+ datetime: The datetime object in UTC timezone.
"""
- Save in FileSecretDownload
- and Generate Secret Download URL.
-
+ try:
+ local_naive_dt = dt.strptime(str_date, '%Y-%m-%d')
+ except ValueError:
+ current_app.logger.error(f'Failed to parse date string: {str_date}')
+ return None
+ local_tz = timezone(timedelta(minutes=-offset_minutes))
+ local_aware_dt = local_naive_dt.replace(tzinfo=local_tz)
+ utc_dt = local_aware_dt.astimezone(timezone.utc)
+ return utc_dt
+
+
+def validate_secret_url_generation_request(request_json):
+ """Validate request for secret URL generation.
+
+ The reqeust data must contain the following keys:
+ - link_name (optional): The name of the secret link.
+ - expiration_date (optional): The expiration date of the link.
+ - download_limit (optional): The maximum number of downloads allowed.
+ - send_email: True if the user wants to send an email, False otherwise.
+ - timezone_offset_minutes: The timezone offset in minutes.
+
+ Keys marked as optional must exist in the request, but their values can be
+ empty.
+
Args:
- str :record_id:
- str :file_name:
- str :user_mail
- str :restricted_fullname :embed mail string
- str :restricted_data_name :embed mail string
- Return:
- dict: created info
+ request_json (dict): The request.json data from the user.
+
+ Returns:
+ bool: True if the request is valid, False otherwise.
"""
- # Save to Database.
- secret_obj:FileSecretDownload = _create_secret_download_url(
- file_name, record_id, user_mail)
-
- # generate url
- secret_file_url = _generate_secret_download_url(
- file_name, record_id, secret_obj.id , secret_obj.created)
-
- return_dict:dict = {
- "restricted_download_link":"",
- "mail_recipient":"",
- "file_name":file_name,
- "restricted_expiration_date": "",
- "restricted_expiration_date_ja": "",
- "restricted_expiration_date_en": "",
- "restricted_download_count":"",
- "restricted_download_count_ja":"",
- "restricted_download_count_en":"",
- "restricted_fullname" :restricted_fullname,
- "restricted_data_name" :restricted_data_name,
- }
- return_dict["mail_recipient"] = secret_obj.user_mail
- return_dict["restricted_download_link"] = secret_file_url
-
- max_int :int = current_app.config["WEKO_ADMIN_RESTRICTED_ACCESS_MAX_INTEGER"]
- if secret_obj.expiration_date < max_int:
- expiration_date = timedelta(days=secret_obj.expiration_date)
- expiration_date = dt.today() + expiration_date
- expiration_date = expiration_date.strftime("%Y-%m-%d")
- return_dict['restricted_expiration_date'] = expiration_date
- else:
- return_dict["restricted_expiration_date_ja"] = "無制限"
- return_dict["restricted_expiration_date_en"] = "Unlimited"
-
+ # Validate format of the request data
+ if not isinstance(request_json, dict):
+ return False
+ expected_keys = ['link_name',
+ 'expiration_date',
+ 'download_limit',
+ 'send_email',
+ 'timezone_offset_minutes']
+ if not all(key in request_json for key in expected_keys):
+ return False
- if secret_obj.download_count < max_int :
- return_dict["restricted_download_count"] = str(secret_obj.download_count)
- else:
- return_dict["restricted_download_count_ja"] = "無制限"
- return_dict["restricted_download_count_en"] = "Unlimited"
-
- return return_dict
+ # Validate each value in the request data
+ link_name = request_json['link_name']
+ expiration_str = request_json['expiration_date']
+ download_limit = request_json['download_limit']
+ send_email = request_json['send_email']
+ offset_minutes = request_json['timezone_offset_minutes']
+ if not isinstance(link_name, str) or len(link_name) > 255:
+ return False
+ if (not isinstance(offset_minutes, int) or
+ abs(offset_minutes) > 720): # Max timezone offset is ±720 minutes
+ return False
+ if not isinstance(expiration_str, str):
+ return False
+ if not validate_expiration_date(expiration_str, offset_minutes):
+ return False
+ if not isinstance(download_limit, int) or download_limit <= 0:
+ return False
+ if not isinstance(send_email, bool):
+ return False
+ return True
-def _generate_secret_download_url(file_name: str, record_id: str, id: str ,created :dt) -> str:
- """Generate Secret download URL.
-
- Args
- str: file_name: File name
- str: record_id: File Version ID
- str: id: FileSecretDownload id
- datetime :created :FileSecretDownload created
-
- Returns
- str: generated url
- """
- secret_key = current_app.config['WEKO_RECORDS_UI_SECRET_KEY']
- download_pattern = current_app.config[
- 'WEKO_RECORDS_UI_SECRET_DOWNLOAD_PATTERN']
- current_date = created
- hash_value = download_pattern.format(file_name, record_id, id,
- current_date.isoformat())
- secret_token = oracle10.hash(secret_key, hash_value)
-
- token_pattern = "{} {} {} {}"
- token = token_pattern.format(record_id, id, current_date.isoformat(),
- secret_token)
- token_value = base64.b64encode(token.encode()).decode()
- host_name = request.host_url
- url = "{}record/{}/file/secret/{}?token={}" \
- .format(host_name, record_id, file_name, token_value)
- current_app.logger.debug("secret_file_url:{}".format(url))
- return url
+def validate_expiration_date(expiration_str, offset_minutes):
+ """Validate the expiration date.
-def parse_secret_download_token(token: str) -> Tuple[str, Tuple]:
- """Parse secret download token.
+ Args:
+ expiration_str (str): The expiration date string.
+ offset_minutes (int): The timezone offset in minutes.
- Args
- token:
- Returns:
- str : error message
- Tuple : (record_id, id, date, secret_token)
+ Returns:
+ bool: True if the expiration date is valid, False otherwise.
"""
- # current_app.logger.debug("token:{}".format(token))
- error = _("Token is invalid.")
- if token is None:
- return error, ()
- try:
- decode_token = base64.b64decode(token.encode()).decode()
- current_app.logger.debug("decode_token:{}".format(decode_token))
- param = decode_token.split(" ")
- if not param or len(param) != 4:
- return error, ()
+ # Check the format of the expiration date.
+ expiration_dt = to_utc_datetime(expiration_str, offset_minutes)
+ if not expiration_dt:
+ return False
+
+ # Check if the expiration date is in the future.
+ expiration_dt += timedelta(days=1)
+ if expiration_dt < dt.now(timezone.utc):
+ return False
+
+ # Check if the expiration date is within the range of the allowed period.
+ secret_url_settings = get_restricted_access('secret_URL_file_download')
+ if not secret_url_settings:
+ return False
+ expiration_days = secret_url_settings.get('secret_expiration_date', 30) + 1
+ if expiration_dt > dt.now(timezone.utc) + timedelta(days=expiration_days):
+ return False
+ return True
- return "", (param[0], param[1], param[2], param[3]) #record_id, id, current_date, secret_token
- except Exception as err:
- current_app.logger.error(err)
- return error, ()
+def create_secret_url_record(record_id, file_name, request_data):
+ """Create a secret URL record.
-def validate_secret_download_token(
- secret_download: FileSecretDownload , file_name: str, record_id: str,
- id: str, date: str, token: str
-) -> Tuple[bool, str]:
- """Validate secret download token.
+ Args:
+ record_id (int): The record(item) ID to which the file belongs.
+ file_name (str): The file name for which the secret URL is created.
+ request_data (dict): The request data from the user.
- Args
- FileSecretDownload:secret_download:
- str:file_name:
- str:record_id:
- str:id:
- str:date:
- str:token:
- Returns
- Tuple:
- bool : is valid
- str : error message
+ Returns:
+ FileSecretDownload, or None:
+ The created secret URL object, or None if the restricted access
+ settings are not configured properly.
+
+ Raises:
+ Exception: If an unexpected error occurs during the creation.
"""
- token_invalid = _("Token is invalid.")
- secret_key = current_app.config['WEKO_RECORDS_UI_SECRET_KEY']
- download_pattern = current_app.config[
- 'WEKO_RECORDS_UI_SECRET_DOWNLOAD_PATTERN']
- hash_value = download_pattern.format(
- file_name, record_id, id, date)
-
- if not oracle10.verify(secret_key, token, hash_value):
- current_app.logger.error('Validate token error: {}'.format(hash_value))
- return False, token_invalid
- try:
- if not secret_download:
- return False, token_invalid
- try:
- expiration_date = timedelta(secret_download.expiration_date)
- download_date = secret_download.created.date() + expiration_date
- current_date = dt.utcnow().date()
- if current_date > download_date:
- return False, _(
- "The expiration date for download has been exceeded.")
- except OverflowError:
- # in case of "Unlimited"
- current_app.logger.debug('date value out of range:'+
- str(secret_download.expiration_date))
-
- if secret_download.download_count <= 0:
- return False, _("The download limit has been exceeded.")
- return True, ""
- except Exception as err:
- current_app.logger.error('Validate secret download token error:')
- current_app.logger.error(err)
- return False, token_invalid
-
-def get_secret_download(file_name: str, record_id: str,
- id: str , created :dt ) -> Optional[FileSecretDownload]:
- """Get secret download count.
-
- Args :
- str:file_name
- str:record_id
- str:id
- dt :created
- @return:
- FileSecretDownload or None
+ secret_url_settings = get_restricted_access('secret_URL_file_download')
+ if (not secret_url_settings or
+ not isinstance(secret_url_settings, dict)):
+ return None
+
+ label_name = request_data['link_name']
+ local_expiration_str = request_data['expiration_date']
+ download_limit = request_data['download_limit']
+ offset_minutes = request_data['timezone_offset_minutes']
+ # Set default values if these values are empty.
+ if label_name == '':
+ utc_today = dt.now(timezone.utc).strftime('%Y-%m-%d')
+ url_created_at = to_utc_datetime(
+ utc_today, offset_minutes).strftime('%Y-%m-%d')
+ label_name = f'{file_name}_{url_created_at}'
+ if local_expiration_str == '':
+ expiration_days = secret_url_settings.get('secret_expiration_date', 30)
+ local_tz = timezone(timedelta(minutes=offset_minutes))
+ local_date = dt.now(timezone.utc).replace(tzinfo=local_tz).date()
+ local_expiration_date = local_date + timedelta(expiration_days)
+ local_expiration_str = dt.strftime(local_expiration_date, '%Y-%m-%d')
+ utc_expiration_dt = to_utc_datetime(local_expiration_str, offset_minutes)
+ utc_expiration_dt += timedelta(days=1) # To include the last day
+ if download_limit is None:
+ download_limit = secret_url_settings.get('secret_download_limit', 10)
+
+ secret_url_obj = FileSecretDownload.create(
+ creator_id = current_user.id,
+ record_id = record_id,
+ file_name = file_name,
+ label_name = label_name,
+ expiration_date = utc_expiration_dt,
+ download_limit = download_limit)
+ return secret_url_obj
+
+
+def create_onetime_url_record(activity_id, record_id, file_name,
+ user_mail, is_guest=False):
+ """Create onetime download record.
+
+ Args:
+ activity_id: The ID of the usage application activity.
+ record_id: The ID of the record which the file belongs to.
+ file_name: The name of the file to be downloaded.
+ user_mail: The email address of the user who requested the download.
+ is_guest: True if the user is a guest user, False otherwise.
+
+ Returns:
+ FileOnetimeDownload or None:
+ The created onetime download record, or None if the restricted
+ access settings are not configured properly.
"""
- file_downloads = FileSecretDownload.find(
- file_name=file_name, record_id=record_id, id=id ,created=created
+ onetime_url_settings = get_restricted_access('content_file_download')
+ if (not onetime_url_settings or
+ not isinstance(onetime_url_settings, dict)):
+ return None
+
+ expiration_days = onetime_url_settings.get('expiration_date', 30)
+ expiration_date = dt.now(timezone.utc) + timedelta(days=expiration_days)
+ expiration_date += timedelta(days=1) # To include the last day
+ download_limit = onetime_url_settings.get('download_limit', 10)
+ extra_info = {'usage_application_activity_id': activity_id,
+ 'send_usage_report': True}
+
+ onetime_url_obj = FileOnetimeDownload.create(
+ approver_id = current_user.id,
+ record_id = record_id,
+ file_name = file_name,
+ expiration_date = expiration_date,
+ download_limit = download_limit,
+ user_mail = user_mail,
+ is_guest = is_guest,
+ extra_info = extra_info
)
- if file_downloads and len(file_downloads) == 1:
- return file_downloads[0]
+ return onetime_url_obj
+
+
+def create_download_url(url_obj):
+ """Create a download URL from a object.
+
+ Note:
+ - This function can be used for both secret URL and onetime URL.
+ - Same URL is generated from a same object.
+
+ Args:
+ url_obj (FileSecretDownload or FileOnetimeDownload):
+ The secret URL or onetime URL object.
+ is_secret_url (bool):
+ True if the URL is for secret URL, False if for onetime URL.
+
+ Returns:
+ str: The generated URL.
+ """
+ if isinstance(url_obj, FileSecretDownload):
+ url_type = 'secret'
+ elif isinstance(url_obj, FileOnetimeDownload):
+ url_type = 'onetime'
else:
return None
+ host_url = request.host_url
+ hash = generate_sha256_hash(url_obj)
+ bytes = hash + b'_' + str(url_obj.id).encode()
+ token = base64.urlsafe_b64encode(bytes).decode()
+ url = (f'{host_url}record/{url_obj.record_id}/file/{url_type}/'
+ f'{url_obj.file_name}?token={token}')
+ return url
-def _create_secret_download_url(file_name: str, record_id: str, user_mail: str) -> FileSecretDownload:
- """Create secret download.
+
+def generate_sha256_hash(url_obj):
+ """Generate a SHA-256 hash value from a download URL object.
+
+ Note:
+ Same object always generates the same value, so it can be used both for
+ creating a new hash and verifying it.
Args:
- str : file_name:
- str : record_id:
- str : user_mail:
+ url_obj (FileSecretDownload or FileOnetimeDownload):
+ The secret URL or onetime URL object.
+
Returns:
- FileSecretDownload : inserted record
+ bytes: The SHA-256 hash value.
"""
- secret_url_file_download:dict = get_restricted_access('secret_URL_file_download')
-
- expiration_date = secret_url_file_download.get("secret_expiration_date", 30)
- download_limit = secret_url_file_download.get("secret_download_limit", 10)
-
- file_secret = FileSecretDownload.create(**{
- "file_name": file_name,
- "record_id": record_id,
- "user_mail": user_mail,
- "expiration_date": expiration_date,
- "download_count": download_limit,
- })
- return file_secret
-
+ secret_key = current_app.config['WEKO_RECORDS_UI_SECRET_KEY']
+ token_parts = [
+ secret_key,
+ str(url_obj.created),
+ str(url_obj.id),
+ str(url_obj.record_id),
+ str(url_obj.file_name),
+ str(url_obj.expiration_date),
+ str(url_obj.download_limit),
+ ]
+ hash_obj = hashlib.sha256()
+ for part in token_parts:
+ hash_obj.update(part.encode())
+ return hash_obj.digest()
+
+
+def send_secret_url_mail(uuid, secret_url_obj, item_title):
+ """Send an email with a secret URL.
+
+ Args:
+ uuid (UUID): The UUID of the item.
+ secret_url_obj (FileSecretDownload): The secret URL object.
+ item_title (str): The item title.
+
+ Returns:
+ bool: True if the email sent successfully, False otherwise.
+ """
+ # Setup mail info
+ user_profile = UserProfile.get_by_userid(current_user.id)
+ fullname = user_profile._displayname if user_profile else ''
+ expiration_dt = secret_url_obj.expiration_date
+ jst_date = expiration_dt.astimezone(timezone(timedelta(hours=9))).date()
+ jst_str = jst_date.strftime('%Y-%m-%d') + ' 23:59:59(JST)'
+ secret_url_info = {
+ 'restricted_download_link' : create_download_url(secret_url_obj),
+ 'mail_recipient' : current_user.email,
+ 'file_name' : secret_url_obj.file_name,
+ 'restricted_expiration_date': jst_str,
+ 'restricted_download_count' : str(secret_url_obj.download_limit),
+ 'restricted_fullname' : fullname,
+ 'restricted_data_name' : item_title,
+ }
+ mail_info = set_mail_info(get_item_info(uuid),
+ type('' ,(object,), {'activity_id': ''})())
+ mail_info.update(secret_url_info)
+ # Send mail
+ mail_pattern = current_app.config.get(
+ 'WEKO_RECORDS_UI_MAIL_TEMPLATE_SECRET_URL')
+ is_succeeded = process_send_mail(mail_info, mail_pattern)
+ return is_succeeded
-def update_secret_download(**kwargs) -> Optional[List[FileSecretDownload]]:
- """Update secret download.
- Args
- kwargs:
- Returns
- updated List[FileSecretDownload] or None
+def validate_token(token, is_secret_url):
+ """Validate the provided token.
+
+ This function can be used for both secret URL and onetime URL.
+
+ Args:
+ token (str): The token to validate.
+ is_secret_url (bool): True if for secret URL, False if for onetime URL.
+
+ Returns:
+ bool: True if the token is valid, False otherwise.
+ """
+ try:
+ bytes = base64.urlsafe_b64decode(token.encode())
+ parts = bytes.split(b'_')
+ if len(parts) < 2: # Generated hash may contain additional '_'
+ return False
+ token_id = parts[-1].decode() # The last part is the URL object ID
+ token_hash = b'_'.join(parts[:-1]) # The rest is hash value
+ if is_secret_url:
+ url_obj = FileSecretDownload.get_by_id(token_id)
+ else:
+ url_obj = FileOnetimeDownload.get_by_id(token_id)
+ if url_obj and (token_hash == generate_sha256_hash(url_obj)):
+ return True
+ else:
+ return False
+ except Exception as e:
+ current_app.logger.error(e)
+ return False
+
+
+def convert_token_into_obj(token, is_secret_url):
+ """Convert the token into a download URL object.
+
+ Args:
+ token (str): The token to convert.
+ is_secret_url (bool):
+ True if the URL is for secret URL, False if for onetime URL.
+
+ Returns:
+ FileSecretDownload or FileOnetimeDownload or None:
+ The download URL object, or None if the token is invalid.
+ """
+ if not validate_token(token, is_secret_url):
+ return None
+ bytes = base64.urlsafe_b64decode(token.encode())
+ url_obj_id = bytes.split(b'_')[-1].decode()
+ if is_secret_url:
+ url_obj = FileSecretDownload.get_by_id(url_obj_id)
+ else:
+ url_obj = FileOnetimeDownload.get_by_id(url_obj_id)
+ return url_obj
+
+
+def validate_url_download(record, filename, token, is_secret_url):
+ """Validate the request for URL download.
+
+ Args:
+ record (WekoRecord): The record object.
+ filename (str): The name of the target file.
+ token (str): The token for the download URL.
+ is_secret_url (bool):
+ True if the URL is for secret URL, False if for onetime URL.
+
+ Returns:
+ Tuple[bool, str]: A tuple of the validation result and error message.
"""
- current_app.logger.debug("update_secret_download:{}".format(kwargs))
- return FileSecretDownload.update_download(**kwargs)
\ No newline at end of file
+ # Check if the token is valid
+ if not validate_token(token, is_secret_url):
+ return False, _('The provided token is invalid.')
+
+ if is_secret_url:
+ if not is_secret_url_feature_enabled():
+ return False, _('This feature is currently disabled.')
+
+ # Check if the file is available for download
+ if (not validate_file_access(record, filename, is_secret_url) or
+ not validate_download_record(record)):
+ return False, _('This file is currently not available for this feature.')
+
+ # Check if the URL is still valid
+ url_obj = convert_token_into_obj(token, is_secret_url)
+ if url_obj.is_deleted is True:
+ return False, _('This URL has been deactivated.')
+ if url_obj.download_count >= url_obj.download_limit:
+ return False, _('The download limit has been exceeded.')
+ limit_date = url_obj.expiration_date.replace(tzinfo=timezone.utc)
+ if limit_date < dt.now(timezone.utc):
+ return False, _('The expiration date for download has been exceeded.')
+
+ return True, ''
+
+
+def validate_file_access(record, filename, is_secret_url):
+ if is_secret_url:
+ return is_secret_file(record, filename)
+ else:
+ return is_onetime_file(record, filename)
+
+
+def save_download_log(record, file_name, token, is_secret_url):
+ """Save the download log for the given token.
+
+ Befor calling this function, the token must be validated by the function
+ 'validate_url_download()' to ensure that the token is valid. Especially,
+ the 'accessrole' value in the 'file_data' must be already checked.
+
+ Args:
+ record (WekoRecord): The record metadata of the item.
+ file_name (str): The name of the downloaded file.
+ token (str): The token used for the download.
+ is_secret_url (bool): True if for secret URL, False if for onetime URL.
+
+ Raises:
+ Exception: If an unexpected error occurs during the log creation.
+
+ Returns:
+ FileUrlDownloadLog: The created download log object.
+ """
+ target_data = {}
+ for file_data in record.get_file_data():
+ if file_data.get('filename') == file_name:
+ target_data = file_data
+ break
+ url_obj = convert_token_into_obj(token, is_secret_url)
+ if is_secret_url:
+ return FileUrlDownloadLog.create(
+ url_type = UrlType.SECRET,
+ secret_url_id = url_obj.id,
+ onetime_url_id = None,
+ ip_address = request.remote_addr,
+ access_status = (AccessStatus.OPEN_NO
+ if target_data.get('accessrole') == 'open_no'
+ else AccessStatus.OPEN_DATE),
+ used_token = token,
+ )
+ else:
+ return FileUrlDownloadLog.create(
+ url_type = UrlType.ONETIME,
+ secret_url_id = None,
+ onetime_url_id = url_obj.id,
+ ip_address = None,
+ access_status = AccessStatus.OPEN_RESTRICTED,
+ used_token = token,
+ )
diff --git a/modules/weko-records-ui/weko_records_ui/views.py b/modules/weko-records-ui/weko_records_ui/views.py
index d2eb347950..1e0b5d20ab 100644
--- a/modules/weko-records-ui/weko_records_ui/views.py
+++ b/modules/weko-records-ui/weko_records_ui/views.py
@@ -60,22 +60,25 @@
remove_weko2_special_character, selected_value_by_language
from weko_search_ui.api import get_search_detail_keyword
from weko_schema_ui.models import PublishStatus
-from weko_user_profiles.models import UserProfile
from weko_workflow.api import WorkFlow
from weko_records_ui.fd import add_signals_info
-from weko_records_ui.utils import check_items_settings, get_file_info_list
-from weko_workflow.utils import get_item_info, process_send_mail, set_mail_info
+from weko_records_ui.utils import check_items_settings, get_file_info_list,can_manage_onetime_url
+from weko_records_ui.models import FileSecretDownload, FileOnetimeDownload
from .ipaddr import check_site_license_permission
-from .models import FilePermission, PDFCoverPageSettings
+from .models import FileOnetimeDownload, FilePermission, FileSecretDownload, \
+ PDFCoverPageSettings
from .permissions import check_content_clickable, check_created_id, \
check_file_download_permission, check_original_pdf_download_permission, \
check_permission_period, file_permission_factory, get_permission
-from .utils import create_secret_url, get_billing_file_download_permission, \
- get_google_detaset_meta, get_google_scholar_meta, get_groups_price, \
+from .utils import can_manage_onetime_url, can_manage_secret_url, \
+ create_download_url, create_secret_url_record, \
+ get_billing_file_download_permission, get_google_detaset_meta, \
+ get_google_scholar_meta, get_groups_price, \
get_min_price_billing_file_download, get_record_permalink, hide_by_email, \
- delete_version, is_show_email_of_creator,hide_by_itemtype
+ delete_version, is_show_email_of_creator,hide_by_itemtype, \
+ send_secret_url_mail, validate_secret_url_generation_request
from .utils import restore as restore_imp
from .utils import soft_delete as soft_delete_imp
@@ -722,95 +725,232 @@ def _get_rights_title(result, rights_key_str, rights_values, current_lang, meta_
flg_display_itemtype = current_app.config.get('WEKO_RECORDS_UI_DISPLAY_ITEM_TYPE') ,
flg_display_resourcetype = current_app.config.get('WEKO_RECORDS_UI_DISPLAY_RESOURCE_TYPE') ,
search_author_flg=search_author_flg,
- show_secret_URL=_get_show_secret_url_button(record,filename),
+ show_secret_URL=can_manage_secret_url(record, filename),
+ show_onetime_URL=can_manage_onetime_url(record, filename),
+ active_secret_URLs=FileSecretDownload.fetch_active_urls(
+ record_id=pid.pid_value, file_name=filename, ascending=True),
+ active_onetime_URLs=FileOnetimeDownload.fetch_active_urls(
+ record_id=pid.pid_value, file_name=filename, ascending=True),
**ctx,
**kwargs
)
+@blueprint.route('/get-secret-settings', methods=['GET'])
+def get_secret_setting():
+ """
+ Get secret URL settings.
+
+ :return: JSON result containing secret download settings.
+ """
+ try:
+ # 初期化
+ result = {}
+
+ # AdminSettingsから設定を取得
+ admin_settings = AdminSettings.query.filter_by(name='restricted_access').first()
+ if admin_settings:
+ settings = admin_settings.settings
+ # 値を取得し、結果に追加
+ result['secret_expiration_date'] = settings.get('secret_URL_file_download', {}).get('secret_expiration_date',30)
+ result['secret_download_limit'] = settings.get('secret_URL_file_download', {}).get('secret_download_limit',10)
+ result['max_secret_expiration_date'] = settings.get('secret_URL_file_download', {}).get('max_secret_expiration_date',30)
+ result['max_secret_download_limit'] = settings.get('secret_URL_file_download', {}).get('max_secret_download_limit',10)
+ else:
+ # デフォルト値を設定
+ result['secret_expiration_date'] = 30
+ result['secret_download_limit'] = 10
+ result['max_secret_expiration_date'] = 30
+ result['max_secret_download_limit'] = 10
+
+ # JSON形式で返す
+ return jsonify(result)
+ except Exception as e:
+ return jsonify({"error": str(e)}), 500
+
+def create_secret_url_and_send_mail(pid, record, filename, **kwargs):
+ """Issue a new secret URL for a file in a record.
+
+ This method issues a new secret URL by creating a new record in the
+ FileSecretDownload table. The method also sends an email including the
+ URL to the user if the 'send_email' parameter of the request is set to
+ True.
-def create_secret_url_and_send_mail(pid:PersistentIdentifier, record:WekoRecord, filename:str, **kwargs) -> str:
- """on click button 'Secret URL'
- generate secret URL and send mail.
- about entrypoint settings, see at .config RECORDS_UI_ENDPOINTS.recid_secret_url
-
Args:
- pid: PID object.
- record: Record object.
- filename: File name.
+ pid (PersistentIdentifier): The identifier for the item.
+ record (WekoRecord): The record metadata of the item.
+ filename (str): The file name to download.
Returns:
- result status and message text.
+ flask.Response:
+ A JSON response containing result messages.
+
+ Raises:
+ flask.abort:
+ - 400 if the request is invalid.
+ - 403 if the user does not have enough permissions.
+ - 500 if an error occurs while creating the secret URL.
"""
- current_app.logger.info("pid:" + pid.pid_value)
- current_app.logger.info("record:" + str(record.id))
- current_app.logger.info("filename:" + filename)
-
- #permission check
- # "Someone who can show Secret URL button" can also use generate Secret URL function.
- if not _get_show_secret_url_button(record ,filename):
+ if not validate_secret_url_generation_request(request.json):
+ abort(400)
+ if not can_manage_secret_url(record, filename):
abort(403)
- userprof:UserProfile = UserProfile.get_by_userid(current_user.id)
- restricted_fullname = userprof._displayname or '' if userprof else ''
- restricted_data_name = record.get('item_title','')
+ try:
+ url_obj = create_secret_url_record(pid.pid_value,
+ filename,
+ request.json)
+ except Exception as e:
+ current_app.logger.error(e)
+ abort(500)
- #generate url and regist db(FileSecretDownload)
- result = create_secret_url(pid.pid_value,filename,current_user.email , restricted_fullname , restricted_data_name)
-
- #send mail
- mail_pattern_name:str = current_app.config.get('WEKO_RECORDS_UI_MAIL_TEMPLATE_SECRET_URL')
+ message = _('Secret URL generated successfully')
+ if request.json['send_email'] is True:
+ sending_result = send_secret_url_mail(
+ pid.object_uuid, url_obj, record.get('item_title', ''))
+ if sending_result:
+ message += _(', please check your email inbox')
+ else:
+ message += _(', but there was an error while sending the email. '
+ 'To use the URL, please refresh the page and copy it '
+ 'from the issued URL list')
+ return jsonify({'message': message + _('.')})
- mail_info = set_mail_info(get_item_info(pid.object_uuid), type("" ,(object,),dict(activity_id = '')))
- mail_info.update(result)
- if process_send_mail( mail_info = mail_info, mail_pattern_name=mail_pattern_name) :
- return _('Success Secret URL Generate')
- else:
+
+def copy_secret_url(pid, record, **kwargs):
+ """
+ Validate the request and return a secret URL to the user.
+
+ Args:
+ pid (str): A persistent identifier of the record.
+ record (dict): Record data associated with the target file.
+ **kwargs: Additional arguments, including:
+ - filename (str): The name of the file.
+ - url_id (str): The ID of the URL to be copied.
+
+ Returns:
+ flask.Response:
+ A JSON response containing the URL and a success message.
+
+ Raises:
+ flask.abort:
+ - 403 if the user does not have enough permissions.
+ - 500 if an error occurs while preparing the URL.
+ """
+ try:
+ if not can_manage_secret_url(record, kwargs['filename']):
+ abort(403)
+ url_record = FileSecretDownload.get_by_id(kwargs['secret_url_id'])
+ url = create_download_url(url_record)
+ except Exception as e:
+ current_app.logger.error(e)
+ abort(500)
+
+ return jsonify({'url': url,
+ 'message': 'The secret URL copied to your clipboard.'})
+
+
+def copy_onetime_url(pid, record, **kwargs):
+ """
+ Validate the request and return a onetime URL to the user.
+
+ Args:
+ pid (str): A persistent identifier of the record.
+ record (dict): Record data associated with the target file.
+ **kwargs: Additional arguments, including:
+ - filename (str): The name of the file.
+ - url_id (str): The ID of the URL to be copied.
+
+ Returns:
+ flask.Response:
+ A JSON response containing the URL and a success message.
+
+ Raises:
+ flask.abort:
+ - 403 if the user does not have enough permissions.
+ - 500 if an error occurs while preparing the URL.
+ """
+ try:
+ if not can_manage_onetime_url(record, kwargs['filename']):
+ abort(403)
+ url_record = FileOnetimeDownload.get_by_id(kwargs['onetime_url_id'])
+ url = create_download_url(url_record)
+ except Exception as e:
+ current_app.logger.error(e)
abort(500)
-def _get_show_secret_url_button(record : WekoRecord, filename :str) -> bool:
- """
- Args:
- WekoRecord : records_metadata for target item
- str : target content name
- Returns:
- bool : return true if be able to show Secret URL button. or false.
+ return jsonify({'url': url,
+ 'message': 'The onetime URL copied to your clipboard.'})
+
+
+def delete_secret_url(pid, record, **kwargs):
+ """
+ Delete a secret URL from the database.
+
+ Args:
+ pid (str): A persistent identifier of the record.
+ record (dict): Record data associated with the target file.
+ **kwargs: Additional arguments, including:
+ - filename (str): The name of the file.
+ - url_id (str): The ID of the URL to be deleted.
+
+ Returns:
+ flask.Response:
+ A JSON response containing a success message.
+
+ Raises:
+ flask.abort:
+ - 403 if the user does not have enough permissions.
+ - 500 if an error occurs while deleting the URL.
"""
+ try:
+ if not can_manage_secret_url(record, kwargs['filename']):
+ abort(403)
+ url_record = FileSecretDownload.get_by_id(kwargs['secret_url_id'])
+ if not url_record:
+ abort(404)
+ url_record.delete_logically()
+ except Exception as e:
+ current_app.logger.error(e)
+ abort(500)
+
+ return jsonify(
+ {'message': 'The secret URL has been successfully deleted.'})
+
+
+def delete_onetime_url(pid, record, **kwargs):
+ """
+ Delete an onetime URL from the database.
+
+ Args:
+ pid (str): A persistent identifier of the record.
+ record (dict): Record data associated with the target file.
+ **kwargs: Additional arguments, including:
+ - filename (str): The name of the file.
+ - url_id (str): The ID of the URL to be deleted.
+
+ Returns:
+ flask.Response:
+ A JSON response containing a success message.
+
+ Raises:
+ flask.abort:
+ - 403 if the user does not have enough permissions.
+ - 500 if an error occurs while deleting the URL.
+ """
+ try:
+ if not can_manage_onetime_url(record, kwargs['filename']):
+ abort(403)
+ url_record = FileOnetimeDownload.get_by_id(kwargs['onetime_url_id'])
+ if not url_record:
+ abort(404)
+ url_record.delete_logically()
+ except Exception as e:
+ current_app.logger.error(e)
+ abort(500)
+
+ return jsonify(
+ {'message': 'The one-time URL has been successfully deleted.'})
- #1.check secret url function is enabled
- restricted_access = AdminSettings.get('restricted_access', False)
- if not restricted_access:
- restricted_access = current_app.config[
- 'WEKO_ADMIN_RESTRICTED_ACCESS_SETTINGS']
-
- enable:bool = restricted_access.get('secret_URL_file_download',{}).get('secret_enable',False)
-
- #2.check the user has permittion
- has_parmission = False
- # Registered user
- owner_user_id = [int(record['owner'])] if record.get('owner') else []
- shared_user_id = [int(record['weko_shared_id'])] if int(record.get('weko_shared_id', -1)) != -1 else []
- if current_user and current_user.is_authenticated and \
- current_user.id in owner_user_id + shared_user_id:
- has_parmission = True
- # Super users
- supers = current_app.config['WEKO_PERMISSION_SUPER_ROLE_USER']
- for role in list(current_user.roles or []):
- if role.name in supers:
- has_parmission = True
-
- #3.check the file's accessrole is "open_no" ,or "open_date" and not open yet.
- is_secret_file = False
- current_app.logger.info(record.get_file_data())
- for content in record.get_file_data():
- if content.get('filename') == filename:
- if content.get('accessrole') == "open_no":
- is_secret_file = True
- elif content.get('accessrole') == "open_date" and \
- datetime.now() < datetime.strptime(content.get('date',[{"dateValue" :'1970-01-01'}])[0].get("dateValue" ,'1970-01-01'), '%Y-%m-%d') :
- is_secret_file = True
-
- # all true is show
- return enable and has_parmission and is_secret_file
@blueprint.route('/r/', methods=['GET'])
@blueprint.route('/r/.', methods=['GET'])
diff --git a/modules/weko-workflow/tests/test_api.py b/modules/weko-workflow/tests/test_api.py
index 8707c6f781..340b9fd16a 100644
--- a/modules/weko-workflow/tests/test_api.py
+++ b/modules/weko-workflow/tests/test_api.py
@@ -1,6 +1,11 @@
from flask_login.utils import login_user
-from weko_workflow.api import Flow, WorkActivity
+from weko_workflow.api import Flow, WorkActivity,UpdateItem, PublishStatus
+import unittest
+from unittest.mock import MagicMock, patch
+from weko_deposit.api import WekoIndexer
+from weko_records_ui.models import FileSecretDownload
+from weko_schema_ui.models import PublishStatus
# .tox/c1/bin/pytest --cov=weko_workflow tests/test_api.py::test_Flow_action -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_Flow_action(app, client, users, db, action_data):
@@ -134,3 +139,153 @@ def test_WorkActivity_get_corresponding_usage_activities(app, db_register):
usage_application_list, output_report_list = activity.get_corresponding_usage_activities(1)
assert usage_application_list == {'activity_data_type': {}, 'activity_ids': []}
assert output_report_list == {'activity_data_type': {}, 'activity_ids': []}
+
+from unittest.mock import call, patch, MagicMock
+
+class MockRecord(dict):
+ def commit(self):
+ pass
+
+# .tox/c1/bin/pytest --cov=weko_workflow tests/test_api.py::test_publish -vv -s --cov-branch --cov-report=html --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
+@patch('weko_records_ui.models.FileSecretDownload')
+@patch('weko_deposit.api.WekoIndexer')
+@patch('weko_workflow.api.db.session.commit')
+def test_publish(mock_db_commit, mock_WekoIndexer, mock_FileSecretDownload):
+ def create_mock_record(publish_status, accessroles, filenames, recid='12345'):
+ attribute_value_mlt = [{'accessrole': role, 'filename': filename} for role, filename in zip(accessroles, filenames)]
+ record = MockRecord({
+ 'publish_status': publish_status,
+ 'recid': recid,
+ 'some_field': {
+ 'attribute_value_mlt': attribute_value_mlt
+ }
+ })
+ record.commit = MagicMock()
+ return record
+
+ def assert_publish(record, reset_mock=True):
+ update_item.publish(record)
+ assert record['publish_status'] == PublishStatus.PUBLIC.value
+ record.commit.assert_called_once()
+ mock_db_commit.assert_called()
+ mock_WekoIndexer.return_value.update_es_data.assert_called_with(record, update_revision=False, field='publish_status')
+ if reset_mock:
+ mock_FileSecretDownload.query.filter_by.return_value.all.reset_mock()
+
+ # Mock record objects
+ record1 = create_mock_record(None, [None], ['testfile.txt'])
+ record2 = create_mock_record(PublishStatus.PRIVATE.value, ['open_date'], ['testfile.txt'])
+ record3 = create_mock_record(PublishStatus.NEW.value, ['open_no'], ['testfile.txt'])
+ record4 = create_mock_record(PublishStatus.DELETE.value, ['other_date'], ['testfile.txt'])
+ record5 = create_mock_record(PublishStatus.PUBLIC.value, ['other_date'], ['testfile.txt'], None)
+ record_multiple_files = create_mock_record(PublishStatus.PUBLIC.value, ['open_no', 'open_date', 'other_date'], ['testfile1.txt', 'testfile2.txt', 'testfile3.txt'])
+
+ # Mock secret URLs
+ mock_secret_url = MagicMock()
+ mock_secret_url.delete_logically = MagicMock()
+ mock_FileSecretDownload.query.filter_by.return_value.all.return_value = [mock_secret_url]
+
+ # Create instance of UpdateItem
+ update_item = UpdateItem()
+
+ # record1のテスト
+ assert_publish(record1)
+
+ # record2のテスト
+ assert_publish(record2)
+
+ # record3のテスト
+ assert_publish(record3)
+
+ # record4のテスト
+ assert_publish(record4, reset_mock=False)
+ # record4のシークレットURL削除確認
+ mock_FileSecretDownload.query.filter_by.assert_called_with(record_id='12345', is_deleted=False, file_name='testfile.txt')
+ assert mock_secret_url.delete_logically.call_count == 1
+
+ # モックの呼び出し履歴をリセット
+ mock_FileSecretDownload.query.filter_by.reset_mock()
+ mock_secret_url.delete_logically.reset_mock()
+
+ # record5のテスト (recidがNoneの場合)
+ assert_publish(record5, reset_mock=False)
+ mock_FileSecretDownload.query.filter_by.assert_not_called()
+ mock_secret_url.delete_logically.assert_not_called()
+
+
+ # 複数のファイルが含まれている場合のテスト
+ record_multiple_files = create_mock_record(PublishStatus.DELETE.value, ['other_date', 'other_date'], ['testfile1.txt', 'testfile2.txt'])
+ assert_publish(record_multiple_files, reset_mock=False)
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile1.txt')
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile2.txt')
+ assert mock_secret_url.delete_logically.call_count == 2
+
+ # モックの呼び出し履歴をリセット
+ mock_secret_url.delete_logically.reset_mock()
+
+ # 片方のファイルが更新され、片方が更新されない場合のテスト
+ record_partial_update = create_mock_record(PublishStatus.DELETE.value, ['other_date', 'open_no'], ['testfile1.txt', 'testfile2.txt'])
+ assert_publish(record_partial_update, reset_mock=False)
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile1.txt')
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile2.txt')
+ assert mock_secret_url.delete_logically.call_count == 1
+
+ # モックの呼び出し履歴をリセット
+ mock_secret_url.delete_logically.reset_mock()
+
+ # どちらのファイルも論理削除が行われない場合のテスト
+ record_partial_update = create_mock_record(PublishStatus.DELETE.value, ['open_no', 'open_no'], ['testfile1.txt', 'testfile2.txt'])
+ assert_publish(record_partial_update, reset_mock=False)
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile1.txt')
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile2.txt')
+ mock_secret_url.delete_logically.assert_not_called()
+
+ # モックの呼び出し履歴をリセット
+ mock_secret_url.delete_logically.reset_mock()
+
+ # 2つ以上のファイルすべてが更新され、論理削除が行われる場合のテスト
+ record_partial_update = create_mock_record(PublishStatus.DELETE.value, ['other_date', 'other_date','other_date'], ['testfile1.txt', 'testfile2.txt', 'testfile3.txt'])
+ assert_publish(record_partial_update, reset_mock=False)
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile1.txt')
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile2.txt')
+ mock_FileSecretDownload.query.filter_by.assert_any_call(record_id='12345', is_deleted=False, file_name='testfile3.txt')
+ assert mock_secret_url.delete_logically.call_count == 3
+
+ # モックの呼び出し履歴をリセット
+ mock_secret_url.delete_logically.reset_mock()
+
+ # attribute_value_mltが空のリストの場合のテスト
+ record_empty_role = MockRecord({
+ 'publish_status': PublishStatus.PRIVATE.value,
+ 'recid': '12345',
+ 'some_field': {
+ 'attribute_value_mlt': []
+ }
+ })
+ update_item.publish(record_empty_role)
+ mock_secret_url.delete_logically.assert_not_called()
+ assert record_empty_role['publish_status'] == PublishStatus.PUBLIC.value
+
+ # "accessrole"が欠落しているケースのテスト
+ record_no_role = MockRecord({
+ 'publish_status': PublishStatus.PRIVATE.value,
+ 'recid': '12345',
+ 'some_field': {
+ 'attribute_value_mlt': [{'filename': 'testfile.txt'}]
+ }
+ })
+ update_item.publish(record_no_role)
+ mock_secret_url.delete_logically.assert_not_called()
+ assert record_no_role['publish_status'] == PublishStatus.PUBLIC.value
+
+ # "attribute_value_mlt"が辞書ではない場合のテスト
+ record_non_dict_attribute_value_mlt = MockRecord({
+ 'publish_status': PublishStatus.PRIVATE.value,
+ 'recid': '12345',
+ 'some_field': {
+ 'attribute_value_mlt': ['not_dict']
+ }
+ })
+ update_item.publish(record_non_dict_attribute_value_mlt)
+ mock_secret_url.delete_logically.assert_not_called()
+ assert record_non_dict_attribute_value_mlt['publish_status'] == PublishStatus.PUBLIC.value
\ No newline at end of file
diff --git a/modules/weko-workflow/tests/test_utils.py b/modules/weko-workflow/tests/test_utils.py
index 515ded0e5a..bb00ed4854 100644
--- a/modules/weko-workflow/tests/test_utils.py
+++ b/modules/weko-workflow/tests/test_utils.py
@@ -2245,68 +2245,38 @@ def test_validate_guest_activity_expired(app,workflow,mocker):
with patch("weko_workflow.utils.timedelta",side_effect=OverflowError):
result = validate_guest_activity_expired(activity_id)
assert result == ""
-# def create_onetime_download_url_to_guest(activity_id: str,
-# .tox/c1/bin/pytest --cov=weko_workflow tests/test_utils.py::test_create_onetime_download_url_to_guest -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
-def test_create_onetime_download_url_to_guest(app, workflow,mocker):
- with app.test_request_context():
- today = datetime.datetime(2022,10,6,1,2,3,4)
- datetime_mock = mocker.patch("weko_workflow.utils.datetime")
- datetime_mock.today.return_value=today
- datetime_mock.utcnow.return_value=today
- file_name="test_file.txt"
- record_id = str(uuid.uuid4())
- user_mail = "user@test.org"
- extra_info = {
- "file_name":file_name,
- "record_id":record_id,
- "user_mail":user_mail
- }
- token_value="A-20221003-00001 2022-10-01 guest@test.org CE06FDFB15823A5C"
- token_value = base64.b64encode(token_value.encode()).decode()
- activity_id = "A-20221003-00001"
- guest_activity = GuestActivity.create(
- user_mail="guest@test.org",
- record_id=record_id,
- file_name=file_name,
- activity_id=activity_id,
- token=token_value,
- expiration_date=30
- )
- datetime_mock_ui = mocker.patch("weko_records_ui.utils.dt")
- datetime_mock_ui.utcnow.return_value=today
- expiration_date = today + datetime.timedelta(days=30)
- mocker.patch("weko_records_ui.utils.oracle10.hash",return_value="CE06FDFB15823A5C")
- url_token = "{} {} {} {}".format(record_id,user_mail,"2022-10-06","CE06FDFB15823A5C")
- url_token_value = base64.b64encode(url_token.encode()).decode()
- url = 'http://TEST_SERVER.localdomain/record/{}/file/onetime/test_file.txt?token={}'.format(record_id,url_token_value)
- test = {
- "file_url":url,
- "expiration_date":expiration_date.strftime("%Y-%m-%d"),
- "expiration_date_ja":"",
- "expiration_date_en":""
- }
- result = create_onetime_download_url_to_guest(activity_id, extra_info)
- assert result == test
-
- # not exist user_mail
- extra_info = {
- "file_name":file_name,
- "record_id":record_id,
- "guest_mail":user_mail
- }
- result = create_onetime_download_url_to_guest(activity_id, extra_info)
- assert result == test
-
- # raise OverflowError
- with patch("weko_workflow.utils.timedelta",side_effect=OverflowError):
- test = {
- "file_url":url,
- "expiration_date":"",
- "expiration_date_ja":"無制限",
- "expiration_date_en":"Unlimited"
- }
- result = create_onetime_download_url_to_guest(activity_id, extra_info)
- assert result == test
+
+
+# .tox/c1/bin/pytest --cov=weko_workflow tests/test_utils.py::test_create_onetime_download_url_to_guest -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp -p no:warnings
+@patch('weko_workflow.utils.delete_guest_activity')
+@patch('weko_records_ui.utils.current_user')
+def test_create_onetime_download_url_to_guest(login_user, delete_activity, db,
+ users):
+ login_user.id = 1
+ valid_dicts = [
+ {'file_name': 'test_file.txt',
+ 'record_id': '1',
+ 'user_mail': 'test@example.org'},
+ {'file_name':
+ 'test_file.txt',
+ 'record_id': '1',
+ 'guest_mail': 'test@example.org'},
+ ]
+ invalid_dicts = [
+ {'record_id': '1', 'user_mail': 'test@example.org'},
+ {'file_name': 'test_file.txt', 'user_mail': 'test@example.org'},
+ {'file_name': 'test_file.txt', 'record_id': '1'},
+ ]
+ for valid_dict in valid_dicts:
+ result = create_onetime_download_url_to_guest(1, valid_dict)
+ assert 'file_url' in result
+ assert 'expiration_date' in result
+ delete_activity.reset_mock()
+ for invalid_dict in invalid_dicts:
+ result = create_onetime_download_url_to_guest(1, invalid_dict)
+ assert result == {}
+
+
# def delete_guest_activity(activity_id: str) -> bool:
# .tox/c1/bin/pytest --cov=weko_workflow tests/test_utils.py::test_delete_guest_activity -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-workflow/.tox/c1/tmp
def test_delete_guest_activity(client,workflow):
diff --git a/modules/weko-workflow/weko_workflow/api.py b/modules/weko-workflow/weko_workflow/api.py
index 7ef1f2c466..457520bfdf 100644
--- a/modules/weko-workflow/weko_workflow/api.py
+++ b/modules/weko-workflow/weko_workflow/api.py
@@ -2709,7 +2709,7 @@ class UpdateItem(object):
"""The class about item."""
def publish(self, record):
- r"""Record publish status change view.
+ """Record publish status change view.
Change record publish status with given status and renders record
export template.
@@ -2718,6 +2718,8 @@ def publish(self, record):
:return: The rendered template.
"""
from weko_deposit.api import WekoIndexer
+ from weko_records_ui.models import FileSecretDownload
+
publish_status = record.get('publish_status')
if not publish_status:
record.update({'publish_status': PublishStatus.PUBLIC.value})
@@ -2727,6 +2729,36 @@ def publish(self, record):
record.commit()
db.session.commit()
+ # レコード内のすべてのキーと値をループし、"attribute_value_mlt"の中のすべての"accessrole"と"filename"のペアを検索
+ file_access_pairs = []
+
+ for key, value in record.items():
+ # 値が辞書であり、"attribute_value_mlt"キーを持つ場合
+ if isinstance(value, dict):
+ attribute_values = value.get("attribute_value_mlt", [])
+ # attribute_valuesがリストで、最初のアイテムが辞書で "accessrole" と "filename" が含まれているか確認
+ if attribute_values and isinstance(attribute_values, list):
+ for item in attribute_values:
+ if isinstance(item, dict):
+ accessrole = item.get("accessrole")
+ filename = item.get("filename")
+ if accessrole and filename:
+ file_access_pairs.append((filename, accessrole))
+
+ #ワークフロー更新時、accessroleがopen_no, open_dateまたはNone以外の場合、シークレットURLを論理削除
+ rec_number = record.get('recid') # recid=record_id
+ if rec_number is not None:
+ for filename, accessrole in file_access_pairs:
+ # accessroleがopen_no, open_dateまたはNone以外の場合、シークレットURLを論理削除
+ if accessrole and accessrole not in ['open_no', 'open_date']:
+ secret_urls = FileSecretDownload.query.filter_by(record_id=rec_number, is_deleted=False, file_name=filename).all()
+ for urls in secret_urls:
+ # 論理削除メソッドを使用
+ urls.delete_logically()
+ # 処理するデータ量に応じて以下のような一括で論理削除を行うような処理を使用する。
+ # FileSecretDownload.query.filter_by(record_id=rec_number, is_deleted=False).update({'is_deleted': True})
+ db.session.commit()
+
indexer = WekoIndexer()
indexer.update_es_data(record, update_revision=False, field='publish_status')
diff --git a/modules/weko-workflow/weko_workflow/utils.py b/modules/weko-workflow/weko_workflow/utils.py
index 5569bc6bed..ec5f6e89f6 100644
--- a/modules/weko-workflow/weko_workflow/utils.py
+++ b/modules/weko-workflow/weko_workflow/utils.py
@@ -3324,10 +3324,15 @@ def create_onetime_download_url_to_guest(activity_id: str,
extra_info: dict):
"""Create onetime download URL to guest.
- @param activity_id:
- @param extra_info:
- @return:
+ Args:
+ activity_id (str): The ID of the usage application activity.
+ extra_info (dict): Additional information.
+
+ Returns:
+ dict: onetime URL and expiration date.
"""
+ from weko_records_ui.utils import (create_download_url,
+ create_onetime_url_record)
file_name = extra_info.get('file_name')
record_id = extra_info.get('record_id')
user_mail = extra_info.get('user_mail')
@@ -3335,39 +3340,23 @@ def create_onetime_download_url_to_guest(activity_id: str,
if not user_mail:
user_mail = extra_info.get('guest_mail')
is_guest_user = True
- if file_name and record_id and user_mail:
- from weko_records_ui.utils import generate_one_time_download_url
- onetime_file_url = generate_one_time_download_url(
- file_name, record_id, user_mail)
-
- # Delete guest activity.
- delete_guest_activity(activity_id)
-
- # Save onetime to Database.
- from weko_records_ui.utils import create_onetime_download_url
- one_time_obj = create_onetime_download_url(
- activity_id, file_name, record_id, user_mail, is_guest_user)
- expiration_tmp = {
- "expiration_date": "",
- "expiration_date_ja": "",
- "expiration_date_en": "",
- }
- if one_time_obj:
- try:
- expiration_date = timedelta(days=one_time_obj.expiration_date)
- expiration_date = datetime.today() + expiration_date
- expiration_date = expiration_date.strftime("%Y-%m-%d")
- expiration_tmp['expiration_date'] = expiration_date
- except OverflowError:
- expiration_tmp["expiration_date_ja"] = "無制限"
- expiration_tmp["expiration_date_en"] = "Unlimited"
- return {
- "file_url": onetime_file_url,
- **expiration_tmp,
- }
- else:
- current_app.logger.error("Can not create onetime download.")
- return False
+ if not file_name or not record_id or not user_mail:
+ return {}
+
+ try:
+ url_obj = create_onetime_url_record(
+ activity_id, record_id, file_name, user_mail, is_guest_user)
+ except:
+ return {}
+ if not url_obj:
+ return {}
+
+ delete_guest_activity(activity_id)
+
+ return {
+ 'file_url': create_download_url(url_obj),
+ 'expiration_date': url_obj.expiration_date
+ }
def delete_guest_activity(activity_id: str) -> bool: