From 85428244fba673f66d6467fd6081987a198d1210 Mon Sep 17 00:00:00 2001 From: "robinwilliam.hundt" <robinwilliam.hundt@stud.uni-goettingen.de> Date: Tue, 21 Nov 2017 22:07:24 +0100 Subject: [PATCH] Refactored GradyUserFactory to factories.py --- backend/core/tests/test_student_page.py | 14 +++ backend/core/tests/tests.py | 2 +- backend/util/factories.py | 110 ++++++++++++++++++++++++ backend/util/importer.py | 109 +---------------------- 4 files changed, 129 insertions(+), 106 deletions(-) create mode 100644 backend/core/tests/test_student_page.py create mode 100644 backend/util/factories.py diff --git a/backend/core/tests/test_student_page.py b/backend/core/tests/test_student_page.py new file mode 100644 index 00000000..72a8aedc --- /dev/null +++ b/backend/core/tests/test_student_page.py @@ -0,0 +1,14 @@ +from rest_framework.test import APIClient, APITestCase +from util.factories import GradyUserFactory + + +class StudentPageTests(APITestCase): + @classmethod + def setUpTestData(cls): + cls.factory = GradyUserFactory() + cls.student = cls.factory.make_student(username='student01', matrikel_no='12345', + exam='Exam01') + cls.tutor = cls.factory.make_tutor(username='tutor01') + cls.reviewer = cls.factory.make_reviewer(username='reviewer01') + + diff --git a/backend/core/tests/tests.py b/backend/core/tests/tests.py index f3290fbe..408ebb75 100644 --- a/backend/core/tests/tests.py +++ b/backend/core/tests/tests.py @@ -2,7 +2,7 @@ from django.test import TestCase from core.models import (Feedback, Reviewer, Student, Submission, SubmissionType, Tutor) -from util.importer import GradyUserFactory +from util.factories import GradyUserFactory class FeedbackTestCase(TestCase): diff --git a/backend/util/factories.py b/backend/util/factories.py new file mode 100644 index 00000000..953d323d --- /dev/null +++ b/backend/util/factories.py @@ -0,0 +1,110 @@ +import configparser +import secrets + +from core.models import UserAccount as User, Student, Tutor, Reviewer +from util.importer import PASSWORDS + + +class GradyUserFactory: + + def __init__(self, password_generator_func=get_xkcd_password, *args, **kwargs): + self.password_generator_func = password_generator_func + + @staticmethod + def _get_random_name(prefix='', suffix='', k=1): + return ''.join((prefix, get_xkcd_password(k), suffix)) + + def _make_base_user(self, username, groupname, store_pw=False, **kwargs): + """ This is a specific wrapper for the django update_or_create method of + objects. + * A new user is created and password and group are set accordingly + * If the user was there before password is NOT change but group is. A + user must only have one group. + + Returns: + (User object, str): The user object that was added to the group and + the password of that user if it was created. + """ + username = username.strip() + + user, created = User.objects.update_or_create( + username=username, + defaults=kwargs) + + if created: + password = self.password_generator_func() + user.set_password(password) + user.save() + + if created and store_pw: + store_password(username, groupname, password) + + return user + + def _get_user_model_for_group(self, groupname): + """ Returns the model class for a usergroup """ + return { + STUDENTS: Student, + TUTORS: Tutor, + REVIEWERS: Reviewer, + }[groupname] + + def _make_user_generic(self, username, groupname, **kwargs): + """ Provides a model with a associated user but without any defaults + """ + + if not username: + username = self._get_random_name(prefix=groupname.lower() + '_') + + model = self._get_user_model_for_group(groupname) + user = self._make_base_user(username, groupname, **kwargs) + + generic_user, _ = model.objects.get_or_create(user=user) + + return generic_user + + def make_student(self, username=None, matrikel_no=None, exam=None, **kwargs): + """ Creates a student. Defaults can be passed via kwargs like in + relation managers objects.update method. """ + user = self._make_user_generic(username, STUDENTS, **kwargs) + if matrikel_no: + user.objects.update(matrikel_no=matrikel_no) + if exam: + user.objects.update(exam=exam) + return user + + def make_tutor(self, username=None, **kwargs): + """ Creates or updates a tutor if needed with defaults """ + return self._make_user_generic(username, TUTORS, **kwargs) + + def make_reviewer(self, username=None, **kwargs): + """ Creates or updates a reviewer if needed with defaults """ + return self._make_user_generic(username, REVIEWERS, **kwargs) + + +STUDENTS = 'students' +TUTORS = 'tutors' +REVIEWERS = 'reviewers' + + +def get_xkcd_password(k=2): + with open('/usr/share/dict/words') as words: + choose_from = list({word.strip().lower() + for word in words if 5 < len(word) < 8}) + + return ''.join(secrets.choice(choose_from) for _ in range(k)) + + +def store_password(username, groupname, password): + storage = configparser.ConfigParser() + storage.read(PASSWORDS) + + if not groupname in storage: + storage[groupname] = {} + + storage[groupname][username] = password + + with open(PASSWORDS, 'w') as passwd_file: + storage.write(passwd_file) + + diff --git a/backend/util/importer.py b/backend/util/importer.py index 299f4ae5..0c77ba2f 100644 --- a/backend/util/importer.py +++ b/backend/util/importer.py @@ -1,23 +1,18 @@ -import configparser import csv import json import os import readline -import secrets from typing import Callable import util.convert import util.processing +from core.models import (ExamType, Feedback, Student, Submission, + SubmissionType, Test) from core.models import UserAccount as User -from core.models import (ExamType, Feedback, Reviewer, Student, Submission, - SubmissionType, Test, Tutor) +from util.factories import GradyUserFactory, STUDENTS, TUTORS, REVIEWERS from util.messages import info, warn from util.processing import EmptyTest -STUDENTS = 'students' -TUTORS = 'tutors' -REVIEWERS = 'reviewers' - HISTFILE = '.importer_history' RECORDS = '.importer' PASSWORDS = '.importer_passwords' @@ -62,14 +57,6 @@ class chdir_context(object): os.chdir(self.old_dir) -def get_xkcd_password(k=2): - with open('/usr/share/dict/words') as words: - choose_from = list({word.strip().lower() - for word in words if 5 < len(word) < 8}) - - return ''.join(secrets.choice(choose_from) for _ in range(k)) - - def i(prompt: str, default: str='', is_path: bool=False, is_file: bool=False): if default is YES or default is NO: answer = valid[input(f'[Q] {prompt} ({default}): ').lower() or ('y' if YES == default else 'n')] @@ -85,97 +72,9 @@ def i(prompt: str, default: str='', is_path: bool=False, is_file: bool=False): return answer -def store_password(username, groupname, password): - storage = configparser.ConfigParser() - storage.read(PASSWORDS) - - if not groupname in storage: - storage[groupname] = {} - - storage[groupname][username] = password - - with open(PASSWORDS, 'w') as passwd_file: - storage.write(passwd_file) - - -class GradyUserFactory: - - def __init__(self, password_generator_func=get_xkcd_password, *args, **kwargs): - self.password_generator_func = password_generator_func - - @staticmethod - def _get_random_name(prefix='', suffix='', k=1): - return ''.join((prefix, get_xkcd_password(k), suffix)) - - def _make_base_user(self, username, groupname, store_pw=False, **kwargs): - """ This is a specific wrapper for the django update_or_create method of - objects. - * A new user is created and password and group are set accordingly - * If the user was there before password is NOT change but group is. A - user must only have one group. - - Returns: - (User object, str): The user object that was added to the group and - the password of that user if it was created. - """ - username = username.strip() - - user, created = User.objects.update_or_create( - username=username, - defaults=kwargs) - - if created: - password = self.password_generator_func() - user.set_password(password) - user.save() - - if created and store_pw: - store_password(username, groupname, password) - - return user - - def _get_user_model_for_group(self, groupname): - """ Returns the model class for a usergroup """ - return { - STUDENTS: Student, - TUTORS: Tutor, - REVIEWERS: Reviewer, - }[groupname] - - def _make_user_generic(self, username, groupname, **kwargs): - """ Provides a model with a associated user but without any defaults - """ - - if not username: - username = self._get_random_name(prefix=groupname.lower() + '_') - - model = self._get_user_model_for_group(groupname) - user = self._make_base_user(username, groupname, **kwargs) - - generic_user, _ = model.objects.get_or_create(user=user) - - return generic_user - - def make_student(self, username=None, matrikel_no=None, exam=None, **kwargs): - """ Creates a student. Defaults can be passed via kwargs like in - relation managers objects.update method. """ - user = self._make_user_generic(username, STUDENTS, **kwargs) - if matrikel_no: - user.objects.update(matrikel_no=matrikel_no) - if exam: - user.objects.update(exam=exam) - return user - - def make_tutor(self, username=None, **kwargs): - """ Creates or updates a tutor if needed with defaults """ - return self._make_user_generic(username, TUTORS, **kwargs) - - def make_reviewer(self, username=None, **kwargs): - """ Creates or updates a reviewer if needed with defaults """ - return self._make_user_generic(username, REVIEWERS, **kwargs) - # TODO more factories + def add_user(username, group, **kwargs): user = GradyUserFactory()._make_base_user( username, group, store_pw=True, **kwargs -- GitLab