• 
      

    Add central registration of available API token policies.

    Review Request #15316 — Created Sept. 17, 2026 and updated

    Information

    Review Board
    release-9.x

    Reviewers

    When configuring API tokens, the client code had a pre-built set of API
    token policies that could be chosen alongside a custom policy document.
    This presented "Read-only" and "Full access".

    Some in-progress work will be adding at least one more token policy
    template to the list, and it won't be in core Review Board code.

    To prepare for this, we now have new central definitions maintained
    within the server-side code, which extensions can also provide. This is
    all defined in a reviewboard.webapi.token_policies module, which has a
    registry, base class, and the built-in Read-only and Full Access
    policies.

    All policies from the registry are passed to the My Account page for
    managing API tokens. The JavaScript code then takes this and introspects
    it instead of hard-coding a bunch of token types.

    Some error handling has also been added when setting policies in order
    to avoid silently erroring out if a token policy references some invalid
    resource, which I found during testing.

    Unit tests pass.

    Tested adding a new token policy in an extension and seeing it show up
    (and match on load) in the tokens view.

    Tested setting all the policies.

    Summary ID
    Add central registration of available API token policies.
    When configuring API tokens, the client code had a pre-built set of API token policies that could be chosen alongside a custom policy document. This presented "Read-only" and "Full access". Some in-progress work will be adding at least one more token policy template to the list, and it won't be in core Review Board code. To prepare for this, we now have new central definitions maintained within the server-side code, which extensions can also provide. This is all defined in a `reviewboard.webapi.token_policies` module, which has a registry, base class, and the built-in Read-only and Full Access policies. All policies from the registry are passed to the My Account page for managing API tokens. The JavaScript code then takes this and introspects it instead of hard-coding a bunch of token types. Some error handling has also been added when setting policies in order to avoid silently erroring out if a token policy references some invalid resource, which I found during testing.
    716e365cc035ff34d3160afa4125343a7b8eb795
    Description From Last Updated

    WebAPITokenManager.get_or_create_client_token now filters by policy. That seems like something that we might want to have in the change description since …

    david david

    The new tests cover the manager, but not the registry, base class, built-in policies, extension hook, or form data. At …

    david david

    This is iterating over the registry, but registries don't have a stable sort order. We should either sort these here, …

    david david

    Swap the order on these.

    david david

    We should use xhr.errorPayload here.

    david david

    If the save fails, the server still has the old data but we don't reset the UI back to it. …

    david david

    Can we also say in here that "An empty policy and no policy are treated as equivalent"?

    david david

    This parses as (norm_policy == token.policy) or None (and several manager tests are broken by this)

    david david

    The comma ended up inside the string, so the list is 'GET' and 'HEAD,OPTIONS'

    david david

    available as option -> available as an option

    david david
    Checks run (2 succeeded)
    flake8 passed.
    JSHint passed.
    david
    1. 
        
    2. Show all issues

      WebAPITokenManager.get_or_create_client_token now filters by policy. That seems like something that we might want to have in the change description since it has a meaningful fix for the behavior of service accounts (if a new version of service account code updates the policy), and we'll want that in the release notes.

    3. Show all issues

      The new tests cover the manager, but not the registry, base class, built-in policies, extension hook, or form data.

      At a minimum:

      • In test_token_policies:

      • check that get_token_policy('read-only') and get_token_policy('read-write') resolve.

      • Assert the built-in policy docs
      • Assert that unknown IDs return None.

      • Create a new hook test case (similar to the existing test_webapi_capabilities_hook)

    4. reviewboard/accounts/forms/pages.py (Diff revision 1)
       
       
      Show all issues

      This is iterating over the registry, but registries don't have a stable sort order. We should either sort these here, or have the registry inherit from OrderedRegistry instead.

    5. reviewboard/extensions/hooks/webapi.py (Diff revision 1)
       
       
       
       
       
       
       
       
       
      Show all issues

      Swap the order on these.

    6. Show all issues

      We should use xhr.errorPayload here.

    7. Show all issues

      If the save fails, the server still has the old data but we don't reset the UI back to it. Can we do:

      const prevPolicyType = this.previous('policyType');
      
      this.savePolicy(policyDoc).then(saved => {
          if (!saved) {
              this.set('policyType', prevPolicyType);
          }
      });
      
    8. reviewboard/webapi/managers.py (Diff revision 1)
       
       
       
       
       
       
      Show all issues

      Can we also say in here that "An empty policy and no policy are treated as equivalent"?

    9. reviewboard/webapi/managers.py (Diff revision 1)
       
       
      Show all issues

      This parses as (norm_policy == token.policy) or None (and several manager tests are broken by this)

    10. reviewboard/webapi/token_policies.py (Diff revision 1)
       
       
      Show all issues

      The comma ended up inside the string, so the list is 'GET' and 'HEAD,OPTIONS'

    11. reviewboard/webapi/token_policies.py (Diff revision 1)
       
       
      Show all issues

      available as option -> available as an option

    12.