mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-25 22:22:26 +00:00
Improve internationalisation for email templates, scripts, commands and error messages
This commit is contained in:
parent
7894e3267a
commit
e26d21064e
19 changed files with 135 additions and 120 deletions
|
@ -80,21 +80,21 @@ def hash_password_salt(hashed_password):
|
||||||
try:
|
try:
|
||||||
digest = b64decode(hashed_password[6:])
|
digest = b64decode(hashed_password[6:])
|
||||||
except TypeError as error:
|
except TypeError as error:
|
||||||
raise ValueError("b64 error for `hashed_password` : %s" % error)
|
raise ValueError("b64 error for `hashed_password`: %s." % error)
|
||||||
if len(digest) < 20:
|
if len(digest) < 20:
|
||||||
raise ValueError("`hashed_password` too short")
|
raise ValueError("`hashed_password` too short.")
|
||||||
return digest[20:]
|
return digest[20:]
|
||||||
elif hashed_password.upper().startswith("{SMD5}"):
|
elif hashed_password.upper().startswith("{SMD5}"):
|
||||||
try:
|
try:
|
||||||
digest = b64decode(hashed_password[7:])
|
digest = b64decode(hashed_password[7:])
|
||||||
except TypeError as error:
|
except TypeError as error:
|
||||||
raise ValueError("b64 error for `hashed_password` : %s" % error)
|
raise ValueError("b64 error for `hashed_password`: %s." % error)
|
||||||
if len(digest) < 16:
|
if len(digest) < 16:
|
||||||
raise ValueError("`hashed_password` too short")
|
raise ValueError("`hashed_password` too short.")
|
||||||
return digest[16:]
|
return digest[16:]
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"`hashed_password` should start with '{SSHA}' or '{CRYPT}' or '{SMD5}'"
|
"`hashed_password` should start with '{SSHA}' or '{CRYPT}' or '{SMD5}'."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Command(BaseCommand):
|
||||||
for item in os.popen("git shortlog -s -n").read().split("\n")
|
for item in os.popen("git shortlog -s -n").read().split("\n")
|
||||||
if "\t" in item
|
if "\t" in item
|
||||||
]
|
]
|
||||||
self.stdout.write(self.style.SUCCESS("Exportation Successful"))
|
self.stdout.write(self.style.SUCCESS("Exportation successful!"))
|
||||||
with open("re2o/contributors.py", "w") as contrib_file:
|
with open("re2o/contributors.py", "w") as contrib_file:
|
||||||
content = self._contrib_file_generator(contributors)
|
content = self._contrib_file_generator(contributors)
|
||||||
contrib_file.write(content)
|
contrib_file.write(content)
|
||||||
|
|
|
@ -61,7 +61,7 @@ class FormRevMixin(object):
|
||||||
)
|
)
|
||||||
elif self.changed_data:
|
elif self.changed_data:
|
||||||
reversion.set_comment(
|
reversion.set_comment(
|
||||||
"Field(s) altered : %s"
|
"Field(s) edited: %s"
|
||||||
% ", ".join(field for field in self.changed_data)
|
% ", ".join(field for field in self.changed_data)
|
||||||
)
|
)
|
||||||
return super(FormRevMixin, self).save(*args, **kwargs)
|
return super(FormRevMixin, self).save(*args, **kwargs)
|
||||||
|
|
|
@ -53,7 +53,7 @@ def get_user(pseudo):
|
||||||
raise CommandError("Invalid user.")
|
raise CommandError("Invalid user.")
|
||||||
if len(user) > 1:
|
if len(user) > 1:
|
||||||
raise CommandError(
|
raise CommandError(
|
||||||
"Several users match this username. This SHOULD" " NOT happen."
|
"Several users match this username. This SHOULD NOT happen."
|
||||||
)
|
)
|
||||||
return user[0]
|
return user[0]
|
||||||
|
|
||||||
|
@ -95,5 +95,5 @@ def form_cli(Form, user, action, *args, **kwargs):
|
||||||
reversion.set_comment(action)
|
reversion.set_comment(action)
|
||||||
|
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
"%s : done. The edit may take several minutes to" " apply.\n" % action
|
"%s: done. The edit may take several minutes to apply.\n" % action
|
||||||
)
|
)
|
||||||
|
|
|
@ -88,7 +88,7 @@ def get_model(model_name):
|
||||||
app_label, name = splitted
|
app_label, name = splitted
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise template.TemplateSyntaxError(
|
raise template.TemplateSyntaxError(
|
||||||
"%r is an inconsistent model name" % model_name
|
"%r is an inconsistent model name." % model_name
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
app_label, name = None, splitted[0]
|
app_label, name = None, splitted[0]
|
||||||
|
@ -101,7 +101,7 @@ def get_model(model_name):
|
||||||
content_type = ContentType.objects.get(model=name.lower())
|
content_type = ContentType.objects.get(model=name.lower())
|
||||||
except ContentType.DoesNotExist:
|
except ContentType.DoesNotExist:
|
||||||
raise template.TemplateSyntaxError(
|
raise template.TemplateSyntaxError(
|
||||||
"%r is not a valid model for an acl tag" % model_name
|
"%r is not a valid model for an acl tag." % model_name
|
||||||
)
|
)
|
||||||
except ContentType.MultipleObjectsReturned:
|
except ContentType.MultipleObjectsReturned:
|
||||||
raise template.TemplateSyntaxError(
|
raise template.TemplateSyntaxError(
|
||||||
|
@ -178,7 +178,7 @@ def get_callback(tag_name, obj=None):
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
|
|
||||||
raise template.TemplateSyntaxError("%r tag is not a valid can_xxx tag" % tag_name)
|
raise template.TemplateSyntaxError("%r tag is not a valid can_xxx tag." % tag_name)
|
||||||
|
|
||||||
|
|
||||||
def acl_fct(callback, reverse):
|
def acl_fct(callback, reverse):
|
||||||
|
@ -264,7 +264,7 @@ def acl_change_filter(parser, token):
|
||||||
args = tag_content[3:]
|
args = tag_content[3:]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise template.TemplateSyntaxError(
|
raise template.TemplateSyntaxError(
|
||||||
"%r tag require at least 2 argument: the model and the field"
|
"%r tag require at least 2 argument: the model and the field."
|
||||||
% token.contents.split()[0]
|
% token.contents.split()[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ def acl_model_filter(parser, token):
|
||||||
args = tag_content[2:]
|
args = tag_content[2:]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise template.TemplateSyntaxError(
|
raise template.TemplateSyntaxError(
|
||||||
"%r tag require at least 1 argument: the model" % token.contents.split()[0]
|
"%r tag require at least 1 argument: the model." % token.contents.split()[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
model = get_model(model_name)
|
model = get_model(model_name)
|
||||||
|
@ -345,7 +345,7 @@ def acl_instance_filter(parser, token):
|
||||||
args = tag_content[2:]
|
args = tag_content[2:]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise template.TemplateSyntaxError(
|
raise template.TemplateSyntaxError(
|
||||||
"%r tag require at least 1 argument: the instance"
|
"%r tag require at least 1 argument: the instance."
|
||||||
% token.contents.split()[0]
|
% token.contents.split()[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% if ticket.user %} {{ ticket.user.get_full_name }} opened a ticket.
|
{% if ticket.user %} {{ ticket.user.get_full_name }} opened a ticket.
|
||||||
Profil: {{site_url}}{% url 'users:profil' ticket.user.id%}
|
Profile: {{site_url}}{% url 'users:profil' ticket.user.id%}
|
||||||
Answer to the address: {{ticket.user.get_mail}}.
|
Answer to the address: {{ticket.user.get_mail}}.
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{% if ticket.user %} {{ ticket.user.get_full_name }} à ouvert un ticket.
|
{% if ticket.user %} {{ ticket.user.get_full_name }} a ouvert un ticket.
|
||||||
Profile: {{site_url}}{% url 'users:profil' ticket.user.id%}
|
Profil : {{site_url}}{% url 'users:profil' ticket.user.id%}
|
||||||
Répondre à l'adresse: {{ticket.user.get_mail}}.
|
Répondre à l'adresse : {{ticket.user.get_mail}}.
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
Un utilisateur anonyme (non connecté) à ouvert un ticket.
|
Un utilisateur anonyme (non connecté) a ouvert un ticket.
|
||||||
Répondre à l'adresse: {{ticket.email}}.
|
Répondre à l'adresse : {{ticket.email}}.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
Titre: {{ticket.title}}
|
Titre : {{ticket.title}}
|
||||||
|
|
||||||
Description: {{ticket.description}}
|
Description : {{ticket.description}}
|
||||||
|
|
|
@ -13,7 +13,7 @@ from random import randint
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Anonymize the data in the database in order to use them on critical servers (dev, personnal...). Every information will be overwritten using non-personnal informations. This script must follow any modification of the database.\nOptionnal argument: {id|id|id|...} to exclude users from anonymisation"
|
help = "Anonymise the data in the database in order to use them on critical servers (dev, personal...). Every information will be overwritten using non-personal information. This script must follow any modification of the database.\nOptional argument: {id|id|id|...} to exclude users from anonymisation."
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument("user_id", nargs="+", type=int, help="User ID")
|
parser.add_argument("user_id", nargs="+", type=int, help="User ID")
|
||||||
|
@ -22,14 +22,14 @@ class Command(BaseCommand):
|
||||||
users_ids = kwargs["user_id"]
|
users_ids = kwargs["user_id"]
|
||||||
for user_id in users_ids:
|
for user_id in users_ids:
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"User: {} will not be anonymised".format(
|
"User: {} will not be anonymised.".format(
|
||||||
User.objects.filter(id=user_id).get().name
|
User.objects.filter(id=user_id).get().name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.WARNING(
|
self.style.WARNING(
|
||||||
"\nDISCLAIMER\nThis function will make your database unusable for production. Are you sure you want to run this ?(doit): "
|
"\nDISCLAIMER\nThis function will make your database unusable for production. Are you sure you want to run this? (doit): "
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if input() == "doit":
|
if input() == "doit":
|
||||||
|
@ -43,52 +43,52 @@ class Command(BaseCommand):
|
||||||
d = Domain.objects.all()
|
d = Domain.objects.all()
|
||||||
m = Machine.objects.filter(~Q(user_id__in=users_ids))
|
m = Machine.objects.filter(~Q(user_id__in=users_ids))
|
||||||
|
|
||||||
self.stdout.write("Supression de l'école...")
|
self.stdout.write("Deletion of the school...")
|
||||||
# Create a fake School to put everyone in it.
|
# Create a fake School to put everyone in it.
|
||||||
ecole = School(name="Ecole des Ninja")
|
ecole = School(name="Ninja School")
|
||||||
ecole.save()
|
ecole.save()
|
||||||
u.update(school=ecole)
|
u.update(school=ecole)
|
||||||
self.stdout.write(self.style.SUCCESS("done ..."))
|
self.stdout.write(self.style.SUCCESS("Done..."))
|
||||||
|
|
||||||
self.stdout.write("Supression des chambres...")
|
self.stdout.write("Deletion of rooms...")
|
||||||
a.update(room=None)
|
a.update(room=None)
|
||||||
c.update(room=None)
|
c.update(room=None)
|
||||||
self.stdout.write(self.style.SUCCESS("done ..."))
|
self.stdout.write(self.style.SUCCESS("Done..."))
|
||||||
|
|
||||||
self.stdout.write("Supression des mails...")
|
self.stdout.write("Deletion of email addresses...")
|
||||||
u.update(
|
u.update(
|
||||||
email="example@example.org",
|
email="example@example.org",
|
||||||
local_email_redirect=False,
|
local_email_redirect=False,
|
||||||
local_email_enabled=False,
|
local_email_enabled=False,
|
||||||
)
|
)
|
||||||
self.stdout.write(self.style.SUCCESS("done ..."))
|
self.stdout.write(self.style.SUCCESS("Done..."))
|
||||||
|
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"Supression des noms, prenoms, pseudo, telephone, commentaire..."
|
"Deletion of first names, surnames, usernames, telephone numbers, comments..."
|
||||||
)
|
)
|
||||||
a.update(name=Concat(Value("name of "), "id"))
|
a.update(name=Concat(Value("First name of "), "id"))
|
||||||
self.stdout.write(self.style.SUCCESS("done name"))
|
self.stdout.write(self.style.SUCCESS("Done for first names..."))
|
||||||
|
|
||||||
a.update(surname=Concat(Value("surname of "), "id"))
|
a.update(surname=Concat(Value("Surname of "), "id"))
|
||||||
self.stdout.write(self.style.SUCCESS("done surname"))
|
self.stdout.write(self.style.SUCCESS("Done for surnames..."))
|
||||||
|
|
||||||
u.update(pseudo=F("id"))
|
u.update(pseudo=F("id"))
|
||||||
self.stdout.write(self.style.SUCCESS("done pseudo"))
|
self.stdout.write(self.style.SUCCESS("Done for usernames..."))
|
||||||
|
|
||||||
a.update(telephone=Concat(Value("phone of "), "id"))
|
a.update(telephone=Concat(Value("Telephone number of "), "id"))
|
||||||
self.stdout.write(self.style.SUCCESS("done phone"))
|
self.stdout.write(self.style.SUCCESS("Done for telephone numbers..."))
|
||||||
|
|
||||||
a.update(comment=Concat(Value("commentaire of "), "id"))
|
a.update(comment=Concat(Value("Comment of "), "id"))
|
||||||
self.stdout.write(self.style.SUCCESS("done ..."))
|
self.stdout.write(self.style.SUCCESS("Done for comments..."))
|
||||||
|
|
||||||
self.stdout.write("Renommage des machines...")
|
self.stdout.write("Renaming of machines...")
|
||||||
m.update(
|
m.update(
|
||||||
name=Concat(Value("Machine "), F("id"), Value(" of "), F("user_id"))
|
name=Concat(Value("Machine "), F("id"), Value(" of "), F("user_id"))
|
||||||
)
|
)
|
||||||
d.update(name=Concat(Value("Domaine id "), F("id")))
|
d.update(name=Concat(Value("Domain id "), F("id")))
|
||||||
self.stdout.write(self.style.SUCCESS("done ..."))
|
self.stdout.write(self.style.SUCCESS("Done..."))
|
||||||
|
|
||||||
self.stdout.write("Unification du mot de passe...")
|
self.stdout.write("Unification of the password...")
|
||||||
# Define the password
|
# Define the password
|
||||||
chars = string.ascii_letters + string.digits + "!@#$%^&*()"
|
chars = string.ascii_letters + string.digits + "!@#$%^&*()"
|
||||||
taille = 20
|
taille = 20
|
||||||
|
@ -99,19 +99,19 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.HTTP_NOT_MODIFIED(
|
self.style.HTTP_NOT_MODIFIED(
|
||||||
"The password will be: {}".format(password)
|
"The password will be: {}.".format(password)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
u.update(pwd_ntlm=hashNT(password))
|
u.update(pwd_ntlm=hashNT(password))
|
||||||
u.update(password=makeSecret(password))
|
u.update(password=makeSecret(password))
|
||||||
self.stdout.write(self.style.SUCCESS("done..."))
|
self.stdout.write(self.style.SUCCESS("Done..."))
|
||||||
|
|
||||||
self.stdout.write("Suppression de l'historique (This may take some time)")
|
self.stdout.write("Deletion of the history (this may take some time)...")
|
||||||
Revision.objects.all().delete()
|
Revision.objects.all().delete()
|
||||||
self.stdout.write(self.style.SUCCESS("done..."))
|
self.stdout.write(self.style.SUCCESS("Done..."))
|
||||||
|
|
||||||
self.stdout.write("Data anonymized!")
|
self.stdout.write("Data anonymised!")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.stdout.write("Anonymisation aborted")
|
self.stdout.write("Anonymisation aborted!")
|
|
@ -45,14 +45,14 @@ class Command(BaseCommand):
|
||||||
"--full",
|
"--full",
|
||||||
"-f",
|
"-f",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Full archive users, i.e. delete their email address, machines and remove them from the LDAP.",
|
help="Fully archive users, i.e. delete their email address, machines and remove them from the LDAP.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--date",
|
"--date",
|
||||||
"-d",
|
"-d",
|
||||||
default=datetime.date.today().strftime("%d/%m/%Y"),
|
default=datetime.date.today().strftime("%d/%m/%Y"),
|
||||||
type=valid_date,
|
type=valid_date,
|
||||||
help="Users which membership ends sooner than this date will be archived.",
|
help="Users whose membership ends sooner than this date will be archived.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--show",
|
"--show",
|
||||||
|
@ -63,7 +63,7 @@ class Command(BaseCommand):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-y",
|
"-y",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Do not ask for confirmation befor full archiving.",
|
help="Do not ask for confirmation before fully archiving.",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **kwargs):
|
def handle(self, *args, **kwargs):
|
||||||
|
@ -87,7 +87,7 @@ class Command(BaseCommand):
|
||||||
if full_archive and not force:
|
if full_archive and not force:
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.WARNING(
|
self.style.WARNING(
|
||||||
"Please confirm full archiving (it is a critical operation !) [Y/n]"
|
"Please confirm fully archiving (it is a critical operation!) [Y/n]"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if input() != "Y":
|
if input() != "Y":
|
||||||
|
@ -95,13 +95,13 @@ class Command(BaseCommand):
|
||||||
return
|
return
|
||||||
if full_archive:
|
if full_archive:
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"Full archiving users with a membership ending prior to %s"
|
"Fully archiving users with a membership ending prior to %s."
|
||||||
% date.strftime("%d/%m/%Y")
|
% date.strftime("%d/%m/%Y")
|
||||||
)
|
)
|
||||||
User.mass_full_archive(to_archive_list)
|
User.mass_full_archive(to_archive_list)
|
||||||
else:
|
else:
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"Archiving users with a membership ending prior to %s"
|
"Archiving users with a membership ending prior to %s."
|
||||||
% date.strftime("%d/%m/%Y")
|
% date.strftime("%d/%m/%Y")
|
||||||
)
|
)
|
||||||
to_archive_list = to_archive_list.exclude(state=User.STATE_ARCHIVE)
|
to_archive_list = to_archive_list.exclude(state=User.STATE_ARCHIVE)
|
||||||
|
|
|
@ -28,7 +28,7 @@ from re2o.script_utils import get_user, get_system_user, form_cli
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Changer le mot de passe d'un utilisateur"
|
help = "Change the password of a user."
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument("target_username", nargs="?")
|
parser.add_argument("target_username", nargs="?")
|
||||||
|
@ -44,8 +44,8 @@ class Command(BaseCommand):
|
||||||
if not ok:
|
if not ok:
|
||||||
raise CommandError(msg)
|
raise CommandError(msg)
|
||||||
|
|
||||||
self.stdout.write("Changement du mot de passe de %s" % target_user.pseudo)
|
self.stdout.write("Password change of %s" % target_user.pseudo)
|
||||||
|
|
||||||
form_cli(
|
form_cli(
|
||||||
PassForm, current_user, "Changement du mot de passe", instance=target_user
|
PassForm, current_user, "Password change", instance=target_user
|
||||||
)
|
)
|
||||||
|
|
|
@ -32,7 +32,7 @@ from re2o.script_utils import get_user, get_system_user
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Change the default shell of a user"
|
help = "Change the default shell of a user."
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument("target_username", nargs="?")
|
parser.add_argument("target_username", nargs="?")
|
||||||
|
@ -52,37 +52,36 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
shells = ListShell.objects.all()
|
shells = ListShell.objects.all()
|
||||||
|
|
||||||
current_shell = "inconnu"
|
current_shell = "unknown"
|
||||||
if target_user.shell:
|
if target_user.shell:
|
||||||
current_shell = target_user.shell.get_pretty_name()
|
current_shell = target_user.shell.get_pretty_name()
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"Choisissez un shell pour l'utilisateur %s (le shell actuel est "
|
"Choose a shell for the user %s (the current shell is"
|
||||||
"%s) :" % (target_user.pseudo, current_shell)
|
" %s):" % (target_user.pseudo, current_shell)
|
||||||
)
|
)
|
||||||
for shell in shells:
|
for shell in shells:
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"%d - %s (%s)" % (shell.id, shell.get_pretty_name(), shell.shell)
|
"%d - %s (%s)" % (shell.id, shell.get_pretty_name(), shell.shell)
|
||||||
)
|
)
|
||||||
shell_id = input("Entrez un nombre : ")
|
shell_id = input("Enter a number: ")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
shell_id = int(shell_id)
|
shell_id = int(shell_id)
|
||||||
except:
|
except:
|
||||||
raise CommandError("Choix invalide")
|
raise CommandError("Invalid choice.")
|
||||||
|
|
||||||
shell = ListShell.objects.filter(id=shell_id)
|
shell = ListShell.objects.filter(id=shell_id)
|
||||||
if not shell:
|
if not shell:
|
||||||
raise CommandError("Choix invalide")
|
raise CommandError("Invalid choice.")
|
||||||
|
|
||||||
target_user.shell = shell.first()
|
target_user.shell = shell.first()
|
||||||
with transaction.atomic(), reversion.create_revision():
|
with transaction.atomic(), reversion.create_revision():
|
||||||
target_user.save()
|
target_user.save()
|
||||||
reversion.set_user(current_user)
|
reversion.set_user(current_user)
|
||||||
reversion.set_comment("Shell modifié")
|
reversion.set_comment("Shell changed.")
|
||||||
|
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(
|
||||||
"Shell modifié. La modification peut prendre quelques minutes "
|
"Shell changed. The change may take a few minutes to apply."
|
||||||
"pour s'appliquer."
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -27,7 +27,7 @@ from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Delete non members users (not yet active)"
|
help = "Delete non members users (not yet active)."
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
"""First deleting invalid invoices, and then deleting the users"""
|
"""First deleting invalid invoices, and then deleting the users"""
|
||||||
|
@ -38,6 +38,6 @@ class Command(BaseCommand):
|
||||||
.exclude(facture__valid=True)
|
.exclude(facture__valid=True)
|
||||||
.distinct()
|
.distinct()
|
||||||
)
|
)
|
||||||
print("Deleting " + str(users_to_delete.count()) + " users")
|
print("Deleting " + str(users_to_delete.count()) + " users.")
|
||||||
Facture.objects.filter(user__in=users_to_delete).delete()
|
Facture.objects.filter(user__in=users_to_delete).delete()
|
||||||
users_to_delete.delete()
|
users_to_delete.delete()
|
||||||
|
|
|
@ -57,8 +57,8 @@ DATE_FORMATS = [
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = (
|
help = (
|
||||||
"Update the time of the latest connection for users by matching "
|
"Update the time of the latest connection for users by matching"
|
||||||
"stdin against a set of regular expressions"
|
" stdin against a set of regular expressions."
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
|
|
@ -96,8 +96,8 @@ def sync_ldap():
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = (
|
help = (
|
||||||
"Destroy the current LDAP data and rebuild it from the DB data. "
|
"Destroy the current LDAP data and rebuild it from the DB data."
|
||||||
"Use with caution."
|
" Use with caution."
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
@ -109,6 +109,6 @@ class Command(BaseCommand):
|
||||||
server = settings.DATABASES["ldap"]["NAME"]
|
server = settings.DATABASES["ldap"]["NAME"]
|
||||||
|
|
||||||
flush_ldap(binddn, bindpass, server, usersdn, groupsdn)
|
flush_ldap(binddn, bindpass, server, usersdn, groupsdn)
|
||||||
self.stdout.write("LDAP emptied")
|
self.stdout.write("LDAP emptied.")
|
||||||
sync_ldap()
|
sync_ldap()
|
||||||
self.stdout.write("LDAP rebuilt")
|
self.stdout.write("LDAP rebuilt.")
|
||||||
|
|
|
@ -22,7 +22,7 @@ from users.models import User
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Synchronise le ldap à partir du sql. A utiliser dans un cron"
|
help = "Synchronise the LDAP from SQL. To be used in a cron."
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class Command(BaseCommand):
|
||||||
action="store_true",
|
action="store_true",
|
||||||
dest="full",
|
dest="full",
|
||||||
default=False,
|
default=False,
|
||||||
help="Régénération complète du ldap (y compris des machines)",
|
help="Complete regeneration of the LDAP (including machines).",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
|
|
@ -1,27 +1,31 @@
|
||||||
<p>Bonjour {{nom}} </p>
|
<p>Bonjour {{ nom }},</p>
|
||||||
|
|
||||||
<p>Une nouvelle machine a automatiquement été inscrite sur votre compte.</p>
|
<p>Une nouvelle machine a automatiquement été inscrite sur votre compte.</p>
|
||||||
|
|
||||||
<p>Si vous êtes à l'origine de la connexion de cet appareil en filaire ou wifi, ne tenez pas compte de cette notification</p>
|
<p>Si vous êtes à l'origine de la connexion de cet appareil en filaire ou Wi-Fi, ne tenez pas compte de ce mail.</p>
|
||||||
|
|
||||||
<p>La nouvelle machine possède l'adresse mac {{ mac_address }}, et s'est vu assigner le nom suivant : {{ interface_name }}</p>
|
<p>La nouvelle machine possède l'adresse MAC {{ mac_address }}, et s'est vu assigner le nom suivant : {{ interface_name }}.</p>
|
||||||
|
|
||||||
<p>Vous pouvez à tout moment modifier ces informations sur votre compte en ligne</p>
|
<p>Vous pouvez à tout moment modifier ces informations sur votre compte en ligne.</p>
|
||||||
|
|
||||||
<p>Si vous n'êtes pas à l'origine de cette connexion, merci de le signaler rapidement à {{asso_email}}</p>
|
<p>Si vous n'êtes pas à l'origine de cette connexion, veuillez le signaler rapidement à {{ asso_email }}.</p>
|
||||||
|
|
||||||
<p>À bientôt,<br>
|
<p>Respectueusement,<br>
|
||||||
L'équipe de {{asso_name}}.</p>
|
L'équipe de {{ asso_name }}.</p>
|
||||||
|
|
||||||
<p>---</p>
|
<p>---</p>
|
||||||
|
|
||||||
<p>A new device has been automatically added on your account.</p>
|
<p>Hello {{ nom }},</p>
|
||||||
|
|
||||||
<p>If you connected a new device recently, please don't take this mail into account<p>
|
<p>A new machine has been automatically added on your account.</p>
|
||||||
|
|
||||||
<p>The new device has this mac address : {{ mac_address }}, and this name : {{ interface_name }}</p>
|
<p>If you are the one who connected this machine with wire of Wi-Fi, don't take this mail into account.<p>
|
||||||
|
|
||||||
<p>Please contact us if you didn't connect a new device with this mail address {{asso_email}}.</p>
|
<p>The new machine has this MAC address: {{ mac_address }}, and has been assigned this name: {{ interface_name }}</p>
|
||||||
|
|
||||||
|
<p>At any time, you can edit this information on your online account.</p>
|
||||||
|
|
||||||
|
<p>If you didn't connect this machine, please report it quickly to {{ asso_email }}.</p>
|
||||||
|
|
||||||
<p>Regards,<br>
|
<p>Regards,<br>
|
||||||
The {{asso_name}} team.</p>
|
The {{ asso_name }} team.</p>
|
||||||
|
|
|
@ -1,8 +1,19 @@
|
||||||
Bonjour {{name}},
|
<p>Bonjour {{ name }},</p>
|
||||||
|
|
||||||
Vous avez été banni par un administrateur de {{ asso_name }} en raison de {{raison}}. Vous n'avez plus accès au réseau jusqu'au {{date_end}}.
|
<p>Vous avez été banni par un administrateur de {{ asso_name }} pour la raison suivante : {{ raison }}. Vous n'avez plus accès au réseau jusqu'au {{ date_end }}.</p>
|
||||||
|
|
||||||
Pour de plus amples informations, rendez-vous à l'accueil de {{ asso_name }}.
|
<p>Pour de plus amples renseignements, contactez le comité de direction de {{ asso_name }}.</p>
|
||||||
|
|
||||||
Cordialement,
|
<p>Respectueusement,<br>
|
||||||
L'équipe de {{ asso_name }}.
|
L'équipe de {{ asso_name }}.</p>
|
||||||
|
|
||||||
|
<p>---</p>
|
||||||
|
|
||||||
|
<p>Hello {{ name }},</p>
|
||||||
|
|
||||||
|
<p>You have been banned by a administrator of {{ asso_name }} for the following reason: {{ raison }}. You don't have access to the network anymore until {{ date_end }}.</p>
|
||||||
|
|
||||||
|
<p>For more information, contact the steering committee of {{ asso_name }}.</p>
|
||||||
|
|
||||||
|
<p>Regards,<br>
|
||||||
|
The {{ asso_name }} team.</p>
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
Bonjour {{ name }},
|
Bonjour {{ name }},
|
||||||
|
|
||||||
Vous trouverez ci-dessous une url permetant d'initialiser ou de reinitialiser votre
|
Vous trouverez ci-dessous une URL permettant d'initialiser ou de réinitialiser votre
|
||||||
compte {{ site_name }}. Celui-ci vous permet de gérer l'ensemble de vos équipements
|
mot de passe pour votre compte {{ site_name }}. Celui-ci vous permet de gérer l'ensemble
|
||||||
connectés, votre compte, vos factures, et tous les services proposés sur le réseau.
|
de vos équipements, votre compte, vos factures, et tous les services proposés sur le réseau.
|
||||||
|
|
||||||
{{ url }}
|
{{ url }}
|
||||||
|
|
||||||
Contactez les administrateurs si vous n'êtes pas à l'origine de cette requête.
|
Contactez les administrateurs si vous n'êtes pas à l'origine de cette requête.
|
||||||
|
|
||||||
Ce lien expirera dans {{ expire_in }}.
|
Ce lien expirera dans {{ expire_in }} heures.
|
||||||
|
|
||||||
Cordialement,
|
Respectueusement,
|
||||||
|
|
||||||
L'équipe de {{ asso }} (contact : {{ asso_mail }}).
|
L'équipe de {{ asso }} (contact : {{ asso_mail }}).
|
||||||
|
|
||||||
----------------------
|
---
|
||||||
|
|
||||||
Hi {{ name }},
|
Hello {{ name }},
|
||||||
|
|
||||||
You will find a link allowing you to change the password of your account on {{ site_name }}.
|
You will find below an URL allowing you to set or reset your the password of your account
|
||||||
On this website you will then be able to manage your devices on the {{ asso }}.
|
on {{ site_name }}. It enables you to manage your devices, your account, your invoices, and all
|
||||||
|
the services offered on the network.
|
||||||
|
|
||||||
{{ url }}
|
{{ url }}
|
||||||
|
|
||||||
This link will expire in {{ expire_in }}.
|
Contact the administrators if you didn't request this.
|
||||||
|
|
||||||
Send an email at {{ asso_mail }} if you didn't request this or if you have
|
This link will expire in {{ expire_in }} hours.
|
||||||
any other question.
|
|
||||||
|
|
||||||
Thanks
|
Regards,
|
||||||
|
|
||||||
The team of {{ asso }} (contact : {{ asso_mail }}).
|
The {{ asso }} team (contact: {{ asso_mail }}).
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<p>Il vous suffit maintenant de payer l'adhésion pour devenir adhérent de {{asso_name}} et bénéficier des services. Pour avoir accès à Internet, il vous faudra payer la connexion.</p>
|
<p>Il vous suffit maintenant de payer l'adhésion pour devenir adhérent de {{asso_name}} et bénéficier des services. Pour avoir accès à Internet, il vous faudra payer la connexion.</p>
|
||||||
|
|
||||||
<p>Pour ce faire, rien de plus simple. Une fois que vous aurez défini votre mot de passe, il vous suffira d'accéder à votre profil et de cliquer sur 'Payer la connexion'</p>
|
<p>Pour ce faire, rien de plus simple. Une fois que vous aurez défini votre mot de passe, il vous suffira d'accéder à votre profil et de cliquer sur « Payer une connexion »</p>
|
||||||
|
|
||||||
<p>Votre pseudo est : {{pseudo}}</p>
|
<p>Votre pseudo est : {{pseudo}}</p>
|
||||||
|
|
||||||
|
@ -10,21 +10,22 @@
|
||||||
|
|
||||||
<p>Pour nous faire part de toute remarque, suggestion ou problème vous pouvez nous envoyer un mail à {{asso_email}}.</p>
|
<p>Pour nous faire part de toute remarque, suggestion ou problème vous pouvez nous envoyer un mail à {{asso_email}}.</p>
|
||||||
|
|
||||||
<p>À bientôt,<br>
|
<p>Respectueusement,<br>
|
||||||
L'équipe de {{asso_name}}.</p>
|
L'équipe de {{asso_name}}.</p>
|
||||||
|
|
||||||
<p>---</p>
|
<p>---</p>
|
||||||
|
|
||||||
<p>You just need to pay membership to become a full member of {{asso_name}} and benefit from the services. To have Internet access, you will need to pay the connexion. </p>
|
<p>Hello {{nom}}!</p>
|
||||||
|
|
||||||
<p>Nothing could be simpler. Once your password is defined, you just need to visit your profile and click on 'Pay for a connexion'.</p>
|
<p>You just need to pay the membership fee to become a contributing member of {{asso_name}} and benefit from the services. To get Internet access, you will need to pay the connection.</p>
|
||||||
|
|
||||||
<p>Your username is : {{pseudo}}<p>
|
<p>Nothing could be simpler. Once your password is defined, you just need to access your profile and click on "Pay for a connection".</p>
|
||||||
|
|
||||||
|
<p>Your username is: {{pseudo}}<p>
|
||||||
|
|
||||||
{{welcome_mail_en|safe}}
|
{{welcome_mail_en|safe}}
|
||||||
|
|
||||||
<p>For any information, suggestion or problem, you can contact us via email at<br>
|
<p>To express any comment, suggestion or problem, you can send us an email to {{asso_email}}.</p>
|
||||||
{{asso_email}}.</p>
|
|
||||||
|
|
||||||
<p>Regards,<br>
|
<p>Regards,<br>
|
||||||
The {{asso_name}} team.</p>
|
The {{asso_name}} team.</p>
|
||||||
|
|
Loading…
Reference in a new issue