
    Id6<                         d dl Z d dlmZmZ d dlmZmZmZmZm	Z	m
Z
mZmZmZ d dlmZ ddlmZmZmZmZmZ ddlmZmZmZmZmZmZ i Z G d d	e      Z G d
 de      Zy)    N)ABCMetaabstractmethod)	ERR_NO_SUCH_OBJECTFLAG_MOD_ADDFLAG_MOD_REPLACELdbErrorMessageMessageElement
SCOPE_BASESCOPE_SUBTREEbinary_encode)SDUtils   )DeleteErrorDoesNotExistMultipleObjectsReturnedProtectErrorUnprotectError)DateTimeFieldDnFieldField	GUIDFieldIntegerFieldStringFieldc                        e Zd Z fdZ xZS )	ModelMetac                     t        |   | |||fi |}|j                  dk7  r5t        t	        j
                  |d             |_        | |_        |t        |<   |S )NModelc                 "    t        | t              S N)
isinstancer   )fs    B/usr/lib/python3/dist-packages/samba/netcmd/domain/models/model.py<lambda>z#ModelMeta.__new__.<locals>.<lambda>.   s    
1e@T     )	super__new____name__dictinspect
getmembersfieldsmetaMODELS)mclsnamebases	namespacekwargscls	__class__s         r#   r'   zModelMeta.__new__*   sW    godD%EfE<<7"g006TUVCJCHF4L
r%   )r(   
__module____qualname__r'   __classcell__)r5   s   @r#   r   r   (   s     r%   r   c                      e Zd Z ed      Z ed      Z ed      Z edd      Z	 e
d      Z ed      Z ed	      Z ed
d       Z ed      Z e
dd      Z e
dd      Z edd      Z edd      Zd Zd Zd Zd Zd Zeed               Zed        Zeed               Zed        Z d Z!d(dZ"d)dZ#ed        Z$ed         Z%ed!        Z&ed"        Z'ed(d#       Z(d$ Z)d% Z*d& Z+d' Z,y)*r   cndistinguishedNamedndsCorePropagationDataT)hiddeninstanceTyper0   objectCategoryobjectClassc                 "    | j                         S r    )get_object_class)objs    r#   r$   zModel.<lambda>?   s    33G3G3I r%   )default
objectGUID
uSNChanged
uSNCreatedwhenChangedwhenCreatedc                     d| _         | j                  j                         D ]O  \  }}||v r||   }n3t        |j                        r|j	                  |       }n|j                  }t        | ||       Q y)zCreate a new model instance and optionally populate fields.

        Does not save the object to the database, call .save() for that.

        :param kwargs: Optional input fields to populate object with
        N)_messager,   itemscallablerE   setattr)selfr3   
field_namefieldrE   s        r#   __init__zModel.__init__F   sm     !%!2!2!4 	/JV# ,%--(-----D*g.	/r%   c                 <    d| j                   j                   d|  dS )z,Return object representation for this model.<z: >)r5   r(   rP   s    r#   __repr__zModel.__repr__[   s"    4>>**+2dV155r%   c                 ,    t        | j                        S )z4Stringify model instance to implement in each model.)strr:   rW   s    r#   __str__zModel.__str___   s    477|r%   c                 :    |y| j                   |j                   k(  S )zBasic object equality check only really checks if the dn matches.

        :param other: The other object to compare with
        Fr<   )rP   others     r#   __eq__zModel.__eq__c   s    
 =77ehh&&r%   c                 F    | j                   t        | j                         S y)zAutomatically called by custom JSONEncoder class.

        When turning an object into json any fields of type RelatedField
        will also end up calling this method.
        N)r<   rZ   rW   s    r#   __json__zModel.__json__m   s!     77tww< r%   c                      y)zReturn the base DN for the container of this model.

        :param ldb: Ldb connection
        :return: Dn to use for new objects
        N )ldbs    r#   get_base_dnzModel.get_base_dnv   s     	r%   c                 $    | j                  |      S )zReturn the DN used for querying.

        By default, this just calls get_base_dn, but it is possible to
        return a different Dn for querying.

        :param ldb: Ldb connection
        :return: Dn to use for searching
        )re   )r4   rd   s     r#   get_search_dnzModel.get_search_dn   s     s##r%   c                       y)z'Returns the objectClass for this model.Nrc   rc   r%   r#   rC   zModel.get_object_class   s     	r%   c                 8     |        }|j                  ||       |S )zCreate a new model instance from the Ldb Message object.

        :param ldb: Ldb connection
        :param message: Ldb Message object to create instance from
        )_apply)r4   rd   messagerD   s       r#   from_messagezModel.from_message   s     e

3 
r%   c           
          || _         | j                  j                         D ]>  \  }}|j                  |v st	        | ||j                  |||j                                  @ y)zInternal method to apply Ldb Message to current object.

        :param ldb: Ldb connection
        :param message: Ldb Message object to apply
        N)rL   r,   rM   r0   rO   from_db_value)rP   rd   rk   attrrR   s        r#   rj   zModel._apply   s[      ;;,,. 	SKD%zzW$dE$7$7WUZZ=P$QR	Sr%   Nc                 T   |r'|D cg c]  }| j                   |   j                   c}nd}	 |j                  | j                  t        |      }| j                  ||d          yc c}w # t
        $ r4}|j                  d   t        k(  rt        d| j                          d}~ww xY w)zRefresh object from database.

        :param ldb: Ldb connection
        :param fields: Optional list of field names to refresh
        N)scopeattrsr   zRefresh failed, object gone: )
r,   r0   searchr<   r   r   argsr   r   rj   )rP   rd   r,   r"   rr   reses          r#   refreshzModel.refresh   s     :@f5Q$$5T	**TWWJe*DC 	CQ  6
  	vvay.."%B477)#LMM	s    A%"A* *	B'3/B""B'c                     i }| j                   j                         D ]2  \  }}|j                  r|st        | |      }|$|||j                  <   4 |S )zReturns a dict representation of the model.

        :param include_hidden: Include fields with hidden=True when set
        :returns: dict representation of model using Ldb field names as keys
        )r,   rM   r>   getattrr0   )rP   include_hiddenobj_dictro   rR   values         r#   as_dictzModel.as_dict   sY     ;;,,. 	1KD%<<>d+$+0HUZZ(		1 r%   c                 D   t        |      }| j                         |d<   t        |      }|dk(  rdnd}|j                         D ]P  \  }}| j                  j                  |      }|st        d| d      |d|j                   dt        |       d	z  }R |dkD  r|d	z  }|S )
zyBuild LDAP search expression from kwargs.

        :kwargs: fields to use for expression using model field names
        object_classr    z(&zUnknown field ''(=))	r)   rC   lenrM   r,   get
ValueErrorr0   r   )r4   r3   criteria
num_fields
expressionrQ   r|   rR   s           r#   build_expressionzModel.build_expression   s     <#&#7#7#9  ]
%?R
!)!1 	CJJJNN:.E ?:,a!@AAAejj\=+?*@BBJ		C >#Jr%   c           	   +   "  K   | j                  |      }	 |j                  |t         | j                  di |      }|D ]  }| j                  ||        y# t        $ r*}|j
                  d   t        k(  rt        d|        d}~ww xY ww)zReturns a search query for this model.

        :param ldb: Ldb connection
        :param kwargs: Search criteria as keyword args
        rq   r   r   Container does not exist: Nrc   )	rg   rs   r   r   r   rt   r   r   rl   )r4   rd   r3   base_dnresultrv   rk   s          r#   queryzModel.query   s      ##C(	ZZ&3+?3+?+?+I&+I   KF  	1G""300	1  	vvay.."%?y#IJJ	s'   B(A B	B"%BBBc           	         |j                  d      }|r	 |j                  |t              }n:| j                  |      }	 |j                  |t         | j                  d
i |      }t        |      }|dkD  rt        d| d	      |dk(  r| j                  ||d         S y# t        $ r!}|j                  d   t
        k(  rY d}~y d}~ww xY w# t        $ r*}|j                  d   t
        k(  rt        d|        d}~ww xY w)a  Get one object, must always return one item.

        Either find object by dn=, or any combination of attributes via kwargs.
        If there are more than one result, MultipleObjectsReturned is raised.

        :param ldb: Ldb connection
        :param kwargs: Search criteria as keyword args
        :returns: User object or None if not found
        :raises: MultipleObjects returned if there are more than one results
        r<   rq   r   Nr   r   r   z#More than one object returned (got z).rc   )r   rs   r   r   rt   r   rg   r   r   r   r   r   rl   )r4   rd   r3   r<   ru   rv   r   counts           r#   r   z	Model.get   s     ZZjj:j6 '',Gjj'4,@C,@,@,J6,J ! L C19)5eWB?A AaZ##CQ00 1  66!9 22	  66!9 22&)CG9'MNNs4   B! (C !	C*CCC	D%C<<Dc                 8     | di |}|j                  |       |S )zCreate object constructs object and calls save straight after.

        :param ldb: Ldb connection
        :param kwargs: Fields to populate object from
        :returns: object
        rc   )save)r4   rd   r3   rD   s       r#   createzModel.create/  s     mFm
r%   c                      | j                   |fi |}|3t        |      }||j                  |        | j                  |fi |dfS |dfS )a!  Retrieve object and if it doesn't exist create a new instance.

        :param ldb: Ldb connection
        :param defaults: Attributes only used for create but not search
        :param kwargs: Attributes used for searching existing object
        :returns: (object, bool created)
        TF)r   r)   updater   )r4   rd   defaultsr3   rD   rr   s         r#   get_or_createzModel.get_or_create;  s^     cggc$V$;LE#X&3::c+U+T11:r%   c                    | j                   | j                  |      }|j                  d| j                  xs | j                          || _         t        | j                         }| j                  j                         D ]M  \  }}|dk7  st        | |      }|j                  |t              }|1t        |      s=|j                  |       O |j                  |       |j                  |t              }| j                  ||d          y| j!                  || j"                        }	t        | j                         }| j                  j                         D ]q  \  }}|dk7  st        | |      }t        |	|      }
||
k7  s*|j                  |t$              }|dg fv rt'        g t$        |j                        }|j                  |       s t        |      r#|j)                  |       | j+                  |       yy)a  Save model to Ldb database.

        The save operation will save all fields excluding fields that
        return None when calling their `to_db_value` methods.

        The `to_db_value` method can either return a ldb Message object,
        or None if the field is to be excluded.

        For updates, the existing object is fetched and only fields
        that are changed are included in the update ldb Message.

        Also for updates, any fields that currently have a value,
        but are to be set to None will be seen as a delete operation.

        After the save operation the object is refreshed from the server,
        as often the server will populate some fields.

        :param ldb: Ldb connection
        NzCN=r]   r<   r   r   )r<   re   	add_childr:   r0   r	   r,   rM   ry   to_db_valuer   r   addrs   r   rj   rl   rL   r   r
   modifyrw   )rP   rd   r<   rk   ro   rR   r|   db_valueru   existing_obj	old_values              r#   r   z
Model.saveM  s   ( 77?!!#&BLL3tww3$))456DG)G#{{002 .e4<#D$/E$00EH  +HH-. GGG **Rz*2CKKSV$  ,,S$--@L )G#{{002 .e4<#D$/E 'd ;I	)#(#4#4U<L#M $bz1'5b6F6;jj(BH  H-.  7|

7# S!	 r%   c                     | j                   t        d      	 |j                  | j                          y# t        $ r}t        d|       d}~ww xY w)zDelete item from Ldb database.

        If self.dn is None then the object has not yet been saved.

        :param ldb: Ldb connection
        Nz,Cannot delete object that doesn't have a dn.zDelete failed: )r<   r   deleter   )rP   rd   rv   s      r#   r   zModel.delete  sP     77?LMM	5JJtww 	5s344	5s   5 	AAAc                     t        |      }	 |j                  | j                  d       y# t        $ r}t	        d|       d}~ww xY w)zUProtect object from accidental deletion.

        :param ldb: Ldb connection
        (D;;DTSD;;;WD)zFailed to protect object: N)r   dacl_add_acer<   r   r   rP   rd   utilsrv   s       r#   protectzModel.protect  sM    
 	Atww(89 	A!;A3?@@	A   * 	AAAc                     t        |      }	 |j                  | j                  d       y# t        $ r}t	        d|       d}~ww xY w)zWUnprotect object from accidental deletion.

        :param ldb: Ldb connection
        r   zFailed to unprotect object: N)r   dacl_delete_acesr<   r   r   r   s       r#   	unprotectzModel.unprotect  sM    
 	E""477,<= 	E #?s!CDD	Er   r    )F)-r(   r6   r7   r   r:   r   distinguished_namer<   r   ds_core_propagation_datar   instance_typer0   object_categoryr   r   object_guidusn_changedusn_createdwhen_changedwhen_createdrS   rX   r[   r_   ra   staticmethodr   re   classmethodrg   rC   rl   rj   rw   r}   r   r   r   r   r   r   r   r   r   rc   r%   r#   r   r   5   s   	T	B !45	B,-D48 : 0MvD./O}'IKLL)K|D9K|D9K t<L t<L/*6'     	$ 	$     S!$   2 1 10 -1 -1^ 	 	  "D"L5
A
Er%   r   )	metaclass) r*   abcr   r   rd   r   r   r   r   r	   r
   r   r   r   samba.sd_utilsr   
exceptionsr   r   r   r   r   r,   r   r   r   r   r   r   r.   r   r   rc   r%   r#   <module>r      sY   .  'F F F "! ! 
 

 
CEi CEr%   