Skip to content

Commit

Permalink
Role management (#260)
Browse files Browse the repository at this point in the history
* chore: add make teacher script

* fix: added psychology faculty icon

* fix: faculty image filter

* chore: linting

* feat: role user mixin

* Calendar view improvements (#257)

* chore: add make teacher script

* fix: added psychology faculty icon

---------

Co-authored-by: tyboro2002 <verslypetybo@hotmail.com>

* chore: user permissions account for is_active

* chore: added role management tests, extracted common logic in helpers

* fix: student service parameter

* chore: linting

* chore: removed comment in seeder

---------

Co-authored-by: tyboro2002 <verslypetybo@hotmail.com>
  • Loading branch information
EwoutV and tyboro2002 authored Apr 9, 2024
1 parent 448249a commit 26e5e43
Show file tree
Hide file tree
Showing 42 changed files with 959 additions and 946 deletions.
1 change: 1 addition & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.venv
.idea
staticfiles
db.sqlite3
__pycache__
*.mo
2 changes: 0 additions & 2 deletions backend/api/fixtures/groups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
students:
- '1'
- '2'
- '000200694919'
- model: api.group
pk: 3
fields:
Expand Down Expand Up @@ -45,4 +44,3 @@
- '1'
- '2'
- '3'
- '000200694919'
23 changes: 23 additions & 0 deletions backend/api/management/commands/make_teacher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from django.core.management.base import BaseCommand
from api.models.student import Student
from api.models.teacher import Teacher


class Command(BaseCommand):

help = 'make yourself teacher'

def add_arguments(self, parser):
parser.add_argument('username', type=str, help='The username of the student user to make teacher')

def handle(self, *args, **options):
username = options['username']
student = Student.objects.filter(username=username)

if student.count() == 0:
self.stdout.write(self.style.ERROR('User not found, first log in !'))
return

Teacher.create(student.get(), create_time=student.create_time)

self.stdout.write(self.style.SUCCESS('Successfully made the user teacher!'))
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from django.db.models import Max
from faker.providers import BaseProvider, DynamicProvider
import random
import time

from authentication.models import Faculty
from api.models.student import Student
Expand Down Expand Up @@ -106,7 +105,8 @@ def provide_teacher(self, errHandler, min_faculty=1, max_faculty=2, staf_prob=0.
)

if faculty is not None:
teacher.faculties.add(*faculty) # Add faculties in bulk
for fac in faculty:
teacher.faculties.add(fac)

return teacher
except Exception:
Expand Down Expand Up @@ -140,7 +140,8 @@ def provide_assistant(self, errHandler, min_faculty=1, max_faculty=3, staf_prob=
)

if faculty is not None:
assistant.faculties.add(*faculty) # Add faculties in bulk
for fac in faculty:
assistant.faculties.add(fac)

return assistant
except Exception:
Expand Down Expand Up @@ -175,7 +176,8 @@ def provide_student(self, errHandler, min_faculty=1, max_faculty=3, staf_prob=0.
)

if faculty is not None:
student.faculties.add(*faculty) # Add faculties in bulk
for fac in faculty:
student.faculties.add(fac)

return student
except Exception:
Expand Down Expand Up @@ -212,34 +214,28 @@ def provide_course(

# add students
student_count = fake.random_int(min=min_students, max=max_students)
students_list = []
while len(students_list) < student_count:
while course.students.count() < student_count:
student = fake.student_provider()
if student not in students_list:
students_list.append(student)
course.students.add(*students_list) # Add students in bulk
if student not in course.students.all():
course.students.add(student)

# add teachers
teacher_count = fake.random_int(min=min_teachers, max=max_teachers)
teachers_list = []
while len(teachers_list) < teacher_count:
while course.teachers.count() < teacher_count:
teacher = fake.teacher_provider()
if teacher not in teachers_list:
teachers_list.append(teacher)
course.teachers.add(*teachers_list) # Add teachers in bulk
if teacher not in course.teachers.all():
course.teachers.add(teacher)

# add assistants
assistant_count = fake.random_int(min=min_assistants, max=max_assistants)
assistants_list = []
while len(assistants_list) < assistant_count:
while course.assistants.count() < assistant_count:
assistant = fake.assistant_provider()
if assistant not in assistants_list:
assistants_list.append(assistant)
course.assistants.add(*assistants_list) # Add assistants in bulk
if assistant not in course.assistants.all():
course.assistants.add(assistant)

# print(course_name)
return course
except Exception as e:
print(e)
except Exception:
tries += 1
errHandler.stdout.write(errHandler.style.WARNING("Exceeded maximum number of attempts to generate a unique Course."))

Expand Down Expand Up @@ -311,12 +307,10 @@ def provide_group(self, errHandler, min_score=0):
elif len(students_not_in_group) < max_group_size:
group.students.extend(students_not_in_group)
else:
choosen_students = []
for _ in range(0, max_group_size):
random_student = students_not_in_group[fake.random_int(min=0, max=len(students_not_in_group))]
choosen_students.append(random_student)
group.students.add(random_student)
students_not_in_group.remove(random_student)
group.students.add(*choosen_students) # bulk add the students

return group
except Exception:
Expand Down Expand Up @@ -392,9 +386,10 @@ def provide_structure_check(self, errHandler, min_extensions=1, max_extensions=5
if extension not in blocked_extensions and extension not in obligated_extensions:
blocked_extensions.append(extension)

check.obligated_extensions.add(*obligated_extensions)
check.blocked_extensions.add(*blocked_extensions)

for ext in obligated_extensions:
check.obligated_extensions.add(ext)
for ext in blocked_extensions:
check.blocked_extensions.add(ext)
return check
except Exception:
tries += 1
Expand All @@ -415,46 +410,6 @@ def update_providers():
structureCheck_provider.elements = StructureCheck.objects.all()


def update_Faculty_providers():
faculty_provider.elements = Faculty.objects.all()


def update_Student_providers():
student_provider.elements = Student.objects.all()


def update_Assistant_providers():
assistant_provider.elements = Assistant.objects.all()


def update_Teacher_providers():
teacher_provider.elements = Teacher.objects.all()


def update_Course_providers():
course_provider.elements = Course.objects.all()


def update_Project_providers():
project_provider.elements = Project.objects.all()


def update_Group_providers():
group_provider.elements = Group.objects.all()


def update_Submission_providers():
Submission_provider.elements = Submission.objects.all()


def update_FileExtension_providers():
fileExtension_provider.elements = FileExtension.objects.all()


def update_StructureCheck_providers():
structureCheck_provider.elements = StructureCheck.objects.all()


# add new providers to faker instance
fake.add_provider(Providers)
fake.add_provider(faculty_provider)
Expand All @@ -469,67 +424,34 @@ def update_StructureCheck_providers():
fake.add_provider(structureCheck_provider)


def format_time(execution_time):
if execution_time < 1:
return f"{execution_time * 1000:.2f} milliseconds"
elif execution_time < 60:
return f"{execution_time:.2f} seconds"
elif execution_time < 3600:
return f"{execution_time / 60:.2f} minutes"
else:
return f"{execution_time / 3600:.2f} hours"


class Command(BaseCommand):
help = 'seed the db with data'

def seed_data(self, amount, provider_function, update_function):
def seed_data(self, amount, provider_function):
for _ in range(amount):
provider_function(self)
update_function()
update_providers()

def handle(self, *args, **options):
start_time = time.time()
# TODO maybey take as option
amount_of_students = 50_000
amount_of_assistants = 300
amount_of_teachers = 500
amount_of_students = 10_000
amount_of_assistants = 1_000
amount_of_teachers = 1_000
amount_of_courses = 1_000
amount_of_projects = 3_000
amount_of_groups = 9_000
amount_of_projects = 5_000
amount_of_groups = 20_000
amount_of_submissions = 50_000
amount_of_file_extensions = 20
amount_of_structure_checks = 12_000

# amount_of_students = 0
# amount_of_assistants = 0
# amount_of_teachers = 0
# amount_of_courses = 1
# amount_of_projects = 0
# amount_of_groups = 0
# amount_of_submissions = 0
# amount_of_file_extensions = 0
# amount_of_structure_checks = 0

self.seed_data(amount_of_students, fake.provide_student, update_Student_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded students!'))
self.seed_data(amount_of_assistants, fake.provide_assistant, update_Assistant_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded assistants!'))
self.seed_data(amount_of_teachers, fake.provide_teacher, update_Teacher_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded teachers!'))
self.seed_data(amount_of_courses, fake.provide_course, update_Course_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded courses!'))
self.seed_data(amount_of_projects, fake.provide_project, update_Project_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded projects!'))
self.seed_data(amount_of_groups, fake.provide_group, update_Group_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded groups!'))
self.seed_data(amount_of_submissions, fake.provide_submission, update_Submission_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded submissions!'))
self.seed_data(amount_of_file_extensions, fake.provide_fileExtension, update_FileExtension_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded fileExtensions!'))
self.seed_data(amount_of_structure_checks, fake.provide_structure_check, update_StructureCheck_providers)
self.stdout.write(self.style.SUCCESS('Successfully seeded structure_checks!'))

end_time = time.time()
execution_time = end_time - start_time
self.stdout.write(self.style.SUCCESS(f"Successfully seeded db in {format_time(execution_time)}!"))
amount_of_structure_checks = 10_000

self.seed_data(amount_of_students, fake.provide_student)
self.seed_data(amount_of_assistants, fake.provide_assistant)
self.seed_data(amount_of_teachers, fake.provide_teacher)
self.seed_data(amount_of_courses, fake.provide_course)
self.seed_data(amount_of_projects, fake.provide_project)
self.seed_data(amount_of_groups, fake.provide_group)
self.seed_data(amount_of_submissions, fake.provide_submission)
self.seed_data(amount_of_file_extensions, fake.provide_fileExtension)
self.seed_data(amount_of_structure_checks, fake.provide_structure_check)

self.stdout.write(self.style.SUCCESS('Successfully seeded db!'))
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 5.0.4 on 2024-04-09 10:47

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0011_revise_extra_checks'),
]

operations = [
migrations.CreateModel(
name='ErrorTemplate',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('message_key', models.CharField(max_length=256)),
],
),
migrations.AlterField(
model_name='extrachecksresult',
name='error_message',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='extra_checks_results', to='api.errortemplate'),
),
migrations.DeleteModel(
name='ErrorTemplates',
),
]
18 changes: 18 additions & 0 deletions backend/api/migrations/0013_student_is_active.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.4 on 2024-04-09 10:51

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0012_errortemplate_alter_extrachecksresult_error_message_and_more'),
]

operations = [
migrations.AddField(
model_name='student',
name='is_active',
field=models.BooleanField(default=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 5.0.4 on 2024-04-09 10:53

from django.db import migrations, models


class Migration(migrations.Migration):

replaces = [('api', '0013_student_is_active'), ('api', '0014_assistant_is_active_teacher_is_active')]

dependencies = [
('api', '0012_errortemplate_alter_extrachecksresult_error_message_and_more'),
]

operations = [
migrations.AddField(
model_name='student',
name='is_active',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='assistant',
name='is_active',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='teacher',
name='is_active',
field=models.BooleanField(default=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.0.4 on 2024-04-09 10:51

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0013_student_is_active'),
]

operations = [
migrations.AddField(
model_name='assistant',
name='is_active',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='teacher',
name='is_active',
field=models.BooleanField(default=True),
),
]
Loading

0 comments on commit 26e5e43

Please sign in to comment.