mirror of
https://gitlab.crans.org/bde/nk20-scripts
synced 2025-02-18 22:21:21 +00:00
Compare commits
19 Commits
2495128755
...
654492f9e9
Author | SHA1 | Date | |
---|---|---|---|
|
654492f9e9 | ||
|
84be9d0062 | ||
|
7e27c3b71b | ||
|
0107dd0a94 | ||
|
e5b76b7c35 | ||
|
4506dd4dc0 | ||
|
bac22dcbac | ||
|
4f5a794798 | ||
|
69c5c3bb36 | ||
|
7479671b3f | ||
|
7246f4d18a | ||
|
2a113d22b9 | ||
|
525f091b0c | ||
|
4e1bcd1808 | ||
|
1145f75a96 | ||
|
c1c0a87971 | ||
|
2b1c05ff98 | ||
|
4179cad611 | ||
|
81709539a2 |
57
management/commands/extract_ml_registrations.py
Normal file
57
management/commands/extract_ml_registrations.py
Normal file
@ -0,0 +1,57 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from datetime import date
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.management import BaseCommand
|
||||
from django.db.models import Q
|
||||
from member.models import Membership, Club
|
||||
from wei.models import WEIClub
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Get mailing list registrations from the last wei. " \
|
||||
"Usage: manage.py extract_ml_registrations -t {events,art,sport} -t {fr, en}. " \
|
||||
"You can write this into a file with a pipe, then paste the document into your mail manager."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--type', '-t', choices=["members", "clubs", "events", "art", "sport"], default="members",
|
||||
help='Select the type of the mailing list (default members)')
|
||||
parser.add_argument('--lang', '-l', type=str, choices=['fr', 'en'], default='fr',
|
||||
help='Select the registred users of the ML of the given language. Useful only for the '
|
||||
'events mailing list.')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# TODO: Improve the mailing list extraction system, and link it automatically with Mailman.
|
||||
|
||||
if options["type"] == "members":
|
||||
for membership in Membership.objects.filter(
|
||||
club__name="BDE",
|
||||
date_start__lte=date.today(),
|
||||
date_end__gte=date.today(),
|
||||
).all():
|
||||
self.stdout.write(membership.user.email)
|
||||
return
|
||||
|
||||
if options["type"] == "clubs":
|
||||
for club in Club.objects.all():
|
||||
self.stdout.write(club.email)
|
||||
return
|
||||
|
||||
# Get the list of mails that want to be registered to the events mailing list.
|
||||
# Don't filter to valid members, old members can receive these mails as long as they want.
|
||||
if options["type"] == "events":
|
||||
for user in User.objects.filter(profile__ml_events_registration=options["lang"]).all():
|
||||
self.stdout.write(user.email)
|
||||
return
|
||||
|
||||
if options["type"] == "art":
|
||||
for user in User.objects.filter(profile__ml_art_registration=True).all():
|
||||
self.stdout.write(user.email)
|
||||
return
|
||||
|
||||
if options["type"] == "sport":
|
||||
for user in User.objects.filter(profile__ml_sport_registration=True).all():
|
||||
self.stdout.write(user.email)
|
||||
return
|
@ -6,6 +6,7 @@ import psycopg2.extras as pge
|
||||
import datetime
|
||||
import json
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.timezone import make_aware, now
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
@ -33,6 +34,11 @@ MAP_IDBDE = {
|
||||
# some Aliases have been created in the fixtures
|
||||
ALIAS_SET = {a[0] for a in Alias.objects.all().values_list("normalized_name")}
|
||||
|
||||
# Some people might loose some aliases due to normalization. We warn them on them.
|
||||
LOST_ALIASES = {}
|
||||
# In some rare cases, the username might be in conflict with some others. We change them and warn the users.
|
||||
CHANGED_USERNAMES = []
|
||||
|
||||
note_user_type = ContentType.objects.get(app_label="note", model="noteuser")
|
||||
note_club_type = ContentType.objects.get(app_label="note", model="noteclub")
|
||||
|
||||
@ -85,9 +91,10 @@ class Command(ImportCommand):
|
||||
pseudo = row["pseudo"]
|
||||
pseudo_norm = Alias.normalize(pseudo)
|
||||
self.update_line(idx, n, pseudo)
|
||||
# clean pseudo (normalized pseudo must be unique)
|
||||
if pseudo_norm in ALIAS_SET:
|
||||
# clean pseudo (normalized pseudo must be unique and not empty)
|
||||
if not pseudo_norm or pseudo_norm in ALIAS_SET:
|
||||
pseudo = pseudo + str(row["idbde"])
|
||||
CHANGED_USERNAMES.append((pk_note, row["idbde"], pseudo))
|
||||
else:
|
||||
ALIAS_SET.add(pseudo_norm)
|
||||
# clean date
|
||||
@ -95,7 +102,7 @@ class Command(ImportCommand):
|
||||
"pk": pk_note,
|
||||
"balance": row['solde'],
|
||||
"last_negative": None,
|
||||
"is_active": True,
|
||||
"is_active": not row["bloque"],
|
||||
"display_image": "pic/default.png",
|
||||
}
|
||||
if row["last_negatif"] is not None:
|
||||
@ -107,6 +114,11 @@ class Command(ImportCommand):
|
||||
else:
|
||||
passwd_nk15 = ''
|
||||
|
||||
# Note account should have no password and be active
|
||||
if int(row["idbde"]) == 3508:
|
||||
passwd_nk15 = "ipbased$127.0.0.1"
|
||||
row["bloque"] = False
|
||||
|
||||
if row["idbde"] not in MAP_IDBDE_PROMOTION:
|
||||
# NK12 bug. Applying default values
|
||||
MAP_IDBDE_PROMOTION[row["idbde"]] = {"promo": 2014,
|
||||
@ -119,7 +131,7 @@ class Command(ImportCommand):
|
||||
"first_name": row["prenom"],
|
||||
"last_name": row["nom"],
|
||||
"email": row["mail"],
|
||||
"is_active": True, # temporary
|
||||
"is_active": not row["bloque"],
|
||||
"date_joined": make_aware(MAP_IDBDE_PROMOTION[row["idbde"]]["created_at"]),
|
||||
}
|
||||
profile_dict = {
|
||||
@ -131,7 +143,7 @@ class Command(ImportCommand):
|
||||
"registration_valid": True,
|
||||
"email_confirmed": True,
|
||||
"promotion": MAP_IDBDE_PROMOTION[row["idbde"]]["promo"],
|
||||
"report_frequency": row["report_period"],
|
||||
"report_frequency": max(row["report_period"], 0),
|
||||
"last_report": make_aware(row["previous_report_date"]),
|
||||
}
|
||||
note_dict["created_at"] = make_aware(MAP_IDBDE_PROMOTION[row["idbde"]]["created_at"])
|
||||
@ -206,7 +218,9 @@ class Command(ImportCommand):
|
||||
alias_norm = Alias.normalize(alias_name)
|
||||
self.update_line(idx, n, alias_norm)
|
||||
# clean pseudo (normalized pseudo must be unique)
|
||||
if alias_norm in ALIAS_SET:
|
||||
if not alias_norm or alias_norm in ALIAS_SET:
|
||||
LOST_ALIASES.setdefault(MAP_IDBDE[row["idbde"]], [])
|
||||
LOST_ALIASES[MAP_IDBDE[row["idbde"]]].append(alias_name)
|
||||
continue
|
||||
else:
|
||||
ALIAS_SET.add(alias_norm)
|
||||
@ -237,3 +251,7 @@ class Command(ImportCommand):
|
||||
filename = kwargs["save"]
|
||||
with open(filename, 'w') as fp:
|
||||
json.dump(MAP_IDBDE, fp, sort_keys=True, indent=2)
|
||||
with open(filename + ".changed-usernames", 'w') as fp:
|
||||
json.dump(CHANGED_USERNAMES, fp, sort_keys=True, indent=2)
|
||||
with open(filename + ".removed-aliases", 'w') as fp:
|
||||
json.dump(LOST_ALIASES, fp, sort_keys=True, indent=2)
|
||||
|
@ -107,7 +107,6 @@ class Command(ImportCommand):
|
||||
|
||||
def _template_transaction(self, row, obj_dict, child_dict):
|
||||
if self.buttons.get(row["description"]):
|
||||
child_dict["category_id"] = self.buttons[row["description"]][1]
|
||||
child_dict["template_id"] = self.buttons[row["description"]][0]
|
||||
# elif self.categories.get(row["categorie"]):
|
||||
# child_dict["category_id"] = self.categories[row["categorie"]]
|
||||
@ -215,7 +214,7 @@ class Command(ImportCommand):
|
||||
"amount": row["montant"],
|
||||
"created_at": date,
|
||||
"destination_alias": "",
|
||||
"invalidity_reason": None,
|
||||
"invalidity_reason": "",
|
||||
"quantity": row["quantite"],
|
||||
"reason": row["description"],
|
||||
"source_alias": "",
|
||||
@ -317,6 +316,12 @@ class Command(ImportCommand):
|
||||
)
|
||||
bulk_mgr.done()
|
||||
|
||||
# Note account has a different treatment
|
||||
for m in Membership.objects.filter(user_username="note").all():
|
||||
m.date_end = "3142-12-12"
|
||||
m.roles.set([20]) # PC Kfet role
|
||||
m.save()
|
||||
|
||||
@timed
|
||||
@transaction.atomic
|
||||
def import_remittances(self, cur, chunk_size):
|
||||
|
@ -13,7 +13,7 @@ from activity.models import Activity
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
acl_header = "#acl NoteKfet2015:read,write,admin NoteKfet2020:read,write,admin All:read Default\n"
|
||||
acl_header = "#acl NoteKfet2020:read,write,admin All:read Default\n"
|
||||
|
||||
warning_header = """## NE PAS ÉDITER CETTE PAGE MANUELLEMENT
|
||||
## ELLE EST GÉNÉRÉE AUTOMATIQUEMENT PAR LA NOTE KFET 2020
|
||||
@ -24,7 +24,7 @@ class Command(BaseCommand):
|
||||
* Ne pas éditer cette page manuellement, toute modification sera annulée automatiquement.
|
||||
* Pour annoncer un nouvel événement, rendez-vous sur {activities_url}
|
||||
|
||||
""".format(activities_url="https://" + os.getenv("NOTE_URL") + reverse("activity:activity_list"))
|
||||
""".format(activities_url="https://" + os.getenv("NOTE_URL", "") + reverse("activity:activity_list"))
|
||||
|
||||
@staticmethod
|
||||
def connection(url):
|
||||
@ -100,7 +100,7 @@ class Command(BaseCommand):
|
||||
title=act.name,
|
||||
start=timezone.localtime(act.date_start).strftime("%Y-%m-%d %H:%M"),
|
||||
end=timezone.localtime(act.date_end).strftime("%Y-%m-%d %H:%M"),
|
||||
description=act.description,
|
||||
description=act.description.replace("\r", "").replace("\n", "<<BR>>"),
|
||||
club=act.organizer.name,
|
||||
location=act.location,
|
||||
)
|
||||
@ -108,7 +108,7 @@ class Command(BaseCommand):
|
||||
return "|| {start} || {title} || {description} || {club} || {location} ||".format(
|
||||
title=act.name,
|
||||
start=timezone.localtime(act.date_start).strftime("%d/%m/%Y"),
|
||||
description=act.description,
|
||||
description=act.description.replace("\r", "").replace("\n", "<<BR>>"),
|
||||
club=act.organizer.name,
|
||||
location=act.location,
|
||||
)
|
||||
@ -150,30 +150,31 @@ class Command(BaseCommand):
|
||||
return page, header + body
|
||||
|
||||
@staticmethod
|
||||
def refresh_raw_wiki_page(comment="refresh", debug=True):
|
||||
def refresh_raw_wiki_page(comment="refresh", print_stdout=False, edit_wiki=False):
|
||||
page, content = Command.get_raw_page()
|
||||
if debug:
|
||||
if print_stdout:
|
||||
print(content)
|
||||
else:
|
||||
if edit_wiki:
|
||||
Command.edit_wiki(page, content, comment)
|
||||
|
||||
@staticmethod
|
||||
def refresh_human_readable_wiki_page(comment="refresh", debug=True):
|
||||
def refresh_human_readable_wiki_page(comment="refresh", print_stdout=False, edit_wiki=False):
|
||||
page, content = Command.get_human_readable_page()
|
||||
if debug:
|
||||
if print_stdout:
|
||||
print(content)
|
||||
else:
|
||||
if edit_wiki:
|
||||
Command.edit_wiki(page, content, comment)
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("--human", "-H", action="store_true", help="Save human readable page")
|
||||
parser.add_argument("--raw", "-r", action="store_true", help="Save raw page, for the calendar")
|
||||
parser.add_argument("--comment", "-c", action="store", type=str, default="", help="Comment of the modification")
|
||||
parser.add_argument("--debug", "-d", action="store_true", help="Don't commit to the wiki, render in stdout")
|
||||
parser.add_argument("--stdout", "-o", action="store_true", help="Render the wiki page in stdout")
|
||||
parser.add_argument("--wiki", "-w", action="store_true", help="Send modifications to the wiki")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if options["raw"]:
|
||||
Command.refresh_raw_wiki_page(options["comment"], options["debug"])
|
||||
Command.refresh_raw_wiki_page(options["comment"], options["stdout"], options["wiki"])
|
||||
if options["human"]:
|
||||
Command.refresh_human_readable_wiki_page(options["comment"], options["debug"])
|
||||
Command.refresh_human_readable_wiki_page(options["comment"], options["stdout"], options["wiki"])
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from datetime import date
|
||||
|
||||
from django.core.mail import send_mail
|
||||
from django.core.management import BaseCommand
|
||||
from django.db.models import Q
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import activate
|
||||
|
||||
from note.models import NoteUser
|
||||
from note.models import NoteUser, Note
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@ -19,9 +21,10 @@ class Command(BaseCommand):
|
||||
|
||||
def handle(self, *args, **options):
|
||||
activate('fr')
|
||||
notes = NoteUser.objects.filter(
|
||||
notes = Note.objects.filter(
|
||||
Q(noteuser__user__memberships__date_end__gte=date.today()) | Q(noteclub__isnull=False),
|
||||
balance__lte=-options["negative_amount"],
|
||||
user__memberships__date_end__gte=timezone.now().date(),
|
||||
is_active=True,
|
||||
).order_by('balance').distinct().all()
|
||||
|
||||
if options["spam"]:
|
||||
|
@ -14,8 +14,15 @@ from note.tables import HistoryTable
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--notes', '-n', type=int, nargs='+', help='Select note ids')
|
||||
parser.add_argument('--debug', '-d', action='store_true', help='Debug mode, print mails in stdout')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
activate('fr')
|
||||
if "notes" in options:
|
||||
notes = NoteUser.objects.filter(pk__in=options["notes"]).all()
|
||||
else:
|
||||
notes = NoteUser.objects.filter(
|
||||
user__memberships__date_end__gte=timezone.now(),
|
||||
user__profile__report_frequency__gt=0,
|
||||
@ -41,11 +48,16 @@ class Command(BaseCommand):
|
||||
context = dict(
|
||||
user=note.user,
|
||||
table=table,
|
||||
last_transactions=last_transactions,
|
||||
incoming=incoming,
|
||||
outcoming=outcoming,
|
||||
diff=incoming - outcoming,
|
||||
now=now,
|
||||
last_report=last_report,
|
||||
)
|
||||
plain = render_to_string("note/mails/weekly_report.txt", context)
|
||||
html = render_to_string("note/mails/weekly_report.html", context)
|
||||
note.user.email_user("[Note Kfet] Rapport de la Note Kfet", html, html_message=html)
|
||||
if options["debug"]:
|
||||
self.stdout.write(plain)
|
||||
else:
|
||||
note.user.email_user("[Note Kfet] Rapport de la Note Kfet", plain, html_message=html)
|
||||
|
@ -1,11 +1,9 @@
|
||||
#!/bin/bash
|
||||
# Create backups directory
|
||||
[[ -d /var/www/note_kfet/backups ]] || (mkdir /var/www/note_kfet/backups && chown www-data:www-data /var/www/note_kfet/backups)
|
||||
# Create temporary backups directory
|
||||
[[ -d /tmp/note-backups ]] || mkdir /tmp/note-backups
|
||||
date=$(date +%Y-%m-%d)
|
||||
# Backup database and save it as tar archive
|
||||
su postgres -c "pg_dump -F t note_db" | tee "/var/www/note_kfet/backups/$date.tar" > /dev/null
|
||||
su postgres -c "pg_dump -F t note_db" | tee "/tmp/note-backups/$date.tar" > /dev/null
|
||||
# Compress backup as gzip
|
||||
gzip "/var/www/note_kfet/backups/$date.tar"
|
||||
chown www-data:www-data "/var/www/note_kfet/backups/$date.tar.gz"
|
||||
# Delete backups that have more than 30 days
|
||||
find /var/www/note_kfet/backups -type f -mtime +30 -exec rm {} \;
|
||||
gzip "/tmp/note-backups/$date.tar"
|
||||
scp "/tmp/note-backups/$date.tar.gz" "club-bde@zamok.crans.org:backup/$date.tar.gz"
|
||||
|
12
shell/docker_bash
Executable file
12
shell/docker_bash
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -r Dockerfile ]; then
|
||||
if [ -w /var/run/docker.sock ]; then
|
||||
docker build -t nk20 .
|
||||
docker run -it -u $(id -u):$(id -g) --rm -v "$(pwd):/var/www/note_kfet/" -p 80:8080 nk20 bash
|
||||
else
|
||||
echo "Merci de rejoindre le groupe docker (ou lancez ce script en sudo) afin de pouvoir vous connecter au socket Docker."
|
||||
fi
|
||||
else
|
||||
echo "N'exécutez ce fichier que dans la racine de votre projet, afin de pouvoir localiser le fichier Dockerfile."
|
||||
fi
|
@ -3,7 +3,5 @@ sudo service postgresql stop
|
||||
sudo service postgresql start
|
||||
sudo -u postgres sh -c "dropdb note_db && psql -c 'CREATE DATABASE note_db OWNER note;'";
|
||||
echo 'reset db';
|
||||
find apps/ -path "*/migrations/*.py*" -not -name "__init__.py" -delete
|
||||
./manage.py makemigrations
|
||||
./manage.py migrate
|
||||
./manage.py loaddata initial
|
||||
|
27
templates/scripts/deleted_aliases.txt
Normal file
27
templates/scripts/deleted_aliases.txt
Normal file
@ -0,0 +1,27 @@
|
||||
Bonjour {{ user.first_name }} {{ user.last_name }},
|
||||
|
||||
Ce message vous est envoyé automatiquement par la Note Kfet du BDE de
|
||||
l'ENS Cachan, à laquelle vous êtes inscrit·e. Si vous n'êtes plus
|
||||
adhérent·e, vous n'êtes pas nécessairement concerné·e par la suite
|
||||
de ce message.
|
||||
|
||||
La Note Kfet 2020 vient d'être déployée, succédant à la Note Kfet 2015.
|
||||
Les données ont été migrées.
|
||||
|
||||
Toutefois, la nouvelle note utilise un algorithme de normalisation des alias
|
||||
permettant de rechercher plus facilement un nom de note, et empêchant la
|
||||
création d'un alias trop proche d'un autre.
|
||||
|
||||
Nous vous informons que les alias suivants ont été supprimés de votre compte,
|
||||
jugés trop proches d'autres alias déjà existants :
|
||||
|
||||
{{ aliases_list|join:", " }}
|
||||
|
||||
Nous nous excusons pour le désagrément, et espérons que vous pourrez
|
||||
profiter de la nouvelle Note Kfet.
|
||||
|
||||
Cordialement,
|
||||
|
||||
--
|
||||
Le BDE
|
||||
|
27
templates/scripts/unsupported_username.txt
Normal file
27
templates/scripts/unsupported_username.txt
Normal file
@ -0,0 +1,27 @@
|
||||
Bonjour {{ user.first_name }} {{ user.last_name }},
|
||||
|
||||
Ce message vous est envoyé automatiquement par la Note Kfet du BDE de
|
||||
l'ENS Cachan, à laquelle vous êtes inscrit·e. Si vous n'êtes plus
|
||||
adhérent·e, vous n'êtes pas nécessairement concerné·e par la suite
|
||||
de ce message.
|
||||
|
||||
La Note Kfet 2020 vient d'être déployée, succédant à la Note Kfet 2015.
|
||||
Les données ont été migrées.
|
||||
|
||||
Toutefois, la nouvelle note utilise un algorithme de normalisation des alias
|
||||
permettant de rechercher plus facilement un nom de note, et empêchant la
|
||||
création d'un alias trop proche d'un autre.
|
||||
|
||||
Nous vous informons que votre pseudo {{ old_username }} fait pas partie des
|
||||
alias problématiques. Il a été remplacé par le pseudo {{ new_username }},
|
||||
que vous devrez utiliser pour pouvoir vous connecter. Il sera ensuite
|
||||
possible de modifier votre pseudo.
|
||||
|
||||
Nous nous excusons pour le désagrément, et espérons que vous pourrez
|
||||
profiter de la nouvelle Note Kfet.
|
||||
|
||||
Cordialement,
|
||||
|
||||
--
|
||||
Le BDE
|
||||
|
Loading…
x
Reference in New Issue
Block a user