Allow the open browser and web login options to be used on all commands.

Review Request #14573 — Created Sept. 8, 2025 and updated

Information

RBTools
release-5.x

Reviewers

We received a bug report that the web login option was not working for
the rbt post command. Upon investigation, it was found that web login only
actually worked correctly for rbt login. It also worked for commands that
call get_authenticated_session before doing any requests that require
authentication (such as rbt status), but this only worked when the
WEB_LOGIN option was set in .reviewboardrc, not when the option was
passed through the command line.

This change is the beginning in a series of ones that allow web login to be
used for authentication when using any rbt command. This change only
generalizes command options, it doesn't actually implement web login on the
commands (that happens in /r/14575 and /r/14576).

We make the web login option a general server option, instead of only
applying to the login command. The command's long form has been renamed to
--web-login instead of just --web, but we keep the existing -w/--web
option on the login command for compatibility and since -w is a
convenient short-form of the option.

Similarly, we make the open browser option a general one, instead of only
applying to the login and post commands. In the future, any commands that
navigate to a URL can make use of this option to open URLs automatically in a
browser. It has also been renamed to --open-browser, but keeping the old
-o/--open version like we did for the --web option.

We also deprecate the --enable-logging option for rbt login, instead we'll
just use the --debug option to enable server logs.

These options now get set on RBClient as the web_login_options dict. It
makes sense to centralize these settings onto the client, so that callers can
easily set things in one place instead of having to plumb values through
various functions to reach the web login server. This will make more sense
in the context of the upcoming changes.

  • Used in upcoming changes.
  • Ran unit tests.
  • Tested using all versions of the web login, open browser, and
    debug/logging options and their .reviewboardrc config values
    on rbt login, rbt post and rbt status.
Summary ID
Allow the open browser and web login options to be used on all commands.
We received a bug report that the web login option was not working for the `rbt post` command. Upon investigation, it was found that web login only actually worked correctly for `rbt login`. It also worked for commands that call `get_authenticated_session` before doing any requests that require authentication (such as `rbt status`), but this only worked when the `WEB_LOGIN` option was set in `.reviewboardrc`, not when the option was passed through the command line. This change is the beginning in a series of ones that fix web login, allowing it to be used for authentication when using any rbt command. We make the web login option a general server option, instead of only applying to the login command. The command's long form has been renamed to `--web-login` instead of just `--web`, but we keep and deprecate the old `--web` version on the login command for compatibility. Similarly, we make the open browser option a general one, instead of only applying to the login and post commands. In the future, any commands that navigate to a URL can make use of this option to open URLs automatically in a browser. It has also been renamed to `--open-browser`, but keeping the old `--open` version like we did for the `--web` option. We also deprecate the `--enable-logging` option for `rbt login`, instead we'll just use the `--debug` option to enable server logs. These options now get passed to `RBClient`, which will make more sense with the next change. These are needed here to get around a problem with the commands that call `get_authenticated_session` before doing any authentication requests (before our web-login auth handler, which is added in an upcoming change, can kick in). In those cases we have no way to pass these options to the web login server unless we update every function call that directly or indirectly calls `get_authenticated_session` to include the options. Right now that includes `get_user`, `get_username` and `find_review_request_by_change_id`. That seemed too messy to deal with and it's not reasonable to make every function which calls `get_authenticated_session` have to include web-based login related options in their definitions.
ff33cd7379280856195f9b01d5ac63d27ad43313
Description From Last Updated

I don't like the idea of storing the options as an attribute on RBClient when the client isn't actually using …

daviddavid

I think -o is still very important here, and we should keep it for the long term. rbt post -o …

daviddavid

Perhaps we should use a dataclass here instead of a dict?

daviddavid

This should be RBClientWebLoginOptions | None

daviddavid

This should use (RBClientWebLoginOptions | None) = None

daviddavid

Type here is incorrect.

daviddavid

This should be able to go in the if TYPE_CHECKING block.

daviddavid

I have an idea here. Right now, this will make it so help output will show two separate lines each …

daviddavid

Can we add something that triggers a deprecation warning if this option is used?

daviddavid

Can you add docs for the return value and CommandError raise?

daviddavid

This should be able to go in the if TYPE_CHECKING block.

daviddavid

This is no longer true.

daviddavid

We could do the same thing here modifying self._global_options instead of duplicating the option.

daviddavid

These should use | None syntax

daviddavid

This should fit on one line.

daviddavid

Let's go with 5.4 for this release, since we're introducing new abilities. This will apply to other version references.

chipx86chipx86

Blank line between the class docstring and attributes.

chipx86chipx86

Can we alphabetize these?

chipx86chipx86

Both of these need their own Version Changed.

chipx86chipx86

I think this will end up polluting the shared options. We'd have to make a copy. Also, do we want …

chipx86chipx86

Same note here as with the other location.

chipx86chipx86

line too long (80 > 79 characters) Column: 80 Error code: E501

reviewbotreviewbot

Each one of these needs its own Version Changed.

chipx86chipx86

I think this probably should be a Sequence, unless we're allowing manipulation of it. This may become a larger change …

chipx86chipx86

Same note here with Sequence, if going this route for this change.

chipx86chipx86
david
  1. Two big-picture things before I get into a detailed review.

  2. Show all issues

    I don't like the idea of storing the options as an attribute on RBClient when the client isn't actually using it at all. I also can't see where web-based auth is implemented for commands other than rbt login.

    Architecturally, how does this sound:

    1. Update auth_callback to return a dict instead of a tuple[str, str]. This dict can include either username/password or an API token (actually, probably either dict or tuple and trigger a DeprecationWarning if the caller receives a tuple back).
    2. Update ReviewBoardHTTPPasswordMgr to also plumb that through.
    3. Update ReviewBoardServer.retry_http_basic_auth to handle an API token result.
    4. Add the web-login implementation to BaseCommand.credentials_prompt. This has access to self.options directly.
    1. Web-based auth gets implemented for all commands in /r/14576 (and /r/14575 has some context). This was just the first change in the stack where I generalize our command options (I'll clarify this in the description).

      You're right that web-based auth for commands doesn't necessitate storing the options on RBClient, since our auth callback (which in my changes is BaseCommand.web_login_callback) will have access to self.options directly. But the reason why I put these settings on RBClient is because it simplifies supplying these options to the web login server when using get_authenticated_session() and other potential areas that deal with authenticating a client.

      We do have the via_web, open_browser and enable_logging args for get_authenticated_session() which were added when I originally implemented web-based auth. Ideally I would've made this one RBClientWebLoginOptions-typed argument instead of individual arguments but oh well. Anyways while working on this I realized how messy it could be to only rely on these arguments. We have the get_user() and get_username() functions that both call get_authenticated_session(). And those functions are used in some of our commands, which kick off the auth process before our HTTP handlers can. Without the web login attributes on RBClient, I'd have to add a RBClientWebLoginOptions argument to get_user() and to get_username(), and update each of their calls so that we're passing in the options. And any new functions that call get_authenticated_session() and want to benefit from web login would have to add and care about a RBClientWebLoginOptions argument as well, just to plumb it through to get_authenticated_session().

      With the web login attributes on RBClient, the caller doesn't have to care about the web login options each time they call get_user(), get_username(), and get_authenticated_session().

      The RBClient isn't technically "using" these options itself, but its still information that is relevant to the client. It's saying whether this client is allowed to authenticate using web-based login or not, and details on how to use it. And then, from any function/class that deals with authenticating a client (commands, http handlers, these user session functions, the new attempt_web_login() function) we can define these options on the RBClient, or expect them to already be defined (as is the case with commands that call these user session functions), instead of being forced to include these options in all the function or class definitions that want to benefit from web login.

  3. rbtools/commands/post.py (Diff revision 1)
     
     
    Show all issues

    I think -o is still very important here, and we should keep it for the long term. rbt post -o is a lot easier to type than rbt post --open-browser

    1. That's a good point, we can keep it.

  4. 
      
maubin
maubin
david
  1. 
      
  2. rbtools/api/client.py (Diff revision 3)
     
     
    Show all issues

    Perhaps we should use a dataclass here instead of a dict?

  3. rbtools/api/client.py (Diff revision 3)
     
     
    Show all issues

    This should be RBClientWebLoginOptions | None

  4. rbtools/api/client.py (Diff revision 3)
     
     
    Show all issues

    This should use (RBClientWebLoginOptions | None) = None

  5. rbtools/api/client.py (Diff revision 3)
     
     
    Show all issues

    Type here is incorrect.

  6. rbtools/commands/login.py (Diff revision 3)
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    Show all issues

    I have an idea here. Right now, this will make it so help output will show two separate lines each of these.

    How about, instead of duplicating the options, we do:

    def create_parser(
        self,
        config: RBToolsConfig,
        argv: (list[str] | None) = None,
    ) -> argparse.ArgumentParser:
        for option in self._global_options:
            if option.opts[0] == '--open-browser':
                option.opts = ['-o', '--open', '--open-browser']
            elif option.opts[0] == '--web-login':
                option.opts = ['-w', '--web', '--web-login']
    
        return super.create_parser(config, argv)
    

    That'll simplify the RBClientWebLoginOptions creation too.

  7. rbtools/commands/login.py (Diff revision 3)
     
     
    Show all issues

    Can we add something that triggers a deprecation warning if this option is used?

    1. Python 3.13 adds a deprecated arg to add_argument which would be nice to use. For now I'll make our own custom thing in a separate change, so that we can use it for any deprecated arg.

  8. rbtools/commands/login.py (Diff revision 3)
     
     
    Show all issues

    Can you add docs for the return value and CommandError raise?

  9. rbtools/commands/post.py (Diff revision 3)
     
     
     
     
    Show all issues

    This is no longer true.

  10. rbtools/commands/post.py (Diff revision 3)
     
     
     
     
     
     
     
    Show all issues

    We could do the same thing here modifying self._global_options instead of duplicating the option.

  11. rbtools/utils/users.py (Diff revision 3)
     
     
     
    Show all issues

    These should use | None syntax

  12. rbtools/utils/users.py (Diff revision 3)
     
     
     
    Show all issues

    This should fit on one line.

  13. 
      
maubin
david
  1. 
      
  2. rbtools/commands/login.py (Diff revisions 3 - 4)
     
     
    Show all issues

    This should be able to go in the if TYPE_CHECKING block.

  3. rbtools/commands/post.py (Diff revisions 3 - 4)
     
     
    Show all issues

    This should be able to go in the if TYPE_CHECKING block.

  4. 
      
maubin
david
  1. Ship It!
  2. 
      
chipx86
  1. 
      
  2. rbtools/api/client.py (Diff revision 5)
     
     
    Show all issues

    Let's go with 5.4 for this release, since we're introducing new abilities.

    This will apply to other version references.

  3. rbtools/api/client.py (Diff revision 5)
     
     
     
    Show all issues

    Blank line between the class docstring and attributes.

  4. rbtools/api/client.py (Diff revision 5)
     
     
     
     
     
     
    Show all issues

    Can we alphabetize these?

  5. rbtools/commands/login.py (Diff revision 5)
     
     
     
     
     
     
    Show all issues

    Both of these need their own Version Changed.

  6. rbtools/commands/login.py (Diff revision 5)
     
     
     
     
     
     
     
     
    Show all issues

    I think this will end up polluting the shared options. We'd have to make a copy.

    Also, do we want to break after we find the option?

  7. rbtools/commands/post.py (Diff revision 5)
     
     
     
     
    Show all issues

    Same note here as with the other location.

  8. 
      
maubin
Review request changed
Change Summary:
  • Changed to target version 5.4.
  • Doesn't modify shared option lists on the base command class.
Commits:
Summary ID
Allow the open browser and web login options to be used on all commands.
We received a bug report that the web login option was not working for the `rbt post` command. Upon investigation, it was found that web login only actually worked correctly for `rbt login`. It also worked for commands that call `get_authenticated_session` before doing any requests that require authentication (such as `rbt status`), but this only worked when the `WEB_LOGIN` option was set in `.reviewboardrc`, not when the option was passed through the command line. This change is the beginning in a series of ones that fix web login, allowing it to be used for authentication when using any rbt command. We make the web login option a general server option, instead of only applying to the login command. The command's long form has been renamed to `--web-login` instead of just `--web`, but we keep and deprecate the old `--web` version on the login command for compatibility. Similarly, we make the open browser option a general one, instead of only applying to the login and post commands. In the future, any commands that navigate to a URL can make use of this option to open URLs automatically in a browser. It has also been renamed to `--open-browser`, but keeping the old `--open` version like we did for the `--web` option. We also deprecate the `--enable-logging` option for `rbt login`, instead we'll just use the `--debug` option to enable server logs. These options now get passed to `RBClient`, which will make more sense with the next change. These are needed here to get around a problem with the commands that call `get_authenticated_session` before doing any authentication requests (before our web-login auth handler, which is added in an upcoming change, can kick in). In those cases we have no way to pass these options to the web login server unless we update every function call that directly or indirectly calls `get_authenticated_session` to include the options. Right now that includes `get_user`, `get_username` and `find_review_request_by_change_id`. That seemed too messy to deal with and it's not reasonable to make every function which calls `get_authenticated_session` have to include web-based login related options in their definitions.
6d3e0136fbfd254a7af117e4cf3b0aa689d732a0
Allow the open browser and web login options to be used on all commands.
We received a bug report that the web login option was not working for the `rbt post` command. Upon investigation, it was found that web login only actually worked correctly for `rbt login`. It also worked for commands that call `get_authenticated_session` before doing any requests that require authentication (such as `rbt status`), but this only worked when the `WEB_LOGIN` option was set in `.reviewboardrc`, not when the option was passed through the command line. This change is the beginning in a series of ones that fix web login, allowing it to be used for authentication when using any rbt command. We make the web login option a general server option, instead of only applying to the login command. The command's long form has been renamed to `--web-login` instead of just `--web`, but we keep and deprecate the old `--web` version on the login command for compatibility. Similarly, we make the open browser option a general one, instead of only applying to the login and post commands. In the future, any commands that navigate to a URL can make use of this option to open URLs automatically in a browser. It has also been renamed to `--open-browser`, but keeping the old `--open` version like we did for the `--web` option. We also deprecate the `--enable-logging` option for `rbt login`, instead we'll just use the `--debug` option to enable server logs. These options now get passed to `RBClient`, which will make more sense with the next change. These are needed here to get around a problem with the commands that call `get_authenticated_session` before doing any authentication requests (before our web-login auth handler, which is added in an upcoming change, can kick in). In those cases we have no way to pass these options to the web login server unless we update every function call that directly or indirectly calls `get_authenticated_session` to include the options. Right now that includes `get_user`, `get_username` and `find_review_request_by_change_id`. That seemed too messy to deal with and it's not reasonable to make every function which calls `get_authenticated_session` have to include web-based login related options in their definitions.
ff33cd7379280856195f9b01d5ac63d27ad43313

Checks run (1 failed, 1 succeeded)

flake8 failed.
JSHint passed.

flake8

david
  1. Ship It!
  2. 
      
chipx86
  1. 
      
  2. rbtools/commands/login.py (Diff revision 6)
     
     
     
     
     
     
    Show all issues

    Each one of these needs its own Version Changed.

  3. rbtools/commands/login.py (Diff revision 6)
     
     
    Show all issues

    I think this probably should be a Sequence, unless we're allowing manipulation of it. This may become a larger change though, I'm not sure. If so, don't worry about this.

  4. rbtools/commands/post.py (Diff revision 6)
     
     
    Show all issues

    Same note here with Sequence, if going this route for this change.

  5.