Skip to content

Fix/issue62783 - #1923

Merged
ivis-miyachi merged 2 commits into
RCOSDP:develop_v2.1.0from
ivis-weko3-dev:fix/issue62783
Sep 29, 2026
Merged

ivis-miyachi merged 2 commits into
RCOSDP:develop_v2.1.0from
ivis-weko3-dev:fix/issue62783

Conversation

@asuzuki1

@asuzuki1 asuzuki1 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

概要 (Summary)

  • 21+1APIエンドポイントの認証・認可修正
    • check_authorityデコレーターの修正(拡張)
    • repository_scope_requiredデコレーター新規追加

関連Issue / チケット (Related Issues)

  • #62783

変更タイプ (Type of Change)

  • 🚀 新機能追加 (Feature)
  • 🐛 バグ修正 (Bug Fix)
  • 🔒 セキュリティ修正 (Security Fix)
  • 🚫 機能のクローズ・非公開化・削除 (Feature Deprecation/Disable)
  • ⚠️ 破壊的変更・データ移行を伴う修正 (Breaking Change / Migration)
  • 📚 仕様書・マニュアル・APIリストの更新 (Documentation)

🤖 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 §3a

  • CI が PASS している、または FAIL の各項目に対処済み
    Secret (API_INVENTORY_REPO / API_INVENTORY_SSH_KEY) が未設定のリポジトリ、
    および fork からの PR では、このジョブは何もせずスキップされる。

API を追加・変更した場合(必須)

  • プライベートリポジトリ側の作業ブランチを、この PR のブランチと同名で切った
    この 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) G1〜G7 のいずれかに該当
台帳との突き合わせ (reconcile.md) A + B + C + D + E の合計が 1 件以上
変更行の到達可否測定 (probe) G8 / G9 に該当(結果は artifact に含めないので Actions のログで件数を見る)
検出 意味 対処
G1 / G2 新規経路に認証系デコレータが無い / 認証系デコレータが削除された 実装を直す。意図的な公開なら台帳に根拠を書いてベースライン更新
G3 認証・認可デコレータのコメントアウトが増えた 原則やり直し。残す場合は理由をコード中のコメントに明記する
G4 *_PERMISSION_FACTORY / CSRF 保護 等が危険側の値に変わった 原則やり直し
G5 ModelView の can_delete / can_export が False → True 意図的なら台帳の data_op を更新
G6 静的解析で属性が取れない経路が追加された 台帳に行を追加してレビューする(外部ライブラリ由来など)
G7 依存パッケージの更新で経路が増減した 増えた経路は台帳に追加。消えた経路は行を削除するか allow に登録
G8 台帳で data_op が作成/更新/削除の経路に、未認証で到達した 原則やり直し。意図的な公開なら台帳の根拠を更新。data_op の記載誤りなら台帳を直す
G9 台帳では遮断なのに実測で到達(認可の回帰) 原則やり直し
reconcile A / E 実機にあるが台帳に無い(A: URI 単位 / E: 同一 URI の endpoint 単位) 台帳に行を追加する
reconcile B 台帳にあるが実機の url_map に無い 理由を確認し、正当なら allow に登録する
reconcile C / D メソッド・app 列の記載誤り 台帳を実機に合わせる

reconcile B のうち、実機に存在しないことが正当な行(プラグイン未登録・config で無効等)は
プライベートリポジトリの reconcile_allow.json に理由付きで登録する。理由なしの登録は不可。
登録済みの行は B'(既知・許容)として集計され、E'(endpoint が実機に無い)と併せてゲート対象外になる。

W1〜W6 は WARN でゲートは通るが、レビューでは見ること
(ModelView の追加 / 実装本体の変化 / HTTP メソッド・URL の変化 / 監視対象 config の変化 /
依存パッケージの版の変化)。特に W6(依存の版)は、ベースラインを CI と異なる環境で作ると
毎回出続けて形骸化するため、ベースラインは install.sh で作った環境から生成する。

CI の出力は件数のみ。該当した経路名は Actions には出ないので、プライベートリポジトリ側の
完全版レポート(--summary-only なしで再実行したもの)で確認すること
(このリポジトリは public で、ログ・artifact・PR コメントは誰でも読めるため)。


🔒 1. セキュリティ & API アクセス制御チェック (必須)

認証・認可 (Authentication & Authorization)

  • 新規/変更された Blueprint・View・REST リソースに適切なデコレータ / Permission を設定している
    • 例: @login_required, @pass_record, need(...), Invenio Access Action
    • /api/* では Permission.require(http_exception=403) を使うこと。
      @login_required は API アプリに security.login が無いため 401 ではなく 500 になる
    • CI: G1 / G2 が自動検出(デコレータの有無・削除)
  • 状態変更・破壊的メソッド (POST / PUT / PATCH / DELETE) の権限が正しく制限されている
    • CI: G8 が変更行を未認証で実測(使い捨て環境なので --allow-writes 付きで
      GET / HEAD 以外も叩く)
  • 未ログイン(Anonymous)状態でアクセスした際、意図しないデータ取得・変更が拒絶される
    • CI: G8 / G9 が変更行を実測。ただし測定対象は変更行のみ、かつ既定プロファイルで
      起動した経路のみ。ワークフロー系など未解決プレースホルダの行は skip される
  • 認可を config の permission factory に委ねている場合、None で無効化していない
    • CI: G4 が *_PERMISSION_FACTORY 等を監視

機能クローズ・非公開化の場合 (Feature Disable)

  • UI(画面・ボタン)の非表示だけでなく、バックエンド API(ルーティング・View)も完全に遮断されている
  • 無効化状態で直接 API を叩いた場合、404 Not Found または 403 Forbidden が返ることを確認した

🧪 2. テストコード観点チェック (pytest / Invenio Test Suite)

権限・異常系テスト (Negative & Authorization Tests)

  • 未認証アクセス (Anonymous): トークン/セッションなしのリクエストで 401 Unauthorized または 403 Forbidden / 404 Not Found が返ることを検証するテストがある
  • 権限不足ユーザー (Forbidden): 閲覧権限のみのユーザーが更新/削除 API を叩いた際に 403 になるテストがある
  • 無効化/非公開機能の遮断テスト: 対象機能が無効化されている場合、エンドポイントが 404 / 403 を返すテストがある

境界値・入力バリデーションテスト (Boundary & Validation)

  • 不正なパラメータ(巨大ファイル、異常な MIME タイプ、無効な JSON/XML スキーマ、SQLi/XSS ペイロード等)で適切に 400 Bad Request / バリデーションエラーが返るテストがある

データ整合性・トランザクションテスト (Integrity & Rollback)

  • ファイルストレージ(S3/ローカル)書き込み失敗時や DB エラー時に、中途半端なレコードやゴミファイルが残らずロールバックされるテストがある

🛡️ 3. データ保護 & 破壊的変更防止チェック (Data Safety)

  • 物理削除・上書きの安全性:
    • ファイル・アイテム・メタデータの完全削除/置換処理に、意図しない一括削除や別レコードへの誤適用リスクがない
    • 論理削除、バージョン管理、バックアップ等のロールバック機構が考慮されている
  • トランザクション整合性:
    • DB 更新とストレージ操作がアトミックに管理されている

⚙️ 4. マイグレーション & システム影響チェック (Invenio / WEKO3 Stack)

データベース (DB / Alembic)

  • invenio alembic upgrade(適用)および downgrade(ロールバック)スクリプトを作成・検証した
  • 既存データに対する破壊的変更(カラム削除、型変更、NOT NULL 制約追加等)の移行スクリプト/データパッチを用意した

検索インデックス (Elasticsearch / OpenSearch)

  • マッピング定義変更の有無を確認した
  • インデックス再作成(Reindex)やエイリアス切り替え手順を準備・検証した

設定 & 非同期処理 (Config / Celery / Cache)

  • invenio.cfg / 環境変数のデフォルト値を設定した
  • Celery タスクのシグネチャ変更によるキュー滞留・不整合が発生しない
  • キャッシュ(Redis/Memcached)のパージが必要か確認した

📚 5. ドキュメント・仕様書更新チェック (weko-document)

  • API インベントリ: ツールは本リポジトリの tools/api-inventory/、
    台帳・調査記録はプライベートリポジトリ(public リポジトリには置かない)。
    §0 のチェック項目で対応済みなら、ここは確認のみ。
    • エンドポイントの追加・変更・廃止、メソッド、認証・認可要件、リクエスト/レスポンス仕様を更新した
    • 調査記録(weko3_api_auth_findings.md)もプライベートリポジトリに置く。台帳は二重管理しない
  • WEKO3 機能仕様書:
    • 対象機能の仕様追加・変更・クローズ(非公開化)内容を反映した
  • 各種マニュアル (管理者 / 利用者マニュアル):
    • 画面導線・操作手順・権限仕様の変更を反映した
  • 更新不要な場合(理由):

📋 6. 動作検証エビデンス (Verification Evidence)

テスト実行結果

cd modules/<対象モジュール> && pytest
# -> PASS

CI の成果物 (artifact: api-inventory-summary)

ファイル 内容
drift.md ベースラインとの差分(件数のみ)
reconcile.md 台帳と実機の突き合わせ(件数のみ)

明細(該当した経路名・実測結果)は公開できないため artifact に含めていない。
プライベートリポジトリ側で同じコマンドを --summary-only なしで実行して確認する。

手動で確認したこと

Summary by Sourcery

Harden authentication and authorization across administrative, record, grid layout, and workflow APIs while preventing unauthorized data access and abuse.

Bug Fixes:

  • Prevent unauthorized access to repository-scoped administration, record export, workflow, citation, and file URI operations.

Enhancements:

  • Add repository-scope authorization for administrators and community administrators, including ownership checks for existing records and repository moves.
  • Strengthen workflow authorization by restricting activity access to permitted roles, owners, shared users, or guests with matching activity tokens.
  • Improve guest workflow request validation and enforce request rate limits.
  • Restrict workflow navigation visibility to users with supported roles.

Tests:

  • Add comprehensive authorization, repository-scope, ownership, validation, and rate-limit coverage across affected modules.

asuzuki1 and others added 2 commits September 25, 2026 09:34
Add repository-scope and ownership checks across weko-admin,
weko-gridlayout, weko-items-ui, weko-records-ui, and weko-workflow.

- weko-admin: add repository_scope_required to get_send_mail_history
- weko-gridlayout: reuse repository_scope_required on 5 widget endpoints
- weko-items-ui: skip non-owned/private records during item export
- weko-records-ui: restore permission check on cites API, add edit
  permission check to get_uri
- weko-workflow: restrict activity creation/listing to Contributor+,
  harden guest activity init, verify ownership on activity deletion,
  extend check_authority for request-maillist access

Add unit tests for each fix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- add _lookup_param to repository_scope_required so nested keys such as
  'data.repository' can be referenced with dot notation
- when both the record's current repository (source) and the requested
  repository (destination) are resolvable, require both to be in scope,
  preventing records from being moved to an unassigned community
- apply repository_scope_required to save_widget_item, blocking widget
  creation in arbitrary communities, overwriting of widgets outside the
  user's scope, and moves to unassigned communities
- add unit tests in weko-admin/weko-gridlayout and update existing tests
  that assumed the old DB-value-priority behavior

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

This security-focused PR fixes authentication and authorization across 21+1 API paths by introducing repository-scoped decorators, applying role and ownership checks to administrative, record, export, citation, and workflow operations, and adding guest-input validation and rate limiting. The accompanying tests cover anonymous access, role boundaries, repository ownership and transfer scenarios, invalid identifiers, guest-token binding, and export filtering.

Sequence diagram for repository-scoped API authorization

sequenceDiagram
    participant Client
    participant API
    participant repository_scope_required
    participant CurrentUser
    participant Repository
    participant Handler

    Client->>API: Request protected endpoint
    API->>repository_scope_required: wrapped()
    alt unauthenticated
        repository_scope_required-->>Client: 401 Unauthorized
    else system or repository administrator
        repository_scope_required->>Handler: f()
        Handler-->>Client: Response
    else community administrator
        repository_scope_required->>Repository: Community.get_repositories_by_user(current_user)
        alt all requested repositories are in scope
            repository_scope_required->>Handler: f()
            Handler-->>Client: Response
        else repository outside scope
            repository_scope_required-->>Client: 403 Forbidden
        end
    end
Loading

Sequence diagram for workflow activity deletion authorization

sequenceDiagram
    participant Client
    participant WorkflowAPI
    participant verify_deletion
    participant WorkActivity
    participant CurrentUser

    Client->>WorkflowAPI: Request deletion with activity_id
    WorkflowAPI->>verify_deletion: verify_deletion(activity_id)
    alt guest user
        verify_deletion->>CurrentUser: Check guest session
        alt guest_token activity_id matches
            verify_deletion->>WorkActivity: Delete activity
            WorkActivity-->>Client: Deletion result
        else token mismatch or missing
            verify_deletion-->>Client: 403 Authorization required
        end
    else authenticated user
        verify_deletion->>WorkActivity: get_activity_by_id(activity_id)
        alt owner or administrator authority
            verify_deletion->>WorkActivity: Delete activity
            WorkActivity-->>Client: Deletion result
        else unauthorized
            verify_deletion-->>Client: 403 Authorization required
        end
    end
Loading

Flow diagram for guest workflow initialization safeguards

flowchart TD
    A[Guest workflow initialization] --> B[limiter.limit]
    B -->|within 5 per minute| C{guest_mail provided?}
    B -->|rate limit exceeded| D[Reject request]
    C -->|yes| E[validate_email]
    C -->|no| F[Create guest activity]
    E -->|invalid| G[400 Invalid guest_mail]
    E -->|valid| F
    F --> H[Return guest workflow URL]
Loading

File-Level Changes

Change Details Files
Added repository-aware authorization for administrative APIs and widget operations.
  • Introduced repository_scope_required with superuser bypass, community-admin scope checks, source/destination validation, nested request parameter lookup, and configurable primary-key handling.
  • Applied repository scope enforcement to feedback-mail history and grid layout create/update/delete endpoints.
  • Updated application test configuration and added extensive anonymous, role, scope, missing-record, and cross-repository movement coverage.
modules/weko-admin/weko_admin/permissions.py
modules/weko-admin/weko_admin/views.py
modules/weko-admin/tests/conftest.py
modules/weko-admin/tests/test_permissions.py
modules/weko-admin/tests/test_views.py
modules/weko-gridlayout/weko_gridlayout/views.py
modules/weko-gridlayout/tests/conftest.py
modules/weko-gridlayout/tests/test_views.py
Strengthened record and export access control across records, items, and citation APIs.
  • Restricted record URI generation to authenticated users with record edit permission.
  • Added API authentication, OAuth read scope, and record visibility checks to citation retrieval.
  • Skipped unauthorized records during single and bulk exports while preserving public and owner access paths.
modules/weko-records-ui/weko_records_ui/views.py
modules/weko-records-ui/weko_records_ui/rest.py
modules/weko-records-ui/tests/test_views.py
modules/weko-items-ui/weko_items_ui/utils.py
modules/weko-items-ui/tests/test_utils.py
Expanded workflow authorization and protected guest workflow initiation.
  • Required item access for workflow creation and listing, and extended activity authority checks to owner/shared-user cases and endpoints without action IDs.
  • Validated guest email input, handled missing workflow IDs safely, and enforced a five-per-minute per-IP rate limit using an application-bound limiter.
  • Restricted deletion verification to the matching guest token activity or authorized logged-in users, including administrator checks.
modules/weko-workflow/weko_workflow/views.py
modules/weko-workflow/weko_workflow/ext.py
modules/weko-workflow/weko_workflow/utils.py
modules/weko-workflow/tests/test_views.py
Limited workflow navigation visibility to recognized workflow-capable roles.
  • Changed the theme workflow-tab condition from any role to an allowlist of system, repository, community administrator, and contributor roles.
modules/weko-theme/weko_theme/templates/weko_theme/macros/tabs_selector.html

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Sep 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: cacfe91a-2450-4de5-906a-1b67a5f4e211

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="modules/weko-workflow/weko_workflow/views.py" line_range="647-650" />
<code_context>
     """
     post_data = request.get_json()

+    if post_data.get('guest_mail'):
+        try:
+            validate_email(post_data.get('guest_mail'), check_deliverability=False)
+        except EmailNotValidError:
</code_context>
<issue_to_address>
**issue (bug_risk):** `init_activity_guest` calls `post_data.get(...)` immediately after `request.get_json()` without checking that a JSON object was supplied; an empty body, malformed JSON, or a JSON scalar therefore raises `AttributeError` and produces a 500 response instead of a client validation error.

**Triggers:** When an unauthenticated guest submits the endpoint without a JSON object.

**Suggested fix:** Reject a non-dict payload with a 400 response before accessing `.get()`.
</issue_to_address>

### Comment 2
<location path="modules/weko-records-ui/weko_records_ui/rest.py" line_range="653-657" />
<code_context>

-    # @pass_record
-    # @need_record_permission('read_permission_factory')
+    @require_api_auth(allow_anonymous=True)
+    @require_oauth_scopes(item_read_scope.id)
     def get(self, pid_value, **kwargs):
</code_context>
<issue_to_address>
**issue (bug_risk):** `page_permission_factory(record).can()` is evaluated inside the broad citation `except Exception` block, so a permission-check failure is logged as a citation-formatting failure and converted into a 404 response; infrastructure or database errors in authorization are silently disguised as 'Not found' rather than being escalated or handled distinctly.

**Triggers:** When the permission query or permission helper raises an unexpected exception while serving a citation.

**Suggested fix:** Perform the authorization check outside the citation-formatting `try`, or catch permission-denial and unexpected permission failures separately.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 2 findings to address first, and the change adds authorization and scope checks across record export, repository administration, workflow actions, and deletion paths; a faulty check could expose private records or let an unauthorized user delete data or perform workflow actions. Reverting would stop future access decisions, but it would not undo data already exposed or deleted.

Blocking findings: modules/weko-workflow/weko_workflow/views.py:650, modules/weko-records-ui/weko_records_ui/rest.py:657


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines 647 to +650
post_data = request.get_json()

if post_data.get('guest_mail'):
try:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): init_activity_guest calls post_data.get(...) immediately after request.get_json() without checking that a JSON object was supplied; an empty body, malformed JSON, or a JSON scalar therefore raises AttributeError and produces a 500 response instead of a client validation error.

Triggers: When an unauthenticated guest submits the endpoint without a JSON object.

Suggested fix: Reject a non-dict payload with a 400 response before accessing .get().

Comment on lines +653 to 657
@require_api_auth(allow_anonymous=True)
@require_oauth_scopes(item_read_scope.id)
def get(self, pid_value, **kwargs):
"""Render citation for record according to style and language."""
from weko_records.serializers import citeproc_v1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): page_permission_factory(record).can() is evaluated inside the broad citation except Exception block, so a permission-check failure is logged as a citation-formatting failure and converted into a 404 response; infrastructure or database errors in authorization are silently disguised as 'Not found' rather than being escalated or handled distinctly.

Triggers: When the permission query or permission helper raises an unexpected exception while serving a citation.

Suggested fix: Perform the authorization check outside the citation-formatting try, or catch permission-denial and unexpected permission failures separately.

return Permission(action_class)


def _is_super_user(user):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.208

return value


def repository_scope_required(repository_id_param=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.208,291

return any(role.name in comadmin for role in (user.roles or []))


def _lookup_param(data, kwargs, path):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.291


@blueprint_api.route('/get_send_mail_history', methods=['GET'])
@repository_scope_required(repository_id_param='repo_id')
def get_send_mail_history():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.208

methods=['POST'])
@login_required
@repository_scope_required(repository_id_param='repository_id')
def load_widget_list_design_setting():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.283

@repository_scope_required(repository_id_param='repository_id',
id_param='page_id', id_model=WidgetDesignPage)
# TODO: Allow this to be used for both or make a different path
def save_widget_layout_setting():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.284

@login_required
@repository_scope_required(repository_id_param='repository_id',
id_param='page_id', id_model=WidgetDesignPage)
def save_widget_design_page():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.288

@blueprint_api.route('/delete_widget_design_page', methods=['POST'])
@login_required
@repository_scope_required(id_param='page_id', id_model=WidgetDesignPage)
def delete_widget_design_page():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.289

@repository_scope_required(repository_id_param='data.repository',
id_param='data_id', id_model=WidgetItem,
pk_attr='widget_id')
def save_widget_item():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.291

@login_required
@repository_scope_required(id_param='data_id', id_model=WidgetItem,
pk_attr='widget_id')
def delete_widget_item():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.292

include_contents,
record_path,
)
if not exported_item:

@ivis-miyachi ivis-miyachi Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.399, 400

record = WekoRecord.get_record_by_pid(record_id)
list_item_role = {}
if record:
roles = get_user_roles()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.399,400


# @pass_record
# @need_record_permission('read_permission_factory')
@require_api_auth(allow_anonymous=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.470

try:
pid = PersistentIdentifier.get('depid', pid_value)
record = WekoRecord.get_record(pid.object_uuid)
if not page_permission_factory(record).can():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.470

current_app.logger.exception(
'Citation formatting for record {0} failed.'.format(
str(record.id)))
str(pid_value))) # record.id ではなく pid_value を参照(UnboundLocalError修正)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.470

return True

@blueprint.route("/get_uri", methods=['POST'])
@login_required

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.499

{%- if community_id %}
<li role="presentation" {% if tab_value=='top' %}class="active"{% endif %}><a href="/?c={{community_id}}">{{ _('Top') }}</a></li>
{%- if current_user.is_authenticated and current_user.roles %}
{%- if current_user.is_authenticated and current_user.roles | selectattr('name', 'in', ['System Administrator', 'Repository Administrator', 'Community Administrator', 'Contributor']) | list %}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.600, 998, 602, 1000

{%- else %}
<li role="presentation" {% if tab_value=='top' %}class="active"{% endif %}><a href="/">{{ _('Top') }}</a></li>
{%- if current_user.is_authenticated and current_user.roles %}
{%- if current_user.is_authenticated and current_user.roles | selectattr('name', 'in', ['System Administrator', 'Repository Administrator', 'Community Administrator', 'Contributor']) | list %}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.600, 998, 602, 1000


@workflow_blueprint.route('/activity/new', methods=['GET'])
@login_required
@item_permission.require(http_exception=403)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.600, 998, 602, 1000


@workflow_blueprint.route('/activity/list', methods=['GET'])
@login_required
@item_permission.require(http_exception=403)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.600, 998, 602, 1000

from .sessions import upt_activity_item
from .views import depositactivity_blueprint, workflow_blueprint
self.init_config(app)
self.init_limiter(app)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.603, 1001

app.register_blueprint(depositactivity_blueprint)
app.extensions['weko-workflow'] = self

def init_limiter(self, app):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.603, 1001



@workflow_blueprint.route('/activity/init-guest', methods=['POST'])
@limiter.limit("5 per minute", key_func=get_remote_address)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.603, 1001

return Limiter(app=Flask(__name__), key_func=get_remote_address, default_limits=WEKO_WORKFLOW_API_LIMIT_RATE_DEFAULT)


# NOTE: create_limmiter() above binds the Limiter to a throw-away Flask app

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.603, 1001

"""
post_data = request.get_json()

if post_data.get('guest_mail'):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.603, 1001

password_for_download = hash_password(pwd)

if is_terms_of_use_only(post_data["workflow_id"]):
if is_terms_of_use_only(post_data.get('workflow_id')):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.603, 1001

Returns:
dict: JSON response with code, is_deleted, and for_delete status.
"""
# 当事者検証。login_required_customize は session["guest_token"] の

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.606, 1004

)


def _get_shared_user_ids_from_list(shared_user_ids_list):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.619, 1017

if check_authority_by_admin(activity_detail):
return func(*args, **kwargs)

action_id = kwargs.get('action_id')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.619, 1017

action_order=0):
"""Check authority."""

def _get_shared_user_ids_from_list(shared_user_ids_list):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.619, 1017


@workflow_blueprint.route('/get_request_maillist/<string:activity_id>', methods=['GET'])
@login_required
@check_authority

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.619, 1017

return any(role.name in supers for role in (user.roles or []))


def _is_community_admin(user):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix no.208

@ivis-miyachi
ivis-miyachi merged commit bc24b58 into RCOSDP:develop_v2.1.0 Sep 29, 2026
147 of 148 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants