Develop v2.1.0 - #1933
Develop v2.1.0#1933
Conversation
weko#57254 fix delete index issue
weko#60332 fix locaion issue
Develop w2025 16 1.3
Compile multilingual files(#60737)
…d_permissions fix #59547
Fix/issue61275
add issue/58577
…eline migration(#61275)
Create SQL migration for item_type_mapping constraints(#61275)
Top page, item landing page and search-result page each called get_search_setting() three times per request to read display_control sub-settings (display_facet_search / display_index_tree / display_community). get_search_setting() issues DB queries via SearchManagement.get() and is not cached, so the same setting object was fetched 3x per view (~4 extra DB round-trips each). Fetch display_control once per view and reuse it. Semantics are unchanged (read-only reuse of the same dict); ~12 redundant queries removed across the three pages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three independent issues prevented these tests from running:
- records-ui itemtypes fixture: ItemType uses SQLAlchemy-Continuum
versioning, under which a single interleaved flush could emit the
item_type_mapping INSERTs ahead of their parent item_type rows,
raising fk_item_type_mapping_item_type_id_item_type. Add item_type
rows and flush them before adding the mappings.
- weko-theme db fixture: create_all() creates only the parent
(range-partitioned) user_activity_logs table, not a child partition,
so activity logging during tests failed with "no partition of
relation ... found". Create the current-month partition after
create_all().
- weko-theme test_get_weko_contents: passed a bare string 'comm1' where
get_weko_contents expects request.args (dict-like); 'c' in 'comm1' is
a substring match, so get_community_id then called str.get() and
raised AttributeError. Pass {'c': 'comm1'} instead.
Verified: weko-theme test_utils/test_views, weko-search-ui test_search,
weko-records-ui test_default_view_method[1-4] all pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
default_view_method looped over record.navi paths twice and called Indexes.get_index() for every path in each loop (building path_name_dict and then belonging_community), issuing the same DB lookups twice over. Cache Indexes.get_index() results by path and reuse them in both loops. Behaviour is unchanged; redundant per-path index queries are eliminated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WidgetDesignSetting.select_by_repository_id() is queried several times while rendering a page (get_design_layout and has_widget_design both read the same repository's design), each time hitting the DB and re-parsing settings JSON. Memoize the lookup on flask.g so it runs once per request. g is cleared each request, so no cross-request invalidation is needed; the result is only read by callers. update()/create() drop the cached entry to avoid serving a stale value within the same request. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
get_search_detail_keyword() rebuilt the detail-search conditions on every page render (top page and item landing page): loading all item types and walking the browsing tree each time. The result depends only on the current language and authentication state (guest vs authenticated get different browsing trees); item types / indexes / settings change infrequently. Cache the JSON result on the shared cache keyed by host + language + auth state, with a short TTL (WEKO_SEARCH_DETAIL_KEYWORD_CACHE_TTL, default 300s) so staleness is bounded without needing strict invalidation hooks. The str_ argument is unused by the body, so it does not affect the result or key. test_get_search_detail_keyword clears the cache between calls that change underlying data, since it verifies the computation rather than caching. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two test-fixture gaps in weko-items-ui:
- db fixture: create_all() only creates the parent (range-partitioned)
user_activity_logs table, so activity logging during a test failed with
"no partition of relation ... found". Create the current-month
partition after create_all() (same fix already applied to weko-theme).
- app fixture configured CACHE_* but never called InvenioCache(app_), so
current_cache raised KeyError('invenio-cache'). Initialise it so cache-
backed code paths can be exercised.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The top-page ranking runs up to five Elasticsearch aggregations and then a per-item permission check for every candidate, on every render when the front page is set to show rankings. Cache the result on the shared cache with a short TTL (WEKO_ITEMS_UI_RANKING_CACHE_TTL, default 300s). The key includes the settings signature, the date, and the user identity: guests share one key (high hit rate for the common anonymous case) while each authenticated user gets their own, because permission filtering can surface a user's own not-yet-public items and must not leak across users. Caching is skipped when the cache extension is not configured. This also bounds the per-item N+1 record lookups to once per TTL per user-context. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (4-3) For each search-result hit, sort_meta_data_by_options re-fetched and recomputed the item-type derived data (ItemTypes.get_by_id, option/order lists, hide list and JPCOAR mapping) even though a results page renders many hits that share the same item type. This data depends only on item_type_id and is read-only for the rest of the function (to_orderdict only reads the order list; solst_dict_array is built into a fresh list), so memoize it per request on flask.g. g is cleared each request, so no cross-request invalidation is needed. Verified with test_sort_meta_data_by_options[*] and the sample / no_item_type_id / exception variants. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
default_view_method rebuilt the full JPCOAR OAI-PMH XML on every render (etree.tostring(getrecord(...))) only to feed the Google Scholar / Dataset meta tags. The XML depends only on the record, not the user. Cache it on the shared cache keyed by OAI id + record revision, so an edit (which bumps the revision) invalidates the entry immediately, with a short TTL (WEKO_RECORDS_UI_GOOGLE_XML_CACHE_TTL, default 300s) as a backstop for changes not reflected in the revision. Caching is skipped when the cache extension is not configured. Verified with test_default_view_method (records-ui test app has the cache extension, so the cache path is exercised). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The records_rest item type fixture added item_type_name, item_type and the FK-referencing item_type_mapping in a single begin_nested() flush. ItemType uses SQLAlchemy-Continuum versioning, under which that interleaved flush can emit the item_type_mapping INSERT ahead of its parent item_type row and raise fk_item_type_mapping_item_type_id_item_type. Flush the item type before adding the mapping (same fix already applied in weko-records-ui). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- invenio-stats: リクエストの後はフィクスチャのオブジェクトがセッションから 外れるので、比較に使う id を先に控える - weko-search-ui: テスト用のインデックスを、フィクスチャのインデックスと (parent, position) が重ならない位置に作る Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
権限判定はファイル実体の JSON にある accessrole を見る。アイテム登録時は メタデータがそこへ書き込まれるが、テストのフィクスチャは書き込んでいない ため、判定が常に許可になりテストが成立していなかった。登録時と同じく メタデータを書き込んでから判定させる。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
画像を開く処理に権限判定を入れたため、リクエストの外で動くサムネイル作成 タスクが、利用者の情報が無く失敗するようになっていた。内部処理なので対象の オブジェクトを直接解決し、画像を開く処理にはそれを使わせる。利用者の リクエストで通る経路の判定は変えない。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
直前のコミットは、UI 側と共有の limiter を /api アプリにも初期化したため、 既定の制限(WEKO_API_LIMIT_RATE_DEFAULT)が /api 配下の全経路にかかって いた。検索・統計・ファイル・IIIF の画像などは、同じ IP を共有する環境で 通常の閲覧でも制限に達しうる。 - 既定の制限を持たないログイン専用の Limiter を /api アプリにだけ初期化し、 ログイン API にだけ付ける。制限値は WEKO_API_LIMIT_RATE_DEFAULT を使う - 共有の limiter は従来どおり /api アプリには初期化しない - Flask-Limiter はビュー関数の名前で制限を照合するため、MethodView の メソッドではなく decorators 属性で as_view() の関数に付ける (メソッドに付けた従来の指定は名前が合わず効いていなかった) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SP の属性は、Web サーバ上のログインスクリプト(secure/login.py, login.php)が WEKO へ送る。その受け付けを、送信元のアドレスで限定する。 - weko-accounts: 受け付けるアドレスを WEKO_ACCOUNTS_SHIB_SP_ALLOWED_ADDRS (既定 127.0.0.1 / ::1)に限るデコレータを付ける。それ以外は 403 - login.py / login.php: 送り先をループバックアドレスにし、Host ヘッダに 公開ホスト名を入れる - nginx: /weko/shib/login への GET 以外をループバックアドレスからだけ許可する (weko.conf / weko-ams.conf / weko-ams-restricted.conf) 既存の環境では、login.py / login.php と nginx の設定を同時に更新すること。 どちらかだけでは Shibboleth ログインが通らなくなる。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
real_ip は信頼するプロキシ(プライベートアドレス)からの接続について X-Forwarded-For で $remote_addr を書き換える。そのため $remote_addr で ループバックかを判定すると、信頼するアドレスから X-Forwarded-For に ループバックを入れた要求を通してしまう。 /weko/shib/login の判定を $realip_remote_addr(書き換える前の接続元)で 行い、WEKO へ渡す REMOTE_ADDR も同じ値にする。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix group permission issue (No. 307, 312~326)
fix widget permission issue (No. 290, 303, 304)
fix: Shibboleth SP の属性の受け付けを SP のログインスクリプトからの要求に限る
fix: ログイン API の失敗応答を揃え、回数制限をログイン API にかける
fix: 管理系 API の担当範囲を確認し、SWORD の登録可能ロールの設定を効かせる
fix: 公開向けの配信・統計・補助 API で公開状態と閲覧権限を確認する
fix: ファイルの取得・プレビュー・IIIF でファイル単位の権限判定を行う
fix: デポジット・レコードの更新系 API の権限判定を有効にする
Fix/issue62783
fix: nginx の gzip が HTTP/1.0 のリクエストで効かない問題と、起動時の警告を直す
Fix/issue62782/issue62796(No.557, 560, 618, 1016)
Delete unnecessary instance.cfg (#63281)
|
Important Review skippedToo many files! This PR contains 672 files, which is 572 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. Usage-priced reviews support at most 300 files. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (121)
📒 Files selected for processing (672)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ❌ FAIL (FAIL 1 / WARN 2)サマリ
[FAIL] G2 認証系デコレータが削除された — 3件
[WARN] W2 実装本体が変化(data_op / 情報露出を再確認) — 8件
[WARN] W5 監視対象 config が変化した — 2件
台帳との突き合わせ(生成されませんでした) ソース由来の経路検知(生成されませんでした) |
概要 (Summary)
関連Issue / チケット (Related Issues)
変更タイプ (Type of Change)
🤖 0. CI 自動チェック (API Inventory Drift)
PR ごとに WEKO3 コンテナを起動し、
url_mapのダンプ・台帳との突き合わせ・変更行の到達可否測定を自動実行する。結果は PR コメントと Actions の artifact
(
api-inventory-summary) に出る。このリポジトリは public のため、台帳もベースラインも同梱していない。
実データはプライベートリポジトリ
RCOSDP/weko-secretにあり、CI は Secret 経由で取得する。以降この文書では、そこを単にプライベートリポジトリと呼ぶ。
台帳はブランチごとに内容が違うため、CI は weko 側と同名のブランチを
プライベートリポジトリから探して使う(head → base → 既定ブランチ の順)。
採用されたブランチ名は PR コメントの冒頭に出るので、件数を読む前にそこを見ること。
対応ブランチが無い場合は既定ブランチと比較され、コメント冒頭に警告が出る。
その件数は当てにならないので、PASS でも「確認済み」と読まないこと。
詳細:
tools/api-inventory/ci/README.md§3aSecret (
API_INVENTORY_REPO/API_INVENTORY_SSH_KEY) が未設定のリポジトリ、および fork からの PR では、このジョブは何もせずスキップされる。
API を追加・変更した場合(必須)
この PR が
fix/issue62569→develop_v2.0.4なら、プライベート側もfix/issue62569→develop_v2.0.4。同名にしておけば台帳 PR が未マージでもCI がそれを見るので、2つの PR のマージ順を気にしなくてよい。
api_snapshot.jsonを更新し、対応する PR を出したbash export WEKO_API_INVENTORY_DIR=/path/to/weko-secret ./install.sh python3 tools/api-inventory/scripts/snapshot.py --out "$WEKO_API_INVENTORY_DIR/api_snapshot.json"更新しないと CI が落ちる。公開リポジトリのコード変更とは別の PRになる。
weko3_api_list_full.tsvに行を追加・更新し、build_checklist.pyで 24 列版を再生成した(未収載だと reconcile が FAIL する)(
git statusに*.tsv/api_snapshot.jsonが出ていないこと)FAIL したときの対処(要約)
まず PR コメント冒頭の台帳ブランチを見る。警告が出ていれば、件数を追う前に
プライベートリポジトリ側の対応ブランチを用意すること(比較相手が違うので件数に意味がない)。
ジョブが落ちる条件は 3 つある。PR コメントのどのセクションに件数が出ているかで切り分ける。
drift.md)reconcile.md)*_PERMISSION_FACTORY/ CSRF 保護 等が危険側の値に変わったcan_delete/can_exportがFalse→Truedata_opを更新data_opが作成/更新/削除の経路に、未認証で到達したdata_opの記載誤りなら台帳を直すurl_mapに無いreconcile B のうち、実機に存在しないことが正当な行(プラグイン未登録・config で無効等)は
プライベートリポジトリの
reconcile_allow.jsonに理由付きで登録する。理由なしの登録は不可。登録済みの行は B'(既知・許容)として集計され、E'(endpoint が実機に無い)と併せてゲート対象外になる。
W1〜W6 は WARN でゲートは通るが、レビューでは見ること
(ModelView の追加 / 実装本体の変化 / HTTP メソッド・URL の変化 / 監視対象 config の変化 /
依存パッケージの版の変化)。特に W6(依存の版)は、ベースラインを CI と異なる環境で作ると
毎回出続けて形骸化するため、ベースラインは
install.shで作った環境から生成する。🔒 1. セキュリティ & API アクセス制御チェック (必須)
認証・認可 (Authentication & Authorization)
@login_required,@pass_record,need(...), Invenio Access Action/api/*ではPermission.require(http_exception=403)を使うこと。@login_requiredは API アプリにsecurity.loginが無いため 401 ではなく 500 になる--allow-writes付きでGET / HEAD 以外も叩く)
起動した経路のみ。ワークフロー系など未解決プレースホルダの行は skip される
Noneで無効化していない*_PERMISSION_FACTORY等を監視機能クローズ・非公開化の場合 (Feature Disable)
404 Not Foundまたは403 Forbiddenが返ることを確認した🧪 2. テストコード観点チェック (pytest / Invenio Test Suite)
権限・異常系テスト (Negative & Authorization Tests)
401 Unauthorizedまたは403 Forbidden/404 Not Foundが返ることを検証するテストがある403になるテストがある404/403を返すテストがある境界値・入力バリデーションテスト (Boundary & Validation)
400 Bad Request/ バリデーションエラーが返るテストがあるデータ整合性・トランザクションテスト (Integrity & Rollback)
🛡️ 3. データ保護 & 破壊的変更防止チェック (Data Safety)
⚙️ 4. マイグレーション & システム影響チェック (Invenio / WEKO3 Stack)
データベース (DB / Alembic)
invenio alembic upgrade(適用)およびdowngrade(ロールバック)スクリプトを作成・検証した検索インデックス (Elasticsearch / OpenSearch)
設定 & 非同期処理 (Config / Celery / Cache)
invenio.cfg/ 環境変数のデフォルト値を設定した📚 5. ドキュメント・仕様書更新チェック (weko-document)
tools/api-inventory/、台帳・調査記録はプライベートリポジトリ(public リポジトリには置かない)。
§0 のチェック項目で対応済みなら、ここは確認のみ。
weko3_api_auth_findings.md)もプライベートリポジトリに置く。台帳は二重管理しない📋 6. 動作検証エビデンス (Verification Evidence)
テスト実行結果
CI の成果物 (artifact:
api-inventory-summary)drift.mdreconcile.md明細(該当した経路名・実測結果)は公開できないため artifact に含めていない。
プライベートリポジトリ側で同じコマンドを
--summary-onlyなしで実行して確認する。手動で確認したこと