8
0
Fork 0
mirror of https://gitlab.federez.net/re2o/re2o synced 2024-07-04 05:04:06 +00:00

Merge branch 'handle_email_errors' into 'dev'

Handle email-related errors

See merge request re2o/re2o!503
This commit is contained in:
chirac 2020-04-19 23:03:52 +02:00
commit c2f3c17ab6
21 changed files with 372 additions and 264 deletions

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2019-01-07 01:37+0100\n" "PO-Revision-Date: 2019-01-07 01:37+0100\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-03-31 16:09+0002\n" "PO-Revision-Date: 2018-03-31 16:09+0002\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language: fr_FR\n" "Language: fr_FR\n"
@ -37,7 +37,7 @@ msgstr "Vous n'avez pas le droit de voir cette application."
msgid "Select a payment method" msgid "Select a payment method"
msgstr "Sélectionnez un moyen de paiement" msgstr "Sélectionnez un moyen de paiement"
#: cotisations/forms.py:73 cotisations/models.py:682 #: cotisations/forms.py:73 cotisations/models.py:687
msgid "Member" msgid "Member"
msgstr "Adhérent" msgstr "Adhérent"
@ -154,7 +154,7 @@ msgstr "Peut voir un objet facture"
msgid "Can edit all the previous invoices" msgid "Can edit all the previous invoices"
msgstr "Peut modifier toutes les factures précédentes" msgstr "Peut modifier toutes les factures précédentes"
#: cotisations/models.py:145 cotisations/models.py:456 cotisations/views.py:376 #: cotisations/models.py:145 cotisations/models.py:461 cotisations/views.py:376
#: cotisations/views.py:571 #: cotisations/views.py:571
msgid "invoice" msgid "invoice"
msgstr "facture" msgstr "facture"
@ -217,115 +217,115 @@ msgstr "Il n'y a pas de moyens de paiement que vous puissiez utiliser."
msgid "There are no articles that you can buy." msgid "There are no articles that you can buy."
msgstr "Il n'y a pas d'articles que vous puissiez acheter." msgstr "Il n'y a pas d'articles que vous puissiez acheter."
#: cotisations/models.py:372 #: cotisations/models.py:377
msgid "Can view a custom invoice object" msgid "Can view a custom invoice object"
msgstr "Peut voir un objet facture personnalisée" msgstr "Peut voir un objet facture personnalisée"
#: cotisations/models.py:374 #: cotisations/models.py:379
msgid "recipient" msgid "recipient"
msgstr "destinataire" msgstr "destinataire"
#: cotisations/models.py:375 #: cotisations/models.py:380
msgid "payment type" msgid "payment type"
msgstr "type de paiement" msgstr "type de paiement"
#: cotisations/models.py:376 #: cotisations/models.py:381
msgid "address" msgid "address"
msgstr "adresse" msgstr "adresse"
#: cotisations/models.py:377 #: cotisations/models.py:382
msgid "paid" msgid "paid"
msgstr "payé" msgstr "payé"
#: cotisations/models.py:378 #: cotisations/models.py:383
msgid "remark" msgid "remark"
msgstr "remarque" msgstr "remarque"
#: cotisations/models.py:383 #: cotisations/models.py:388
msgid "Can view a cost estimate object" msgid "Can view a cost estimate object"
msgstr "Peut voir un objet devis" msgstr "Peut voir un objet devis"
#: cotisations/models.py:386 #: cotisations/models.py:391
msgid "period of validity" msgid "period of validity"
msgstr "période de validité" msgstr "période de validité"
#: cotisations/models.py:421 #: cotisations/models.py:426
msgid "You don't have the right to delete a cost estimate." msgid "You don't have the right to delete a cost estimate."
msgstr "Vous n'avez pas le droit de supprimer un devis." msgstr "Vous n'avez pas le droit de supprimer un devis."
#: cotisations/models.py:427 #: cotisations/models.py:432
msgid "The cost estimate has an invoice and can't be deleted." msgid "The cost estimate has an invoice and can't be deleted."
msgstr "Le devis a une facture et ne peut pas être supprimé." msgstr "Le devis a une facture et ne peut pas être supprimé."
#: cotisations/models.py:449 cotisations/models.py:688 #: cotisations/models.py:454 cotisations/models.py:693
#: cotisations/models.py:946 #: cotisations/models.py:951
msgid "Connection" msgid "Connection"
msgstr "Connexion" msgstr "Connexion"
#: cotisations/models.py:450 cotisations/models.py:689 #: cotisations/models.py:455 cotisations/models.py:694
#: cotisations/models.py:947 #: cotisations/models.py:952
msgid "Membership" msgid "Membership"
msgstr "Adhésion" msgstr "Adhésion"
#: cotisations/models.py:451 cotisations/models.py:684 #: cotisations/models.py:456 cotisations/models.py:689
#: cotisations/models.py:690 cotisations/models.py:948 #: cotisations/models.py:695 cotisations/models.py:953
msgid "Both of them" msgid "Both of them"
msgstr "Les deux" msgstr "Les deux"
#: cotisations/models.py:460 #: cotisations/models.py:465
msgid "amount" msgid "amount"
msgstr "montant" msgstr "montant"
#: cotisations/models.py:463 #: cotisations/models.py:468
msgid "article" msgid "article"
msgstr "article" msgstr "article"
#: cotisations/models.py:466 #: cotisations/models.py:471
msgid "price" msgid "price"
msgstr "prix" msgstr "prix"
#: cotisations/models.py:469 cotisations/models.py:702 #: cotisations/models.py:474 cotisations/models.py:707
msgid "duration (in months)" msgid "duration (in months)"
msgstr "durée (en mois)" msgstr "durée (en mois)"
#: cotisations/models.py:475 cotisations/models.py:708 #: cotisations/models.py:480 cotisations/models.py:713
msgid "duration (in days, will be added to duration in months)" msgid "duration (in days, will be added to duration in months)"
msgstr "durée (en jours, sera ajoutée à la durée en mois)" msgstr "durée (en jours, sera ajoutée à la durée en mois)"
#: cotisations/models.py:483 cotisations/models.py:722 #: cotisations/models.py:488 cotisations/models.py:727
#: cotisations/models.py:959 #: cotisations/models.py:964
msgid "subscription type" msgid "subscription type"
msgstr "type de cotisation" msgstr "type de cotisation"
#: cotisations/models.py:488 #: cotisations/models.py:493
msgid "Can view a purchase object" msgid "Can view a purchase object"
msgstr "Peut voir un objet achat" msgstr "Peut voir un objet achat"
#: cotisations/models.py:489 #: cotisations/models.py:494
msgid "Can edit all the previous purchases" msgid "Can edit all the previous purchases"
msgstr "Peut modifier tous les achats précédents" msgstr "Peut modifier tous les achats précédents"
#: cotisations/models.py:491 cotisations/models.py:953 #: cotisations/models.py:496 cotisations/models.py:958
msgid "purchase" msgid "purchase"
msgstr "achat" msgstr "achat"
#: cotisations/models.py:492 #: cotisations/models.py:497
msgid "purchases" msgid "purchases"
msgstr "achats" msgstr "achats"
#: cotisations/models.py:545 cotisations/models.py:742 #: cotisations/models.py:550 cotisations/models.py:747
msgid "Duration must be specified for a subscription." msgid "Duration must be specified for a subscription."
msgstr "La durée doit être renseignée pour une cotisation." msgstr "La durée doit être renseignée pour une cotisation."
#: cotisations/models.py:556 #: cotisations/models.py:561
msgid "You don't have the right to edit a purchase." msgid "You don't have the right to edit a purchase."
msgstr "Vous n'avez pas le droit de modifier un achat." msgstr "Vous n'avez pas le droit de modifier un achat."
#: cotisations/models.py:562 #: cotisations/models.py:567
msgid "You don't have the right to edit this user's purchases." msgid "You don't have the right to edit this user's purchases."
msgstr "Vous n'avez pas le droit de modifier les achats de cet utilisateur." msgstr "Vous n'avez pas le droit de modifier les achats de cet utilisateur."
#: cotisations/models.py:571 #: cotisations/models.py:576
msgid "" msgid ""
"You don't have the right to edit a purchase already controlled or " "You don't have the right to edit a purchase already controlled or "
"invalidated." "invalidated."
@ -333,15 +333,15 @@ msgstr ""
"Vous n'avez pas le droit de modifier un achat précédemment contrôlé ou " "Vous n'avez pas le droit de modifier un achat précédemment contrôlé ou "
"invalidé." "invalidé."
#: cotisations/models.py:586 #: cotisations/models.py:591
msgid "You don't have the right to delete a purchase." msgid "You don't have the right to delete a purchase."
msgstr "Vous n'avez pas le droit de supprimer un achat." msgstr "Vous n'avez pas le droit de supprimer un achat."
#: cotisations/models.py:592 #: cotisations/models.py:597
msgid "You don't have the right to delete this user's purchases." msgid "You don't have the right to delete this user's purchases."
msgstr "Vous n'avez pas le droit de supprimer les achats de cet utilisateur." msgstr "Vous n'avez pas le droit de supprimer les achats de cet utilisateur."
#: cotisations/models.py:599 #: cotisations/models.py:604
msgid "" msgid ""
"You don't have the right to delete a purchase already controlled or " "You don't have the right to delete a purchase already controlled or "
"invalidated." "invalidated."
@ -349,134 +349,134 @@ msgstr ""
"Vous n'avez pas le droit de supprimer un achat précédemment contrôlé ou " "Vous n'avez pas le droit de supprimer un achat précédemment contrôlé ou "
"invalidé." "invalidé."
#: cotisations/models.py:615 #: cotisations/models.py:620
msgid "You don't have the right to view someone else's purchase history." msgid "You don't have the right to view someone else's purchase history."
msgstr "" msgstr ""
"Vous n'avez pas le droit de voir l'historique des achats d'un autre " "Vous n'avez pas le droit de voir l'historique des achats d'un autre "
"utilisateur." "utilisateur."
#: cotisations/models.py:683 #: cotisations/models.py:688
msgid "Club" msgid "Club"
msgstr "Club" msgstr "Club"
#: cotisations/models.py:693 #: cotisations/models.py:698
msgid "designation" msgid "designation"
msgstr "désignation" msgstr "désignation"
#: cotisations/models.py:696 #: cotisations/models.py:701
msgid "unit price" msgid "unit price"
msgstr "prix unitaire" msgstr "prix unitaire"
#: cotisations/models.py:714 #: cotisations/models.py:719
msgid "type of users concerned" msgid "type of users concerned"
msgstr "type d'utilisateurs concernés" msgstr "type d'utilisateurs concernés"
#: cotisations/models.py:725 cotisations/models.py:826 #: cotisations/models.py:730 cotisations/models.py:831
msgid "is available for every user" msgid "is available for every user"
msgstr "est disponible pour chaque utilisateur" msgstr "est disponible pour chaque utilisateur"
#: cotisations/models.py:732 #: cotisations/models.py:737
msgid "Can view an article object" msgid "Can view an article object"
msgstr "Peut voir un objet article" msgstr "Peut voir un objet article"
#: cotisations/models.py:733 #: cotisations/models.py:738
msgid "Can buy every article" msgid "Can buy every article"
msgstr "Peut acheter chaque article" msgstr "Peut acheter chaque article"
#: cotisations/models.py:740 #: cotisations/models.py:745
msgid "Solde is a reserved article name." msgid "Solde is a reserved article name."
msgstr "Solde est un nom d'article réservé." msgstr "Solde est un nom d'article réservé."
#: cotisations/models.py:765 #: cotisations/models.py:770
msgid "You can't buy this article." msgid "You can't buy this article."
msgstr "Vous ne pouvez pas acheter cet article." msgstr "Vous ne pouvez pas acheter cet article."
#: cotisations/models.py:806 #: cotisations/models.py:811
msgid "Can view a bank object" msgid "Can view a bank object"
msgstr "Peut voir un objet banque" msgstr "Peut voir un objet banque"
#: cotisations/models.py:807 #: cotisations/models.py:812
msgid "bank" msgid "bank"
msgstr "banque" msgstr "banque"
#: cotisations/models.py:808 #: cotisations/models.py:813
msgid "banks" msgid "banks"
msgstr "banques" msgstr "banques"
#: cotisations/models.py:824 #: cotisations/models.py:829
msgid "method" msgid "method"
msgstr "moyen" msgstr "moyen"
#: cotisations/models.py:831 #: cotisations/models.py:836
msgid "is user balance" msgid "is user balance"
msgstr "est solde utilisateur" msgstr "est solde utilisateur"
#: cotisations/models.py:832 #: cotisations/models.py:837
msgid "There should be only one balance payment method." msgid "There should be only one balance payment method."
msgstr "Il ne devrait y avoir qu'un moyen de paiement solde." msgstr "Il ne devrait y avoir qu'un moyen de paiement solde."
#: cotisations/models.py:838 #: cotisations/models.py:843
msgid "Can view a payment method object" msgid "Can view a payment method object"
msgstr "Peut voir un objet moyen de paiement" msgstr "Peut voir un objet moyen de paiement"
#: cotisations/models.py:839 #: cotisations/models.py:844
msgid "Can use every payment method" msgid "Can use every payment method"
msgstr "Peut utiliser chaque moyen de paiement" msgstr "Peut utiliser chaque moyen de paiement"
#: cotisations/models.py:841 #: cotisations/models.py:846
msgid "payment method" msgid "payment method"
msgstr "moyen de paiement" msgstr "moyen de paiement"
#: cotisations/models.py:842 #: cotisations/models.py:847
msgid "payment methods" msgid "payment methods"
msgstr "moyens de paiement" msgstr "moyens de paiement"
#: cotisations/models.py:881 cotisations/payment_methods/comnpay/views.py:62 #: cotisations/models.py:886 cotisations/payment_methods/comnpay/views.py:62
#, python-format #, python-format
msgid "The subscription of %(member_name)s was extended to %(end_date)s." msgid "The subscription of %(member_name)s was extended to %(end_date)s."
msgstr "La cotisation de %(member_name)s a été étendue au %(end_date)s." msgstr "La cotisation de %(member_name)s a été étendue au %(end_date)s."
#: cotisations/models.py:891 #: cotisations/models.py:896
msgid "The invoice was created." msgid "The invoice was created."
msgstr "La facture a été créée." msgstr "La facture a été créée."
#: cotisations/models.py:911 #: cotisations/models.py:916
msgid "You can't use this payment method." msgid "You can't use this payment method."
msgstr "Vous ne pouvez pas utiliser ce moyen de paiement." msgstr "Vous ne pouvez pas utiliser ce moyen de paiement."
#: cotisations/models.py:930 #: cotisations/models.py:935
msgid "No custom payment methods." msgid "No custom payment methods."
msgstr "Pas de moyens de paiement personnalisés." msgstr "Pas de moyens de paiement personnalisés."
#: cotisations/models.py:961 #: cotisations/models.py:966
msgid "start date" msgid "start date"
msgstr "date de début" msgstr "date de début"
#: cotisations/models.py:962 #: cotisations/models.py:967
msgid "end date" msgid "end date"
msgstr "date de fin" msgstr "date de fin"
#: cotisations/models.py:966 #: cotisations/models.py:971
msgid "Can view a subscription object" msgid "Can view a subscription object"
msgstr "Peut voir un objet cotisation" msgstr "Peut voir un objet cotisation"
#: cotisations/models.py:967 #: cotisations/models.py:972
msgid "Can edit the previous subscriptions" msgid "Can edit the previous subscriptions"
msgstr "Peut modifier les cotisations précédentes" msgstr "Peut modifier les cotisations précédentes"
#: cotisations/models.py:969 #: cotisations/models.py:974
msgid "subscription" msgid "subscription"
msgstr "cotisation" msgstr "cotisation"
#: cotisations/models.py:970 #: cotisations/models.py:975
msgid "subscriptions" msgid "subscriptions"
msgstr "cotisations" msgstr "cotisations"
#: cotisations/models.py:976 #: cotisations/models.py:981
msgid "You don't have the right to edit a subscription." msgid "You don't have the right to edit a subscription."
msgstr "Vous n'avez pas le droit de modifier une cotisation." msgstr "Vous n'avez pas le droit de modifier une cotisation."
#: cotisations/models.py:985 #: cotisations/models.py:990
msgid "" msgid ""
"You don't have the right to edit a subscription already controlled or " "You don't have the right to edit a subscription already controlled or "
"invalidated." "invalidated."
@ -484,11 +484,11 @@ msgstr ""
"Vous n'avez pas le droit de modifier une cotisation précédemment contrôlée " "Vous n'avez pas le droit de modifier une cotisation précédemment contrôlée "
"ou invalidée." "ou invalidée."
#: cotisations/models.py:997 #: cotisations/models.py:1002
msgid "You don't have the right to delete a subscription." msgid "You don't have the right to delete a subscription."
msgstr "Vous n'avez pas le droit de supprimer une cotisation." msgstr "Vous n'avez pas le droit de supprimer une cotisation."
#: cotisations/models.py:1004 #: cotisations/models.py:1009
msgid "" msgid ""
"You don't have the right to delete a subscription already controlled or " "You don't have the right to delete a subscription already controlled or "
"invalidated." "invalidated."
@ -496,7 +496,7 @@ msgstr ""
"Vous n'avez pas le droit de supprimer une cotisation précédemment contrôlée " "Vous n'avez pas le droit de supprimer une cotisation précédemment contrôlée "
"ou invalidée." "ou invalidée."
#: cotisations/models.py:1020 #: cotisations/models.py:1025
msgid "You don't have the right to view someone else's subscription history." msgid "You don't have the right to view someone else's subscription history."
msgstr "" msgstr ""
"Vous n'avez pas le droit de voir l'historique des cotisations d'un autre " "Vous n'avez pas le droit de voir l'historique des cotisations d'un autre "
@ -933,6 +933,11 @@ msgstr "Créer une facture"
msgid "Control the invoices" msgid "Control the invoices"
msgstr "Contrôler les factures" msgstr "Contrôler les factures"
#: cotisations/utils.py:57
#, python-format
msgid "Failed to send email: %(error)s."
msgstr ""
#: cotisations/views.py:157 #: cotisations/views.py:157
msgid "You need to choose at least one article." msgid "You need to choose at least one article."
msgstr "Vous devez choisir au moins un article." msgstr "Vous devez choisir au moins un article."

View file

@ -329,10 +329,16 @@ class Facture(BaseInvoice):
purchase.save() purchase.save()
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
try:
request = kwargs.pop("request")
except:
request = None
super(Facture, self).save(*args, **kwargs) super(Facture, self).save(*args, **kwargs)
if not self.__original_valid and self.valid: if not self.__original_valid and self.valid:
self.reorder_purchases() self.reorder_purchases()
send_mail_invoice(self) send_mail_invoice(self, request)
if ( if (
self.is_subscription() self.is_subscription()
and not self.__original_control and not self.__original_control
@ -340,7 +346,7 @@ class Facture(BaseInvoice):
and CotisationsOption.get_cached_value("send_voucher_mail") and CotisationsOption.get_cached_value("send_voucher_mail")
and self.user.is_adherent() and self.user.is_adherent()
): ):
send_mail_voucher(self) send_mail_voucher(self, request)
def __str__(self): def __str__(self):
return str(self.user) + " " + str(self.date) return str(self.user) + " " + str(self.date)
@ -870,7 +876,7 @@ class Paiement(RevMixin, AclMixin, models.Model):
# So make this invoice valid, trigger send mail # So make this invoice valid, trigger send mail
invoice.valid = True invoice.valid = True
invoice.save() invoice.save(request=request)
# In case a cotisation was bought, inform the user, the # In case a cotisation was bought, inform the user, the
# cotisation time has been extended too # cotisation time has been extended too

View file

@ -23,6 +23,7 @@ import os
from django.template.loader import get_template from django.template.loader import get_template
from django.core.mail import EmailMessage from django.core.mail import EmailMessage
from re2o.mail_utils import send_mail_object
from .tex import create_pdf from .tex import create_pdf
from preferences.models import AssoOption, GeneralOption, CotisationsOption, Mandate from preferences.models import AssoOption, GeneralOption, CotisationsOption, Mandate
@ -43,7 +44,7 @@ def find_payment_method(payment):
return None return None
def send_mail_invoice(invoice): def send_mail_invoice(invoice, request=None):
"""Creates the pdf of the invoice and sends it by email to the client""" """Creates the pdf of the invoice and sends it by email to the client"""
purchases_info = [] purchases_info = []
for purchase in invoice.vente_set.all(): for purchase in invoice.vente_set.all():
@ -90,10 +91,11 @@ def send_mail_invoice(invoice):
[invoice.user.get_mail], [invoice.user.get_mail],
attachments=[("invoice.pdf", pdf, "application/pdf")], attachments=[("invoice.pdf", pdf, "application/pdf")],
) )
mail.send()
send_mail_object(mail, request)
def send_mail_voucher(invoice): def send_mail_voucher(invoice, request=None):
"""Creates a voucher from an invoice and sends it by email to the client""" """Creates a voucher from an invoice and sends it by email to the client"""
president = Mandate.get_mandate(invoice.date).president president = Mandate.get_mandate(invoice.date).president
ctx = { ctx = {
@ -126,4 +128,5 @@ def send_mail_voucher(invoice):
[invoice.user.get_mail], [invoice.user.get_mail],
attachments=[("voucher.pdf", pdf, "application/pdf")], attachments=[("voucher.pdf", pdf, "application/pdf")],
) )
mail.send()
send_mail_object(mail, request)

View file

@ -1008,7 +1008,7 @@ def credit_solde(request, user, **_kwargs):
else: else:
price_ok = True price_ok = True
if price_ok: if price_ok:
invoice.save() invoice.save(request=request)
Vente.objects.create( Vente.objects.create(
facture=invoice, facture=invoice,
name="solde", name="solde",

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-06-23 16:01+0200\n" "PO-Revision-Date: 2018-06-23 16:01+0200\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-06-23 16:35+0200\n" "PO-Revision-Date: 2018-06-23 16:35+0200\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2019-11-16 00:22+0100\n" "PO-Revision-Date: 2019-11-16 00:22+0100\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-06-24 15:54+0200\n" "PO-Revision-Date: 2018-06-24 15:54+0200\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-03-31 16:09+0002\n" "PO-Revision-Date: 2018-03-31 16:09+0002\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"
@ -74,6 +74,11 @@ msgstr "Format : {main} {more}"
msgid "Format: {main}" msgid "Format: {main}"
msgstr "Format : {main}" msgstr "Format : {main}"
#: re2o/mail_utils.py:42
#, python-format
msgid "Failed to send email: %(error)s."
msgstr "Échec de l'envoi du mail : %(error)s."
#: re2o/mixins.py:113 #: re2o/mixins.py:113
#, python-format #, python-format
msgid "You don't have the right to create a %s object." msgid "You don't have the right to create a %s object."

59
re2o/mail_utils.py Normal file
View file

@ -0,0 +1,59 @@
# -*- mode: python; coding: utf-8 -*-
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyright © 2020 Jean-Romain Garnier
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# -*- coding: utf-8 -*-
# Jean-Romain Garnier
"""
Regroupe les fonctions en lien avec les mails
"""
from django.utils.translation import ugettext_lazy as _
from django.core.mail import send_mail as django_send_mail
from django.contrib import messages
from smtplib import SMTPException
from socket import herror, gaierror
def send_mail(request, *args, **kwargs):
"""Wrapper for Django's send_mail which handles errors"""
try:
kwargs["fail_silently"] = request is None
django_send_mail(*args, **kwargs)
except (SMTPException, ConnectionError, herror, gaierror) as e:
messages.error(
request,
_("Failed to send email: %(error)s.") % {
"error": e,
},
)
def send_mail_object(mail, request):
"""Wrapper for Django's EmailMessage.send which handles errors"""
try:
mail.send()
except (SMTPException, ConnectionError, herror, gaierror) as e:
if request:
messages.error(
request,
_("Failed to send email: %(error)s.") % {
"error": e,
},
)

View file

@ -181,6 +181,9 @@ MEDIA_URL = os.path.join(BASE_DIR, "/media/")
# Models to use for graphs # Models to use for graphs
GRAPH_MODELS = {"all_applications": True, "group_models": True} GRAPH_MODELS = {"all_applications": True, "group_models": True}
# Timeout when sending emails through Django (in seconds)
EMAIL_TIMEOUT = 10
# Activate API # Activate API
if "api" in INSTALLED_APPS: if "api" in INSTALLED_APPS:
from api.settings import * from api.settings import *

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-06-24 20:10+0200\n" "PO-Revision-Date: 2018-06-24 20:10+0200\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-03-31 16:09+0002\n" "PO-Revision-Date: 2018-03-31 16:09+0002\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2019-11-16 00:35+0100\n" "PO-Revision-Date: 2019-11-16 00:35+0100\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"
@ -42,33 +42,33 @@ msgstr "Description du ticket."
msgid "An email address to get back to you." msgid "An email address to get back to you."
msgstr "Une adresse mail pour vous recontacter." msgstr "Une adresse mail pour vous recontacter."
#: tickets/models.py:43 #: tickets/models.py:44
msgid "Can view a ticket object" msgid "Can view a ticket object"
msgstr "Peut voir un objet ticket" msgstr "Peut voir un objet ticket"
#: tickets/models.py:44 #: tickets/models.py:45
msgid "ticket" msgid "ticket"
msgstr "ticket" msgstr "ticket"
#: tickets/models.py:45 #: tickets/models.py:46
msgid "tickets" msgid "tickets"
msgstr "tickets" msgstr "tickets"
#: tickets/models.py:49 #: tickets/models.py:50
#, python-format #, python-format
msgid "Ticket from %(name)s. Date: %(date)s." msgid "Ticket from %(name)s. Date: %(date)s."
msgstr "Ticket de %(name)s. Date : %(date)s." msgstr "Ticket de %(name)s. Date : %(date)s."
#: tickets/models.py:51 #: tickets/models.py:52
#, python-format #, python-format
msgid "Anonymous ticket. Date: %s." msgid "Anonymous ticket. Date: %s."
msgstr "Ticket anonyme. Date : %s." msgstr "Ticket anonyme. Date : %s."
#: tickets/models.py:82 #: tickets/models.py:85
msgid "You don't have the right to view other tickets than yours." msgid "You don't have the right to view other tickets than yours."
msgstr "Vous n'avez pas le droit de voir d'autres tickets que les vôtres." msgstr "Vous n'avez pas le droit de voir d'autres tickets que les vôtres."
#: tickets/models.py:94 #: tickets/models.py:97
msgid "You don't have the right to view the list of tickets." msgid "You don't have the right to view the list of tickets."
msgstr "Vous n'avez pas le droit de voir la liste des tickets." msgstr "Vous n'avez pas le droit de voir la liste des tickets."
@ -214,7 +214,7 @@ msgstr "Modifier"
msgid "Ticket opening" msgid "Ticket opening"
msgstr "Ouverture de ticket" msgstr "Ouverture de ticket"
#: tickets/templates/tickets/form_ticket.html:39 tickets/views.py:88 #: tickets/templates/tickets/form_ticket.html:39 tickets/views.py:90
msgid "" msgid ""
"You are not authenticated. Please log in or provide an email address so we " "You are not authenticated. Please log in or provide an email address so we "
"can get back to you." "can get back to you."
@ -280,21 +280,21 @@ msgstr "Langue du mail"
msgid "No tickets" msgid "No tickets"
msgstr "Pas de tickets" msgstr "Pas de tickets"
#: tickets/views.py:69 tickets/views.py:80 #: tickets/views.py:71 tickets/views.py:82
msgid "" msgid ""
"Your ticket has been succesfully opened. We will take care of it as soon as " "Your ticket has been succesfully opened. We will take care of it as soon as "
"possible." "possible."
msgstr "" msgstr ""
"Votre ticket a bien été ouvert. Nous nous en occuperons dès que possible." "Votre ticket a bien été ouvert. Nous nous en occuperons dès que possible."
#: tickets/views.py:125 tickets/views.py:175 #: tickets/views.py:127 tickets/views.py:177
msgid "Never" msgid "Never"
msgstr "Jamais" msgstr "Jamais"
#: tickets/views.py:152 #: tickets/views.py:154
msgid "The tickets preferences were edited." msgid "The tickets preferences were edited."
msgstr "Les préférences de tickets ont été modifiées." msgstr "Les préférences de tickets ont été modifiées."
#: tickets/views.py:155 #: tickets/views.py:157
msgid "Invalid form." msgid "Invalid form."
msgstr "Formulaire invalide." msgstr "Formulaire invalide."

View file

@ -1,11 +1,11 @@
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.mail import send_mail
from django.template import loader from django.template import loader
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from re2o.mixins import AclMixin from re2o.mixins import AclMixin
from re2o.mail_utils import send_mail
from preferences.models import GeneralOption from preferences.models import GeneralOption
@ -38,6 +38,7 @@ class Ticket(AclMixin, models.Model):
help_text=_("An email address to get back to you."), max_length=100, null=True help_text=_("An email address to get back to you."), max_length=100, null=True
) )
solved = models.BooleanField(default=False) solved = models.BooleanField(default=False)
request = None
class Meta: class Meta:
permissions = (("view_tickets", _("Can view a ticket object")),) permissions = (("view_tickets", _("Can view a ticket object")),)
@ -50,7 +51,7 @@ class Ticket(AclMixin, models.Model):
else: else:
return _("Anonymous ticket. Date: %s.") % (self.date) return _("Anonymous ticket. Date: %s.") % (self.date)
def publish_mail(self): def publish_mail(self, request=None):
site_url = GeneralOption.objects.first().main_site_url site_url = GeneralOption.objects.first().main_site_url
to_addr = Preferences.objects.first().publish_address to_addr = Preferences.objects.first().publish_address
context = {"ticket": self, "site_url": site_url} context = {"ticket": self, "site_url": site_url}
@ -62,7 +63,9 @@ class Ticket(AclMixin, models.Model):
else: else:
obj = "New ticket opened" obj = "New ticket opened"
template = loader.get_template("tickets/publication_mail_en") template = loader.get_template("tickets/publication_mail_en")
send_mail( send_mail(
request,
obj, obj,
template.render(context), template.render(context),
GeneralOption.get_cached_value("email_from"), GeneralOption.get_cached_value("email_from"),
@ -108,4 +111,4 @@ def ticket_post_save(**kwargs):
if kwargs["created"]: if kwargs["created"]:
if Preferences.objects.first().publish_address: if Preferences.objects.first().publish_address:
ticket = kwargs["instance"] ticket = kwargs["instance"]
ticket.publish_mail() ticket.publish_mail(ticket.request)

View file

@ -60,6 +60,8 @@ def new_ticket(request):
if ticketform.is_valid(): if ticketform.is_valid():
email = ticketform.cleaned_data.get("email") email = ticketform.cleaned_data.get("email")
ticket = ticketform.save(commit=False) ticket = ticketform.save(commit=False)
ticket.request = request
if request.user.is_authenticated: if request.user.is_authenticated:
ticket.user = request.user ticket.user = request.user
ticket.save() ticket.save()

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-06-25 14:53+0200\n" "PO-Revision-Date: 2018-06-25 14:53+0200\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"

View file

@ -21,7 +21,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2.5\n" "Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-19 17:12+0200\n" "POT-Creation-Date: 2020-04-19 20:16+0200\n"
"PO-Revision-Date: 2018-06-27 23:35+0200\n" "PO-Revision-Date: 2018-06-27 23:35+0200\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n" "Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n" "Language-Team: \n"
@ -56,7 +56,7 @@ msgid "The current password is incorrect."
msgstr "Le mot de passe actuel est incorrect." msgstr "Le mot de passe actuel est incorrect."
#: users/forms.py:132 users/forms.py:189 users/forms.py:425 #: users/forms.py:132 users/forms.py:189 users/forms.py:425
#: users/models.py:1894 #: users/models.py:1908
msgid "Password" msgid "Password"
msgstr "Mot de passe" msgstr "Mot de passe"
@ -114,7 +114,7 @@ msgstr "Prénom"
msgid "Surname" msgid "Surname"
msgstr "Nom" msgstr "Nom"
#: users/forms.py:329 users/forms.py:566 users/models.py:1894 #: users/forms.py:329 users/forms.py:566 users/models.py:1908
#: users/templates/users/aff_emailaddress.html:36 #: users/templates/users/aff_emailaddress.html:36
#: users/templates/users/profil.html:209 #: users/templates/users/profil.html:209
msgid "Email address" msgid "Email address"
@ -336,7 +336,7 @@ msgstr "Non confirmé"
msgid "Waiting for email confirmation" msgid "Waiting for email confirmation"
msgstr "En attente de confirmation" msgstr "En attente de confirmation"
#: users/models.py:204 users/models.py:1550 #: users/models.py:204 users/models.py:1561
msgid "Must only contain letters, numerals or dashes." msgid "Must only contain letters, numerals or dashes."
msgstr "Doit seulement contenir des lettres, chiffres ou tirets." msgstr "Doit seulement contenir des lettres, chiffres ou tirets."
@ -362,82 +362,82 @@ msgstr "Commentaire, promotion."
msgid "enable shortcuts on Re2o website" msgid "enable shortcuts on Re2o website"
msgstr "activer les raccourcis sur le site de Re2o" msgstr "activer les raccourcis sur le site de Re2o"
#: users/models.py:250 #: users/models.py:251
msgid "Can change the password of a user" msgid "Can change the password of a user"
msgstr "Peut changer le mot de passe d'un utilisateur" msgstr "Peut changer le mot de passe d'un utilisateur"
#: users/models.py:251 #: users/models.py:252
msgid "Can edit the state of a user" msgid "Can edit the state of a user"
msgstr "Peut changer l'état d'un utilisateur" msgstr "Peut changer l'état d'un utilisateur"
#: users/models.py:252 #: users/models.py:253
msgid "Can force the move" msgid "Can force the move"
msgstr "Peut forcer le déménagement" msgstr "Peut forcer le déménagement"
#: users/models.py:253 #: users/models.py:254
msgid "Can edit the shell of a user" msgid "Can edit the shell of a user"
msgstr "Peut modifier l'interface en ligne de commande d'un utilisateur" msgstr "Peut modifier l'interface en ligne de commande d'un utilisateur"
#: users/models.py:256 #: users/models.py:257
msgid "Can edit the groups of rights of a user (critical permission)" msgid "Can edit the groups of rights of a user (critical permission)"
msgstr "" msgstr ""
"Peut modifier les groupes de droits d'un utilisateur (permission critique)" "Peut modifier les groupes de droits d'un utilisateur (permission critique)"
#: users/models.py:258 #: users/models.py:259
msgid "Can edit all users, including those with rights" msgid "Can edit all users, including those with rights"
msgstr "" msgstr ""
"Peut modifier tous les utilisateurs, y compris ceux possédant des droits" "Peut modifier tous les utilisateurs, y compris ceux possédant des droits"
#: users/models.py:259 #: users/models.py:260
msgid "Can view a user object" msgid "Can view a user object"
msgstr "Peut voir un objet utilisateur" msgstr "Peut voir un objet utilisateur"
#: users/models.py:261 #: users/models.py:262
msgid "user (member or club)" msgid "user (member or club)"
msgstr "utilisateur (adhérent ou club)" msgstr "utilisateur (adhérent ou club)"
#: users/models.py:262 #: users/models.py:263
msgid "users (members or clubs)" msgid "users (members or clubs)"
msgstr "utilisateurs (adhérents ou clubs)" msgstr "utilisateurs (adhérents ou clubs)"
#: users/models.py:280 users/models.py:308 users/models.py:318 #: users/models.py:281 users/models.py:309 users/models.py:319
msgid "Unknown type." msgid "Unknown type."
msgstr "Type inconnu." msgstr "Type inconnu."
#: users/models.py:314 users/templates/users/aff_listright.html:75 #: users/models.py:315 users/templates/users/aff_listright.html:75
#: users/templates/users/aff_listright.html:180 #: users/templates/users/aff_listright.html:180
msgid "Member" msgid "Member"
msgstr "Adhérent" msgstr "Adhérent"
#: users/models.py:316 #: users/models.py:317
msgid "Club" msgid "Club"
msgstr "Club" msgstr "Club"
#: users/models.py:891 #: users/models.py:896
msgid "Maximum number of registered machines reached." msgid "Maximum number of registered machines reached."
msgstr "Nombre maximum de machines enregistrées atteint." msgstr "Nombre maximum de machines enregistrées atteint."
#: users/models.py:893 #: users/models.py:898
msgid "Re2o doesn't know wich machine type to assign." msgid "Re2o doesn't know wich machine type to assign."
msgstr "Re2o ne sait pas quel type de machine attribuer." msgstr "Re2o ne sait pas quel type de machine attribuer."
#: users/models.py:916 users/templates/users/user_autocapture.html:64 #: users/models.py:921 users/templates/users/user_autocapture.html:64
msgid "OK" msgid "OK"
msgstr "OK" msgstr "OK"
#: users/models.py:1010 #: users/models.py:1019
msgid "This user is archived." msgid "This user is archived."
msgstr "Cet utilisateur est archivé." msgstr "Cet utilisateur est archivé."
#: users/models.py:1024 users/models.py:1078 #: users/models.py:1033 users/models.py:1087
msgid "You don't have the right to edit this club." msgid "You don't have the right to edit this club."
msgstr "Vous n'avez pas le droit de modifier ce club." msgstr "Vous n'avez pas le droit de modifier ce club."
#: users/models.py:1036 #: users/models.py:1045
msgid "User with critical rights, can't be edited." msgid "User with critical rights, can't be edited."
msgstr "Utilisateur avec des droits critiques, ne peut être modifié." msgstr "Utilisateur avec des droits critiques, ne peut être modifié."
#: users/models.py:1043 #: users/models.py:1052
msgid "" msgid ""
"Impossible to edit the organisation's user without the \"change_all_users\" " "Impossible to edit the organisation's user without the \"change_all_users\" "
"right." "right."
@ -445,61 +445,61 @@ msgstr ""
"Impossible de modifier l'utilisateur de l'association sans le droit « " "Impossible de modifier l'utilisateur de l'association sans le droit « "
"change_all_users »." "change_all_users »."
#: users/models.py:1055 users/models.py:1093 #: users/models.py:1064 users/models.py:1102
msgid "You don't have the right to edit another user." msgid "You don't have the right to edit another user."
msgstr "Vous n'avez pas le droit de modifier un autre utilisateur." msgstr "Vous n'avez pas le droit de modifier un autre utilisateur."
#: users/models.py:1119 #: users/models.py:1128
msgid "You don't have the right to change the room." msgid "You don't have the right to change the room."
msgstr "Vous n'avez pas le droit de changer la chambre." msgstr "Vous n'avez pas le droit de changer la chambre."
#: users/models.py:1136 #: users/models.py:1145
msgid "You don't have the right to change the state." msgid "You don't have the right to change the state."
msgstr "Vous n'avez pas le droit de changer l'état." msgstr "Vous n'avez pas le droit de changer l'état."
#: users/models.py:1156 #: users/models.py:1165
msgid "You don't have the right to change the shell." msgid "You don't have the right to change the shell."
msgstr "Vous n'avez pas le droit de changer l'interface en ligne de commande." msgstr "Vous n'avez pas le droit de changer l'interface en ligne de commande."
#: users/models.py:1173 users/models.py:1188 #: users/models.py:1182 users/models.py:1197
msgid "Local email accounts must be enabled." msgid "Local email accounts must be enabled."
msgstr "Les comptes mail locaux doivent être activés." msgstr "Les comptes mail locaux doivent être activés."
#: users/models.py:1203 #: users/models.py:1212
msgid "You don't have the right to force the move." msgid "You don't have the right to force the move."
msgstr "Vous n'avez pas le droit de forcer le déménagement." msgstr "Vous n'avez pas le droit de forcer le déménagement."
#: users/models.py:1218 #: users/models.py:1227
msgid "You don't have the right to edit the user's groups of rights." msgid "You don't have the right to edit the user's groups of rights."
msgstr "" msgstr ""
"Vous n'avez pas le droit de modifier les groupes de droits d'un autre " "Vous n'avez pas le droit de modifier les groupes de droits d'un autre "
"utilisateur." "utilisateur."
#: users/models.py:1234 #: users/models.py:1243
msgid "\"superuser\" right required to edit the superuser flag." msgid "\"superuser\" right required to edit the superuser flag."
msgstr "Droit « superuser » requis pour modifier le signalement superuser." msgstr "Droit « superuser » requis pour modifier le signalement superuser."
#: users/models.py:1259 #: users/models.py:1268
msgid "You don't have the right to view this club." msgid "You don't have the right to view this club."
msgstr "Vous n'avez pas le droit de voir ce club." msgstr "Vous n'avez pas le droit de voir ce club."
#: users/models.py:1268 #: users/models.py:1277
msgid "You don't have the right to view another user." msgid "You don't have the right to view another user."
msgstr "Vous n'avez pas le droit de voir un autre utilisateur." msgstr "Vous n'avez pas le droit de voir un autre utilisateur."
#: users/models.py:1283 users/models.py:1488 #: users/models.py:1292 users/models.py:1497
msgid "You don't have the right to view the list of users." msgid "You don't have the right to view the list of users."
msgstr "Vous n'avez pas le droit de voir la liste des utilisateurs." msgstr "Vous n'avez pas le droit de voir la liste des utilisateurs."
#: users/models.py:1300 #: users/models.py:1309
msgid "You don't have the right to delete this user." msgid "You don't have the right to delete this user."
msgstr "Vous n'avez pas le droit de supprimer cet utilisateur." msgstr "Vous n'avez pas le droit de supprimer cet utilisateur."
#: users/models.py:1323 #: users/models.py:1332
msgid "This username is already used." msgid "This username is already used."
msgstr "Ce pseudo est déjà utilisé." msgstr "Ce pseudo est déjà utilisé."
#: users/models.py:1331 #: users/models.py:1340
msgid "" msgid ""
"There is neither a local email address nor an external email address for " "There is neither a local email address nor an external email address for "
"this user." "this user."
@ -507,7 +507,7 @@ msgstr ""
"Il n'y a pas d'adresse mail locale ni d'adresse mail externe pour cet " "Il n'y a pas d'adresse mail locale ni d'adresse mail externe pour cet "
"utilisateur." "utilisateur."
#: users/models.py:1338 #: users/models.py:1347
msgid "" msgid ""
"You can't redirect your local emails if no external email address has been " "You can't redirect your local emails if no external email address has been "
"set." "set."
@ -515,195 +515,195 @@ msgstr ""
"Vous ne pouvez pas rediriger vos mails locaux si aucune adresse mail externe " "Vous ne pouvez pas rediriger vos mails locaux si aucune adresse mail externe "
"n'a été définie." "n'a été définie."
#: users/models.py:1358 #: users/models.py:1367
msgid "member" msgid "member"
msgstr "adhérent" msgstr "adhérent"
#: users/models.py:1359 #: users/models.py:1368
msgid "members" msgid "members"
msgstr "adhérents" msgstr "adhérents"
#: users/models.py:1376 #: users/models.py:1385
msgid "A GPG fingerprint must contain 40 hexadecimal characters." msgid "A GPG fingerprint must contain 40 hexadecimal characters."
msgstr "Une empreinte GPG doit contenir 40 caractères hexadécimaux." msgstr "Une empreinte GPG doit contenir 40 caractères hexadécimaux."
#: users/models.py:1401 #: users/models.py:1410
msgid "Self registration is disabled." msgid "Self registration is disabled."
msgstr "L'auto inscription est désactivée." msgstr "L'auto inscription est désactivée."
#: users/models.py:1411 #: users/models.py:1420
msgid "You don't have the right to create a user." msgid "You don't have the right to create a user."
msgstr "Vous n'avez pas le droit de créer un utilisateur." msgstr "Vous n'avez pas le droit de créer un utilisateur."
#: users/models.py:1441 #: users/models.py:1450
msgid "club" msgid "club"
msgstr "club" msgstr "club"
#: users/models.py:1442 #: users/models.py:1451
msgid "clubs" msgid "clubs"
msgstr "clubs" msgstr "clubs"
#: users/models.py:1453 #: users/models.py:1462
msgid "You must be authenticated." msgid "You must be authenticated."
msgstr "Vous devez être authentifié." msgstr "Vous devez être authentifié."
#: users/models.py:1461 #: users/models.py:1470
msgid "You don't have the right to create a club." msgid "You don't have the right to create a club."
msgstr "Vous n'avez pas le droit de créer un club." msgstr "Vous n'avez pas le droit de créer un club."
#: users/models.py:1554 #: users/models.py:1565
msgid "Comment." msgid "Comment."
msgstr "Commentaire." msgstr "Commentaire."
#: users/models.py:1560 #: users/models.py:1571
msgid "Can view a service user object" msgid "Can view a service user object"
msgstr "Peut voir un objet utilisateur service" msgstr "Peut voir un objet utilisateur service"
#: users/models.py:1561 users/views.py:356 #: users/models.py:1572 users/views.py:360
msgid "service user" msgid "service user"
msgstr "utilisateur service" msgstr "utilisateur service"
#: users/models.py:1562 #: users/models.py:1573
msgid "service users" msgid "service users"
msgstr "utilisateurs service" msgstr "utilisateurs service"
#: users/models.py:1566 #: users/models.py:1577
#, python-brace-format #, python-brace-format
msgid "Service user <{name}>" msgid "Service user <{name}>"
msgstr "Utilisateur service <{name}>" msgstr "Utilisateur service <{name}>"
#: users/models.py:1633 #: users/models.py:1644
msgid "Can view a school object" msgid "Can view a school object"
msgstr "Peut voir un objet établissement" msgstr "Peut voir un objet établissement"
#: users/models.py:1634 #: users/models.py:1645
msgid "school" msgid "school"
msgstr "établissement" msgstr "établissement"
#: users/models.py:1635 #: users/models.py:1646
msgid "schools" msgid "schools"
msgstr "établissements" msgstr "établissements"
#: users/models.py:1654 #: users/models.py:1665
msgid "UNIX group names can only contain lower case letters." msgid "UNIX group names can only contain lower case letters."
msgstr "" msgstr ""
"Les noms de groupe UNIX peuvent seulement contenir des lettres minuscules." "Les noms de groupe UNIX peuvent seulement contenir des lettres minuscules."
#: users/models.py:1660 #: users/models.py:1671
msgid "Description." msgid "Description."
msgstr "Description." msgstr "Description."
#: users/models.py:1663 #: users/models.py:1674
msgid "Can view a group of rights object" msgid "Can view a group of rights object"
msgstr "Peut voir un objet groupe de droits" msgstr "Peut voir un objet groupe de droits"
#: users/models.py:1664 #: users/models.py:1675
msgid "group of rights" msgid "group of rights"
msgstr "groupe de droits" msgstr "groupe de droits"
#: users/models.py:1665 #: users/models.py:1676
msgid "groups of rights" msgid "groups of rights"
msgstr "groupes de droits" msgstr "groupes de droits"
#: users/models.py:1710 #: users/models.py:1721
msgid "Can view a shell object" msgid "Can view a shell object"
msgstr "Peut voir un objet interface en ligne de commande" msgstr "Peut voir un objet interface en ligne de commande"
#: users/models.py:1711 users/views.py:671 #: users/models.py:1722 users/views.py:679
msgid "shell" msgid "shell"
msgstr "interface en ligne de commande" msgstr "interface en ligne de commande"
#: users/models.py:1712 #: users/models.py:1723
msgid "shells" msgid "shells"
msgstr "interfaces en ligne de commande" msgstr "interfaces en ligne de commande"
#: users/models.py:1730 #: users/models.py:1741
msgid "HARD (no access)" msgid "HARD (no access)"
msgstr "HARD (pas d'accès)" msgstr "HARD (pas d'accès)"
#: users/models.py:1731 #: users/models.py:1742
msgid "SOFT (local access only)" msgid "SOFT (local access only)"
msgstr "SOFT (accès local uniquement)" msgstr "SOFT (accès local uniquement)"
#: users/models.py:1732 #: users/models.py:1743
msgid "RESTRICTED (speed limitation)" msgid "RESTRICTED (speed limitation)"
msgstr "RESTRICTED (limitation de vitesse)" msgstr "RESTRICTED (limitation de vitesse)"
#: users/models.py:1742 #: users/models.py:1754
msgid "Can view a ban object" msgid "Can view a ban object"
msgstr "Peut voir un objet bannissement" msgstr "Peut voir un objet bannissement"
#: users/models.py:1743 users/views.py:407 #: users/models.py:1755 users/views.py:415
msgid "ban" msgid "ban"
msgstr "bannissement" msgstr "bannissement"
#: users/models.py:1744 #: users/models.py:1756
msgid "bans" msgid "bans"
msgstr "bannissements" msgstr "bannissements"
#: users/models.py:1779 #: users/models.py:1793
msgid "You don't have the right to view other bans than yours." msgid "You don't have the right to view other bans than yours."
msgstr "" msgstr ""
"Vous n'avez pas le droit de voir d'autres bannissements que les vôtres." "Vous n'avez pas le droit de voir d'autres bannissements que les vôtres."
#: users/models.py:1827 #: users/models.py:1841
msgid "Can view a whitelist object" msgid "Can view a whitelist object"
msgstr "Peut voir un objet accès gracieux" msgstr "Peut voir un objet accès gracieux"
#: users/models.py:1828 #: users/models.py:1842
msgid "whitelist (free of charge access)" msgid "whitelist (free of charge access)"
msgstr "Accès gracieux" msgstr "Accès gracieux"
#: users/models.py:1829 #: users/models.py:1843
msgid "whitelists (free of charge access)" msgid "whitelists (free of charge access)"
msgstr "Accès gracieux" msgstr "Accès gracieux"
#: users/models.py:1849 #: users/models.py:1863
msgid "You don't have the right to view other whitelists than yours." msgid "You don't have the right to view other whitelists than yours."
msgstr "" msgstr ""
"Vous n'avez pas le droit de voir d'autres accès gracieux que les vôtres." "Vous n'avez pas le droit de voir d'autres accès gracieux que les vôtres."
#: users/models.py:2047 #: users/models.py:2061
msgid "User of the local email account." msgid "User of the local email account."
msgstr "Utilisateur du compte mail local." msgstr "Utilisateur du compte mail local."
#: users/models.py:2050 #: users/models.py:2064
msgid "Local part of the email address." msgid "Local part of the email address."
msgstr "Partie locale de l'adresse mail." msgstr "Partie locale de l'adresse mail."
#: users/models.py:2055 #: users/models.py:2069
msgid "Can view a local email account object" msgid "Can view a local email account object"
msgstr "Peut voir un objet compte mail local" msgstr "Peut voir un objet compte mail local"
#: users/models.py:2057 #: users/models.py:2071
msgid "local email account" msgid "local email account"
msgstr "compte mail local" msgstr "compte mail local"
#: users/models.py:2058 #: users/models.py:2072
msgid "local email accounts" msgid "local email accounts"
msgstr "comptes mail locaux" msgstr "comptes mail locaux"
#: users/models.py:2086 users/models.py:2121 users/models.py:2155 #: users/models.py:2100 users/models.py:2135 users/models.py:2169
#: users/models.py:2189 #: users/models.py:2203
msgid "The local email accounts are not enabled." msgid "The local email accounts are not enabled."
msgstr "Les comptes mail locaux ne sont pas activés." msgstr "Les comptes mail locaux ne sont pas activés."
#: users/models.py:2091 #: users/models.py:2105
msgid "You don't have the right to add a local email account to another user." msgid "You don't have the right to add a local email account to another user."
msgstr "" msgstr ""
"Vous n'avez pas le droit d'ajouter un compte mail local à un autre " "Vous n'avez pas le droit d'ajouter un compte mail local à un autre "
"utilisateur." "utilisateur."
#: users/models.py:2101 #: users/models.py:2115
msgid "You reached the limit of {} local email accounts." msgid "You reached the limit of {} local email accounts."
msgstr "Vous avez atteint la limite de {} comptes mail locaux." msgstr "Vous avez atteint la limite de {} comptes mail locaux."
#: users/models.py:2127 #: users/models.py:2141
msgid "You don't have the right to view another user's local email account." msgid "You don't have the right to view another user's local email account."
msgstr "" msgstr ""
"Vous n'avez pas le droit de voir le compte mail local d'un autre utilisateur." "Vous n'avez pas le droit de voir le compte mail local d'un autre utilisateur."
#: users/models.py:2147 #: users/models.py:2161
msgid "" msgid ""
"You can't delete a local email account whose local part is the same as the " "You can't delete a local email account whose local part is the same as the "
"username." "username."
@ -711,13 +711,13 @@ msgstr ""
"Vous ne pouvez pas supprimer un compte mail local dont la partie locale est " "Vous ne pouvez pas supprimer un compte mail local dont la partie locale est "
"la même que le pseudo." "la même que le pseudo."
#: users/models.py:2161 #: users/models.py:2175
msgid "You don't have the right to delete another user's local email account." msgid "You don't have the right to delete another user's local email account."
msgstr "" msgstr ""
"Vous n'avez pas le droit de supprimer le compte mail local d'un autre " "Vous n'avez pas le droit de supprimer le compte mail local d'un autre "
"utilisateur." "utilisateur."
#: users/models.py:2181 #: users/models.py:2195
msgid "" msgid ""
"You can't edit a local email account whose local part is the same as the " "You can't edit a local email account whose local part is the same as the "
"username." "username."
@ -725,13 +725,13 @@ msgstr ""
"Vous ne pouvez pas modifier un compte mail local dont la partie locale est " "Vous ne pouvez pas modifier un compte mail local dont la partie locale est "
"la même que le pseudo." "la même que le pseudo."
#: users/models.py:2195 #: users/models.py:2209
msgid "You don't have the right to edit another user's local email account." msgid "You don't have the right to edit another user's local email account."
msgstr "" msgstr ""
"Vous n'avez pas le droit de modifier le compte mail local d'un autre " "Vous n'avez pas le droit de modifier le compte mail local d'un autre "
"utilisateur." "utilisateur."
#: users/models.py:2204 #: users/models.py:2218
msgid "The local part must not contain @ or +." msgid "The local part must not contain @ or +."
msgstr "La partie locale ne doit pas contenir @ ou +." msgstr "La partie locale ne doit pas contenir @ ou +."
@ -888,8 +888,8 @@ msgstr "pour %(name)s."
#: users/templates/users/confirm_email.html:39 #: users/templates/users/confirm_email.html:39
#: users/templates/users/delete.html:36 #: users/templates/users/delete.html:36
#: users/templates/users/mass_archive.html:36 #: users/templates/users/mass_archive.html:36
#: users/templates/users/resend_confirmation_email.html:35 users/views.py:628 #: users/templates/users/resend_confirmation_email.html:35 users/views.py:636
#: users/views.py:732 #: users/views.py:740
msgid "Confirm" msgid "Confirm"
msgstr "Confirmer" msgstr "Confirmer"
@ -1086,14 +1086,14 @@ msgstr "Pas de machine"
msgid "Detailed information" msgid "Detailed information"
msgstr "Informations détaillées" msgstr "Informations détaillées"
#: users/templates/users/profil.html:161 users/views.py:202 users/views.py:233 #: users/templates/users/profil.html:161 users/views.py:206 users/views.py:237
#: users/views.py:252 users/views.py:269 users/views.py:341 users/views.py:395 #: users/views.py:256 users/views.py:273 users/views.py:345 users/views.py:403
#: users/views.py:449 users/views.py:514 users/views.py:561 users/views.py:597 #: users/views.py:457 users/views.py:522 users/views.py:569 users/views.py:605
#: users/views.py:657 users/views.py:703 #: users/views.py:665 users/views.py:711
msgid "Edit" msgid "Edit"
msgstr "Modifier" msgstr "Modifier"
#: users/templates/users/profil.html:165 users/views.py:288 users/views.py:1035 #: users/templates/users/profil.html:165 users/views.py:292 users/views.py:1043
msgid "Change the password" msgid "Change the password"
msgstr "Changer le mot de passe" msgstr "Changer le mot de passe"
@ -1333,160 +1333,160 @@ msgstr "Connecté avec l'appareil :"
msgid "MAC address %(mac)s" msgid "MAC address %(mac)s"
msgstr "Adresse MAC %(mac)s" msgstr "Adresse MAC %(mac)s"
#: users/views.py:133 #: users/views.py:135
#, python-format #, python-format
msgid "The user %s was created, a confirmation email was sent." msgid "The user %s was created, a confirmation email was sent."
msgstr "L'utilisateur %s a été créé, un mail de confirmation a été envoyé." msgstr "L'utilisateur %s a été créé, un mail de confirmation a été envoyé."
#: users/views.py:140 #: users/views.py:142
#, python-format #, python-format
msgid "The user %s was created, an email to set the password was sent." msgid "The user %s was created, an email to set the password was sent."
msgstr "" msgstr ""
"L'utilisateur %s a été créé, un mail pour initialiser le mot de passe a été " "L'utilisateur %s a été créé, un mail pour initialiser le mot de passe a été "
"envoyé." "envoyé."
#: users/views.py:153 #: users/views.py:155
msgid "Commit" msgid "Commit"
msgstr "Valider" msgstr "Valider"
#: users/views.py:174 #: users/views.py:178
#, python-format #, python-format
msgid "The club %s was created, an email to set the password was sent." msgid "The club %s was created, an email to set the password was sent."
msgstr "" msgstr ""
"Le club %s a été créé, un mail pour initialiser le mot de passe a été envoyé." "Le club %s a été créé, un mail pour initialiser le mot de passe a été envoyé."
#: users/views.py:179 #: users/views.py:183
msgid "Create a club" msgid "Create a club"
msgstr "Créer un club" msgstr "Créer un club"
#: users/views.py:194 #: users/views.py:198
msgid "The club was edited." msgid "The club was edited."
msgstr "Le club a été modifié." msgstr "Le club a été modifié."
#: users/views.py:226 #: users/views.py:230
msgid "The user was edited." msgid "The user was edited."
msgstr "L'utilisateur a été modifié." msgstr "L'utilisateur a été modifié."
#: users/views.py:229 #: users/views.py:233
msgid "Sent a new confirmation email." msgid "Sent a new confirmation email."
msgstr "Un nouveau mail de confirmation a été envoyé." msgstr "Un nouveau mail de confirmation a été envoyé."
#: users/views.py:247 #: users/views.py:251
msgid "The states were edited." msgid "The states were edited."
msgstr "Les états ont été modifié." msgstr "Les états ont été modifié."
#: users/views.py:249 #: users/views.py:253
msgid "An email to confirm the address was sent." msgid "An email to confirm the address was sent."
msgstr "Un mail pour confirmer l'adresse a été envoyé." msgstr "Un mail pour confirmer l'adresse a été envoyé."
#: users/views.py:266 #: users/views.py:270
msgid "The groups were edited." msgid "The groups were edited."
msgstr "Les groupes ont été modifiés." msgstr "Les groupes ont été modifiés."
#: users/views.py:285 users/views.py:1032 #: users/views.py:289 users/views.py:1040
msgid "The password was changed." msgid "The password was changed."
msgstr "Le mot de passe a été changé." msgstr "Le mot de passe a été changé."
#: users/views.py:300 #: users/views.py:304
#, python-format #, python-format
msgid "%s was removed from the group." msgid "%s was removed from the group."
msgstr "%s a été retiré du groupe." msgstr "%s a été retiré du groupe."
#: users/views.py:310 #: users/views.py:314
#, python-format #, python-format
msgid "%s is no longer superuser." msgid "%s is no longer superuser."
msgstr "%s n'est plus superutilisateur." msgstr "%s n'est plus superutilisateur."
#: users/views.py:321 #: users/views.py:325
msgid "The service user was created." msgid "The service user was created."
msgstr "L'utilisateur service a été créé." msgstr "L'utilisateur service a été créé."
#: users/views.py:324 users/views.py:378 users/views.py:429 users/views.py:487 #: users/views.py:328 users/views.py:384 users/views.py:437 users/views.py:495
#: users/views.py:579 users/views.py:642 users/views.py:685 #: users/views.py:587 users/views.py:650 users/views.py:693
msgid "Add" msgid "Add"
msgstr "Ajouter" msgstr "Ajouter"
#: users/views.py:338 #: users/views.py:342
msgid "The service user was edited." msgid "The service user was edited."
msgstr "L'utilisateur service a été modifié." msgstr "L'utilisateur service a été modifié."
#: users/views.py:353 #: users/views.py:357
msgid "The service user was deleted." msgid "The service user was deleted."
msgstr "L'utilisateur service a été supprimé." msgstr "L'utilisateur service a été supprimé."
#: users/views.py:373 #: users/views.py:379
msgid "The ban was added." msgid "The ban was added."
msgstr "Le bannissement a été ajouté." msgstr "Le bannissement a été ajouté."
#: users/views.py:376 #: users/views.py:382
msgid "Warning: this user already has an active ban." msgid "Warning: this user already has an active ban."
msgstr "Attention : cet utilisateur a déjà un bannissement actif." msgstr "Attention : cet utilisateur a déjà un bannissement actif."
#: users/views.py:392 #: users/views.py:400
msgid "The ban was edited." msgid "The ban was edited."
msgstr "Le bannissement a été modifié." msgstr "Le bannissement a été modifié."
#: users/views.py:405 #: users/views.py:413
msgid "The ban was deleted." msgid "The ban was deleted."
msgstr "Le bannissement a été supprimé." msgstr "Le bannissement a été supprimé."
#: users/views.py:422 #: users/views.py:430
msgid "The whitelist was added." msgid "The whitelist was added."
msgstr "L'accès gracieux a été ajouté." msgstr "L'accès gracieux a été ajouté."
#: users/views.py:426 #: users/views.py:434
msgid "Warning: this user already has an active whitelist." msgid "Warning: this user already has an active whitelist."
msgstr "Attention : cet utilisateur a déjà un accès gracieux actif." msgstr "Attention : cet utilisateur a déjà un accès gracieux actif."
#: users/views.py:446 #: users/views.py:454
msgid "The whitelist was edited." msgid "The whitelist was edited."
msgstr "L'accès gracieux a été ajouté." msgstr "L'accès gracieux a été ajouté."
#: users/views.py:461 #: users/views.py:469
msgid "The whitelist was deleted." msgid "The whitelist was deleted."
msgstr "L'accès gracieux a été supprimé." msgstr "L'accès gracieux a été supprimé."
#: users/views.py:466 #: users/views.py:474
msgid "whitelist" msgid "whitelist"
msgstr "accès gracieux" msgstr "accès gracieux"
#: users/views.py:481 #: users/views.py:489
msgid "The local email account was created." msgid "The local email account was created."
msgstr "Le compte mail local a été créé." msgstr "Le compte mail local a été créé."
#: users/views.py:504 #: users/views.py:512
msgid "The local email account was edited." msgid "The local email account was edited."
msgstr "Le compte mail local a été modifié." msgstr "Le compte mail local a été modifié."
#: users/views.py:527 #: users/views.py:535
msgid "The local email account was deleted." msgid "The local email account was deleted."
msgstr "Le compte mail local a été supprimé." msgstr "Le compte mail local a été supprimé."
#: users/views.py:532 #: users/views.py:540
msgid "email address" msgid "email address"
msgstr "adresse mail" msgstr "adresse mail"
#: users/views.py:548 #: users/views.py:556
msgid "The email settings were edited." msgid "The email settings were edited."
msgstr "Les paramètres mail ont été modifiés." msgstr "Les paramètres mail ont été modifiés."
#: users/views.py:551 users/views.py:1077 #: users/views.py:559 users/views.py:1085
msgid "An email to confirm your address was sent." msgid "An email to confirm your address was sent."
msgstr "Un mail pour confirmer votre adresse a été envoyé." msgstr "Un mail pour confirmer votre adresse a été envoyé."
#: users/views.py:576 #: users/views.py:584
msgid "The school was added." msgid "The school was added."
msgstr "L'établissement a été ajouté." msgstr "L'établissement a été ajouté."
#: users/views.py:594 #: users/views.py:602
msgid "The school was edited." msgid "The school was edited."
msgstr "L'établissement a été modifié." msgstr "L'établissement a été modifié."
#: users/views.py:616 #: users/views.py:624
msgid "The school was deleted." msgid "The school was deleted."
msgstr "L'établissement a été supprimé." msgstr "L'établissement a été supprimé."
#: users/views.py:621 #: users/views.py:629
#, python-format #, python-format
msgid "" msgid ""
"The school %s is assigned to at least one user, impossible to delete it." "The school %s is assigned to at least one user, impossible to delete it."
@ -1494,31 +1494,31 @@ msgstr ""
"L'établissement %s est assigné à au moins un utilisateur, impossible de le " "L'établissement %s est assigné à au moins un utilisateur, impossible de le "
"supprimer." "supprimer."
#: users/views.py:639 #: users/views.py:647
msgid "The shell was added." msgid "The shell was added."
msgstr "L'interface en ligne de commande a été ajoutée." msgstr "L'interface en ligne de commande a été ajoutée."
#: users/views.py:654 #: users/views.py:662
msgid "The shell was edited." msgid "The shell was edited."
msgstr "L'interface en ligne de commande a été modifiée." msgstr "L'interface en ligne de commande a été modifiée."
#: users/views.py:669 #: users/views.py:677
msgid "The shell was deleted." msgid "The shell was deleted."
msgstr "L'interface en ligne de commande a été supprimée." msgstr "L'interface en ligne de commande a été supprimée."
#: users/views.py:682 #: users/views.py:690
msgid "The group of rights was added." msgid "The group of rights was added."
msgstr "Le groupe de droits a été ajouté." msgstr "Le groupe de droits a été ajouté."
#: users/views.py:700 #: users/views.py:708
msgid "The group of rights was edited." msgid "The group of rights was edited."
msgstr "Le groupe de droits a été modifié." msgstr "Le groupe de droits a été modifié."
#: users/views.py:720 #: users/views.py:728
msgid "The group of rights was deleted." msgid "The group of rights was deleted."
msgstr "Le groupe de droits a été supprimé." msgstr "Le groupe de droits a été supprimé."
#: users/views.py:725 #: users/views.py:733
#, python-format #, python-format
msgid "" msgid ""
"The group of rights %s is assigned to at least one user, impossible to " "The group of rights %s is assigned to at least one user, impossible to "
@ -1527,37 +1527,37 @@ msgstr ""
"Le groupe de droits %s est assigné à au moins un utilisateur, impossible de " "Le groupe de droits %s est assigné à au moins un utilisateur, impossible de "
"le supprimer." "le supprimer."
#: users/views.py:761 #: users/views.py:769
#, python-format #, python-format
msgid "%s users were archived." msgid "%s users were archived."
msgstr "%s utilisateurs ont été archivés." msgstr "%s utilisateurs ont été archivés."
#: users/views.py:990 users/views.py:1073 #: users/views.py:998 users/views.py:1081
msgid "The user doesn't exist." msgid "The user doesn't exist."
msgstr "L'utilisateur n'existe pas." msgstr "L'utilisateur n'existe pas."
#: users/views.py:992 users/views.py:1000 #: users/views.py:1000 users/views.py:1008
msgid "Reset" msgid "Reset"
msgstr "Réinitialiser" msgstr "Réinitialiser"
#: users/views.py:997 #: users/views.py:1005
msgid "An email to reset the password was sent." msgid "An email to reset the password was sent."
msgstr "Un mail pour réinitialiser le mot de passe a été envoyé." msgstr "Un mail pour réinitialiser le mot de passe a été envoyé."
#: users/views.py:1015 #: users/views.py:1023
msgid "Error: please contact an admin." msgid "Error: please contact an admin."
msgstr "Erreur : veuillez contacter un admin." msgstr "Erreur : veuillez contacter un admin."
#: users/views.py:1053 #: users/views.py:1061
#, python-format #, python-format
msgid "The %s address was confirmed." msgid "The %s address was confirmed."
msgstr "L'adresse mail %s a été confirmée." msgstr "L'adresse mail %s a été confirmée."
#: users/views.py:1100 #: users/views.py:1108
msgid "Incorrect URL, or already registered device." msgid "Incorrect URL, or already registered device."
msgstr "URL incorrect, ou appareil déjà enregistré." msgstr "URL incorrect, ou appareil déjà enregistré."
#: users/views.py:1112 #: users/views.py:1120
msgid "" msgid ""
"Successful registration! Please disconnect and reconnect your Ethernet cable " "Successful registration! Please disconnect and reconnect your Ethernet cable "
"to get Internet access." "to get Internet access."
@ -1565,7 +1565,7 @@ msgstr ""
"Enregistrement réussi ! Veuillez débrancher et rebrancher votre câble " "Enregistrement réussi ! Veuillez débrancher et rebrancher votre câble "
"Ethernet pour avoir accès à Internet." "Ethernet pour avoir accès à Internet."
#: users/views.py:1152 users/views.py:1176 users/views.py:1191 #: users/views.py:1160 users/views.py:1184 users/views.py:1199
msgid "The mailing list doesn't exist." msgid "The mailing list doesn't exist."
msgstr "La liste de diffusion n'existe pas." msgstr "La liste de diffusion n'existe pas."

View file

@ -60,7 +60,6 @@ from django.db.models.signals import post_save, post_delete, m2m_changed
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.template import loader from django.template import loader
from django.core.mail import send_mail
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import transaction from django.db import transaction
from django.utils import timezone from django.utils import timezone
@ -84,6 +83,7 @@ from re2o.settings import LDAP, GID_RANGES, UID_RANGES
from re2o.field_permissions import FieldPermissionModelMixin from re2o.field_permissions import FieldPermissionModelMixin
from re2o.mixins import AclMixin, RevMixin from re2o.mixins import AclMixin, RevMixin
from re2o.base import smtp_check from re2o.base import smtp_check
from re2o.mail_utils import send_mail
from cotisations.models import Cotisation, Facture, Paiement, Vente from cotisations.models import Cotisation, Facture, Paiement, Vente
from machines.models import Domain, Interface, Machine, regen from machines.models import Domain, Interface, Machine, regen
@ -244,6 +244,7 @@ class User(
REQUIRED_FIELDS = ["surname", "email"] REQUIRED_FIELDS = ["surname", "email"]
objects = UserManager() objects = UserManager()
request = None
class Meta: class Meta:
permissions = ( permissions = (
@ -749,7 +750,7 @@ class User(
name__in=list(queryset_users.values_list("pseudo", flat=True)) name__in=list(queryset_users.values_list("pseudo", flat=True))
) )
def notif_inscription(self): def notif_inscription(self, request=None):
""" Prend en argument un objet user, envoie un mail de bienvenue """ """ Prend en argument un objet user, envoie un mail de bienvenue """
template = loader.get_template("users/email_welcome") template = loader.get_template("users/email_welcome")
mailmessageoptions, _created = MailMessageOption.objects.get_or_create() mailmessageoptions, _created = MailMessageOption.objects.get_or_create()
@ -761,7 +762,9 @@ class User(
"welcome_mail_en": mailmessageoptions.welcome_mail_en, "welcome_mail_en": mailmessageoptions.welcome_mail_en,
"pseudo": self.pseudo, "pseudo": self.pseudo,
} }
send_mail( send_mail(
request,
"Bienvenue au %(name)s / Welcome to %(name)s" "Bienvenue au %(name)s / Welcome to %(name)s"
% {"name": AssoOption.get_cached_value("name")}, % {"name": AssoOption.get_cached_value("name")},
"", "",
@ -769,7 +772,6 @@ class User(
[self.email], [self.email],
html_message=template.render(context), html_message=template.render(context),
) )
return
def reset_passwd_mail(self, request): def reset_passwd_mail(self, request):
""" Prend en argument un request, envoie un mail de """ Prend en argument un request, envoie un mail de
@ -789,7 +791,9 @@ class User(
), ),
"expire_in": str(GeneralOption.get_cached_value("req_expire_hrs")), "expire_in": str(GeneralOption.get_cached_value("req_expire_hrs")),
} }
send_mail( send_mail(
request,
"Changement de mot de passe de %(name)s / Password change for " "Changement de mot de passe de %(name)s / Password change for "
"%(name)s" % {"name": AssoOption.get_cached_value("name")}, "%(name)s" % {"name": AssoOption.get_cached_value("name")},
template.render(context), template.render(context),
@ -797,7 +801,6 @@ class User(
[req.user.email], [req.user.email],
fail_silently=False, fail_silently=False,
) )
return
def send_confirm_email_if_necessary(self, request): def send_confirm_email_if_necessary(self, request):
"""Update the user's email state: """Update the user's email state:
@ -873,7 +876,9 @@ class User(
"confirm_before_fr": self.confirm_email_before_date().strftime("%d/%m/%Y"), "confirm_before_fr": self.confirm_email_before_date().strftime("%d/%m/%Y"),
"confirm_before_en": self.confirm_email_before_date().strftime("%Y-%m-%d"), "confirm_before_en": self.confirm_email_before_date().strftime("%Y-%m-%d"),
} }
send_mail( send_mail(
request,
"Confirmation du mail de %(name)s / Email confirmation for " "Confirmation du mail de %(name)s / Email confirmation for "
"%(name)s" % {"name": AssoOption.get_cached_value("name")}, "%(name)s" % {"name": AssoOption.get_cached_value("name")},
template.render(context), template.render(context),
@ -883,7 +888,7 @@ class User(
) )
return return
def autoregister_machine(self, mac_address, nas_type): def autoregister_machine(self, mac_address, nas_type, request=None):
""" Fonction appellée par freeradius. Enregistre la mac pour """ Fonction appellée par freeradius. Enregistre la mac pour
une machine inconnue sur le compte de l'user""" une machine inconnue sur le compte de l'user"""
allowed, _message, _rights = Machine.can_create(self, self.id) allowed, _message, _rights = Machine.can_create(self, self.id)
@ -927,7 +932,9 @@ class User(
"asso_email": AssoOption.get_cached_value("contact"), "asso_email": AssoOption.get_cached_value("contact"),
"pseudo": self.pseudo, "pseudo": self.pseudo,
} }
send_mail( send_mail(
None,
"Ajout automatique d'une machine / New machine autoregistered", "Ajout automatique d'une machine / New machine autoregistered",
"", "",
GeneralOption.get_cached_value("email_from"), GeneralOption.get_cached_value("email_from"),
@ -936,7 +943,7 @@ class User(
) )
return return
def notif_disable(self): def notif_disable(self, request=None):
"""Envoi un mail de notification informant que l'adresse mail n'a pas été confirmée""" """Envoi un mail de notification informant que l'adresse mail n'a pas été confirmée"""
template = loader.get_template("users/email_disable_notif") template = loader.get_template("users/email_disable_notif")
context = { context = {
@ -945,7 +952,9 @@ class User(
"asso_email": AssoOption.get_cached_value("contact"), "asso_email": AssoOption.get_cached_value("contact"),
"site_name": GeneralOption.get_cached_value("site_name"), "site_name": GeneralOption.get_cached_value("site_name"),
} }
send_mail( send_mail(
request,
"Suspension automatique / Automatic suspension", "Suspension automatique / Automatic suspension",
template.render(context), template.render(context),
GeneralOption.get_cached_value("email_from"), GeneralOption.get_cached_value("email_from"),
@ -1509,8 +1518,10 @@ def user_post_save(**kwargs):
is_created = kwargs["created"] is_created = kwargs["created"]
user = kwargs["instance"] user = kwargs["instance"]
EMailAddress.objects.get_or_create(local_part=user.pseudo.lower(), user=user) EMailAddress.objects.get_or_create(local_part=user.pseudo.lower(), user=user)
if is_created: if is_created:
user.notif_inscription() user.notif_inscription(user.request)
user.state_sync() user.state_sync()
user.ldap_sync( user.ldap_sync(
base=True, access_refresh=True, mac_refresh=False, group_refresh=True base=True, access_refresh=True, mac_refresh=False, group_refresh=True
@ -1737,13 +1748,14 @@ class Ban(RevMixin, AclMixin, models.Model):
date_start = models.DateTimeField(auto_now_add=True) date_start = models.DateTimeField(auto_now_add=True)
date_end = models.DateTimeField() date_end = models.DateTimeField()
state = models.IntegerField(choices=STATES, default=STATE_HARD) state = models.IntegerField(choices=STATES, default=STATE_HARD)
request = None
class Meta: class Meta:
permissions = (("view_ban", _("Can view a ban object")),) permissions = (("view_ban", _("Can view a ban object")),)
verbose_name = _("ban") verbose_name = _("ban")
verbose_name_plural = _("bans") verbose_name_plural = _("bans")
def notif_ban(self): def notif_ban(self, request=None):
""" Prend en argument un objet ban, envoie un mail de notification """ """ Prend en argument un objet ban, envoie un mail de notification """
template = loader.get_template("users/email_ban_notif") template = loader.get_template("users/email_ban_notif")
context = { context = {
@ -1752,7 +1764,9 @@ class Ban(RevMixin, AclMixin, models.Model):
"date_end": self.date_end, "date_end": self.date_end,
"asso_name": AssoOption.get_cached_value("name"), "asso_name": AssoOption.get_cached_value("name"),
} }
send_mail( send_mail(
request,
"Déconnexion disciplinaire / Disciplinary disconnection", "Déconnexion disciplinaire / Disciplinary disconnection",
template.render(context), template.render(context),
GeneralOption.get_cached_value("email_from"), GeneralOption.get_cached_value("email_from"),
@ -1795,7 +1809,7 @@ def ban_post_save(**kwargs):
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False) user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
regen("mailing") regen("mailing")
if is_created: if is_created:
ban.notif_ban() ban.notif_ban(ban.request)
regen("dhcp") regen("dhcp")
regen("mac_ip_list") regen("mac_ip_list")
if user.has_access(): if user.has_access():

View file

@ -119,6 +119,8 @@ def new_user(request):
""" Vue de création d'un nouvel utilisateur, """ Vue de création d'un nouvel utilisateur,
envoie un mail pour le mot de passe""" envoie un mail pour le mot de passe"""
user = AdherentCreationForm(request.POST or None, user=request.user) user = AdherentCreationForm(request.POST or None, user=request.user)
user.request = request
GTU_sum_up = GeneralOption.get_cached_value("GTU_sum_up") GTU_sum_up = GeneralOption.get_cached_value("GTU_sum_up")
GTU = GeneralOption.get_cached_value("GTU") GTU = GeneralOption.get_cached_value("GTU")
is_set_password_allowed = OptionalUser.get_cached_value("allow_set_password_during_user_creation") is_set_password_allowed = OptionalUser.get_cached_value("allow_set_password_during_user_creation")
@ -165,6 +167,8 @@ def new_club(request):
""" Vue de création d'un nouveau club, """ Vue de création d'un nouveau club,
envoie un mail pour le mot de passe""" envoie un mail pour le mot de passe"""
club = ClubForm(request.POST or None, user=request.user) club = ClubForm(request.POST or None, user=request.user)
club.request = request
if club.is_valid(): if club.is_valid():
club = club.save(commit=False) club = club.save(commit=False)
club.save() club.save()
@ -368,6 +372,8 @@ def add_ban(request, user, userid):
Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement""" Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement"""
ban_instance = Ban(user=user) ban_instance = Ban(user=user)
ban = BanForm(request.POST or None, instance=ban_instance) ban = BanForm(request.POST or None, instance=ban_instance)
ban.request = request
if ban.is_valid(): if ban.is_valid():
ban.save() ban.save()
messages.success(request, _("The ban was added.")) messages.success(request, _("The ban was added."))
@ -386,6 +392,8 @@ def edit_ban(request, ban_instance, **_kwargs):
(a fortiori bureau) (a fortiori bureau)
Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement""" Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement"""
ban = BanForm(request.POST or None, instance=ban_instance) ban = BanForm(request.POST or None, instance=ban_instance)
ban.request = request
if ban.is_valid(): if ban.is_valid():
if ban.changed_data: if ban.changed_data:
ban.save() ban.save()