From dfa9c9e7385ebba357bac4702083508e46106133 Mon Sep 17 00:00:00 2001 From: Alireza Zare <78508222+azare242@users.noreply.github.com> Date: Wed, 6 Dec 2023 01:07:10 +0330 Subject: [PATCH] feat(backend): add export Skyroom credentials action (#45) * feat: extract emails for every w/p * add json files to gitignore * feat: xlsx * feat(backend): make exporter an action & change output format to .csv --------- Co-authored-by: Adibov --- backend/.gitignore | 3 +- backend/backend_api/admin.py | 77 +++- .../migrations/0057_make_passwords_random.py | 26 ++ backend/backend_api/models.py | 6 +- backend/requirements.txt | Bin 517 -> 1036 bytes backend/templates/html/AAISS_Info.html | 412 ------------------ backend/utils/skyroom_exporter.py | 21 + 7 files changed, 105 insertions(+), 440 deletions(-) create mode 100644 backend/backend_api/migrations/0057_make_passwords_random.py delete mode 100644 backend/templates/html/AAISS_Info.html create mode 100644 backend/utils/skyroom_exporter.py diff --git a/backend/.gitignore b/backend/.gitignore index 088ebe0..03c9941 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,3 +1,4 @@ data media -static \ No newline at end of file +static +*.json \ No newline at end of file diff --git a/backend/backend_api/admin.py b/backend/backend_api/admin.py index f3919bf..15a51d0 100644 --- a/backend/backend_api/admin.py +++ b/backend/backend_api/admin.py @@ -3,27 +3,8 @@ from backend_api import models from backend_api.email import MailerThread -from backend_api.models import Discount - - -def desc_creator(selected_model): - class AdminForm(forms.ModelForm): - desc = forms.CharField(widget=forms.Textarea) - - class Meta: - model = selected_model - fields = '__all__' - - class Admin(admin.ModelAdmin): - form = AdminForm - if selected_model == models.Workshop: - list_display = ('__str__', 'capacity', 'cost', 'has_project', 'level', 'no_of_participants', 'year') - readonly_fields = ('participants',) - elif selected_model == models.Presentation: - list_display = ('__str__', 'level', 'no_of_participants', 'year') - readonly_fields = ('participants',) - - return Admin +from backend_api.models import Discount, Presentation +from utils.skyroom_exporter import SkyroomCredentials, convert_credentials_to_csv_response class TeacherAdminForm(forms.ModelForm): @@ -129,6 +110,54 @@ class Meta: fields = '__all__' +class PresentationAdmin(admin.ModelAdmin): + list_display = ('__str__', 'level', 'no_of_participants', 'year') + readonly_fields = ('participants',) + actions = ['export_login_credentials'] + + class Meta: + model = Presentation + fields = '__all__' + + @admin.action(description='Export login credentials') + def export_login_credentials(self, request, obj): + user_credentials: list[SkyroomCredentials] = [] + for presentation in obj: + for presentation_registration in presentation.presentationparticipation_set.all(): + user_credentials.append( + SkyroomCredentials(presentation_registration.username, presentation_registration.password, + presentation_registration.user.account.email)) + return convert_credentials_to_csv_response(user_credentials) + + +class WorkshopAdmin(admin.ModelAdmin): + list_display = ('__str__', 'capacity', 'cost', 'has_project', 'level', 'no_of_participants', 'year') + readonly_fields = ('participants',) + actions = ['export_login_credentials'] + + class Meta: + model = models.Workshop + fields = '__all__' + + @admin.action(description='Export login credentials') + def export_login_credentials(self, request, obj): + user_credentials: list[SkyroomCredentials] = [] + for workshop in obj: + for workshop_registration in workshop.workshopregistration_set.all(): + user_credentials.append( + SkyroomCredentials(workshop_registration.username, workshop_registration.password, + workshop_registration.user.account.email)) + return convert_credentials_to_csv_response(user_credentials) + + +class MiscAdmin(admin.ModelAdmin): + list_display = ('__str__', 'year') + + class Meta: + model = models.Misc + fields = '__all__' + + admin.site.register(models.Teacher, TeacherAdmin) admin.site.register(models.Presenter, PresenterAdmin) admin.site.register(models.User, UserAdmin) @@ -141,6 +170,6 @@ class Meta: admin.site.register(models.Committee) admin.site.register(models.FieldOfInterest) admin.site.register(models.Staff) -admin.site.register(models.Workshop, desc_creator(models.Workshop)) -admin.site.register(models.Presentation, desc_creator(models.Presentation)) -admin.site.register(models.Misc, desc_creator(models.Misc)) +admin.site.register(models.Workshop, WorkshopAdmin) +admin.site.register(models.Presentation, PresentationAdmin) +admin.site.register(models.Misc, MiscAdmin) diff --git a/backend/backend_api/migrations/0057_make_passwords_random.py b/backend/backend_api/migrations/0057_make_passwords_random.py new file mode 100644 index 0000000..1b4d256 --- /dev/null +++ b/backend/backend_api/migrations/0057_make_passwords_random.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.4 on 2023-12-05 21:26 + +from django.db import migrations + +from utils.random import create_random_string + + +def make_passwords_random(apps, schema_editor): + WorkshopRegistration = apps.get_model('backend_api', 'WorkshopRegistration') + PresentationParticipation = apps.get_model('backend_api', 'PresentationParticipation') + for registration in WorkshopRegistration.objects.all(): + registration.password = create_random_string(16) + registration.save() + for participation in PresentationParticipation.objects.all(): + participation.password = create_random_string(16) + participation.save() + + +class Migration(migrations.Migration): + dependencies = [ + ('backend_api', '0056_presentationparticipation_password_and_more'), + ] + + operations = [ + migrations.RunPython(make_passwords_random) + ] diff --git a/backend/backend_api/models.py b/backend/backend_api/models.py index d14ed6f..22ac4e7 100644 --- a/backend/backend_api/models.py +++ b/backend/backend_api/models.py @@ -1,5 +1,6 @@ import datetime import uuid +from urllib.parse import quote from urllib.parse import urljoin from django.contrib.auth.models import AbstractBaseUser @@ -10,10 +11,10 @@ from django.template.loader import render_to_string from django.urls import reverse from django.utils import timezone +from django.utils.html import escape from django.utils.translation import gettext_lazy as _ -from rest_framework.exceptions import ValidationError from rest_framework import status -from django.utils.html import escape +from rest_framework.exceptions import ValidationError from aaiss_backend import settings from aaiss_backend.settings import BASE_URL @@ -21,7 +22,6 @@ from backend_api.email import MailerThread from utils.random import create_random_string from utils.renderers import new_detailed_response -from urllib.parse import quote SMALL_MAX_LENGTH = 255 BIG_MAX_LENGTH = 65535 diff --git a/backend/requirements.txt b/backend/requirements.txt index d1a076692756b78fcda2639fe2d3aa70351c9ea3..719333d55d679169cdc4e910a7f4ab997f8f9bf4 100644 GIT binary patch literal 1036 zcmZ{j-A=+#5QO)dcPXI-|1P}q%EZLP2QU>|sFb$yBgn(6-|Xo@)R?BEoZX$Bo!RsG zk=xp4R@ur5EA5(RY(u-?&1_(~ZFpAXD3W{6cFlU^8+#$%z^irKiL)8n1ia^ySOU7x*5J-T%880oU>mE%^=DN9 z_M6Y#@}=%0I;8&lJ6pP}VP1lp!@IDZ_gr|Lv`XO>6glnke_aAz1yY9s1=H+67l$)Y zgeL|w+rq5s=L;M&I?0ugQ87~kqo|#c-Z3?IV6AKco6a8iE_+k0~c|XE3ec9Pvcf=j=0so zGZNqK*g;wHNqYXx+`y-W%@g=_?`pse6Ug^{uYoY+j3!&dsdgR1J<%+hT29E<4U>27 r-pn4s-gBZI7M|4j-gn(QaofU9npbcc_d2Loz|*ZOKvbW2OH%s+(MY0X literal 517 zcmZuuL2kn!5WMpjBV(MTJ#g!(Ql(0LKt=4evk3+QxK8r=?mA6Qy}|4-J2TikVuHaK zEqAgJwv?2OX|zdl@DpM4sVe7X+z| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
-
-
- - - -
-
- -
- - - - - - - - -
- - - - - -
- - AAISS-header - -
- -
- - -
- -
-
- - -
-
-
- - -
-
-
- - - -
-
- -
- - - - - - - - -
- -
-
-
-

- به نام خدا -

-

- شرکت کننده گرامی، -

-

- با سلام -

-

- ثبت نام شما در سومین دوره رویداد دانشجویی هوش مصنوعی و علم داده دانشگاه امیرکبیر AAISS2021 با موفقیت انجام شد. - -

- - - {% if workshops_text != '' %} -

- کارگاه های ثبت نام شده شما:{{workshops_text}} -

- {% endif %} - - {% if presentation is True %} -

- شما در ارائه ها ثبت نام شدید! -

- {% endif %} -

- - لطفا برای ارتباط با اساتید و شرکت کنندگان، و نیز دسترسی به محتوای آموزشی کارگاه‌ها، به لینک زیر در دیسکورد وارد شوید: - -

- - -
- -

- Discord -

- - -
-

- - هم‌چنین برای کسب اطلاعات بیشتر و مطلع شدن از اطلاعیه های رویداد، به کانال رویداد مراجعه فرمایید: - -

- - -
-

- Telegram -

- - -
-

- - با آرزوی سلامت و کامیابی - -

-

- - انجمن علمی دانشکده ی کامپیوتر دانشگاه صنعتی امیرکبیر - -

-
-
-
- -
- - -
- -
-
- - -
-
-
- - -
-
-
- - - -
-
- -
- - - - - - - - -
- - - - - -
- - AAISS-footer - -
- -
- - -
- -
-
- - -
-
-
- - - -
- - - - - \ No newline at end of file diff --git a/backend/utils/skyroom_exporter.py b/backend/utils/skyroom_exporter.py new file mode 100644 index 0000000..d1059c0 --- /dev/null +++ b/backend/utils/skyroom_exporter.py @@ -0,0 +1,21 @@ +import csv +from dataclasses import dataclass + +from django.http import HttpResponse + + +@dataclass +class SkyroomCredentials: + username: str + password: str + full_name: str + + +def convert_credentials_to_csv_response(credentials: list[SkyroomCredentials]) -> HttpResponse: + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="login_credentials.csv"' + writer = csv.writer(response) + writer.writerow(['username', 'password', 'full_name', 'room', 'access']) + for credential in credentials: + writer.writerow([credential.username, credential.password, credential.full_name, 'aaiss', 'normal']) + return response