Mehmet,
    Can you explain to me what the situation would be that an app could simply not be backend agnostic? Given that AUTHENTICATION_BACKENDS is a /user/ configuration, it seems odd that an app would ever design around specific backends being installed. I'm not sure I follow your logic on this.

Regarding an API that will allow picking and choosing I already have some ideas, but I think Carlton made an excellent point that that is another discussion all together.

Cheers,
    Andrew

On 1/17/2018 5:34 PM, Mehmet Dogan wrote:
Andrew,

Thank you for the input. Having options is good. My concern about that is, it may divide the already small backends population. If a backend relies on PermissionAuthorizationBackend, and another require the ModelOnlyPermissionAuthorizationBackend; then one cannot use both. Guardian, at its core, is agnostic of the default backend behavior, however, relies on it in some utilities. However, I am working on a simple RolePermissionsBackend now that leverages existing Object and Model backends at its core. Currently, if I do `user.has_perm('foo.change_bar')` or `user.has_perm('foo.change_bar', obj)` I know one is the model and the other is the object permissions. In case of plug-ins, that will go away, and it will be even harder to leverage existing backends. Also, the logic that polls backends is in auth/models.py, I do not see how would it be possible to design an API that will let picking and choosing.

On Wed, Jan 17, 2018 at 12:58 PM Andrew Standley <astand...@linear-systems.com <mailto:astand...@linear-systems.com>> wrote:

    Hi Carlton,
        Thanks for the thoughts. I just wanted to share my opinion on
    your options.

    1. "Won't Fix"
        I have yet to find anywhere the original design decisions were
    documented. Based on what I can find, it appears that object level
    permissions where a bit of an after-though for the initial auth
    framework. Unless we can find the motivation for the original
    design decision it seems foolish to leave /unexpected/ behaviour
    simply because that's how it has always been.

    I understand the motivation for wanting to only check object level
    permissions, but I would argue that the design of the API
    insinuates a hierarchical behaviour which is part of the reason
    the current behaviour is unexpected.
    Specifically why use an 'obj' kwarg instead of having two methods?

    To me if the API where:
    ```
    has_perm('foo.change_bar')
    has_obj_perm('foo.change_bar', bar_obj)
    ```
    I would expect `has_perm` to only deal with model level
    permissions and `has_obj_perm` to only deal with object level
    permissions

    To me the current API:
    ```
    has_perm('foo.change_bar', obj=bar_obj)
    ```
    Implies that the method will always check model level permissions
    and can /optionally/ check object level permissions.

    Having to always call `if user.has_perm('foo.change_bar', obj=bar)
    or user.has_perm('foo.change_bar')` both seems ugly, and relies on
    backend authors following ModelBackend's example of caching
    permission look-ups. Otherwise there may be a performance cost.
    The AUTH_BACKEND system's strength is the ability to plug in
    third-party and custom backends, it seems dangerous to make
    assumptions based on ModelBackend unless those assumptions are
    clearly documented.

    2. Change ModelBackend
    Initially this would have been my preferred option. However having
    given the issue significant thought, I think that it is important
    that users are still given the option of the current behaviour.
    Having an API return only object level permissions when called
    with obj, while returning only model level permissions when called
    without obj is a legitimate use case.
    Which leads me to

    3. Break out permissions aspects.
    I agree this would require some planning for migration. It also
    requires discussion on whether the desire would be to separate
    authentication from authorization or if the auth framework should
    just offer more default options.
    However overall I think this is the best option. It leverages the
    flexibility of the backend system and offers the option of
    maintaining BC if desired.

    For example it would make sense to me to plan on restructuring the
    auth.backends to something like:

    ```
    ModelAuthenticationBackend(object):
    # defines get_user and authenticate

    PermissionAuthorizationBackend(object):
    # defines get_user_permissions, get_group_permissions,
    get_all_permissions, has_perm, has_module_perms
    # 'New' behaviour: checks model level permissions /even/ when obj
    is None

    ModelOnlyPermissionAuthorizationBackend(object):
    # defines get_user_permissions, get_group_permissions,
    get_all_permissions, has_perm, has_module_perms
    # Current behaviour: checks model level permissions /only/ when
    obj is Non

    ModelPermissionBackend(ModelAuthenticationBackend,
    PermissionAuthorizationBackend):

       pass

    ModelBackend(ModelAuthenticationBackend,
    ModelOnlyPermissionAuthorizationBackend):

        pass
    ```

    This offers users more options for their
    authorization/authentication needs, and should make migration
    easier as you could gradually depreciate the name 'ModelBackend'
    in favour of something like 'ModelPermissionOnlyBackend'

    Additionally if Mehmet wanted to finalize an API that allowed
    users to specify a subset of backends to check against, this
    approach would support that.

    Cheers,
        Andrew


    On 1/17/2018 2:45 AM, Carlton Gibson wrote:
    Hi Mehmet,

    Due to the BC issues, this is fairly in-depth.

    Having looked at the history, here are my initial thoughts.



    The initial issue here is this behaviour from `ModelBackend`:

    ```
    user.has_perm('foo.change_bar', obj)
    False
    user.has_perm('for.change_bar')
    True
    ```

    Although the long-standing behaviour, this is considered
    _unexpected_.

    Ticket is: https://code.djangoproject.com/ticket/20218

    There are two related tickets regarding permission-checking in
    the Admin:

    * https://code.djangoproject.com/ticket/13539
    * https://code.djangoproject.com/ticket/11383

    Currently, I see three options:

    1. Close as "Won't Fix", perhaps with a review of the
    documentation to see if we
       can't clarify/emphasise the behaviour somewhere.

        This is the path of least resistance. It conforms to the
    original design
        decision. It preserves the long-standing behaviour. (Whilst,
    yes, some find the
        behaviour unexpected, it has a sense; it just depends how you
    look at it.)

        The objection is to this kind of check:

            if user.has_perm('foo.change_bar', obj=bar) or
    user.has_perm('foo.change_bar'):
                ...

        * Whilst, granted, it's a little clumsy, there's no reason
    this couldn't be
          wrapped in a utility function. (There's a suggestion to
    that effect on the
          Django-Guardian issue tracker[^1]. This seems like a good
    idea, simple enough
          to live in user code.)
        * `ModelBackend` permission lookups are cached[^2] so the
    performance worry
          here should be negligible.

    2. Implement the (straight) backwards incompatible change.

        The difficulty here is (we guess) why this ticket has been
    open so long.

        If we are convinced this is the right way to go — i.e. that
    the current
        behaviour is in fact **wrong** — then we should go ahead
    despite the
        difficulty.

        Working out what that entails is non-trivial. That's why it
    needs a decent
        discussion and consensus here.

        Which leads to...

    3. Break out the permissions aspect of `ModelBackend` in order to
    make it
       pluggable in some way. Then allow users to opt-in to a new
    version with the
       adjusted behaviour.
       There is some discussion of this on one of the related
    tickets[^3].
       Again, exactly what the migration path is needs some planning.

    I'm not sure what the correct answer is.

    [^1]: https://github.com/django-guardian/django-guardian/issues/459
    [^2]:
    
https://docs.djangoproject.com/en/2.0/topics/auth/default/#permission-caching
    [^3]: f.f. https://code.djangoproject.com/ticket/13539#comment:16


    Kind Regards,

    Carlton

-- You received this message because you are subscribed to the
    Google Groups "Django developers (Contributions to Django
    itself)" group.
    To unsubscribe from this group and stop receiving emails from it,
    send an email to django-developers+unsubscr...@googlegroups.com
    <mailto:django-developers+unsubscr...@googlegroups.com>.

    To post to this group, send email to
    django-developers@googlegroups.com
    <mailto:django-developers@googlegroups.com>.
    Visit this group at *MailScanner has detected definite fraud in
    the website at "groups.google.com". Do /not/ trust this website:*
    *MailScanner has detected definite fraud in the website at
    "groups.google.com". Do /not/ trust this website:* *MailScanner
    has detected definite fraud in the website at
    "groups.google.com". Do /not/ trust this website:*
    https://groups.google.com/group/django-developers
    <https://groups.google.com/group/django-developers>.
    To view this discussion on the web visit *MailScanner has
    detected definite fraud in the website at "groups.google.com". Do
    /not/ trust this website:* *MailScanner has detected definite
    fraud in the website at "groups.google.com". Do /not/ trust this
    website:* *MailScanner has detected definite fraud in the website
    at "groups.google.com". Do /not/ trust this website:*
    
https://groups.google.com/d/msgid/django-developers/cab981b8-7dc7-4e9d-9dcc-442b36820cdf%40googlegroups.com
    
<https://groups.google.com/d/msgid/django-developers/cab981b8-7dc7-4e9d-9dcc-442b36820cdf%40googlegroups.com?utm_medium=email&utm_source=footer>.
    For more options, visit *MailScanner has detected definite fraud
    in the website at "groups.google.com". Do /not/ trust this
    website:* *MailScanner has detected definite fraud in the website
    at "groups.google.com". Do /not/ trust this website:*
    *MailScanner has detected definite fraud in the website at
    "groups.google.com". Do /not/ trust this website:*
    https://groups.google.com/d/optout
    <https://groups.google.com/d/optout>.

-- *Andrew Standley*
    /Senior Software Engineer/
    Linear Systems
    (909) 899-4345 <tel:%28909%29%20899-4345> *225
    /astand...@linear-systems.com <mailto:astand...@linear-systems.com> /
-- You received this message because you are subscribed to a topic in
    the Google Groups "Django developers (Contributions to Django
    itself)" group.
    To unsubscribe from this topic, visit *MailScanner has detected
    definite fraud in the website at "groups.google.com". Do /not/
    trust this website:*
    https://groups.google.com/d/topic/django-developers/MLWfvPPVwDk/unsubscribe.
    To unsubscribe from this group and all its topics, send an email
    to django-developers+unsubscr...@googlegroups.com
    <mailto:django-developers+unsubscr...@googlegroups.com>.
    To post to this group, send email to
    django-developers@googlegroups.com
    <mailto:django-developers@googlegroups.com>.
    Visit this group at *MailScanner has detected definite fraud in
    the website at "groups.google.com". Do /not/ trust this website:*
    https://groups.google.com/group/django-developers
    <https://groups.google.com/group/django-developers>.
    To view this discussion on the web visit *MailScanner has detected
    definite fraud in the website at "groups.google.com". Do /not/
    trust this website:*
    
https://groups.google.com/d/msgid/django-developers/cfcefc08-e8a6-71d3-6269-31ccd9eaa52d%40linear-systems.com
    
<https://groups.google.com/d/msgid/django-developers/cfcefc08-e8a6-71d3-6269-31ccd9eaa52d%40linear-systems.com?utm_medium=email&utm_source=footer>.
    For more options, visit *MailScanner has detected definite fraud
    in the website at "groups.google.com". Do /not/ trust this
    website:* https://groups.google.com/d/optout
    <https://groups.google.com/d/optout>.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com <mailto:django-developers+unsubscr...@googlegroups.com>. To post to this group, send email to django-developers@googlegroups.com <mailto:django-developers@googlegroups.com>. Visit this group at *MailScanner has detected definite fraud in the website at "groups.google.com". Do /not/ trust this website:* https://groups.google.com/group/django-developers <https://groups.google.com/group/django-developers>. To view this discussion on the web visit *MailScanner has detected definite fraud in the website at "groups.google.com". Do /not/ trust this website:* https://groups.google.com/d/msgid/django-developers/CAFdefwM82z1MRfPh%3Dgaq0k%3D7X3dfaFMuPyPYzGA1Ggtjydmtug%40mail.gmail.com <https://groups.google.com/d/msgid/django-developers/CAFdefwM82z1MRfPh%3Dgaq0k%3D7X3dfaFMuPyPYzGA1Ggtjydmtug%40mail.gmail.com?utm_medium=email&utm_source=footer>. For more options, visit *MailScanner has detected definite fraud in the website at "groups.google.com". Do /not/ trust this website:* https://groups.google.com/d/optout <https://groups.google.com/d/optout>.

--
*Andrew Standley*
/Senior Software Engineer/
Linear Systems
(909) 899-4345 *225
/astand...@linear-systems.com <mailto:astand...@linear-systems.com> /

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/5ac40a89-55a6-4f98-f9cf-0a7d371c45e8%40linear-systems.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to