• 
      

    Create CommentManager to query for comments that are accessible by a given user

    Review Request #12309 — Created May 30, 2022 and submitted

    Information

    Review Board
    release-5.0.x

    Reviewers

    Currently there is no efficient way to query for comments that are
    accessible by a given user when using <AnyCommentClass>.objects. This change
    creates a CommentManager and adds a method such that
    <AnyCommentClass>.objects.accessible(user) returns a queryset of comments that
    are accessible by the given user.

    • Wrote unit tests for CommentManager and they pass.
    Summary ID Author
    Create CommentManager to query for comments that are accessible
    by a given user
    7360451725a0c15e73d6b3af2c019d1cd9b22484 Michelle
    Description From Last Updated

    Most of my comments on the other manager change apply here as well.

    chipx86chipx86

    This looks great! The only thing I want to see before this ships is some more extensive pieces of test …

    chipx86chipx86

    F401 'reviewboard.reviews.models.GeneralComment' imported but unused

    reviewbotreviewbot

    F401 'reviewboard.reviews.models.ScreenshotComment' imported but unused

    reviewbotreviewbot

    F401 'reviewboard.reviews.models.FileAttachmentComment' imported but unused

    reviewbotreviewbot

    W292 no newline at end of file

    reviewbotreviewbot

    This should probably be isinstance(user_or_username, str). It wouldn't make sense to query for username=False. We could add assert isinstance(user_or_username, (User, …

    daviddavid

    Same issue here.

    daviddavid

    Rather than abbreviating, let's keep the naming consistent with what we use in the other managers. I know in this …

    chipx86chipx86

    We can probably get away with just testing one type, since the manager won't be affected by the model type. …

    chipx86chipx86

    Missing a trailing period.

    chipx86chipx86

    Okay I made some comments about these lines as general guidance, but I think what's ideal here is to not …

    chipx86chipx86

    This can be if user.is_anonymous.

    chipx86chipx86

    Rather than .exclude, we should be able to use .filter and check against True. It's easier to rationalize the logic …

    chipx86chipx86

    Same comment here. Nicer to work as a filter.

    chipx86chipx86

    This comment is no longer applicable.

    chipx86chipx86

    Do we need transform? We should be able to compare the objects directly.

    chipx86chipx86
    Checks run (1 failed, 1 succeeded)
    flake8 failed.
    JSHint passed.

    flake8

    maubin
    maubin
    maubin
    david
    1. 
        
    2. reviewboard/reviews/managers.py (Diff revision 4)
       
       
       
      Show all issues

      This should probably be isinstance(user_or_username, str). It wouldn't make sense to query for username=False.

      We could add assert isinstance(user_or_username, (User, AnonymousUser, str)) to handle incorrect callers.

    3. reviewboard/reviews/managers.py (Diff revision 4)
       
       
      Show all issues

      Same issue here.

    4. 
        
    maubin
    chipx86
    1. 
        
    2. Show all issues

      Most of my comments on the other manager change apply here as well.

    3. reviewboard/reviews/managers.py (Diff revision 5)
       
       
      Show all issues

      Rather than abbreviating, let's keep the naming consistent with what we use in the other managers. I know in this case it's likely to be for line length limits, but you can have the value in Q(field=) wrap to the next line as needed.

    4. reviewboard/reviews/tests/test_comment_manager.py (Diff revision 5)
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      We can probably get away with just testing one type, since the manager won't be affected by the model type.

      If we wanted to ensure we're testing with each comment type, what we'd want to do is create a mixin class that takes the comment model we'd test with, have all unit tests operate on that model, and then have subclasses for each comment type. But it's probably not worth it, given the logic isn't sensitive to the type of model.

      The docstrings can also just be CommentManager instead of worrying about the .objects convention.

    5. 
        
    maubin
    chipx86
    1. 
        
    2. reviewboard/reviews/managers.py (Diff revision 6)
       
       
      Show all issues

      Missing a trailing period.

    3. reviewboard/reviews/managers.py (Diff revision 6)
       
       
       
       
       
       
       
      Show all issues

      Okay I made some comments about these lines as general guidance, but I think what's ideal here is to not have two places that are building queryset logic.

      _query() is already considering quite a lot of options for building up the queryset. It's easy to rationalize what's happening when reading that logic, but harder when we then have to mentally combine those built queries with this block. We should aim to have one and only one block of logic building any query involving access controls.

      I'd suggest we figure out what public should be up-front and pass that in above.

      _query() should also be responsible already for the user access (anonymous vs. authed vs. superuser). It looks like it's trying to at least, and that'd be the end goal so that any other wrappers around _query() get the right behavior without duplicating this block.

      1. Ok this makes sense, originally I was having trouble on how to remove unpublished reviews that do not not belong to the user from the queryset. Now I've found a way to move this logic into the _query() method where we perform other ACL logic (see my next review request).

    4. reviewboard/reviews/managers.py (Diff revision 6)
       
       
      Show all issues

      This can be if user.is_anonymous.

    5. reviewboard/reviews/managers.py (Diff revision 6)
       
       
      Show all issues

      Rather than .exclude, we should be able to use .filter and check against True. It's easier to rationalize the logic if we're not having to inverse.

    6. reviewboard/reviews/managers.py (Diff revision 6)
       
       
       
      Show all issues

      Same comment here. Nicer to work as a filter.

    7. Show all issues

      This comment is no longer applicable.

    8. Show all issues

      Do we need transform? We should be able to compare the objects directly.

      1. You're right, I misread the docs for assertQuerysetEqual and thought that was the transform was needed.

    9. 
        
    maubin
    maubin
    maubin
    maubin
    chipx86
    1. 
        
    2. Show all issues

      This looks great! The only thing I want to see before this ships is some more extensive pieces of test data. When dealing with queries or access checks specifically, we should register objects that should not be queried, in order to ensure we don't see them in results.

      For access-related tests, that means any combination of access controls that should fail should be included. For example, if testing Local Site functionality, we should have objects on the global site and a different Local Site registered, and they shouldn't be in the results.

    3. 
        
    maubin
    maubin
    chipx86
    1. Ship It!
    2. 
        
    maubin
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to release-5.0.x (41fd09b)