base.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 django.db.backends import (BaseDatabaseFeatures, BaseDatabaseOperations,
  35. BaseDatabaseWrapper)
  36. from django.db.backends.creation import BaseDatabaseCreation
  37. class DatabaseCreation(BaseDatabaseCreation):
  38. def create_test_db(self, verbosity=1, autoclobber=False):
  39. """
  40. Creates a test database, prompting the user for confirmation if the
  41. database already exists. Returns the name of the test database created.
  42. """
  43. pass
  44. def destroy_test_db(self, old_database_name, verbosity=1):
  45. """
  46. Destroy a test database, prompting the user for confirmation if the
  47. database already exists. Returns the name of the test database created.
  48. """
  49. pass
  50. class DatabaseCursor(object):
  51. def __init__(self, ldap_connection):
  52. self.connection = ldap_connection
  53. class DatabaseFeatures(BaseDatabaseFeatures):
  54. def __init__(self, connection):
  55. self.connection = connection
  56. self.supports_transactions = False
  57. class DatabaseOperations(BaseDatabaseOperations):
  58. compiler_module = "ldapdb.backends.ldap.compiler"
  59. def quote_name(self, name):
  60. return name
  61. class DatabaseWrapper(BaseDatabaseWrapper):
  62. def __init__(self, *args, **kwargs):
  63. super(DatabaseWrapper, self).__init__(*args, **kwargs)
  64. self.charset = "utf-8"
  65. self.creation = DatabaseCreation(self)
  66. self.features = DatabaseFeatures(self)
  67. if django.VERSION > (1, 4):
  68. self.ops = DatabaseOperations(self)
  69. else:
  70. self.ops = DatabaseOperations()
  71. self.settings_dict['SUPPORTS_TRANSACTIONS'] = False
  72. def close(self):
  73. if hasattr(self, 'validate_thread_sharing'):
  74. # django >= 1.4
  75. self.validate_thread_sharing()
  76. if self.connection is not None:
  77. self.connection.unbind_s()
  78. self.connection = None
  79. def ensure_connection(self):
  80. if self.connection is None:
  81. self.connection = ldap.initialize(self.settings_dict['NAME'])
  82. options = self.settings_dict.get('CONNECTION_OPTIONS', {})
  83. for opt, value in options.items():
  84. self.connection.set_option(opt, value)
  85. if self.settings_dict.get('TLS', False):
  86. self.connection.start_tls_s()
  87. self.connection.simple_bind_s(
  88. self.settings_dict['USER'],
  89. self.settings_dict['PASSWORD'])
  90. def _commit(self):
  91. pass
  92. def _cursor(self):
  93. self.ensure_connection()
  94. return DatabaseCursor(self.connection)
  95. def _rollback(self):
  96. pass
  97. def add_s(self, dn, modlist):
  98. cursor = self._cursor()
  99. return cursor.connection.add_s(dn.encode(self.charset), modlist)
  100. def delete_s(self, dn):
  101. cursor = self._cursor()
  102. return cursor.connection.delete_s(dn.encode(self.charset))
  103. def modify_s(self, dn, modlist):
  104. cursor = self._cursor()
  105. return cursor.connection.modify_s(dn.encode(self.charset), modlist)
  106. def rename_s(self, dn, newrdn):
  107. cursor = self._cursor()
  108. return cursor.connection.rename_s(dn.encode(self.charset),
  109. newrdn.encode(self.charset))
  110. def search_s(self, base, scope, filterstr='(objectClass=*)',
  111. attrlist=None):
  112. cursor = self._cursor()
  113. results = cursor.connection.search_s(base, scope,
  114. filterstr.encode(self.charset),
  115. attrlist)
  116. output = []
  117. for dn, attrs in results:
  118. output.append((dn.decode(self.charset), attrs))
  119. return output