From 2714f25a6db0c2877a01d8b5e39b34a00b68e421 Mon Sep 17 00:00:00 2001 From: MakotoASAOKA Date: Wed, 16 Sep 2026 06:10:49 +0000 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20docker-compose2.yml=20=E3=81=AE?= =?UTF-8?q?=E3=83=93=E3=83=AB=E3=83=89=E5=A4=B1=E6=95=97=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=EF=BC=88=E5=A4=96=E9=83=A8=E4=BE=9D=E5=AD=98=E3=81=AE?= =?UTF-8?q?=E7=B5=8C=E5=B9=B4=E5=8A=A3=E5=8C=96=E5=AF=BE=E5=BF=9C=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debian buster ミラー消滅、NodeSource Node.js 4.x の署名鍵失効、 npm間接依存(psl)のNode4.x非互換、GitHub依存リポジトリ削除の 4点を修正し、docker-compose -f docker-compose2.yml build が 通るようにした。詳細は BUILD_FIX_NOTES.md を参照。 Co-Authored-By: Claude Sonnet 5 --- BUILD_FIX_NOTES.md | 71 +++++++++++++++++++ Dockerfile | 8 +++ .../invenio_deposit/bundles.py | 8 ++- scripts/provision-web.sh | 16 ++++- 4 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 BUILD_FIX_NOTES.md diff --git a/BUILD_FIX_NOTES.md b/BUILD_FIX_NOTES.md new file mode 100644 index 0000000000..8bafba78de --- /dev/null +++ b/BUILD_FIX_NOTES.md @@ -0,0 +1,71 @@ +# docker-compose2.yml ビルド修正メモ(feature/jgss) + +`docker-compose -f docker-compose2.yml build` を実行した際、外部依存の経年劣化により +複数の段階でビルドが失敗した。原因と対応を記録する。 + +## 1. Debian buster のミラー消滅(404 Not Found) + +- **症状**: `apt-get update` が `deb.debian.org` / `security.debian.org` に対して + 404 Not Found で失敗する。 +- **原因**: Debian buster は EOL となり、通常のミラーから削除され + `archive.debian.org` に移動済み。 +- **対応**: `Dockerfile` の `stage_2` で、`provision-web.sh` 実行前に + `/etc/apt/sources.list` を `archive.debian.org` を参照するよう書き換え、 + `Acquire::Check-Valid-Until "false"` を設定した。 + +## 2. NodeSource Node.js 4.x リポジトリの GPG 署名検証失敗 + +- **症状**: `https://deb.nodesource.com/setup_4.x` が追加するリポジトリの + `InRelease` が `NO_PUBKEY 1655A0AB68576280` で検証できず、 + `apt-get update` が失敗する。 +- **原因**: Node.js 4.x 用リポジトリは EOL で、署名鍵が NodeSource 側の + 鍵配布エンドポイントから既に取得できない。 +- **対応**: `scripts/provision-web.sh` で、NodeSource セットアップスクリプト + 実行後に `sources.list.d/nodesource.list` の `[signed-by=...]` オプションを + `[trusted=yes]` に置き換え、このリポジトリのみ検証をスキップするようにした + (他の apt ソースの検証には影響しない)。セットアップスクリプト自体が + 内部で実行する `apt-get update` の失敗で `set -o errexit` により + スクリプト全体が止まらないよう `|| true` を付与し、その後 + 明示的に `apt-get -y update` を再実行している。 + +## 3. npm 間接依存(psl)が Node.js 4.x で構文エラー + +- **症状**: `npm install -g node-sass@3.8.0 ...` の実行中、 + `node-sass/node_modules/request/node_modules/tough-cookie/node_modules/psl` + で `SyntaxError: Unexpected token ...`(スプレッド構文)が発生する。 +- **原因**: `package.json` にバージョン固定(lockfile)がなく、 + `npm install` 実行時点の npm レジストリ最新版の間接依存を解決するため、 + 時間経過とともに `psl` が Node.js 4.x では実行できないモダンな構文を + 使うバージョンに更新されてしまっていた。 +- **対応**: `scripts/provision-web.sh` の該当 `npm install -g` コマンドに + `psl@1.1.31 tough-cookie@2.3.4`(Node.js 4.x 互換の古いバージョン)を + 明示的に追加し、間接依存として新しいバージョンが解決されないようにした。 + +## 4. GitHub 上の依存リポジトリ削除(angular-schema-form-ckeditor) + +- **症状**: `create-instance2.sh` の npm install 中、 + `https://github.com/webcanvas/angular-schema-form-ckeditor.git` の clone で + `Invalid username or token. Password authentication is not supported for + Git operations.` が発生する。 +- **原因**: 元リポジトリ `webcanvas/angular-schema-form-ckeditor` が + GitHub 上から削除(または非公開化)されており、匿名アクセスで + 401 Unauthorized となっていた。 +- **対応**: 同一コミット(`b213fa934759a18b1436e23bfcbd9f0f730f1296`)を + 含むフォーク `nvdnkpr/angular-schema-form-ckeditor` を発見し、 + `modules/invenio-deposit/invenio_deposit/bundles.py` の参照先を + そちらに変更した。また、npm(v2系)のシャロークローンでは + フォーク側のデフォルトブランチ tip 以外のコミットに到達できず + `fatal: bad object` となったため、`git+commit` 参照ではなく + GitHub の tarball URL + (`.../archive/.tar.gz`)を指定する方式に変更した。 + +## 変更ファイル + +- `Dockerfile` +- `scripts/provision-web.sh` +- `modules/invenio-deposit/invenio_deposit/bundles.py` + +## 結果 + +上記 4 点の修正により `docker-compose -f docker-compose2.yml build` が +成功することを確認済み(`weko-web` イメージのビルド完了、exit code 0)。 diff --git a/Dockerfile b/Dockerfile index 3a4bd23d25..dc49e55fde 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,6 +45,14 @@ ENV SEARCH_INDEX_PREFIX=tenant1 ENV INVENIO_DB_POOL_CLASS=QueuePool FROM stage_1 AS stage_2 +# Debian buster is EOL: repoint apt sources to archive.debian.org +# so `apt-get update` doesn't 404 against the removed mirrors. +RUN sed -i \ + -e 's|deb.debian.org/debian |archive.debian.org/debian |g' \ + -e 's|security.debian.org/debian-security|archive.debian.org/debian-security|g' \ + -e '/buster-updates/d' \ + /etc/apt/sources.list && \ + echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/99no-check-valid-until # Install Weko web node pre-requisites: COPY scripts/provision-web.sh /tmp/ RUN /tmp/provision-web.sh diff --git a/modules/invenio-deposit/invenio_deposit/bundles.py b/modules/invenio-deposit/invenio_deposit/bundles.py index 10d0fdd01a..567e3fbab5 100644 --- a/modules/invenio-deposit/invenio_deposit/bundles.py +++ b/modules/invenio-deposit/invenio_deposit/bundles.py @@ -56,9 +56,13 @@ 'node_modules/rr-ng-ckeditor/ng-ckeditor.js', 'node_modules/angular-schema-form-ckeditor/bootstrap-ckeditor.js', npm={ + # Original repo (webcanvas/angular-schema-form-ckeditor) was deleted + # from GitHub; this fork carries the exact same commit. Use a + # tarball URL (not a git+commit ref) since npm's shallow git clone + # can't reach a commit outside the fork's default branch tip. 'angular-schema-form-ckeditor': - 'https://github.com/webcanvas/angular-schema-form-ckeditor' - '.git#b213fa934759a18b1436e23bfcbd9f0f730f1296', + 'https://github.com/nvdnkpr/angular-schema-form-ckeditor' + '/archive/b213fa934759a18b1436e23bfcbd9f0f730f1296.tar.gz', 'ckeditor': '~4.5.10', 'rr-ng-ckeditor': '~0.2.1', } diff --git a/scripts/provision-web.sh b/scripts/provision-web.sh index 2f583fbe43..e8f45e7cdd 100755 --- a/scripts/provision-web.sh +++ b/scripts/provision-web.sh @@ -65,7 +65,16 @@ provision_web_common_ubuntu14 () { # sphinxdoc-add-nodejs-external-repository-ubuntu14-begin if [[ ! -f /etc/apt/sources.list.d/nodesource.list ]]; then - curl -sL https://deb.nodesource.com/setup_4.x | $sudo bash - + # NodeSource's Node.js 4.x repo is EOL: its own setup script runs + # `apt-get update` internally and that fails because the repo's GPG + # signature can no longer be verified (key not served anymore), so + # allow this one command to fail (it still writes the sources.list.d + # file before erroring out) rather than aborting the whole build. + curl -sL https://deb.nodesource.com/setup_4.x | $sudo bash - || true + # Trust this single, already-EOL repo explicitly rather than + # weakening apt verification globally, then refresh package lists. + $sudo sed -i 's/\[signed-by=[^]]*\]/[trusted=yes]/' /etc/apt/sources.list.d/nodesource.list + $sudo apt-get -y update fi # sphinxdoc-add-nodejs-external-repository-ubuntu14-end @@ -153,7 +162,10 @@ setup_npm_and_css_js_filters () { # sphinxdoc-install-npm-and-css-js-filters-begin # $sudo su -c "npm install -g npm" - $sudo su -c "npm install -g node-sass@3.8.0 clean-css@3.4.12 requirejs uglify-js" + # Pin transitive deps of node-sass@3.8.0 (via request -> tough-cookie -> psl) + # to old, ES5-only versions: newer psl/tough-cookie releases use syntax + # (e.g. spread operator) that Node.js 4.x's runtime cannot parse. + $sudo su -c "npm install -g node-sass@3.8.0 clean-css@3.4.12 requirejs uglify-js psl@1.1.31 tough-cookie@2.3.4" # sphinxdoc-install-npm-and-css-js-filters-end } From adc2ddb5d7e78781b73c5aa9ce9f0543aa8d3576 Mon Sep 17 00:00:00 2001 From: MakotoASAOKA Date: Thu, 17 Sep 2026 07:05:22 +0000 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20Elasticsearch=20snapshot=E3=83=AA?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=A2=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B?= =?UTF-8?q?=E3=81=A6=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E3=83=BB?= =?UTF-8?q?=E3=83=9E=E3=82=A6=E3=83=B3=E3=83=88=E8=A8=AD=E5=AE=9A=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Elasticsearch snapshot(6.8.23)を復元できるよう、elasticsearch/Dockerfile の ベースイメージを 6.8.22 から 6.8.23 に変更 - docker-compose2.yml の elasticsearch サービスに snapshot repository 用の 読み取り専用ボリューム(./es_snapshot_restore_new)を追加 - worker サービスの image タグが誤って別名(weko3_b_web)になっており ビルドしたイメージ(weko-web)と一致していなかったため修正 Co-Authored-By: Claude Sonnet 5 --- docker-compose2.yml | 3 ++- elasticsearch/Dockerfile | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docker-compose2.yml b/docker-compose2.yml index cc1766a4dd..08a89466a9 100644 --- a/docker-compose2.yml +++ b/docker-compose2.yml @@ -135,7 +135,7 @@ services: worker: restart: "always" - image: weko3_b_web + image: weko-web sysctls: net.core.somaxconn: 1024 #command: /bin/bash -c "rm -f /code/celeryd.pid; celery worker -A invenio_app.celery --loglevel=INFO -B -D -f /code/celeryd.log && uwsgi --ini /home/invenio/.virtualenvs/invenio/var/instance/conf/uwsgi.ini" @@ -271,6 +271,7 @@ services: dockerfile: ./elasticsearch/Dockerfile volumes: - es-data:/usr/share/elasticsearch/data + - ./es_snapshot_restore_new:/usr/share/elasticsearch/backups:ro environment: - "ES_JAVA_OPTS=-Xms2048m -Xmx2048m" ports: diff --git a/elasticsearch/Dockerfile b/elasticsearch/Dockerfile index 94179ca4aa..b059091757 100644 --- a/elasticsearch/Dockerfile +++ b/elasticsearch/Dockerfile @@ -20,7 +20,9 @@ # Use Elasticsearch 6. #FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.2.2 -FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.22 +# Pinned to 6.8.23 to match the version the JGSS ES snapshot backup was +# created with (a snapshot cannot be restored onto an older ES node). +FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.23 WORKDIR /usr/share/elasticsearch ARG ELASTICSEARCH_S3_ACCESS_KEY ARG ELASTICSEARCH_S3_SECRET_KEY From 9d0a13bf418bbd3e1645f135d9b8fd47fc6e6591 Mon Sep 17 00:00:00 2001 From: MakotoASAOKA Date: Thu, 17 Sep 2026 07:05:50 +0000 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20feature/jgss=20PR=E3=83=AC=E3=83=93?= =?UTF-8?q?=E3=83=A5=E3=83=BC=E7=94=A8=E8=B3=87=E6=96=99=E3=81=A8=E4=B8=8D?= =?UTF-8?q?=E5=85=B7=E5=90=88=E5=86=8D=E7=8F=BE=E3=83=87=E3=83=BC=E3=82=BF?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - WEKO3_BUILD_RESTORE_MANUAL.md: このブランチのビルド〜JGSSデータリストア手順書 - KNOWN_ISSUE_download_button_not_shown.md: 承認済み利用申請でもダウンロード ボタンが表示されない既知の不具合(事象・対応状況・再現データへのポインタ) - scripts/pr_review_init.sh: 上記2点をレビュー開始時にすぐ確認できる初期化スクリプト - scripts/demo/download_button_bug_repro/: 上記不具合を完全な合成データ (本番データ・個人情報は一切含まない)で再現するためのfixture一式 - .gitignore: 本番データ復元の作業ファイル(DBダンプ・ESスナップショット)を追跡対象外に Co-Authored-By: Claude Sonnet 5 --- .gitignore | 6 + KNOWN_ISSUE_download_button_not_shown.md | 55 +++ WEKO3_BUILD_RESTORE_MANUAL.md | 347 ++++++++++++++++++ .../demo/download_button_bug_repro/README.md | 181 +++++++++ .../download_button_bug_repro/attach_file.py | 42 +++ .../download_button_bug_repro/es_bulk.ndjson | 8 + .../download_button_bug_repro/fixture.sql | 218 +++++++++++ .../demo/download_button_bug_repro/load.sh | 65 ++++ .../demo/download_button_bug_repro/verify.py | 80 ++++ scripts/pr_review_init.sh | 40 ++ 10 files changed, 1042 insertions(+) create mode 100644 KNOWN_ISSUE_download_button_not_shown.md create mode 100644 WEKO3_BUILD_RESTORE_MANUAL.md create mode 100644 scripts/demo/download_button_bug_repro/README.md create mode 100644 scripts/demo/download_button_bug_repro/attach_file.py create mode 100644 scripts/demo/download_button_bug_repro/es_bulk.ndjson create mode 100644 scripts/demo/download_button_bug_repro/fixture.sql create mode 100755 scripts/demo/download_button_bug_repro/load.sh create mode 100644 scripts/demo/download_button_bug_repro/verify.py create mode 100755 scripts/pr_review_init.sh diff --git a/.gitignore b/.gitignore index d2ad277d3d..0181f4bef9 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,9 @@ test/data test/import.zip test/dummyfile/import.zip test/dummyfile/data + +# JGSS本番データ復元の作業ファイル(サイズ大・個人情報含むため追跡しない) +/after_restore.dump +/after_restore_jgssdds.dump +/es_snapshot_restore/ +/es_snapshot_restore_new/ diff --git a/KNOWN_ISSUE_download_button_not_shown.md b/KNOWN_ISSUE_download_button_not_shown.md new file mode 100644 index 0000000000..f81c93193c --- /dev/null +++ b/KNOWN_ISSUE_download_button_not_shown.md @@ -0,0 +1,55 @@ +# 既知の不具合: 利用申請承認済みアカウントでもダウンロードボタンではなく申請ボタンが表示される + +> この `feature/jgss` ブランチ上での作業・レビューにあたり、既知の別事象として最初に共有しておくノート。本PRのコード変更(ビルド修正・環境設定)そのものが原因の事象ではない。原因調査・改修方針は別途まとめ済みで、コードへの適用は本PRの範囲外(未実施)。 + +## 1. 事象 + +利用申請(usage application)が承認済み(承認済みステータス)のアカウントでログインし、当該アイテムの詳細画面にアクセスすると、期待される「ダウンロード」ボタンではなく「申請」ボタンが表示される。 + +## 2. 現在の対応状況 + +- 原因調査済み: `FilePermission.status` を承認時に `1`(承認済み)へ更新する処理が `feature/jgss` のコードに存在しないこと、および画面側の権限判定が実際の承認経路(`file_onetime_download` テーブル)を一切参照していないことが根本原因。 +- `jgss-pre` ブランチの実装を参考にした改修案・結合テスト計画を作成済み。 +- Redmineに起票済み(担当者に確認のこと。本ファイルにはチケット番号は含めていない)。 +- 上記いずれもコードへの適用はまだ行っていない。本ブランチのビルド・レビューを進める上で、この事象が別途あることを認識しておくこと。 + +## 3. 詳しい調査資料 + +同一環境(`/home/vagrant`)内に以下の内部ドキュメントがある(このgitリポジトリには含まれない)。 + +- `doc/download_button_not_shown_for_approved_user_report_20260916.md` — 原因調査レポート +- `doc/download_button_fix_proposal_20260916.md` — 改修案(`jgss-pre`参考) +- `doc/download_button_fix_integration_test_plan_20260916.md` — 結合テスト計画 + +## 4. 再現用データ + +本リポジトリに、この事象をレビュアの手元で再現するための**完全に合成した**デモデータ一式を同梱している。本番データ・個人情報は一切含まない(メールアドレスは `populate-instance.sh` が作るデモアカウント `contributor@example.org` のみ)。 + +- 置き場所: `scripts/demo/download_button_bug_repro/` +- 詳細手順: `scripts/demo/download_button_bug_repro/README.md` + +### 投入(`install.sh` による通常の新規構築が済んだ後に実行) + +```bash +./scripts/demo/download_button_bug_repro/load.sh +``` + +`fixture.sql`(PostgreSQL の差分行)と `es_bulk.ndjson`(Elasticsearch の当該アイテム文書)を投入する。自分が作る行だけを先に `DELETE` してから入れるため冪等で、既存行の変更・削除は行わない。 + +### 再現手順 + +1. `contributor@example.org` / `uspass123` でログインする。 +2. `https:///records/2003976`(「サンプル制限公開アイテム / Sample Restricted Item」)を開く。 +3. ファイル `sample_restricted_data.txt` の行に、**「ダウンロード」ではなく「申請」ボタン**が表示される。押すと同じ利用申請ワークフローが最初から始まってしまう。 + +利用申請アクティビティ `A-20260917-00001` は `activity_status='F'`(承認・完了済み)であるにもかかわらず上記になる点が本事象である。 + +### DB 上のシグネチャ + +| テーブル | 期待 | 実際 | +| --- | --- | --- | +| `workflow_activity` (`A-20260917-00001`) | `activity_status='F'` | `activity_status='F'` | +| `file_permission` (`record_id='2003976'`) | `status=1` の行がある | **行が 1 件もない** | +| `file_onetime_download` (`record_id='2003976'`) | — | `contributor@example.org` の行がある | + +シェルからの検証は `docker compose exec -T web invenio shell /code/scripts/demo/download_button_bug_repro/verify.py` で行える。 diff --git a/WEKO3_BUILD_RESTORE_MANUAL.md b/WEKO3_BUILD_RESTORE_MANUAL.md new file mode 100644 index 0000000000..a4752badb1 --- /dev/null +++ b/WEKO3_BUILD_RESTORE_MANUAL.md @@ -0,0 +1,347 @@ +# WEKO3 (feature/jgss) ビルド〜データリストア手順書 + +> このファイルはこの `feature/jgss` ブランチのPRに合わせてリポジトリに同梱したものです。手順書自体の由来・更新は `/home/vagrant/backup_jgss/WEKO3_build_restore_manual.md`(同一環境内)を正本として管理している。 +> +> **本文中で参照する `backup_jgss/WEKO3_OPE-9985_*.gz`(PostgreSQL dump・Elasticsearch snapshot)はこのgitリポジトリには含まれない。** サイズが大きい本番バックアップデータのため、別途担当者から入手し、リポジトリと同階層の `backup_jgss/` に配置すること。 + +## 1. 目的 + +`feature/jgss` ブランチの WEKO3 Docker Compose 環境を新規にビルドし、JGSS(JGSS データダウンロードシステム/`jgssdds_repo_nii_ac_jp`)の本番バックアップ(PostgreSQL + Elasticsearch snapshot)を復元して動作確認可能な状態にするまでの一連の手順をまとめる。 + +対象環境: `/home/vagrant/weko`(git branch: `feature/jgss`) +使用 Compose ファイル: `docker-compose2.yml` + +> **重要:** `docker compose down -v`、`docker volume prune`、`docker system prune -a --volumes` は、データ入り volume(`es-data` 等)を破壊するため実行しない。 + +## 2. 事前準備: ブランチ取得 + +```bash +cd ~/weko +git fetch -p +git checkout feature/jgss +``` + +以降の章のコード修正は `feature/jgss` に対して行い、完了後にコミットする(本手順で実施したビルド修正・環境設定変更は `feature/jgss` に 2 コミットとして反映済み)。 + +## 3. ビルド時の修正 + +`docker-compose -f docker-compose2.yml build` は、リポジトリ内の記述だけでは外部依存の経年劣化により以下 4 点で失敗する。詳細な原因は `BUILD_FIX_NOTES.md` を参照。 + +### 3.1 Debian Buster APT ミラー消滅(404 Not Found) + +Debian buster は EOL となり通常ミラーから削除されているため、`Dockerfile` の `stage_2`(`provision-web.sh` 実行前)で `archive.debian.org` を参照するよう書き換える。 + +```dockerfile +# Debian buster is EOL: repoint apt sources to archive.debian.org +# so `apt-get update` doesn't 404 against the removed mirrors. +RUN sed -i \ + -e 's|deb.debian.org/debian |archive.debian.org/debian |g' \ + -e 's|security.debian.org/debian-security|archive.debian.org/debian-security|g' \ + -e '/buster-updates/d' \ + /etc/apt/sources.list && \ + echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/99no-check-valid-until +``` + +### 3.2 NodeSource Node.js 4.x リポジトリの GPG 署名検証失敗 + +`https://deb.nodesource.com/setup_4.x` は EOL で署名鍵が取得できず `apt-get update` が失敗する。`scripts/provision-web.sh` で、セットアップスクリプト実行の失敗を許容しつつ、当該リポジトリのみ `[trusted=yes]` にして再度 `apt-get update` する。 + +```bash +# NodeSource's Node.js 4.x repo is EOL: its own setup script runs +# `apt-get update` internally and that fails because the repo's GPG +# signature can no longer be verified (key not served anymore), so +# allow this one command to fail (it still writes the sources.list.d +# file before erroring out) rather than aborting the whole build. +curl -sL https://deb.nodesource.com/setup_4.x | $sudo bash - || true +# Trust this single, already-EOL repo explicitly rather than +# weakening apt verification globally, then refresh package lists. +$sudo sed -i 's/\[signed-by=[^]]*\]/[trusted=yes]/' /etc/apt/sources.list.d/nodesource.list +$sudo apt-get -y update +``` + +### 3.3 npm 間接依存(psl / tough-cookie)が Node.js 4.x で構文エラー + +`node-sass@3.8.0` の間接依存 `request → tough-cookie → psl` がバージョン固定なしのため、時間経過で ES5 のみ対応の Node.js 4.x では実行できないモダン構文(スプレッド構文等)を使うバージョンに解決されてしまう。`scripts/provision-web.sh` の該当 `npm install -g` に旧バージョンを明示的に追加する。 + +```bash +# Pin transitive deps of node-sass@3.8.0 (via request -> tough-cookie -> psl) +# to old, ES5-only versions: newer psl/tough-cookie releases use syntax +# (e.g. spread operator) that Node.js 4.x's runtime cannot parse. +$sudo su -c "npm install -g node-sass@3.8.0 clean-css@3.4.12 requirejs uglify-js psl@1.1.31 tough-cookie@2.3.4" +``` + +### 3.4 GitHub 上の依存リポジトリ削除(angular-schema-form-ckeditor) + +元リポジトリ `webcanvas/angular-schema-form-ckeditor` が GitHub 上から削除されており `npm install` 中の clone が 401 で失敗する。同一コミットを含むフォーク `nvdnkpr/angular-schema-form-ckeditor` の tarball URL に参照先を変更する(npm v2 系のシャロークローンはフォークのデフォルトブランチ tip 以外に到達できないため、`git+commit` 参照ではなく tarball URL を使う)。 + +`modules/invenio-deposit/invenio_deposit/bundles.py`: + +```python +# Original repo (webcanvas/angular-schema-form-ckeditor) was deleted +# from GitHub; this fork carries the exact same commit. Use a +# tarball URL (not a git+commit ref) since npm's shallow git clone +# can't reach a commit outside the fork's default branch tip. +'angular-schema-form-ckeditor': + 'https://github.com/nvdnkpr/angular-schema-form-ckeditor' + '/archive/b213fa934759a18b1436e23bfcbd9f0f730f1296.tar.gz', +``` + +### 3.5 ビルド実行 + +```bash +cd ~/weko +docker compose -f docker-compose2.yml build +``` + +`weko-web` イメージのビルド完了・exit code 0 を確認する。 + +補足: 旧いディスク不足・PostgreSQL ポート競合(旧 `weko-pgpool-1` の `25401` 占有)・RabbitMQ 4.x の `transient_nonexcl_queues` 非推奨警告など、ホスト環境要因の問題が発生する場合は本書末尾「9. 過去に遭遇したホスト環境要因の問題」を参照。 + +## 4. Elasticsearch イメージのバージョン合わせ + +リストア対象の Elasticsearch snapshot は `6.8.23` で取得されているため、`elasticsearch/Dockerfile` のベースイメージを合わせておく(snapshot は同一または新しい ES バージョンにしかリストアできない)。 + +```dockerfile +# Pinned to 6.8.23 to match the version the JGSS ES snapshot backup was +# created with (a snapshot cannot be restored onto an older ES node). +FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.23 +``` + +`docker-compose2.yml` の worker サービスの `image:` が `weko3_b_web` のような誤った(ビルドされない)タグになっている場合は、web と同じ `weko-web` に修正する。 + +## 5. 環境起動 + +```bash +cd ~/weko +docker compose -f docker-compose2.yml up -d +docker compose -f docker-compose2.yml ps +``` + +全サービス(postgresql, elasticsearch, redis, rabbitmq, web, worker, nginx, flower)が `Up` であることを確認する。 + +```bash +curl -k -I https://localhost/ +``` + +`HTTP/1.1 200 OK` を確認する(この時点ではまだ初期データ/`tenant1-*` のデモデータ状態)。 + +## 6. PostgreSQL 復元(JGSS 本番データ) + +対象ファイル: `backup_jgss/WEKO3_OPE-9985_jgssdds_repo_nii_ac_jp.sql.gz`(※このgitリポジトリには含まれない。上記の注記を参照) + +このファイルは **plain-text 形式**の `pg_dump` 出力を gzip 圧縮したものであり(`pg_restore` 用の custom-format ではない)、`psql` にパイプしてリストアする。 + +### 6.1 dump の正常性確認 + +```bash +zcat backup_jgss/WEKO3_OPE-9985_jgssdds_repo_nii_ac_jp.sql.gz | head -c 300 +``` + +`-- PostgreSQL database dump` で始まることを確認する。 + +### 6.2 public schema 初期化 + +**破壊的操作。dump の正常性を確認してから実行する。** + +```bash +docker exec weko-postgresql-1 \ + psql -U invenio -d invenio -v ON_ERROR_STOP=1 -c \ + "DROP SCHEMA public CASCADE; CREATE SCHEMA public AUTHORIZATION invenio; GRANT ALL ON SCHEMA public TO invenio; GRANT ALL ON SCHEMA public TO public;" +``` + +### 6.3 復元 + +```bash +zcat backup_jgss/WEKO3_OPE-9985_jgssdds_repo_nii_ac_jp.sql.gz \ + | docker exec -i weko-postgresql-1 psql -U invenio -d invenio -v ON_ERROR_STOP=1 +``` + +### 6.4 復元後バックアップ(custom format で取得し直す) + +```bash +docker exec weko-postgresql-1 \ + pg_dump -U invenio -Fc invenio > ~/weko/after_restore_jgssdds.dump +``` + +### 6.5 復元確認 + +```bash +docker exec weko-postgresql-1 psql -U invenio -d invenio -tAc \ + "SELECT name FROM site_info;" +``` + +`JGSSデータダウンロードシステム` / `JGSS Data Download System` が返ることを確認する(サイト名にリストアしたテナントの情報が入っていることの確認)。 + +```bash +docker exec weko-postgresql-1 psql -U invenio -d invenio -tAc \ + "SELECT count(*) FROM pidstore_pid WHERE pid_value LIKE '%jgssdds%';" +``` + +## 7. Elasticsearch snapshot 復元(JGSS 本番データ) + +対象ファイル: `backup_jgss/WEKO3_OPE-9985_WEKO3_OPE-9985-jgssdds_repo_nii_ac_jp-esbackup.tar.gz`(※このgitリポジトリには含まれない) + +これは Elasticsearch filesystem snapshot repository である。`/usr/share/elasticsearch/data`(= `es-data` volume)へ直接展開しない。 + +### 7.1 展開 + +tar 内部に `WEKO3_OPE-9985/` という 1 階層のディレクトリが含まれるため、これを取り除いて展開する。 + +```bash +cd ~/weko +rm -rf es_snapshot_restore_new +mkdir -p es_snapshot_restore_new +tar -xzf backup_jgss/WEKO3_OPE-9985_WEKO3_OPE-9985-jgssdds_repo_nii_ac_jp-esbackup.tar.gz \ + -C es_snapshot_restore_new --strip-components=1 +``` + +展開後、直下に `index-0` / `index.latest` / `indices/` / `meta-*.dat` / `snap-*.dat` があることを確認する。 + +### 7.2 snapshot repository をマウント + +`docker-compose2.yml` の `elasticsearch` サービス: + +```yaml +elasticsearch: + volumes: + - es-data:/usr/share/elasticsearch/data + - ./es_snapshot_restore_new:/usr/share/elasticsearch/backups:ro +``` + +反映: + +```bash +docker compose -f docker-compose2.yml up -d --force-recreate elasticsearch +docker exec weko-elasticsearch-1 ls -lah /usr/share/elasticsearch/backups +``` + +### 7.3 repository 登録 + +```bash +curl -X PUT 'http://localhost:29201/_snapshot/jgssdds_restore' \ + -H 'Content-Type: application/json' \ + -d '{ + "type": "fs", + "settings": { + "location": "/usr/share/elasticsearch/backups", + "readonly": true + } + }' +``` + +### 7.4 snapshot 確認 + +```bash +curl -s 'http://localhost:29201/_snapshot/jgssdds_restore/_all?pretty' +``` + +- Elasticsearch: `6.8.23` +- インデックス名は本番接頭辞 `jgssdds_repo_nii_ac_jp-*` + +### 7.5 restore(本番接頭辞のまま:参照用) + +```bash +curl -X POST \ + 'http://localhost:29201/_snapshot/jgssdds_restore/snapshot/_restore?pretty' \ + -H 'Content-Type: application/json' \ + -d '{ + "indices": "jgssdds_repo_nii_ac_jp-*", + "include_global_state": false + }' +``` + +### 7.6 restore(`tenant1-*` へリネームして復元:Web アプリが実際に参照する側) + +WEKO3 の `SEARCH_INDEX_PREFIX` は環境で汎用の `tenant1` を使う運用のため、同じ snapshot をもう一度、インデックス名を `tenant1-*` にリネームして復元する(再インデックスではなく ES の snapshot restore の `rename_pattern`/`rename_replacement` 機能を使うことで、データをコピーし直さずに別名で復元できる)。 + +```bash +curl -X POST \ + 'http://localhost:29201/_snapshot/jgssdds_restore/snapshot/_restore?pretty' \ + -H 'Content-Type: application/json' \ + -d '{ + "indices": "jgssdds_repo_nii_ac_jp-*", + "rename_pattern": "jgssdds_repo_nii_ac_jp-(.+)", + "rename_replacement": "tenant1-$1", + "include_global_state": false + }' +``` + +> 既存の初期デモデータ由来の `tenant1-*` インデックスがある場合は、リネーム復元前に削除するか `include_global_state`/`indices` の対象を絞るなどして、復元対象と名前が衝突しないようにする。 + +### 7.7 復元確認 + +```bash +curl -s 'http://localhost:29201/_cat/recovery?v' | grep -E "jgssdds_repo_nii_ac_jp-weko-item|tenant1-weko-item" +``` + +`stage=done`、`files_percent=100.0%`、`bytes_percent=100.0%` であることを確認する。 + +```bash +curl -s 'http://localhost:29201/_cat/indices/tenant1-weko-item-v1.0.0?v' +``` + +single-node で replica=1 のため `yellow` でも復元失敗ではない。 + +## 8. Web/Worker 設定と最終確認 + +### 8.1 SEARCH_INDEX_PREFIX + +`docker-compose2.yml` の `web` / `worker` サービス(`environment`)を確認する。今回は `tenant1-*` へリネーム復元しているため、`SEARCH_INDEX_PREFIX=tenant1` のままでよい(本番接頭辞 `jgssdds_repo_nii_ac_jp` に変更しない)。 + +```bash +docker compose -f docker-compose2.yml config | grep -n -A2 -B2 SEARCH_INDEX_PREFIX +``` + +### 8.2 反映 + +```bash +docker compose -f docker-compose2.yml up -d --force-recreate web worker +docker compose -f docker-compose2.yml restart nginx +``` + +### 8.3 確認 + +```bash +docker exec weko-web-1 sh -c 'echo $SEARCH_INDEX_PREFIX' +# => tenant1 + +curl -k -I https://localhost/ +# => HTTP/1.1 200 OK +``` + +- PostgreSQL: `site_info.name` が JGSS のもの、`pidstore_pid` に `jgssdds` を含む PID が存在する。 +- Elasticsearch: `jgssdds_repo_nii_ac_jp-*`(参照用)と `tenant1-*`(Web 参照用)の両方が `recovery` で `done`。 +- `tenant1-weko-item-v1.0.0` の `docs.count` が `jgssdds_repo_nii_ac_jp-weko-item-v1.0.0` と一致する。 +- ブラウザから検索・アイテム詳細・添付ファイル・管理画面・登録更新処理を確認する。 + +## 9. 過去に遭遇したホスト環境要因の問題(参考) + +以前、今回とは無関係な別テナントのバックアップを復元した際に遭遇した、ホスト環境固有の問題と対処。今回のビルドでは必須ではないが、再発時の参考として残す。 + +- **ディスク不足**: `sudo lvextend -l +100%FREE -r /dev/ubuntu-vg/ubuntu-lv` で LVM のルート LV を拡張。 +- **PostgreSQL ポート競合**: 旧 `weko-pgpool-1` が `25401` を使用していた場合、`docker stop weko-pgpool-1 && docker rm weko-pgpool-1` で不要なコンテナのみ削除。 +- **RabbitMQ 4.x / Celery-Kombu の `transient_nonexcl_queues` 非推奨警告**: `rabbitmq/rabbitmq.conf` に `deprecated_features.permit.transient_nonexcl_queues = true` を設定し、`docker-compose2.yml` の `rabbitmq` に `./rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro` をマウント。無害な警告であり必須対応ではない。 +- **Web 再作成後の Nginx 502**: `docker compose restart nginx` で解消することが多い。 + +## 10. 注意事項 + +- `docker compose down -v` を実行しない。 +- `docker volume prune` を実行しない。 +- `docker system prune -a --volumes` を実行しない。 +- Elasticsearch snapshot を `es-data` に直接コピーしない。 +- PostgreSQL の `public` schema 削除前に dump の正常性(ヘッダ)を確認する。 +- `jgssdds_repo_nii_ac_jp-*`(本番接頭辞・参照用)は、`tenant1-*` 側での動作確認が完了するまで削除しない。 +- 旧バックアップ由来の別テナントのインデックスや `after_restore.dump`(旧バックアップの復元後ダンプ)は、今回の JGSS 復元とは無関係の別テナントのものであり、削除是非は別途判断する。 +- orphan の `weko-inbox-1` / `weko-mongo-1` を確認なしで `--remove-orphans` により削除しない。 +- Elasticsearch snapshot はアップロード済みバイナリファイルそのもののバックアップではない。添付ファイルについては `data_data` 等のファイルストレージを別途確認する。 + +## 11. 最終確認チェックリスト + +- [ ] `feature/jgss` ブランチで `docker compose -f docker-compose2.yml build` が成功する。 +- [ ] 全サービスが `Up` で起動する。 +- [ ] PostgreSQL `public` に JGSS データ(`site_info`、`pidstore_pid` 等)が復元されている。 +- [ ] `after_restore_jgssdds.dump` が取得済み。 +- [ ] Elasticsearch `jgssdds_restore` リポジトリの snapshot が `jgssdds_repo_nii_ac_jp-*` と `tenant1-*` の両方に復元され、`recovery` が `done`/`100.0%`。 +- [ ] `SEARCH_INDEX_PREFIX=tenant1` で Web/Worker が起動している。 +- [ ] HTTPS が `200 OK`。 +- [ ] ブラウザから検索、アイテム詳細、添付ファイル、管理画面、登録・更新処理を確認する。 diff --git a/scripts/demo/download_button_bug_repro/README.md b/scripts/demo/download_button_bug_repro/README.md new file mode 100644 index 0000000000..47a9deff5a --- /dev/null +++ b/scripts/demo/download_button_bug_repro/README.md @@ -0,0 +1,181 @@ +# 再現用データ: 利用申請承認済みでもダウンロードボタンが出ない不具合 + +利用申請(usage application)が **承認済み・ワークフロー完了** のアカウントで +アイテム詳細画面を開いても、「ダウンロード」ボタンではなく「申請」ボタンが +表示されてしまう不具合を、PR レビュアが自分の環境で再現するためのデータ一式です。 + +不具合の概要は `KNOWN_ISSUE_download_button_not_shown.md` を参照してください。 + +--- + +## 0. このデータについて(重要) + +**本番データ・個人情報は一切含まれていません。** すべて合成データです。 + +- メールアドレスは `populate-instance.sh` が作成するデモアカウント + `contributor@example.org` のみ。 +- アイテムのタイトル・本文・申請者氏名・所属はすべて架空 + (「サンプル制限公開アイテム」「デモ 太郎」「デモ 花子」「デモ大学」など)。 +- 添付ファイルは中身のないプレースホルダ(`sample_restricted_data.txt`)。 +- 実在の研究データ・研究者名・機関ドメインは含みません。 + +--- + +## 1. 前提 + +`install.sh`(= `populate-instance.sh` + `item_type3.sql` + +`resticted_access.sql`)による **通常の新規構築が完了している** こと。 +本フィクスチャはその上に載る差分データのみを持ちます。依存しているのは +新規構築時点で必ず存在する以下だけです。 + +| 依存先 | 内容 | +| --- | --- | +| `item_type` 15 | デフォルトアイテムタイプ(フル)— 制限公開アイテム側 | +| `item_type` 31001 | 利用申請(`resticted_access.sql` が作成) | +| `accounts_role` 1–4 | System / Repository / **Contributor(3)** / Community | +| `accounts_user` | `repoadmin@` `contributor@` `user@` `comadmin@example.org` | +| `files_location` id=1 | 既定のファイル保存先 | +| `workflow_action` 1–4 | begin_action / end_action / item_login / approval | + +デモアカウントのパスワードは `populate-instance.sh` が使う +`INVENIO_USER_PASS`(`docker-compose*.yml` の既定値は **`uspass123`**)です。 + +--- + +## 2. ロード方法 + +```bash +./scripts/demo/download_button_bug_repro/load.sh +``` + +`load.sh` は + +1. `fixture.sql` を `docker exec -i weko-postgresql-1 psql -U invenio -d invenio` で流し込み +2. `es_bulk.ndjson` を `curl -X POST /_bulk` で投入 + +します。コンテナ名やポートが違う場合は環境変数で上書きできます。 + +```bash +PG_CONTAINER=weko-postgresql-1 ES_URL=http://localhost:29201 \ +ES_INDEX=tenant1-weko-item-v1.0.0 ./scripts/demo/download_button_bug_repro/load.sh +``` + +`fixture.sql` は冒頭で自分が作る行だけを `DELETE` してから `COPY` するので、 +**何度実行しても安全**(冪等)です。既存行の変更・削除は一切しません。 + +--- + +## 3. 投入されるデータ + +| 対象 | ID | +| --- | --- | +| インデックス | `1758900000001`(デモ: 制限公開アイテム) | +| ワークフロー定義 | `workflow_flow_define` 39001 / `workflow_flow_action` 39001–39004 / `workflow_workflow` 39001(「デモ用データ利用申請 / Demo Data Usage Application」, `itemtype_id=31001`, `open_restricted=t`) | +| 制限公開アイテム | recid `2003976`(+バージョン `2003976.1`)/ファイル `sample_restricted_data.txt`(`accessrole = open_restricted`) | +| 利用申請アイテム | recid `2003977`(+バージョン `2003977.1`, item_type 31001) | +| 利用申請アクティビティ | `A-20260917-00001`(`activity_status = 'F'` = 完了、申請者 user_id=3 = contributor、承認者 user_id=2 = repoadmin) | +| ワンタイムDL許可 | `file_onetime_download`(`user_mail = contributor@example.org`) | +| **`file_permission`** | **行なし(これが不具合のシグネチャ)** | + +`pidstore_pid` は 32056–32069 を明示 ID で使用します(新規構築直後の採番と +衝突しない領域。ロード後にシーケンスを `setval` で進めます)。 + +制限公開ファイルの `provide` には `role_id`/`workflow_id` と `role`/`workflow` +の両方の綴りを入れてあります。画面側の `get_usage_workflow` +(`weko_records_ui/views.py`) は前者を読み、JGSS のアイテムタイプが実際に +保存するのは後者、という食い違いがあるためです(調査レポート 4章参照)。 + +--- + +## 4. 再現手順 + +1. `load.sh` を実行する。 +2. `contributor@example.org` / `uspass123` でログインする。 +3. `https:///records/2003976`(「サンプル制限公開アイテム / Sample + Restricted Item」)を開く。 +4. ファイル `sample_restricted_data.txt` の行のボタンを見る。 + +### 期待される結果(修正後) + +利用申請は承認済み(`A-20260917-00001` は `activity_status='F'`)なので、 +**「ダウンロード」ボタン** が表示され、ファイルをダウンロードできる。 + +### 実際の結果(不具合) + +**「申請」ボタン** が表示される。押すと `/workflow/activity/init` が呼ばれ、 +同じ利用申請ワークフロー(39001)を **もう一度最初から** 開始してしまう。 + +管理画面 → ワークフロー一覧 で `A-20260917-00001` が「完了」になっていること、 +つまり「承認済みなのに申請ボタンのまま」であることを併せて確認できます。 + +--- + +## 5. DB 上のシグネチャ / シェルからの確認 + +```bash +docker compose exec -T web invenio shell \ + /code/scripts/demo/download_button_bug_repro/verify.py +``` + +不具合が再現している場合の出力: + +``` +activity_status : activity_completed +file_permission rows : 0 +file_permission status=1 rows : 0 +file_onetime_download : sample_restricted_data.txt contributor@example.org ... +check_file_download_permission : False +get_permission : None +check_content_file_clickable : True +rendered button classes : ['... term-condtion-modal', 'btn-start-workflow ...'] +rendered download href present : False +=> BUG REPRODUCED: the approved applicant gets the "Apply" button. +``` + +SQL で直接見る場合: + +```sql +SELECT activity_id, activity_status FROM workflow_activity + WHERE activity_id = 'A-20260917-00001'; -- => F(完了) +SELECT * FROM file_permission WHERE record_id = '2003976'; + -- => 0 rows(★これが原因) +SELECT file_name, user_mail, extra_info FROM file_onetime_download + WHERE record_id = '2003976'; -- => contributor@example.org の行 +``` + +### なぜこうなるか + +- `weko_records_ui/permissions.py` の `check_open_restricted_permission` / + `check_permission_period` は **`file_permission.status == 1` の行があること** + を承認済みの判定条件にしている。 +- ところが `FilePermission.update_status()` を呼ぶコードが `feature/jgss` の + `modules/` 配下に **一箇所も存在しない** ため、`status` が `1` になることがない。 +- さらに承認完了時(`weko_workflow/views.py` の `next_action`, 1153–1156 行付近)で + `FilePermission.delete_object()` により、申請時に作られた `status=-1` の行まで + 削除される。 +- 承認の実体は `create_onetime_download_url_to_guest()` + (`weko_workflow/utils.py`)による `file_onetime_download` への書き込みだが、 + 詳細画面のボタン判定はこのテーブルを一切参照しない。 + +結果として `access_permission` は常に `False`、`permission` は常に `None` となり、 +`weko_records_ui/templates/weko_records_ui/_macros.html` の +`{% elif not permission %}`(89 行目付近)の分岐に落ちて「申請」ボタンが描画される。 + +--- + +## 6. 付属ファイル + +| ファイル | 内容 | +| --- | --- | +| `fixture.sql` | PostgreSQL の差分データ(`COPY ... FROM stdin` 形式、約 32KB) | +| `es_bulk.ndjson` | Elasticsearch `_bulk` 形式のアイテムドキュメント 4 件(約 12KB) | +| `load.sh` | 上記 2 つを投入するスクリプト | +| `verify.py` | 不具合が再現しているかを `invenio shell` から検証するスクリプト | +| `attach_file.py` | (任意)プレースホルダのファイル実体を `ObjectVersion` に紐付ける | + +`fixture.sql` は `files_object` の行は入れますが **ファイル実体(バイト列)は +入れません**。ファイル実体は各環境の `files_location` 配下に置かれるもので、 +git に入れるべきものではないためです。本不具合はボタンの描画判定の問題であり、 +詳細画面は `records_metadata` の JSON だけを見てボタンを出し分けるため、 +ファイル実体がなくても再現には影響しません。修正後に実際のダウンロードまで +試したい場合のみ `attach_file.py` を実行してください。 diff --git a/scripts/demo/download_button_bug_repro/attach_file.py b/scripts/demo/download_button_bug_repro/attach_file.py new file mode 100644 index 0000000000..d39cb6b40c --- /dev/null +++ b/scripts/demo/download_button_bug_repro/attach_file.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +"""Attach a tiny placeholder file body to the demo item's ObjectVersion. + +fixture.sql registers the ObjectVersion row (files_object) but intentionally +ships no file body: file bytes are environment specific (they live under the +``files_location`` of the instance) and do not belong in git. + +This script is OPTIONAL. The bug being reproduced is a *button rendering* +bug, and the item detail page renders the button from ``records_metadata`` +alone - it never touches the stored bytes. Run this only if you also want the +download endpoint to serve something once the fix is applied. + +Usage (inside the web container, after fixture.sql has been loaded):: + + docker compose exec -T web invenio shell \ + /code/scripts/demo/download_button_bug_repro/attach_file.py +""" +from __future__ import print_function + +from io import BytesIO + +from invenio_db import db +from invenio_files_rest.models import ObjectVersion + +BUCKET_ID = '19efee91-8841-4e06-a612-8ec571a9d8b3' +VERSION_ID = '76f234e4-2460-4c86-b9b9-e0c871b381ee' +CONTENT = ( + b"This is a synthetic placeholder file for the WEKO3 " + b"download-button reproduction fixture.\n" + b"No real research data. No personal information.\n" +) + +obj = ObjectVersion.get(BUCKET_ID, 'sample_restricted_data.txt', + version_id=VERSION_ID) +if obj is None: + raise SystemExit('ObjectVersion not found - load fixture.sql first.') +if obj.file_id is not None: + print('file body already attached:', obj.file_id) +else: + obj.set_contents(BytesIO(CONTENT)) + db.session.commit() + print('file body attached:', obj.file_id) diff --git a/scripts/demo/download_button_bug_repro/es_bulk.ndjson b/scripts/demo/download_button_bug_repro/es_bulk.ndjson new file mode 100644 index 0000000000..6c47d24db9 --- /dev/null +++ b/scripts/demo/download_button_bug_repro/es_bulk.ndjson @@ -0,0 +1,8 @@ +{"index": {"_index": "tenant1-weko-item-v1.0.0", "_type": "_doc", "_id": "c8af35ea-76bf-40a4-8366-07902b1a532e"}} +{"_created": "2026-09-17T06:32:26.374506+00:00", "_item_metadata": {"_oai": {"id": "oai:weko3.example.org:02003976", "sets": ["1758900000001"]}, "author_link": [], "control_number": "2003976", "item_1617186331708": {"attribute_name": "Title", "attribute_value_mlt": [{"subitem_1551255647225": "サンプル制限公開アイテム / Sample Restricted Item", "subitem_1551255648112": "ja"}]}, "item_1617186419668": {"attribute_name": "Creator", "attribute_type": "creator", "attribute_value_mlt": [{"creatorNames": [{"creatorName": "デモ 太郎", "creatorNameLang": "ja"}]}]}, "item_1617258105262": {"attribute_name": "Resource Type", "attribute_value_mlt": [{"resourcetype": "dataset", "resourceuri": "http://purl.org/coar/resource_type/c_ddb1"}]}, "item_1617605131499": {"attribute_name": "File", "attribute_type": "file", "attribute_value_mlt": [{"accessrole": "open_restricted", "date": [{"dateType": "Available", "dateValue": "2026-09-17"}], "filename": "sample_restricted_data.txt", "filesize": [{"value": "134 B"}], "format": "text/plain", "mimetype": "text/plain", "provide": [{"role_id": "3", "workflow_id": "39001"}, {"role": "3", "workflow": "39001"}], "terms": "term_free", "termsDescription": "これはデモ用の利用規約テキストです(架空)。", "url": {"url": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}, "version_id": "76f234e4-2460-4c86-b9b9-e0c871b381ee"}]}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "item_type_id": "15", "owner": "1", "path": ["1758900000001"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "publish_date": "2026-09-17", "publish_status": "1", "relation_version_is_last": true, "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "weko_shared_id": -1}, "_oai": {"id": "oai:weko3.example.org:02003976", "sets": ["1758900000001"]}, "_updated": "2026-09-17T06:33:55.150625+00:00", "author_link": [], "content": [], "control_number": "2003976", "creator": {"affiliation": {"affiliationName": [], "nameIdentifier": []}, "creatorAlternative": [], "creatorName": ["デモ 太郎"], "familyName": [], "givenName": [], "nameIdentifier": []}, "file": {"URI": [{"value": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}], "date": [{"dateType": "fileDate.fileDateType"}], "extent": ["134 B"], "mimeType": ["text/plain"], "version": []}, "itemtype": "デフォルトアイテムタイプ(フル)", "path": ["1758900000001"], "publish_date": "2026-09-17", "publish_status": "0", "relation_version_is_last": true, "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "type": ["dataset"], "weko_creator_id": "1", "weko_shared_id": -1} +{"index": {"_index": "tenant1-weko-item-v1.0.0", "_type": "_doc", "_id": "d443270e-cbbb-4896-981d-614f9766b5f2"}} +{"_created": "2026-09-17T06:34:25.132515+00:00", "_item_metadata": {"_oai": {"id": "oai:weko3.example.org:02003976.1", "sets": ["1758900000001"]}, "author_link": [], "control_number": "2003976.1", "item_1617186331708": {"attribute_name": "Title", "attribute_value_mlt": [{"subitem_1551255647225": "サンプル制限公開アイテム / Sample Restricted Item", "subitem_1551255648112": "ja"}]}, "item_1617186419668": {"attribute_name": "Creator", "attribute_type": "creator", "attribute_value_mlt": [{"creatorNames": [{"creatorName": "デモ 太郎", "creatorNameLang": "ja"}]}]}, "item_1617258105262": {"attribute_name": "Resource Type", "attribute_value_mlt": [{"resourcetype": "dataset", "resourceuri": "http://purl.org/coar/resource_type/c_ddb1"}]}, "item_1617605131499": {"attribute_name": "File", "attribute_type": "file", "attribute_value_mlt": [{"accessrole": "open_restricted", "date": [{"dateType": "Available", "dateValue": "2026-09-17"}], "filename": "sample_restricted_data.txt", "filesize": [{"value": "134 B"}], "format": "text/plain", "mimetype": "text/plain", "provide": [{"role_id": "3", "workflow_id": "39001"}, {"role": "3", "workflow": "39001"}], "terms": "term_free", "termsDescription": "これはデモ用の利用規約テキストです(架空)。", "url": {"url": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}, "version_id": ""}]}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "item_type_id": "15", "path": ["1758900000001"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "publish_date": "2026-09-17", "publish_status": "1", "relation_version_is_last": true, "title": ["サンプル制限公開アイテム / Sample Restricted Item"]}, "_oai": {"id": "oai:weko3.example.org:02003976.1", "sets": ["1758900000001"]}, "_updated": "2026-09-17T06:34:26.048749+00:00", "author_link": [], "content": [], "control_number": "2003976.1", "creator": {"affiliation": {"affiliationName": [], "nameIdentifier": []}, "creatorAlternative": [], "creatorName": ["デモ 太郎"], "familyName": [], "givenName": [], "nameIdentifier": []}, "file": {"URI": [{"value": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}], "date": [{"dateType": "fileDate.fileDateType"}], "extent": ["134 B"], "mimeType": ["text/plain"], "version": []}, "itemtype": "デフォルトアイテムタイプ(フル)", "path": ["1758900000001"], "publish_date": "2026-09-17", "publish_status": "0", "relation_version_is_last": false, "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "type": ["dataset"]} +{"index": {"_index": "tenant1-weko-item-v1.0.0", "_type": "_doc", "_id": "4a23ff43-5325-4bce-af99-dc6d8f0f4a3b"}} +{"_created": "2026-09-17T06:37:22.220152+00:00", "_item_metadata": {"_oai": {"id": "oai:weko3.example.org:02003977", "sets": ["1758900000001"]}, "author_link": [], "control_number": "2003977", "item_1616221831877": {"attribute_name": "Dataset Usage", "attribute_value_mlt": [{"subitem_restricted_access_dataset_usage": "sample_restricted_data.txt"}]}, "item_1616221941275": {"attribute_name": "Research Title", "attribute_value_mlt": [{"subitem_restricted_access_research_title": "デモ用研究タイトル / Demo Research Title"}]}, "item_1616221960771": {"attribute_name": "Research Plan", "attribute_value_mlt": [{"subitem_restricted_access_research_plan": "これはデモ用の架空の研究計画です。", "subitem_restricted_access_research_plan_type": "Free"}]}, "item_1616222047122": {"attribute_name": "WF Issued Date", "attribute_value_mlt": [{"subitem_restricted_access_wf_issued_date": "2026-09-17", "subitem_restricted_access_wf_issued_date_type": "Created"}]}, "item_1616222067301": {"attribute_name": "Application Date", "attribute_value_mlt": [{"subitem_restricted_access_application_date": "2026-09-17", "subitem_restricted_access_application_date_type": "Created"}]}, "item_1616222093486": {"attribute_name": "Approval Date", "attribute_value_mlt": [{"subitem_restricted_access_approval_date": "2026-09-17", "subitem_restricted_access_approval_date_type": "Created"}]}, "item_1616222117209": {"attribute_name": "Item Title", "attribute_value_mlt": [{"subitem_restricted_access_item_title": "サンプル制限公開アイテム / Sample Restricted Item"}]}, "item_1648134694613": {"attribute_name": "Applicant", "attribute_value_mlt": [{"subitem_affiliated_division/department": "デモ学部", "subitem_fullname": "デモ 花子", "subitem_mail_address": "contributor@example.org", "subitem_phone_number": "000-0000-0000", "subitem_position": "その他", "subitem_university/institution": "デモ大学"}]}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "item_type_id": "31001", "owner": "3", "path": ["1758900000001"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "publish_date": "2026-09-17", "publish_status": "0", "relation_version_is_last": true, "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "weko_shared_id": -1}, "_oai": {"id": "oai:weko3.example.org:02003977", "sets": ["1758900000001"]}, "_updated": "2026-09-17T06:37:22.659792+00:00", "alternative": ["サンプル制限公開アイテム / Sample Restricted Item"], "author_link": [], "control_number": "2003977", "date": [{"dateType": "Created", "value": "2026-09-17"}, {"dateType": "Created", "value": "2026-09-17"}, {"dateType": "Created", "value": "2026-09-17"}], "itemtype": "利用申請", "path": ["1758900000001"], "publish_date": "2026-09-17", "publish_status": "0", "relation_version_is_last": true, "title": ["sample_restricted_data.txt"], "weko_creator_id": "3", "weko_shared_id": -1} +{"index": {"_index": "tenant1-weko-item-v1.0.0", "_type": "_doc", "_id": "556f88a7-2164-4655-96ea-953365168917"}} +{"_created": "2026-09-17T06:37:22.797574+00:00", "_item_metadata": {"_oai": {"id": "oai:weko3.example.org:02003977.1", "sets": ["1758900000001"]}, "author_link": [], "control_number": "2003977.1", "item_1616221831877": {"attribute_name": "Dataset Usage", "attribute_value_mlt": [{"subitem_restricted_access_dataset_usage": "sample_restricted_data.txt"}]}, "item_1616221941275": {"attribute_name": "Research Title", "attribute_value_mlt": [{"subitem_restricted_access_research_title": "デモ用研究タイトル / Demo Research Title"}]}, "item_1616221960771": {"attribute_name": "Research Plan", "attribute_value_mlt": [{"subitem_restricted_access_research_plan": "これはデモ用の架空の研究計画です。", "subitem_restricted_access_research_plan_type": "Free"}]}, "item_1616222047122": {"attribute_name": "WF Issued Date", "attribute_value_mlt": [{"subitem_restricted_access_wf_issued_date": "2026-09-17", "subitem_restricted_access_wf_issued_date_type": "Created"}]}, "item_1616222067301": {"attribute_name": "Application Date", "attribute_value_mlt": [{"subitem_restricted_access_application_date": "2026-09-17", "subitem_restricted_access_application_date_type": "Created"}]}, "item_1616222093486": {"attribute_name": "Approval Date", "attribute_value_mlt": [{"subitem_restricted_access_approval_date": "2026-09-17", "subitem_restricted_access_approval_date_type": "Created"}]}, "item_1616222117209": {"attribute_name": "Item Title", "attribute_value_mlt": [{"subitem_restricted_access_item_title": "サンプル制限公開アイテム / Sample Restricted Item"}]}, "item_1648134694613": {"attribute_name": "Applicant", "attribute_value_mlt": [{"subitem_affiliated_division/department": "デモ学部", "subitem_fullname": "デモ 花子", "subitem_mail_address": "contributor@example.org", "subitem_phone_number": "000-0000-0000", "subitem_position": "その他", "subitem_university/institution": "デモ大学"}]}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "item_type_id": "31001", "owner": "3", "path": ["1758900000001"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "publish_date": "2026-09-17", "publish_status": "0", "relation_version_is_last": true, "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "weko_shared_id": -1}, "_oai": {"id": "oai:weko3.example.org:02003977.1", "sets": ["1758900000001"]}, "_updated": "2026-09-17T06:37:23.029824+00:00", "alternative": ["サンプル制限公開アイテム / Sample Restricted Item"], "author_link": [], "control_number": "2003977.1", "date": [{"dateType": "Created", "value": "2026-09-17"}, {"dateType": "Created", "value": "2026-09-17"}, {"dateType": "Created", "value": "2026-09-17"}], "itemtype": "利用申請", "path": ["1758900000001"], "publish_date": "2026-09-17", "publish_status": "0", "relation_version_is_last": false, "title": ["sample_restricted_data.txt"], "weko_creator_id": "3", "weko_shared_id": -1} diff --git a/scripts/demo/download_button_bug_repro/fixture.sql b/scripts/demo/download_button_bug_repro/fixture.sql new file mode 100644 index 0000000000..20cfe77a07 --- /dev/null +++ b/scripts/demo/download_button_bug_repro/fixture.sql @@ -0,0 +1,218 @@ +-- +-- download_button_bug_repro / fixture.sql +-- +-- 「利用申請が承認済みなのにダウンロードボタンではなく申請ボタンが表示される」 +-- 不具合を再現するための、完全に合成(synthetic)のデモデータ。 +-- +-- Reproduction fixture for: an approved usage application still shows the +-- "申請 (Apply)" button instead of the "ダウンロード (Download)" button. +-- +-- * このファイルに実データ(本番の個人情報・研究データ)は一切含まれない。 +-- メールアドレスは populate-instance.sh が作成するデモアカウント +-- contributor@example.org のみ。 +-- * 実行前提: install.sh / scripts/populate-instance.sh による通常の新規構築が +-- 完了していること(item_type 15 / 31001、デモアカウント、accounts_role 1-4、 +-- files_location id=1 が存在すること)。 +-- * 追加されるのは以下の ID 空間のみ。既存行は一切変更・削除しない。 +-- index : 1758900000001 +-- workflow_flow_define : 39001 +-- workflow_flow_action : 39001 - 39004 +-- workflow_workflow : 39001 +-- pidstore_pid : 32056 - 32069 (recid 2003976 / 2003977 系) +-- workflow_activity : A-20260917-00001 +-- +-- ロード方法は load.sh / README.md を参照。 +-- + +\set ON_ERROR_STOP on + +BEGIN; + +-- +-- 再実行できるように、本フィクスチャが作る行だけを先に削除する。 +-- (FK 依存の逆順) +-- +DELETE FROM public.file_onetime_download WHERE record_id = '2003976'; +DELETE FROM public.file_permission WHERE record_id = '2003976'; +DELETE FROM public.workflow_action_history WHERE activity_id = 'A-20260917-00001'; +DELETE FROM public.workflow_activity_action WHERE activity_id = 'A-20260917-00001'; +DELETE FROM public.workflow_activity WHERE activity_id = 'A-20260917-00001'; +DELETE FROM public.pidrelations_pidrelation WHERE parent_id IN (32058, 32066); +DELETE FROM public.item_metadata WHERE id IN ('c8af35ea-76bf-40a4-8366-07902b1a532e','d443270e-cbbb-4896-981d-614f9766b5f2','4a23ff43-5325-4bce-af99-dc6d8f0f4a3b','556f88a7-2164-4655-96ea-953365168917'); +DELETE FROM public.files_object WHERE bucket_id IN ('19efee91-8841-4e06-a612-8ec571a9d8b3','c1e6b18c-7051-4b54-bf98-00abf99f4717','845ccfdf-6316-452c-983a-68b09a04b982','c69e16b1-f626-42d6-94b2-a99140b9cb89'); +DELETE FROM public.records_buckets WHERE record_id IN ('c8af35ea-76bf-40a4-8366-07902b1a532e','d443270e-cbbb-4896-981d-614f9766b5f2','4a23ff43-5325-4bce-af99-dc6d8f0f4a3b','556f88a7-2164-4655-96ea-953365168917'); +DELETE FROM public.records_metadata WHERE id IN ('c8af35ea-76bf-40a4-8366-07902b1a532e','d443270e-cbbb-4896-981d-614f9766b5f2','4a23ff43-5325-4bce-af99-dc6d8f0f4a3b','556f88a7-2164-4655-96ea-953365168917'); +DELETE FROM public.pidstore_pid WHERE id BETWEEN 32056 AND 32069; +DELETE FROM public.files_bucket WHERE id IN ('19efee91-8841-4e06-a612-8ec571a9d8b3','c1e6b18c-7051-4b54-bf98-00abf99f4717','845ccfdf-6316-452c-983a-68b09a04b982','c69e16b1-f626-42d6-94b2-a99140b9cb89'); +DELETE FROM public.workflow_workflow WHERE id = 39001; +DELETE FROM public.workflow_flow_action WHERE id BETWEEN 39001 AND 39004; +DELETE FROM public.workflow_flow_define WHERE id = 39001; +DELETE FROM public."index" WHERE id = 1758900000001; + +-- --------------------------------------------------------------------- +-- index +-- --------------------------------------------------------------------- +COPY public.index (created, updated, id, parent, "position", index_name, index_name_english, index_link_name, index_link_name_english, harvest_spec, index_link_enabled, comment, more_check, display_no, harvest_public_state, display_format, image_name, public_state, public_date, recursive_public_state, rss_status, coverpage_state, recursive_coverpage_check, browsing_role, recursive_browsing_role, contribute_role, recursive_contribute_role, browsing_group, recursive_browsing_group, contribute_group, recursive_contribute_group, owner_user_id, item_custom_sort, biblio_flag, online_issn) FROM stdin; +2026-09-17 06:32:26.135989 2026-09-17 06:32:26.135993 1758900000001 0 99 デモ: 制限公開アイテム Demo: Restricted Item Demo Restricted Index f f 5 t 1 t \N f f f f 1,2,3,4,-98,-99 f 1,2,3,4,-98,-99 f f f 1 {} f +\. + +-- --------------------------------------------------------------------- +-- workflow_flow_define +-- --------------------------------------------------------------------- +COPY public.workflow_flow_define (status, created, updated, id, flow_id, flow_name, flow_user, flow_status, is_deleted) FROM stdin; +N 2026-09-17 06:36:22.014475 2026-09-17 06:36:22.014487 39001 7a5f0e02-3b91-4c8d-9a6e-0f1d2c3b4a59 デモ用データ利用申請 / Demo Data Usage Application 1 A f +\. + +-- --------------------------------------------------------------------- +-- workflow_flow_action +-- --------------------------------------------------------------------- +COPY public.workflow_flow_action (status, created, updated, id, flow_id, action_id, action_version, action_order, action_condition, action_status, action_date, send_mail_setting) FROM stdin; +N 2026-09-17 06:36:22.030038 2026-09-17 06:36:22.030049 39001 7a5f0e02-3b91-4c8d-9a6e-0f1d2c3b4a59 1 1.0.0 1 \N A 2026-09-17 06:36:22.028668 {"inform_reject": {"mail": "0", "send": false}, "inform_itemReg": {"mail": "0", "send": false}, "inform_approval": {"mail": "0", "send": false}, "request_approval": {"mail": "0", "send": false}} +N 2026-09-17 06:36:22.035653 2026-09-17 06:36:22.03566 39002 7a5f0e02-3b91-4c8d-9a6e-0f1d2c3b4a59 3 1.0.1 2 \N A 2026-09-17 06:36:22.034932 {"inform_reject": {"mail": "0", "send": false}, "inform_itemReg": {"mail": "0", "send": false}, "inform_approval": {"mail": "0", "send": false}, "request_approval": {"mail": "0", "send": false}} +N 2026-09-17 06:36:22.038244 2026-09-17 06:36:22.038252 39003 7a5f0e02-3b91-4c8d-9a6e-0f1d2c3b4a59 4 2.0.0 3 \N A 2026-09-17 06:36:22.037683 {"inform_reject": {"mail": "0", "send": false}, "inform_itemReg": {"mail": "0", "send": false}, "inform_approval": {"mail": "0", "send": false}, "request_approval": {"mail": "0", "send": false}} +N 2026-09-17 06:36:22.041807 2026-09-17 06:36:22.041812 39004 7a5f0e02-3b91-4c8d-9a6e-0f1d2c3b4a59 2 1.0.0 4 \N A 2026-09-17 06:36:22.041239 {"inform_reject": {"mail": "0", "send": false}, "inform_itemReg": {"mail": "0", "send": false}, "inform_approval": {"mail": "0", "send": false}, "request_approval": {"mail": "0", "send": false}} +\. + +-- --------------------------------------------------------------------- +-- workflow_workflow +-- --------------------------------------------------------------------- +COPY public.workflow_workflow (status, created, updated, id, flows_id, flows_name, itemtype_id, index_tree_id, flow_id, is_deleted, open_restricted, is_gakuninrdm) FROM stdin; +N 2026-09-17 06:36:22.047985 2026-09-17 06:36:22.04799 39001 7a5f0e02-3b91-4c8d-9a6e-0f1d2c3b4a59 デモ用データ利用申請 / Demo Data Usage Application 31001 1758900000001 39001 f t f +\. + +-- --------------------------------------------------------------------- +-- files_bucket +-- --------------------------------------------------------------------- +COPY public.files_bucket (created, updated, id, default_location, default_storage_class, size, quota_size, max_file_size, locked, deleted) FROM stdin; +2026-09-17 06:32:26.222457 2026-09-17 06:33:53.153523 19efee91-8841-4e06-a612-8ec571a9d8b3 1 S 0 53687091200 53687091200 f f +2026-09-17 06:34:25.218625 2026-09-17 06:34:25.231642 c1e6b18c-7051-4b54-bf98-00abf99f4717 1 S 0 53687091200 \N f f +2026-09-17 06:37:22.192177 2026-09-17 06:37:22.19218 845ccfdf-6316-452c-983a-68b09a04b982 1 S 0 53687091200 53687091200 f f +2026-09-17 06:37:22.832176 2026-09-17 06:37:22.837614 c69e16b1-f626-42d6-94b2-a99140b9cb89 1 S 0 53687091200 \N f f +\. + +-- --------------------------------------------------------------------- +-- pidstore_pid +-- --------------------------------------------------------------------- +COPY public.pidstore_pid (created, updated, id, pid_type, pid_value, pid_provider, status, object_type, object_uuid) FROM stdin; +2026-09-17 06:32:26.239338 2026-09-17 06:32:26.239343 32056 recid 2003976 \N R rec c8af35ea-76bf-40a4-8366-07902b1a532e +2026-09-17 06:32:26.248785 2026-09-17 06:32:26.24879 32057 depid 2003976 \N R rec c8af35ea-76bf-40a4-8366-07902b1a532e +2026-09-17 06:32:26.453267 2026-09-17 06:32:26.453272 32058 parent parent:2003976 \N R rec c8af35ea-76bf-40a4-8366-07902b1a532e +2026-09-17 06:33:53.272521 2026-09-17 06:33:53.272525 32059 oai oai:weko3.example.org:02003976 oai R rec c8af35ea-76bf-40a4-8366-07902b1a532e +2026-09-17 06:34:25.118677 2026-09-17 06:34:25.118682 32060 recid 2003976.1 \N R rec d443270e-cbbb-4896-981d-614f9766b5f2 +2026-09-17 06:34:25.124467 2026-09-17 06:34:25.124474 32061 depid 2003976.1 \N R rec d443270e-cbbb-4896-981d-614f9766b5f2 +2026-09-17 06:34:25.399155 2026-09-17 06:34:25.39916 32062 oai oai:weko3.example.org:02003976.1 oai R rec d443270e-cbbb-4896-981d-614f9766b5f2 +2026-09-17 06:37:22.149396 2026-09-17 06:37:22.149401 32063 actid A-20260917-00001 \N R \N \N +2026-09-17 06:37:22.20834 2026-09-17 06:37:22.208344 32064 recid 2003977 \N R rec 4a23ff43-5325-4bce-af99-dc6d8f0f4a3b +2026-09-17 06:37:22.212088 2026-09-17 06:37:22.212091 32065 depid 2003977 \N R rec 4a23ff43-5325-4bce-af99-dc6d8f0f4a3b +2026-09-17 06:37:22.228597 2026-09-17 06:37:22.228601 32066 parent parent:2003977 \N R rec 4a23ff43-5325-4bce-af99-dc6d8f0f4a3b +2026-09-17 06:37:22.398027 2026-09-17 06:37:22.398032 32067 oai oai:weko3.example.org:02003977 oai R rec 4a23ff43-5325-4bce-af99-dc6d8f0f4a3b +2026-09-17 06:37:22.792139 2026-09-17 06:37:22.792145 32068 recid 2003977.1 \N R rec 556f88a7-2164-4655-96ea-953365168917 +2026-09-17 06:37:22.795315 2026-09-17 06:37:22.795319 32069 depid 2003977.1 \N R rec 556f88a7-2164-4655-96ea-953365168917 +\. + +-- --------------------------------------------------------------------- +-- records_metadata +-- --------------------------------------------------------------------- +COPY public.records_metadata (created, updated, id, json, version_id) FROM stdin; +2026-09-17 06:37:22.220152 2026-09-17 06:37:22.726298 4a23ff43-5325-4bce-af99-dc6d8f0f4a3b {"_oai": {"id": "oai:weko3.example.org:02003977", "sets": ["1758900000001"]}, "path": ["1758900000001"], "owner": "3", "recid": "2003977", "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "_buckets": {"deposit": "845ccfdf-6316-452c-983a-68b09a04b982"}, "_deposit": {"id": "2003977", "pid": {"type": "depid", "value": "2003977", "revision_id": 0}, "owners": [3], "status": "published", "created_by": 3}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "author_link": [], "item_type_id": "31001", "publish_date": "2026-09-17", "publish_status": "0", "weko_shared_id": -1, "item_1616221831877": {"attribute_name": "Dataset Usage", "attribute_value_mlt": [{"subitem_restricted_access_dataset_usage": "sample_restricted_data.txt"}]}, "item_1616221941275": {"attribute_name": "Research Title", "attribute_value_mlt": [{"subitem_restricted_access_research_title": "デモ用研究タイトル / Demo Research Title"}]}, "item_1616221960771": {"attribute_name": "Research Plan", "attribute_value_mlt": [{"subitem_restricted_access_research_plan": "これはデモ用の架空の研究計画です。", "subitem_restricted_access_research_plan_type": "Free"}]}, "item_1616222047122": {"attribute_name": "WF Issued Date", "attribute_value_mlt": [{"subitem_restricted_access_wf_issued_date": "2026-09-17", "subitem_restricted_access_wf_issued_date_type": "Created"}]}, "item_1616222067301": {"attribute_name": "Application Date", "attribute_value_mlt": [{"subitem_restricted_access_application_date": "2026-09-17", "subitem_restricted_access_application_date_type": "Created"}]}, "item_1616222093486": {"attribute_name": "Approval Date", "attribute_value_mlt": [{"subitem_restricted_access_approval_date": "2026-09-17", "subitem_restricted_access_approval_date_type": "Created"}]}, "item_1616222117209": {"attribute_name": "Item Title", "attribute_value_mlt": [{"subitem_restricted_access_item_title": "サンプル制限公開アイテム / Sample Restricted Item"}]}, "item_1648134694613": {"attribute_name": "Applicant", "attribute_value_mlt": [{"subitem_fullname": "デモ 花子", "subitem_position": "その他", "subitem_mail_address": "contributor@example.org", "subitem_phone_number": "000-0000-0000", "subitem_university/institution": "デモ大学", "subitem_affiliated_division/department": "デモ学部"}]}, "relation_version_is_last": true} 5 +2026-09-17 06:32:26.374506 2026-09-17 06:35:00.688205 c8af35ea-76bf-40a4-8366-07902b1a532e {"_oai": {"id": "oai:weko3.example.org:02003976", "sets": []}, "path": ["1758900000001"], "owner": "1", "recid": "2003976", "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "_buckets": {"deposit": "19efee91-8841-4e06-a612-8ec571a9d8b3"}, "_deposit": {"id": "2003976", "pid": {"type": "depid", "value": "2003976", "revision_id": 0}, "owner": "1", "owners": [1], "status": "published"}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "author_link": [], "item_type_id": "15", "publish_date": "2026-09-17", "publish_status": "0", "weko_shared_id": -1, "item_1617186331708": {"attribute_name": "Title", "attribute_value_mlt": [{"subitem_1551255647225": "サンプル制限公開アイテム / Sample Restricted Item", "subitem_1551255648112": "ja"}]}, "item_1617186419668": {"attribute_name": "Creator", "attribute_type": "creator", "attribute_value_mlt": [{"creatorNames": [{"creatorName": "デモ 太郎", "creatorNameLang": "ja"}]}]}, "item_1617258105262": {"attribute_name": "Resource Type", "attribute_value_mlt": [{"resourceuri": "http://purl.org/coar/resource_type/c_ddb1", "resourcetype": "dataset"}]}, "item_1617605131499": {"attribute_name": "File", "attribute_type": "file", "attribute_value_mlt": [{"url": {"url": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}, "date": [{"dateType": "Available", "dateValue": "2026-09-17"}], "terms": "term_free", "format": "text/plain", "provide": [{"role_id": "3", "workflow_id": "39001"}, {"role": "3", "workflow": "39001"}], "filename": "sample_restricted_data.txt", "filesize": [{"value": "134 B"}], "mimetype": "text/plain", "accessrole": "open_restricted", "version_id": "76f234e4-2460-4c86-b9b9-e0c871b381ee", "termsDescription": "これはデモ用の利用規約テキストです(架空)。"}]}, "relation_version_is_last": true} 6 +2026-09-17 06:34:25.132515 2026-09-17 06:35:00.931397 d443270e-cbbb-4896-981d-614f9766b5f2 {"_oai": {"id": "oai:weko3.example.org:02003976.1", "sets": []}, "path": ["1758900000001"], "owner": "1", "recid": "2003976.1", "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "_buckets": {"deposit": "c1e6b18c-7051-4b54-bf98-00abf99f4717"}, "_deposit": {"id": "2003976.1", "pid": {"type": "depid", "value": "2003976.1", "revision_id": 0}, "owners": [1], "status": "published"}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "author_link": [], "item_type_id": "15", "publish_date": "2026-09-17", "publish_status": "0", "weko_shared_id": -1, "item_1617186331708": {"attribute_name": "Title", "attribute_value_mlt": [{"subitem_1551255647225": "サンプル制限公開アイテム / Sample Restricted Item", "subitem_1551255648112": "ja"}]}, "item_1617186419668": {"attribute_name": "Creator", "attribute_type": "creator", "attribute_value_mlt": [{"creatorNames": [{"creatorName": "デモ 太郎", "creatorNameLang": "ja"}]}]}, "item_1617258105262": {"attribute_name": "Resource Type", "attribute_value_mlt": [{"resourceuri": "http://purl.org/coar/resource_type/c_ddb1", "resourcetype": "dataset"}]}, "item_1617605131499": {"attribute_name": "File", "attribute_type": "file", "attribute_value_mlt": [{"url": {"url": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}, "date": [{"dateType": "Available", "dateValue": "2026-09-17"}], "terms": "term_free", "format": "text/plain", "provide": [{"role_id": "3", "workflow_id": "39001"}, {"role": "3", "workflow": "39001"}], "filename": "sample_restricted_data.txt", "filesize": [{"value": "134 B"}], "mimetype": "text/plain", "accessrole": "open_restricted", "version_id": "", "termsDescription": "これはデモ用の利用規約テキストです(架空)。"}]}, "relation_version_is_last": true} 6 +2026-09-17 06:37:22.797574 2026-09-17 06:37:23.104641 556f88a7-2164-4655-96ea-953365168917 {"_oai": {"id": "oai:weko3.example.org:02003977.1", "sets": ["1758900000001"]}, "path": ["1758900000001"], "owner": "3", "recid": "2003977.1", "title": ["サンプル制限公開アイテム / Sample Restricted Item"], "pubdate": {"attribute_name": "PubDate", "attribute_value": "2026-09-17"}, "_buckets": {"deposit": "c69e16b1-f626-42d6-94b2-a99140b9cb89"}, "_deposit": {"id": "2003977.1", "pid": {"type": "depid", "value": "2003977.1", "revision_id": 0}, "owners": [3], "status": "published", "created_by": 3}, "item_title": "サンプル制限公開アイテム / Sample Restricted Item", "author_link": [], "item_type_id": "31001", "publish_date": "2026-09-17", "publish_status": "0", "weko_shared_id": -1, "item_1616221831877": {"attribute_name": "Dataset Usage", "attribute_value_mlt": [{"subitem_restricted_access_dataset_usage": "sample_restricted_data.txt"}]}, "item_1616221941275": {"attribute_name": "Research Title", "attribute_value_mlt": [{"subitem_restricted_access_research_title": "デモ用研究タイトル / Demo Research Title"}]}, "item_1616221960771": {"attribute_name": "Research Plan", "attribute_value_mlt": [{"subitem_restricted_access_research_plan": "これはデモ用の架空の研究計画です。", "subitem_restricted_access_research_plan_type": "Free"}]}, "item_1616222047122": {"attribute_name": "WF Issued Date", "attribute_value_mlt": [{"subitem_restricted_access_wf_issued_date": "2026-09-17", "subitem_restricted_access_wf_issued_date_type": "Created"}]}, "item_1616222067301": {"attribute_name": "Application Date", "attribute_value_mlt": [{"subitem_restricted_access_application_date": "2026-09-17", "subitem_restricted_access_application_date_type": "Created"}]}, "item_1616222093486": {"attribute_name": "Approval Date", "attribute_value_mlt": [{"subitem_restricted_access_approval_date": "2026-09-17", "subitem_restricted_access_approval_date_type": "Created"}]}, "item_1616222117209": {"attribute_name": "Item Title", "attribute_value_mlt": [{"subitem_restricted_access_item_title": "サンプル制限公開アイテム / Sample Restricted Item"}]}, "item_1648134694613": {"attribute_name": "Applicant", "attribute_value_mlt": [{"subitem_fullname": "デモ 花子", "subitem_position": "その他", "subitem_mail_address": "contributor@example.org", "subitem_phone_number": "000-0000-0000", "subitem_university/institution": "デモ大学", "subitem_affiliated_division/department": "デモ学部"}]}, "relation_version_is_last": true} 5 +\. + +-- --------------------------------------------------------------------- +-- records_buckets +-- --------------------------------------------------------------------- +COPY public.records_buckets (record_id, bucket_id) FROM stdin; +c8af35ea-76bf-40a4-8366-07902b1a532e 19efee91-8841-4e06-a612-8ec571a9d8b3 +d443270e-cbbb-4896-981d-614f9766b5f2 c1e6b18c-7051-4b54-bf98-00abf99f4717 +4a23ff43-5325-4bce-af99-dc6d8f0f4a3b 845ccfdf-6316-452c-983a-68b09a04b982 +556f88a7-2164-4655-96ea-953365168917 c69e16b1-f626-42d6-94b2-a99140b9cb89 +\. + +-- --------------------------------------------------------------------- +-- files_object +-- --------------------------------------------------------------------- +COPY public.files_object (created, updated, version_id, key, bucket_id, file_id, _mimetype, is_head, created_user_id, updated_user_id, is_show, is_thumbnail, root_file_id) FROM stdin; +2026-09-17 06:33:53.155148 2026-09-17 06:33:53.155151 76f234e4-2460-4c86-b9b9-e0c871b381ee sample_restricted_data.txt 19efee91-8841-4e06-a612-8ec571a9d8b3 \N \N t 0 0 f f \N +\. + +-- --------------------------------------------------------------------- +-- item_metadata +-- --------------------------------------------------------------------- +COPY public.item_metadata (created, updated, id, item_type_id, json, version_id) FROM stdin; +2026-09-17 06:34:25.779796 2026-09-17 06:34:26.093626 d443270e-cbbb-4896-981d-614f9766b5f2 15 {"pid": {"type": "depid", "value": "2003976", "revision_id": 0}, "owner": "1", "title": "サンプル制限公開アイテム / Sample Restricted Item", "owners": [1], "status": "published", "$schema": "/items/jsonschema/15", "pubdate": "2026-09-17", "item_1617186331708": [{"subitem_1551255647225": "サンプル制限公開アイテム / Sample Restricted Item", "subitem_1551255648112": "ja"}], "item_1617186419668": [{"creatorNames": [{"creatorName": "デモ 太郎", "creatorNameLang": "ja"}]}], "item_1617258105262": {"resourceuri": "http://purl.org/coar/resource_type/c_ddb1", "resourcetype": "dataset"}, "item_1617605131499": [{"url": {"url": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}, "date": [{"dateType": "Available", "dateValue": "2026-09-17"}], "terms": "term_free", "format": "text/plain", "provide": [{"role_id": "3", "workflow_id": "39001"}, {"role": "3", "workflow": "39001"}], "filename": "sample_restricted_data.txt", "filesize": [{"value": "134 B"}], "mimetype": "text/plain", "accessrole": "open_restricted", "version_id": "", "termsDescription": "これはデモ用の利用規約テキストです(架空)。"}]} 2 +2026-09-17 06:33:55.17853 2026-09-17 06:34:24.740311 c8af35ea-76bf-40a4-8366-07902b1a532e 15 {"id": "2003976", "pid": {"type": "depid", "value": "2003976", "revision_id": 0}, "owner": "1", "title": "サンプル制限公開アイテム / Sample Restricted Item", "owners": [1], "status": "published", "$schema": "/items/jsonschema/15", "pubdate": "2026-09-17", "item_1617186331708": [{"subitem_1551255647225": "サンプル制限公開アイテム / Sample Restricted Item", "subitem_1551255648112": "ja"}], "item_1617186419668": [{"creatorNames": [{"creatorName": "デモ 太郎", "creatorNameLang": "ja"}]}], "item_1617258105262": {"resourceuri": "http://purl.org/coar/resource_type/c_ddb1", "resourcetype": "dataset"}, "item_1617605131499": [{"url": {"url": "https://weko3.example.org/record/2003976/files/sample_restricted_data.txt"}, "date": [{"dateType": "Available", "dateValue": "2026-09-17"}], "terms": "term_free", "format": "text/plain", "provide": [{"role_id": "3", "workflow_id": "39001"}, {"role": "3", "workflow": "39001"}], "filename": "sample_restricted_data.txt", "filesize": [{"value": "134 B"}], "mimetype": "text/plain", "accessrole": "open_restricted", "version_id": "76f234e4-2460-4c86-b9b9-e0c871b381ee", "termsDescription": "これはデモ用の利用規約テキストです(架空)。"}]} 2 +2026-09-17 06:37:22.51334 2026-09-17 06:37:22.671283 4a23ff43-5325-4bce-af99-dc6d8f0f4a3b 31001 {"owner": "3", "title": "サンプル制限公開アイテム / Sample Restricted Item", "$schema": "/items/jsonschema/31001", "pubdate": "2026-09-17", "item_1616221831877": {"subitem_restricted_access_dataset_usage": "sample_restricted_data.txt"}, "item_1616221941275": {"subitem_restricted_access_research_title": "デモ用研究タイトル / Demo Research Title"}, "item_1616221960771": {"subitem_restricted_access_research_plan": "これはデモ用の架空の研究計画です。", "subitem_restricted_access_research_plan_type": "Free"}, "item_1616222047122": {"subitem_restricted_access_wf_issued_date": "2026-09-17", "subitem_restricted_access_wf_issued_date_type": "Created"}, "item_1616222067301": {"subitem_restricted_access_application_date": "2026-09-17", "subitem_restricted_access_application_date_type": "Created"}, "item_1616222093486": {"subitem_restricted_access_approval_date": "2026-09-17", "subitem_restricted_access_approval_date_type": "Created"}, "item_1616222117209": {"subitem_restricted_access_item_title": "サンプル制限公開アイテム / Sample Restricted Item"}, "item_1648134694613": {"subitem_fullname": "デモ 花子", "subitem_position": "その他", "subitem_mail_address": "contributor@example.org", "subitem_phone_number": "000-0000-0000", "subitem_university/institution": "デモ大学", "subitem_affiliated_division/department": "デモ学部"}} 2 +2026-09-17 06:37:22.963799 2026-09-17 06:37:23.040161 556f88a7-2164-4655-96ea-953365168917 31001 {"owner": "3", "title": "サンプル制限公開アイテム / Sample Restricted Item", "$schema": "/items/jsonschema/31001", "pubdate": "2026-09-17", "item_1616221831877": {"subitem_restricted_access_dataset_usage": "sample_restricted_data.txt"}, "item_1616221941275": {"subitem_restricted_access_research_title": "デモ用研究タイトル / Demo Research Title"}, "item_1616221960771": {"subitem_restricted_access_research_plan": "これはデモ用の架空の研究計画です。", "subitem_restricted_access_research_plan_type": "Free"}, "item_1616222047122": {"subitem_restricted_access_wf_issued_date": "2026-09-17", "subitem_restricted_access_wf_issued_date_type": "Created"}, "item_1616222067301": {"subitem_restricted_access_application_date": "2026-09-17", "subitem_restricted_access_application_date_type": "Created"}, "item_1616222093486": {"subitem_restricted_access_approval_date": "2026-09-17", "subitem_restricted_access_approval_date_type": "Created"}, "item_1616222117209": {"subitem_restricted_access_item_title": "サンプル制限公開アイテム / Sample Restricted Item"}, "item_1648134694613": {"subitem_fullname": "デモ 花子", "subitem_position": "その他", "subitem_mail_address": "contributor@example.org", "subitem_phone_number": "000-0000-0000", "subitem_university/institution": "デモ大学", "subitem_affiliated_division/department": "デモ学部"}} 2 +\. + +-- --------------------------------------------------------------------- +-- pidrelations_pidrelation +-- --------------------------------------------------------------------- +COPY public.pidrelations_pidrelation (created, updated, parent_id, child_id, relation_type, index) FROM stdin; +2026-09-17 06:32:27.106201 2026-09-17 06:34:25.159513 32058 32056 2 0 +2026-09-17 06:34:25.152128 2026-09-17 06:34:25.159531 32058 32060 2 1 +2026-09-17 06:37:22.257437 2026-09-17 06:37:22.808889 32066 32064 2 0 +2026-09-17 06:37:22.807676 2026-09-17 06:37:22.808902 32066 32068 2 1 +\. + +-- --------------------------------------------------------------------- +-- workflow_activity +-- --------------------------------------------------------------------- +COPY public.workflow_activity (status, created, updated, id, activity_id, activity_name, item_id, workflow_id, workflow_status, flow_id, action_id, action_status, activity_login_user, activity_update_user, activity_status, activity_start, activity_end, activity_community_id, activity_confirm_term_of_use, title, shared_user_id, temp_data, approval1, approval2, extra_info, action_order) FROM stdin; +N 2026-09-17 06:37:22.124937 2026-09-17 06:37:23.291471 8325 A-20260917-00001 \N 4a23ff43-5325-4bce-af99-dc6d8f0f4a3b 39001 \N 39001 2 F 3 3 F 2026-09-17 06:37:22.123573 2026-09-17 06:37:23.290517 \N t \N \N \N \N \N {"file_name": "sample_restricted_data.txt", "record_id": 2003976, "user_mail": "contributor@example.org", "related_title": "サンプル制限公開アイテム / Sample Restricted Item", "is_restricted_access": true} 4 +\. + +-- --------------------------------------------------------------------- +-- workflow_activity_action +-- --------------------------------------------------------------------- +COPY public.workflow_activity_action (status, created, updated, id, activity_id, action_id, action_status, action_comment, action_handler, action_order) FROM stdin; +N 2026-09-17 06:37:22.173741 2026-09-17 06:37:22.17375 34220 A-20260917-00001 1 F \N 3 1 +N 2026-09-17 06:37:22.17743 2026-09-17 06:37:22.177436 34221 A-20260917-00001 3 F \N 3 2 +N 2026-09-17 06:37:22.178157 2026-09-17 06:37:22.178161 34222 A-20260917-00001 4 F \N -1 3 +N 2026-09-17 06:37:22.178706 2026-09-17 06:37:22.17871 34223 A-20260917-00001 2 F \N 3 4 +\. + +-- --------------------------------------------------------------------- +-- workflow_action_history +-- --------------------------------------------------------------------- +COPY public.workflow_action_history (status, created, updated, id, activity_id, action_id, action_version, action_status, action_user, action_date, action_comment, action_order) FROM stdin; +N 2026-09-17 06:37:22.154563 2026-09-17 06:37:22.15457 33190 A-20260917-00001 1 1.0.0 F 3 2026-09-17 06:37:22.123573 Begin Action 1 +N 2026-09-17 06:37:23.181015 2026-09-17 06:37:23.181021 33191 A-20260917-00001 3 \N \N 3 2026-09-17 06:37:23.173192 \N 2 +N 2026-09-17 06:37:23.29699 2026-09-17 06:37:23.296996 33192 A-20260917-00001 2 1.0.0 F 2 2026-09-17 06:37:23.29614 End Action 4 +\. + +-- --------------------------------------------------------------------- +-- file_onetime_download +-- --------------------------------------------------------------------- +COPY public.file_onetime_download (created, updated, id, file_name, user_mail, record_id, download_count, expiration_date, extra_info) FROM stdin; +2026-09-17 06:37:23.246002 2026-09-17 06:37:23.246007 3100 sample_restricted_data.txt contributor@example.org 2003976 4 7 {"is_guest": false, "send_usage_report": true, "usage_application_activity_id": "A-20260917-00001"} +\. + +-- --------------------------------------------------------------------- +-- file_permission: +-- **意図的に 1 行も入れない。** これが本不具合の DB 上のシグネチャ。 +-- 利用申請の開始時に status=-1 の行が作られるが、承認完了時 +-- (weko_workflow/views.py の next_action, 1153-1156 行付近) で +-- FilePermission.delete_object() により削除され、status=1 に更新される +-- 経路はコード上どこにも存在しない。 +-- そのため weko_records_ui/permissions.py:check_permission_period() は +-- 常に False を返し、詳細画面は「申請」ボタンを出し続ける。 +-- --------------------------------------------------------------------- + +-- +-- 明示 ID を挿入したテーブルのシーケンスを進めておく(既存採番との衝突防止)。 +-- +SELECT setval('public.pidstore_pid_id_seq', GREATEST((SELECT last_value FROM public.pidstore_pid_id_seq), (SELECT max(id) FROM public.pidstore_pid))); +SELECT setval('public.workflow_flow_define_id_seq', GREATEST((SELECT last_value FROM public.workflow_flow_define_id_seq), (SELECT max(id) FROM public.workflow_flow_define))); +SELECT setval('public.workflow_flow_action_id_seq', GREATEST((SELECT last_value FROM public.workflow_flow_action_id_seq), (SELECT max(id) FROM public.workflow_flow_action))); +SELECT setval('public.workflow_workflow_id_seq', GREATEST((SELECT last_value FROM public.workflow_workflow_id_seq), (SELECT max(id) FROM public.workflow_workflow))); +SELECT setval('public.workflow_activity_id_seq', GREATEST((SELECT last_value FROM public.workflow_activity_id_seq), (SELECT max(id) FROM public.workflow_activity))); +SELECT setval('public.workflow_activity_action_id_seq',GREATEST((SELECT last_value FROM public.workflow_activity_action_id_seq),(SELECT max(id) FROM public.workflow_activity_action))); +SELECT setval('public.workflow_action_history_id_seq', GREATEST((SELECT last_value FROM public.workflow_action_history_id_seq), (SELECT max(id) FROM public.workflow_action_history))); +SELECT setval('public.file_onetime_download_id_seq', GREATEST((SELECT last_value FROM public.file_onetime_download_id_seq), (SELECT max(id) FROM public.file_onetime_download))); + +COMMIT; + +\echo '== download_button_bug_repro fixture loaded ==' diff --git a/scripts/demo/download_button_bug_repro/load.sh b/scripts/demo/download_button_bug_repro/load.sh new file mode 100755 index 0000000000..fbf0af7eac --- /dev/null +++ b/scripts/demo/download_button_bug_repro/load.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# +# load.sh - load the "download button not shown for approved user" reproduction +# fixture into a freshly built WEKO3 instance. +# +# PREREQUISITE +# A normal fresh setup has already been done, i.e. install.sh +# (populate-instance.sh + item_type3.sql + resticted_access.sql) has run and +# the containers are up. The fixture relies on what that setup creates: +# - item_type 15 (デフォルトアイテムタイプ(フル)) and 31001 (利用申請) +# - accounts_role 1..4 (System/Repository/Contributor/Community) +# - demo accounts repoadmin@ / contributor@ / user@ / comadmin@example.org +# - files_location id = 1 +# +# WHAT IT DOES +# 1. loads fixture.sql into PostgreSQL (adds rows only - see fixture.sql) +# 2. bulk-loads es_bulk.ndjson into the Elasticsearch item index +# +# It never drops, truncates or overwrites anything outside the ID ranges the +# fixture owns. +# +# USAGE +# ./scripts/demo/download_button_bug_repro/load.sh +# +# Override the defaults with environment variables if your compose project or +# port mapping differs: +# PG_CONTAINER=weko-postgresql-1 PG_USER=invenio PG_DB=invenio \ +# ES_URL=http://localhost:29201 ES_INDEX=tenant1-weko-item-v1.0.0 ./load.sh +# +set -o errexit +set -o nounset +set -o pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +PG_CONTAINER="${PG_CONTAINER:-weko-postgresql-1}" +PG_USER="${PG_USER:-invenio}" +PG_DB="${PG_DB:-invenio}" +ES_URL="${ES_URL:-http://localhost:29201}" +ES_INDEX="${ES_INDEX:-tenant1-weko-item-v1.0.0}" + +echo "==> loading fixture.sql into ${PG_CONTAINER}:${PG_DB}" +docker exec -i "${PG_CONTAINER}" psql -U "${PG_USER}" -d "${PG_DB}" \ + < "${HERE}/fixture.sql" + +echo "==> bulk loading es_bulk.ndjson into ${ES_URL}/${ES_INDEX}" +# The ndjson already carries the index name in every action line, so _bulk on +# the cluster root is enough. A trailing newline is required by the _bulk API. +curl -sS -H 'Content-Type: application/x-ndjson' \ + -X POST "${ES_URL}/_bulk?refresh=true" \ + --data-binary "@${HERE}/es_bulk.ndjson" \ + | python3 -c 'import json,sys; r=json.load(sys.stdin); print(" errors:", r.get("errors")); [print(" ", i) for i in r.get("items", [])[:1]]' + +echo +echo "==> done." +echo " Demo item : https:///records/2003976" +echo " Usage application: activity A-20260917-00001 (status F = 完了)" +echo +echo " Optional - attach a placeholder file body (not needed to see the bug):" +echo " docker compose exec -T web invenio shell \\" +echo " /code/scripts/demo/download_button_bug_repro/attach_file.py" +echo +echo " Verify the bug from the shell:" +echo " docker compose exec -T web invenio shell \\" +echo " /code/scripts/demo/download_button_bug_repro/verify.py" diff --git a/scripts/demo/download_button_bug_repro/verify.py b/scripts/demo/download_button_bug_repro/verify.py new file mode 100644 index 0000000000..af1b3a08cb --- /dev/null +++ b/scripts/demo/download_button_bug_repro/verify.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +"""Verify that the download-button bug reproduces for the demo fixture. + +Usage (inside the web container, after load.sh):: + + docker compose exec -T web invenio shell \ + /code/scripts/demo/download_button_bug_repro/verify.py + +Expected output (= bug present):: + + activity_status : activity_completed <- approved & finished + file_permission rows : 0 <- row was destroyed + file_permission status=1 rows : 0 <- never written at all + file_onetime_download : ... contributor@example.org ... + check_file_download_permission : False <- no Download button + get_permission : None <- -> "Apply" button + rendered button : ... term-condtion-modal / btn-start-workflow +""" +from __future__ import print_function + +import re + +from flask import current_app, render_template_string, session +from flask_login import login_user +from flask_security import url_for_security +from invenio_accounts.models import User +from weko_deposit.api import WekoRecord +from weko_records_ui.models import FileOnetimeDownload, FilePermission +from weko_records_ui.permissions import ( + check_content_clickable, + check_file_download_permission, + get_permission, +) +from weko_workflow.models import Activity + +TARGET_RECID = '2003976' +ACTIVITY_ID = 'A-20260917-00001' +FILE_KEY = 'item_1617605131499' + +activity = Activity.query.filter_by(activity_id=ACTIVITY_ID).one() +print('activity_status :', activity.activity_status) +print('file_permission rows :', FilePermission.query.filter_by( + usage_application_activity_id=ACTIVITY_ID).count()) +print('file_permission status=1 rows :', FilePermission.query.filter_by( + record_id=TARGET_RECID, status=1).count()) +for fod in FileOnetimeDownload.query.filter_by(record_id=TARGET_RECID).all(): + print('file_onetime_download :', fod.file_name, fod.user_mail, + fod.extra_info) + +user = User.query.filter_by(email='contributor@example.org').one() +record = WekoRecord.get_record_by_pid(TARGET_RECID) +fjson = record[FILE_KEY]['attribute_value_mlt'][0] + +tpl = ("{% from 'weko_records_ui/_macros.html' import check_download_file %}" + "{{ check_download_file(record, file, permission, None," + " url_for_security, False, file.filename) }}") + +with current_app.test_request_context( + 'https://localhost/records/' + TARGET_RECID): + login_user(user) + access_permission = check_file_download_permission(record, fjson) + clickable = check_content_clickable(record, fjson) + permission = get_permission(record, fjson) + session['user_id'] = user.id + html = render_template_string(tpl, record=record, file=fjson, + permission=permission, + url_for_security=url_for_security) + +print('check_file_download_permission :', access_permission) +print('get_permission :', permission) +print('check_content_file_clickable :', clickable) +print('rendered button classes :', + re.findall(r']*class="([^"]*)"', html)) +print('rendered download href present :', + '/files/sample_restricted_data.txt' in html) +print('') +if not access_permission and permission is None: + print('=> BUG REPRODUCED: the approved applicant gets the "Apply" button.') +else: + print('=> Bug NOT reproduced (fix applied?).') diff --git a/scripts/pr_review_init.sh b/scripts/pr_review_init.sh new file mode 100755 index 0000000000..23aa8d236b --- /dev/null +++ b/scripts/pr_review_init.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# feature/jgss ブランチのPRレビュー・作業開始時に、 +# ビルド手順書と既知の不具合(事象のみ)をすぐ確認できるようにする初期化スクリプト。 +# +# 使い方: +# ./scripts/pr_review_init.sh +set -euo pipefail + +cd "$(dirname "$0")/.." + +echo "================================================================" +echo " feature/jgss PRレビュー用 初期化ツール" +echo "================================================================" +echo + +echo "---------------------------------------------------------------" +echo " [1/2] ビルド〜データリストア手順書: WEKO3_BUILD_RESTORE_MANUAL.md" +echo "---------------------------------------------------------------" +if [ -f "WEKO3_BUILD_RESTORE_MANUAL.md" ]; then + sed -n '1,20p' WEKO3_BUILD_RESTORE_MANUAL.md + echo + echo " ... (全文はリポジトリ直下の WEKO3_BUILD_RESTORE_MANUAL.md を参照)" +else + echo " WEKO3_BUILD_RESTORE_MANUAL.md が見つかりません。" +fi + +echo +echo "---------------------------------------------------------------" +echo " [2/2] 既知の不具合(事象): KNOWN_ISSUE_download_button_not_shown.md" +echo "---------------------------------------------------------------" +if [ -f "KNOWN_ISSUE_download_button_not_shown.md" ]; then + cat KNOWN_ISSUE_download_button_not_shown.md +else + echo " KNOWN_ISSUE_download_button_not_shown.md が見つかりません。" +fi + +echo +echo "================================================================" +echo " 初期化確認 完了" +echo "================================================================"