base.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. # -*- coding: utf-8 -*-
  2. #
  3. # django-ldapdb
  4. # Copyright (c) 2009-2011, Bolloré telecom
  5. # Copyright (c) 2013, Jeremy Lainé
  6. # All rights reserved.
  7. #
  8. # See AUTHORS file for a full list of contributors.
  9. #
  10. # Redistribution and use in source and binary forms, with or without
  11. # modification, are permitted provided that the following conditions are met:
  12. #
  13. # 1. Redistributions of source code must retain the above copyright notice,
  14. # this list of conditions and the following disclaimer.
  15. #
  16. # 2. Redistributions in binary form must reproduce the above copyright
  17. # notice, this list of conditions and the following disclaimer in the
  18. # documentation and/or other materials provided with the distribution.
  19. #
  20. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  24. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30. # POSSIBILITY OF SUCH DAMAGE.
  31. #
  32. import ldap
  33. import django
  34. from pprint import pprint
  35. from django.db.backends import (BaseDatabaseFeatures, BaseDatabaseOperations,
  36. BaseDatabaseWrapper)
  37. from django.db.backends.creation import BaseDatabaseCreation
  38. class DatabaseCreation(BaseDatabaseCreation):
  39. def create_test_db(self, verbosity=1, autoclobber=False):
  40. """
  41. Creates a test database, prompting the user for confirmation if the
  42. database already exists. Returns the name of the test database created.
  43. """
  44. pass
  45. def destroy_test_db(self, old_database_name, verbosity=1):
  46. """
  47. Destroy a test database, prompting the user for confirmation if the
  48. database already exists. Returns the name of the test database created.
  49. """
  50. pass
  51. class DatabaseCursor(object):
  52. def __init__(self, ldap_connection):
  53. self.connection = ldap_connection
  54. class DatabaseFeatures(BaseDatabaseFeatures):
  55. def __init__(self, connection):
  56. self.connection = connection
  57. self.supports_transactions = False
  58. class DatabaseOperations(BaseDatabaseOperations):
  59. compiler_module = "ldapdb.backends.ldap.compiler"
  60. def quote_name(self, name):
  61. return name
  62. class DatabaseWrapper(BaseDatabaseWrapper):
  63. def __init__(self, *args, **kwargs):
  64. super(DatabaseWrapper, self).__init__(*args, **kwargs)
  65. self.charset = "utf-8"
  66. self.creation = DatabaseCreation(self)
  67. self.features = DatabaseFeatures(self)
  68. if django.VERSION > (1, 4):
  69. self.ops = DatabaseOperations(self)
  70. else:
  71. self.ops = DatabaseOperations()
  72. self.settings_dict['SUPPORTS_TRANSACTIONS'] = False
  73. def close(self):
  74. if hasattr(self, 'validate_thread_sharing'):
  75. # django >= 1.4
  76. self.validate_thread_sharing()
  77. if self.connection is not None:
  78. self.connection.unbind_s()
  79. self.connection = None
  80. def ensure_connection(self):
  81. if self.connection is None:
  82. global_options = self.settings_dict.get('GLOBAL_OPTIONS', {})
  83. for opt, value in global_options.items():
  84. ldap.set_option(opt, value)
  85. self.connection = ldap.initialize(self.settings_dict['NAME'])
  86. connection_options = self.settings_dict.get('CONNECTION_OPTIONS', {})
  87. for opt, value in connection_options.items():
  88. self.connection.set_option(opt, value)
  89. if self.settings_dict.get('TLS', False):
  90. self.connection.start_tls_s()
  91. self.connection.simple_bind_s(
  92. self.settings_dict['USER'],
  93. self.settings_dict['PASSWORD'])
  94. def _commit(self):
  95. pass
  96. def _cursor(self):
  97. self.ensure_connection()
  98. return DatabaseCursor(self.connection)
  99. def _rollback(self):
  100. pass
  101. def add_s(self, dn, modlist):
  102. cursor = self._cursor()
  103. return cursor.connection.add_s(dn.encode(self.charset), modlist)
  104. def delete_s(self, dn):
  105. cursor = self._cursor()
  106. return cursor.connection.delete_s(dn.encode(self.charset))
  107. def modify_s(self, dn, modlist):
  108. cursor = self._cursor()
  109. return cursor.connection.modify_s(dn.encode(self.charset), modlist)
  110. def rename_s(self, dn, newrdn):
  111. cursor = self._cursor()
  112. return cursor.connection.rename_s(dn.encode(self.charset),
  113. newrdn.encode(self.charset))
  114. def search_s(self, base, scope, filterstr='(objectClass=*)',
  115. attrlist=None):
  116. cursor = self._cursor()
  117. results = cursor.connection.search_s(base, scope,
  118. filterstr.encode(self.charset),
  119. attrlist)
  120. output = []
  121. for dn, attrs in results:
  122. output.append((dn.decode(self.charset), attrs))
  123. return output