Update APITokenResource for API Tokens v2

Review Request #12474 — Created July 15, 2022 and submitted

Information

Review Board
release-5.0.x

Reviewers

This change updates the APITokenResource according to the new WebAPIToken
fields addded as part of our move to API Tokens v2. The API now creates tokens
in the vendor checksum format rather than the legacy SHA1 format. Users can also
invalidate tokens via the API.

This change also corrects some PUT, POST and DELETE tests for for the
APITokenResource. These tests were all calling self.api_get instead of the
appropriate HTTP method.

It also updates test utilities that are related to WebAPITokens.

Ran unit tests in reviewboard/webapi/tests.

Summary ID
Update APITokenResource for API Tokens v2
6c5d95516bc6417b362923f5ae4a4f0f7ffca848
Description From Last Updated

Can we update this to use the imperative mood? ("Creates" -> "Create")

daviddavid

'django.utils.timezone' imported but unused Column: 1 Error code: F401

reviewbotreviewbot

Can you alphabetize all the keys? Helps keep it clear where new ones go. Also, all these should have a …

chipx86chipx86

This has to go before Args. Under the hood, Version Added is a .. versionadded::, which is a paragraph-following/generating construct. …

chipx86chipx86

For the else clause, are we handling None/''? We should probably just be explicit with one or the other (probably …

chipx86chipx86

Let's be explicit and say invalid_date here.

daviddavid

Let's be explicit and say last_updated here.

daviddavid

Same here.

daviddavid

Same here.

daviddavid

If we're not modifying this, we should provide it inline where we're using it.

chipx86chipx86

We should maybe create some central concept of what the default token generator is. Maybe this lives in Djblets, as …

chipx86chipx86

Let's simplify this a bit. valid = kwargs.get('valid') if valid is True: return INVALID_FORM_DATA, .... elif value is False: ...

chipx86chipx86

I know we should already have some validation from the field type, but can we explicitly do kwargs['valid'] != False?

daviddavid

Let's avoid setting the key twice and instead compute as one statement.

chipx86chipx86

Paren should be on the previous line, with no trailing , (given that it's a function call).

chipx86chipx86

Let's make this part of the call, so we have that state all together. Same below.

chipx86chipx86

"expiration date" is more in line with the language we tend to use in the docs (I just found out, …

chipx86chipx86

This form for function definitions should only be used if we can't fit argument names and values on a single …

chipx86chipx86

Rather than this form, let's pull this out and pre-compute the generator ID. In fact, we should allow the caller …

chipx86chipx86

As above, we standardize on "expiration date."

chipx86chipx86

No blank line here.

chipx86chipx86

Let's pull out the ID before we call this, to avoid the chaining.

chipx86chipx86

Rather than True or False (here and in the resulting errors), we should use true or false, because these will …

chipx86chipx86

Let's pull this out to avoid the chaining.

chipx86chipx86

We try hard to avoid the ternary if .. else in statements. They're a bit harder to read and format. …

chipx86chipx86
maubin
Review request changed

Change Summary:

  • Serialize the DateTime fields to ISO format.
  • Uses WebAPITokenManager to handle invalidating tokens.

Commits:

Summary ID
Update APITokenResource for API Tokens v2
3008c645dfec118e41186664e2df56564a27413b
Update APITokenResource for API Tokens v2
815e7c9dcfad53f78f3576f77dee392aa4f44b3f

Diff:

Revision 2 (+652 -40)

Show changes

Checks run (1 failed, 1 succeeded)

flake8 failed.
JSHint passed.

flake8

david
  1. 
      
  2. reviewboard/testing/testcase.py (Diff revision 2)
     
     

    Can we update this to use the imperative mood? ("Creates" -> "Create")

  3. Let's be explicit and say invalid_date here.

  4. Let's be explicit and say last_updated here.

  5. Same here.

  6. Same here.

  7. I know we should already have some validation from the field type, but can we explicitly do kwargs['valid'] != False?

  8. 
      
chipx86
  1. 
      
  2. reviewboard/webapi/resources/api_token.py (Diff revision 2)
     
     
     
     
     
     
     
     
     
     
     
     

    Can you alphabetize all the keys? Helps keep it clear where new ones go.

    Also, all these should have a 'added_in': '5.0'. Same with all places where we describe a new field.

  3. reviewboard/webapi/resources/api_token.py (Diff revision 2)
     
     
     
     

    This has to go before Args.

    Under the hood, Version Added is a .. versionadded::, which is a paragraph-following/generating construct. Args, Returns, and Raises are special block-generating directives meant to appear after the paragraph-generating content is done.

    Same below.

  4. reviewboard/webapi/resources/api_token.py (Diff revision 2)
     
     
     
     
     

    For the else clause, are we handling None/''? We should probably just be explicit with one or the other (probably None).

    Same below.

  5. reviewboard/webapi/resources/api_token.py (Diff revision 2)
     
     
     
     

    If we're not modifying this, we should provide it inline where we're using it.

  6. We should maybe create some central concept of what the default token generator is. Maybe this lives in Djblets, as a DJBLETS_DEFAULT_API_TOKEN_GENERATOR, and a function for getting it from the registry?

    This can be a follow-up. Not a P0 for this change or related changes. Given time constraints, this can also just be tracked in Asana for now.

  7. reviewboard/webapi/resources/api_token.py (Diff revision 2)
     
     
     
     
     
     
     
     
     
     
     

    Let's simplify this a bit.

    valid = kwargs.get('valid')
    
    if valid is True:
        return INVALID_FORM_DATA, ....
    elif value is False:
        ...
    
  8. reviewboard/webapi/tests/test_api_token.py (Diff revision 2)
     
     
     

    Let's avoid setting the key twice and instead compute as one statement.

  9. reviewboard/webapi/tests/test_api_token.py (Diff revision 2)
     
     
     

    Paren should be on the previous line, with no trailing , (given that it's a function call).

  10. reviewboard/webapi/tests/test_api_token.py (Diff revision 2)
     
     
     
     
     

    Let's make this part of the call, so we have that state all together.

    Same below.

  11. 
      
maubin
chipx86
  1. 
      
  2. "expiration date" is more in line with the language we tend to use in the docs (I just found out, this is a regional difference).

  3. reviewboard/testing/testcase.py (Diff revision 3)
     
     
     
     
     
     
     
     

    This form for function definitions should only be used if we can't fit argument names and values on a single line. These will all fit, so let's start them off on the create_webapi_token line and then align each next one with that.

  4. reviewboard/testing/testcase.py (Diff revision 3)
     
     
     

    Rather than this form, let's pull this out and pre-compute the generator ID.

    In fact, we should allow the caller to specify a generator ID and token info (default to None, set to these if not specified), so that we can more easily test with variations on the tokens.

  5. As above, we standardize on "expiration date."

  6. reviewboard/webapi/resources/api_token.py (Diff revision 3)
     
     
     
     

    No blank line here.

  7. reviewboard/webapi/resources/api_token.py (Diff revision 3)
     
     
     

    Let's pull out the ID before we call this, to avoid the chaining.

  8. reviewboard/webapi/resources/api_token.py (Diff revision 3)
     
     
     

    Rather than True or False (here and in the resulting errors), we should use true or false, because these will be values going into the API rather than the Python constants for them.

  9. reviewboard/webapi/tests/mixins.py (Diff revision 3)
     
     
     

    Let's pull this out to avoid the chaining.

  10. reviewboard/webapi/tests/test_api_token.py (Diff revision 3)
     
     
     
     
     
     
     
     
     
     
     

    We try hard to avoid the ternary if .. else in statements. They're a bit harder to read and format.

    Instead, can we pre-compute the expected values at the top of the function, and compare against those?

  11. 
      
maubin
chipx86
  1. Ship It!
  2. 
      
maubin
Review request changed

Status: Closed (submitted)

Change Summary:

Pushed to release-5.0.x (2d66417)
Loading...