
    \j:(                        d dl mZ d dlmZ d dlmZmZ d dlmZ d dl	m
Z
mZmZ d dlmZ d dlmZ d dlmZmZmZmZ d d	lmZ ej0                  Zej2                  Z G d
 dej4                        Z G d de      ZddZdddefdZd Zy)    wraps)settings)REDIRECT_FIELD_NAMEmixins)redirect_to_login)
FieldErrorImproperlyConfiguredPermissionDenied)get_object_or_404)	force_str)
CreateView
DeleteView
DetailView
UpdateView)BaseCreateViewc                       e Zd ZdZd Zd Zy)PermissionRequiredMixina  
    CBV mixin to provide object-level permission checking to views. Best used
    with views that inherit from ``SingleObjectMixin`` (``DetailView``,
    ``UpdateView``, etc.), though not required.

    The single requirement is for a ``get_object`` method to be available
    in the view. If there's no ``get_object`` method, permission checking
    is model-level, that is exactly like Django's ``PermissionRequiredMixin``.
    c                     t        | t              s1t        | d      r%t        | j                        r| j	                         S y)z
        Override this method to provide the object to check for permission
        against. By default uses ``self.get_object()`` as provided by
        ``SingleObjectMixin``. Returns None if there's no ``get_object``
        method.
        
get_objectN)
isinstancer   hasattrcallabler   )selfs    =/root/env/lib/python3.12/site-packages/rules/contrib/views.pyget_permission_objectz-PermissionRequiredMixin.get_permission_object   s3     $/t\*x/H((    c                     | j                         }| j                         }| j                  j                  j	                  ||      S N)r   get_permission_requiredrequestuser	has_perms)r   objpermss      r   has_permissionz&PermissionRequiredMixin.has_permission,   s;    ((*,,.||  **5#66r   N)__name__
__module____qualname____doc__r   r&    r   r   r   r      s    7r   r   c                   >     e Zd ZdZedfedfedfedfgZ fdZ	 xZ
S )AutoPermissionRequiredMixina  
    An extended variant of PermissionRequiredMixin which automatically determines
    the permission to check based on the type of view it's used with.

    It works by checking the current view for being an instance of a pre-defined
    list of view types. On a match, the corresponding permission type (such as
    "add" or "change") is converted into the full model-specific permission name
    and checked. See the permission_type_map attribute for the default view type ->
    permission type mappings.

    When a view using this mixin has an attribute ``permission_type``, that type
    is used directly and overwrites the permission_type_map for the particular
    view. A permission type of ``None`` (either as ``permission_type`` or in
    ``permission_type_map``) causes permission checking to be skipped. If the type
    of permission to check for should depend on dynamic factors other than the view
    type, you may overwrite the ``permission_type`` attribute with a ``@property``.

    The ``permission_required`` attribute behaves like it does in
    ``PermissionRequiredMixin`` and can be used to specify concrete permission name(s)
    to be checked in addition to the automatically derived one.

    NOTE: The model-based permission registration from ``rules.contrib.models``
    must be used with the models for which you create views using this mixin,
    because the permission names are derived via ``RulesModelMixin.get_perm()``
    internally. The second requirement is the presence of either an attribute
    ``model`` holding the ``Model`` the view acts on, or the ``get_queryset()``
    method as provided by Django's ``SingleObjectMixin``. Hence with the normal
    model views, you don't need to care about anything.
    addchangedeleteviewc                    	 | j                   }g }|It        | dd      }|| j                         j                  }|j                  |j                  |             | j                  |j                  t        | A                |S # t        $ rU | j                  D ]  \  }}t        | |      s|} n/ t	        dj                  | j                  j                              Y w xY w)z<Adds the correct permission to check according to view type.zAutoPermissionRequiredMixin was used, but permission_type was neither set nor could be determined automatically for {0}. Consider setting permission_type on the view manually or adding {0} to the permission_type_map.Nmodel)permission_typeAttributeErrorpermission_type_mapr   r
   format	__class__r'   getattrget_querysetr3   appendget_permpermission_requiredextendsuperr    )r   	perm_type	view_type
_perm_typer%   r3   r8   s         r   r    z3AutoPermissionRequiredMixin.get_permission_requireda   s    	,,I"  D'40E}))+11LL	23 ##/LL8:;5  	)-)A)A %	:dI. *I
 += >DV//>	  	s   B 'C%/3C%$C%)r'   r(   r)   r*   r   r   r   r   r6   r    __classcell__)r8   s   @r   r-   r-   2   s=    P 
U	X	X	V	 r   r-   c                       fd}|S )a  
    Helper that returns a function suitable for use as the ``fn`` argument
    to the ``permission_required`` decorator. Internally uses
    ``get_object_or_404``, so keep in mind that this may raise ``Http404``.

    ``model`` can be a model class, manager or queryset.

    ``attr_name`` is the name of the view attribute.

    ``field_name`` is the model's field name by which the lookup is made, eg.
    "id", "slug", etc.
    c           	          |vr8t        dj                  dj                  |j                                           	 t	        fi |   iS # t
        $ r t        dj                              w xY w)Nz5Argument {0} is not available. Given arguments: [{1}]z, z Model {0} has no field named {1})r
   r7   joinkeysr   r	   )r!   	view_argsview_kwargs	attr_name
field_namer3   s      r   _getterzobjectgetter.<locals>._getter   s    K'&GNNtyy)9)9);< 
	$USz;y;Q.RSS 	&299%L 	s   A %A5r+   )r3   rJ   rK   rL   s   ``` r   objectgetterrM      s     Nr   NFc                 "      fd}|S )a  
    View decorator that checks for the given permissions before allowing the
    view to execute. Use it like this::

        from django.shortcuts import get_object_or_404
        from rules.contrib.views import permission_required
        from posts.models import Post

        def get_post_by_pk(request, post_id):
            return get_object_or_404(Post, pk=post_id)

        @permission_required('posts.change_post', fn=get_post_by_pk)
        def post_update(request, post_id):
            # ...

    ``perm`` is either a permission name as a string, or a list of permission
    names.

    ``fn`` is an optional callback that receives the same arguments as those
    passed to the decorated view and must return the object to check
    permissions against. If omitted, the decorator behaves just like Django's
    ``permission_required`` decorator, i.e. checks for model-level permissions.

    ``raise_exception`` is a boolean specifying whether to raise a
    ``django.core.exceptions.PermissionDenied`` exception if the check fails.
    You will most likely want to set this argument to ``True`` if you have
    specified a custom 403 response handler in your urlconf. If ``False``,
    the user will be redirected to the URL specified by ``login_url``.

    ``login_url`` is an optional custom URL to redirect the user to if
    permissions check fails. If omitted or empty, ``settings.LOGIN_URL`` is
    used.
    c                 :     t                fd       }|S )Nc                     t        t              rf}n}t              r | g|i |}n}| j                  }|j	                  ||      s$	r
t               t        | j                  
      S  | g|i |S r   )r   strr   r"   r#   r   _redirect_to_loginr'   )r!   argskwargsr%   r$   r"   fn	login_urlpermraise_exceptionredirect_field_name	view_funcs         r   _wrapped_viewz=permission_required.<locals>.decorator.<locals>._wrapped_view   s     $$ |24262 <<D >>%-"*,,-!3!3Y@S 
 !:4:6::r   r   )rZ   r[   rU   rV   rW   rX   rY   s   ` r   	decoratorz&permission_required.<locals>.decorator   s'    	y		; 	; 
	;: r   r+   )rW   rU   rV   rX   rY   r\   s   ````` r   r=   r=      s    R B r   c                     |xs t         j                  }|st        dj                  |            t	        |      }t        | j                         ||      S )Nzpermission_required({0}): You must either provide the "login_url" argument to the "permission_required" decorator or configure settings.LOGIN_URL)r   	LOGIN_URLr
   r7   r   r   get_full_path)r!   	view_namerV   rY   redirect_urls        r   rR   rR      sV    2 2 2L"88>y8I
 	

 \*LW224lDWXXr   )pkrb   )	functoolsr   django.confr   django.contrib.authr   r   django.contrib.auth.viewsr   django.core.exceptionsr	   r
   r   django.shortcutsr   django.utils.encodingr   django.views.genericr   r   r   r   django.views.generic.editr   LoginRequiredMixinUserPassesTestMixinr   r-   rM   r=   rR   r+   r   r   <module>rn      s       ; 7 U U . + O O 5.. 00 7f<< 7>M"9 M`B +JZ	Yr   