
    g	>                         S SK r S SKJrJrJrJrJrJrJrJ	r	J
r
  S SKJr  SSKJrJrJrJrJr  SSKJrJrJrJrJrJrJr  SSKJr  SSKJr   " S	 S
\5      r  " S S\ S9r!g)    N)	ERR_NO_SUCH_OBJECTFLAG_MOD_ADDFLAG_MOD_REPLACELdbErrorMessageMessageElement
SCOPE_BASESCOPE_ONELEVELSCOPE_SUBTREE)SDUtils   )DeleteError
FieldErrorNotFoundProtectErrorUnprotectError)DateTimeFieldDnFieldField	GUIDFieldIntegerFieldSIDFieldStringField)Query)MODELSc                   (   ^  \ rS rSrU 4S jrSrU =r$ )	ModelMeta&   c                    > [         TU ]  " XX#40 UD6n[        [        R                  " US 5      5      Ul        Xl        UR                  5       nU[        U'   U$ )Nc                 "    [        U [        5      $ N)
isinstancer   )fs    ;/usr/lib/python3/dist-packages/samba/domain/models/model.py<lambda>#ModelMeta.__new__.<locals>.<lambda>*   s    Jq%<P    )	super__new__dictinspect
getmembersfieldsmetaget_object_classr   )mclsnamebases	namespacekwargsclsobject_class	__class__s          r$   r)   ModelMeta.__new__(   sT    god%EfE',,S2PQR
++-"|
r'    )__name__
__module____qualname____firstlineno__r)   __static_attributes____classcell__)r7   s   @r$   r   r   &   s     r'   r   c                      \ rS rSr\" S5      r\" S5      r\" S5      r\	" SSSS9r
\" S5      r\" S	5      r\" S
5      r\" SS S9r\" S5      r\" S5      r\" SSSS9r\" SSSS9r\	" SSSS9r\	" SSSS9rS rS rS rS rS r\S 5       r\S 5       r \S 5       r!\S 5       r"S r#S-S jr$S.S! jr%\S" 5       r&\S S\'4S# j5       r(\S$ 5       r)\S% 5       r*\S-S& j5       r+S' r,S( r-S) r.S* r/S+ r0S,r1g)/Model1   cndistinguishedNamedndsCorePropagationDataT)hiddenreadonlyinstanceTyper1   objectCategoryobjectClassc                 "    U R                  5       $ r!   )r/   )objs    r$   r%   Model.<lambda>;   s    33G3G3Ir'   )default
objectGUID	objectSid
uSNChanged
uSNCreatedwhenChangedwhenCreatedc                    SU l         U R                  R                  5        H`  u  p#UR                  U5      nUb  UnO8[	        UR
                  5      (       a  UR                  U 5      nOUR
                  n[        XU5        Mb     g)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getcallablerO   setattr)selfr4   
field_namefieldfield_valuerO   s         r$   __init__Model.__init__C   sp     !%!2!2!4J **Z0K &%%--((-----Dg. "5r'   c                 <    SU R                   R                   SU  S3$ )z,Return object representation for this model.<z: >)r7   r:   r\   s    r$   __repr__Model.__repr__\   s"    4>>**+2dV155r'   c                 ,    [        U R                  5      $ )z4Stringify model instance to implement in each model.)strrC   re   s    r$   __str__Model.__str__`   s    477|r'   c                 <    Uc  gU R                   UR                   :H  $ )zrBasic object equality check only really checks if the dn matches.

:param other: The other object to compare with
FrE   )r\   others     r$   __eq__Model.__eq__d   s    
 =77ehh&&r'   c                 &    U R                   " S0 UD6$ )z1Automatically called by custom JSONEncoder class.r9   )as_dict)r\   r4   s     r$   __json__Model.__json__n   s    ||%f%%r'   c                 "    U R                  5       $ )zwReturn the base DN for the container of this model.

:param samdb: SamDB connection
:return: Dn to use for new objects
)get_default_basedn)samdbs    r$   get_base_dnModel.get_base_dnr   s     ''))r'   c                 $    U R                  U5      $ )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 samdb: SamDB connection
:return: Dn to use for searching
)rx   )r5   rw   s     r$   get_search_dnModel.get_search_dn{   s     u%%r'   c                      g)z'Returns the objectClass for this model.topr9   r9   r'   r$   r/   Model.get_object_class   s     r'   c                 6    U " 5       nUR                  X5        U$ )zCreate a new model instance from the Ldb Message object.

:param samdb: SamDB connection
:param message: Ldb Message object to create instance from
)_apply)r5   rw   messagerM   s       r$   _from_messageModel._from_message   s     e

5"
r'   c           
          X l         U R                  R                  5        H?  u  p4UR                  U;   d  M  [	        XUR                  XUR                     5      5        MA     g)zInternal method to apply Ldb Message to current object.

:param samdb: SamDB connection
:param message: Ldb Message object to apply
N)rW   r-   rX   r1   r[   from_db_value)r\   rw   r   attrr^   s        r$   r   Model._apply   sL      ;;,,.KDzzW$E$7$7uzz?R$ST /r'   Nc                 ^   U(       a)  U Vs/ s H  o0R                   U   R                  PM     snOSn UR                  U R                  [        US9nU R                  XS   5        gs  snf ! [
         a5  nUR                  S   [        :X  a  [        SU R                   35      ee SnAff = f)zuRefresh object from database.

:param samdb: SamDB connection
:param fields: Optional list of field names to refresh
N)scopeattrsr   zRefresh failed, object gone: )
r-   r1   searchrE   r	   r   argsr   r   r   )r\   rw   r-   r#   r   reses          r$   refreshModel.refresh   s     :@f5fQ$$f5T	,,twwj,FC 	Eq6" 6
  	vvay..!>twwiHII	s   "A(A- -
B,70B''B,Fc                     0 nU R                   R                  5        HB  u  pEUR                  (       a	  U(       d  M  [        X5      nUS/ 4;  d  M4  XcUR                  '   MD     U$ )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
N)r-   rX   rG   getattrr1   )r\   include_hiddenr4   obj_dictr   r^   values          r$   rr   Model.as_dict   sV     ;;,,.KD<<>>+r
*+0UZZ(	 / r'   c                 4   [        U5      nU R                  5       US'   [        U5      nUS:X  a  SOSnUR                  5        HE  u  pVU R                  R                  U5      nUc  [        SU S35      eXGR                  U5      -  nMG     US:  a  US-  nU$ )zoBuild LDAP search expression from kwargs.

:param kwargs: fields to use for expression using model field names
r6   r    z(&zUnknown field ''))r*   r/   lenrX   r-   rY   
ValueError
expression)r5   r4   criteria
num_fieldsr   r]   r   r^   s           r$   build_expressionModel.build_expression   s     <#&#7#7#9  ]
%?R
!)!1JJJNN:.E} ?:,a!@AA**511J	 "2 >#Jr'   c           	          Uc  U R                  U5      n UR                  UUU R                  " S0 UD6S9n[        XXb5      $ ! [         a+  nUR                  S   [
        :X  a  [        SU 35      ee SnAff = f)aK  Returns a search query for this model.

NOTE: If polymorphic is enabled then querying will return instances
of that specific model, for example querying User can return Computer
and ManagedServiceAccount instances.

By default, polymorphic querying is disabled, and querying User
will only return User instances.

:param samdb: SamDB connection
:param polymorphic: If true enables polymorphic querying (see note)
:param base_dn: Optional provide base dn for searching or use the model
:param scope: Ldb search scope (default SCOPE_SUBTREE)
:param kwargs: Search criteria as keyword args
N)r   r   r   zContainer does not exist: r9   )r{   r   r   r   r   r   r   r   )r5   rw   polymorphicbase_dnr   r4   resultr   s           r$   queryModel.query   s    $ ?''.G	\\'(--0-A-A-KF-K " MF S55  	vvay..!;G9EFF	s   !A 
A8&A33A8c                 $   UR                  S5      nU(       a)   UR                  U[        S9nU R                  XS   5      $ U R                  " U40 UD6R                  5       $ ! [         a"  nUR                  S   [
        :X  a   SnAge SnAff = f)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 samdb: SamDB connection
:param kwargs: Search criteria as keyword args
:returns: Model instance or None if not found
:raises: MultipleObjects returned if there are more than one results
rE   r   r   N)rY   r   r	   r   r   r   r   r   )r5   rw   r4   rE   r   r   s         r$   rY   	Model.get  s     ZZll2Zl8 $$UF3399U-f-1133  66!9 22	s   A# #
B-B
	B

Bc                 8    U " S0 UD6nUR                  U5        U$ )zCreate object constructs object and calls save straight after.

:param samdb: SamDB connection
:param kwargs: Fields to populate object from
:returns: object
r9   )save)r5   rw   r4   rM   s       r$   createModel.create   s     mFm
r'   c                     U R                   " U40 UD6nUc4  [        U5      nUb  UR                  U5        U R                  " U40 UD6S4$ US4$ )zRetrieve object and if it doesn't exist create a new instance.

:param samdb: SamDB connection
:param defaults: Attributes only used for create but not search
:param kwargs: Attributes used for searching existing object
:returns: (object, bool created)
TF)rY   r*   updater   )r5   rw   defaultsr4   rM   r   s         r$   get_or_createModel.get_or_create,  sZ     gge&v&;LE#X&::e-u-t33:r'   c                 H    [         R                  XR                  [        SS9$ )z/Returns a Query of the current models children.T)r   r   r   )rA   r   rE   r
   )r\   rw   s     r$   childrenModel.children>  s%    {{77.d  L 	Lr'   c                    U R                   Gc  U R                  U5      nUR                  SU R                  =(       d    U R                   35        X l         [        U R                   S9nU R                  R                  5        Hj  u  pEUS:w  d  M  UR                  (       a  M   [        X5      n UR                  X[        5      nUc  MG  [        U5      (       d  MY  UR                  U5        Ml     UR                  U5        UR!                  U["        S9n	U R%                  XS   5        gU R'                  XR(                  5      n
[        U R                   S9nU R                  R                  5        H  u  pEUS:w  d  M  UR                  (       a  M   [        X5      n[        X5      nXk:w  d  M=   UR                  X[*        5      nUS/ 4;   a  [-        / [*        UR                  5      nUR                  U5        M     [        U5      (       a#  UR/                  U5        U R1                  U5        gg! [         a  n[        XS9eSnAff = f! [         a  n[        XS9eSnAff = f)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 samdb: SamDB connection
NzCN=rm   rE   )r^   r   r   )rE   rx   	add_childrC   r1   r   r-   rX   rH   r   to_db_valuer   r   r   r   addr   r	   r   r   rW   r   r   modifyr   )r\   rw   rE   r   r   r^   r   db_valuer   r   existing_obj	old_values               r$   r   
Model.saveC  s   ( 77?!!%(BLL3tww3$))456G)G#{{0024<#D/E9#(#4#4U<#P
  +HH-  3 IIg ,,r,4CKK1v&  --e]]CL )G#{{0024<#D/E ' ;I)=','8'89I(KH $bz1'5b6F6;jj(BH  H-#  3( 7||W% U#	 Q & 9(889:  * =",Q"<<=s0   0H42I4
I>	II
I'	I""I'c                     U R                   c  [        S5      e UR                  U R                   5        g! [         a  n[        SU 35      eSnAff = f)z{Delete item from Ldb database.

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

:param samdb: SamDB connection
Nz,Cannot delete object that doesn't have a dn.zDelete failed: )rE   r   deleter   )r\   rw   r   s      r$   r   Model.delete  sP     77?LMM	5LL! 	5s344	5s   6 
A AAc                     [        U5      n UR                  U R                  S5        g! [         a  n[	        SU 35      eSnAff = f)zIProtect object from accidental deletion.

:param samdb: SamDB connection
(D;;DTSD;;;WD)zFailed to protect object: N)r   dacl_add_acerE   r   r   r\   rw   utilsr   s       r$   protectModel.protect  sM    
 	Atww(89 	A!;A3?@@	A   * 
AAAc                     [        U5      n UR                  U R                  S5        g! [         a  n[	        SU 35      eSnAff = f)zKUnprotect object from accidental deletion.

:param samdb: SamDB connection
r   zFailed to unprotect object: N)r   dacl_delete_acesrE   r   r   r   s       r$   	unprotectModel.unprotect  sM    
 	E""477,<= 	E #?s!CDD	Er   )rW   rE   r!   )F)2r:   r;   r<   r=   r   rC   r   distinguished_namerE   r   ds_core_propagation_datar   instance_typer1   object_categoryr6   r   object_guidr   
object_sidusn_changedusn_createdwhen_changedwhen_createdr`   rf   rj   ro   rs   staticmethodrx   classmethodr{   r/   r   r   r   rr   r   r   r   rY   r   r   r   r   r   r   r   r>   r9   r'   r$   rA   rA   1   s   	T	B !45	B,-D484 I 0MvD./O}'IKLL)K+&J|D4HK|D4HK tdKL tdKL/26'& * * 	& 	&    U#$   2 &+T 6 6@ 4 4< 	 	  "L
K$Z5
A
Er'   rA   )	metaclass)"r+   ldbr   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   registryr   typer   rA   r9   r'   r$   <module>r      sY   . 0 0 0 #) ), , ,   DEi DEr'   