utils.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import os
  4. import hashlib
  5. import binascii
  6. import base64
  7. import html2text
  8. from datetime import date, timedelta
  9. from django.core.mail import EmailMultiAlternatives
  10. from django.core.files.storage import FileSystemStorage
  11. from django.conf import settings
  12. from django.template.loader import get_template
  13. from django.template import Context, TemplateDoesNotExist
  14. from django.contrib.sites.models import Site
  15. # Stockage des fichiers privés (comme les factures par exemple)
  16. private_files_storage = FileSystemStorage(location=settings.PRIVATE_FILES_ROOT)
  17. def str_or_none(obj):
  18. return str(obj) if obj else None
  19. def ldap_hash(password):
  20. """Hash a password for use with LDAP. If the password is already hashed,
  21. do nothing."""
  22. if password and not password.startswith('{SSHA}'):
  23. salt = binascii.hexlify(os.urandom(8))
  24. digest = hashlib.sha1(password.encode() + salt).digest()
  25. return '{SSHA}' + base64.b64encode(digest + salt).decode()
  26. else:
  27. return password
  28. def send_templated_email(to, subject_template, body_template, context={}, attachements=[]):
  29. """
  30. Send a multialternative email based on html and optional txt template.
  31. """
  32. # Ensure arrays when needed
  33. if not isinstance(to, list):
  34. to = [to]
  35. if not isinstance(attachements, list):
  36. attachements = [attachements]
  37. # Add domain in context
  38. context['domain'] = Site.objects.get_current()
  39. # If .html/.txt is specified in template name remove it
  40. body_template = body_template.split('.')[0]
  41. subject_template = subject_template.split('.')[0]
  42. # Get html template for body, fail if not exists
  43. template_html = get_template('%s.html' % (body_template,))
  44. html_content = template_html.render(Context(context))
  45. # Get txt template for subject, fail if not exists
  46. subject_template = get_template('%s.txt' % (subject_template,))
  47. subject = subject_template.render(Context(context))
  48. # Get rid of newlines
  49. subject = subject.strip().replace('\n', '')
  50. # Try to get a txt version, convert from html to markdown style
  51. # (using html2text) if fail
  52. try:
  53. template_txt = get_template('%s.txt' % (body_template,))
  54. text_content = template_txt.render_to_string(Context(context))
  55. except TemplateDoesNotExist:
  56. text_content = html2text.html2text(html_content)
  57. # make multipart email default : text, alternative : html
  58. msg = EmailMultiAlternatives(subject=subject, body=text_content, to=to)
  59. msg.attach_alternative(html_content, "text/html")
  60. # Set attachements
  61. for attachement in attachements:
  62. msg.attach_file(attachement)
  63. # Send email
  64. msg.send()
  65. def delete_selected(modeladmin, request, queryset):
  66. """Overrides QuerySet's delete() function to remove objects one by one
  67. so, that they are deleted in the LDAP (Redmine issue #195)."""
  68. for obj in queryset:
  69. obj.delete()
  70. delete_selected.short_description = "Supprimer tous les objets sélectionnés."
  71. # Time-related functions
  72. def in_one_year():
  73. return date.today() + timedelta(365)
  74. def start_of_month():
  75. return date(date.today().year, date.today().month, 1)
  76. def end_of_month():
  77. return date(date.today().year, date.today().month + 1, 1) - timedelta(days=1)
  78. if __name__ == '__main__':
  79. print(ldap_hash('coin'))