Verified Commit 6b8f2b86 authored by Peter Stanko's avatar Peter Stanko
Browse files

List of clients in the course

parent 6f057659
...@@ -94,6 +94,7 @@ class TestConfig(Config): ...@@ -94,6 +94,7 @@ class TestConfig(Config):
BROKER_URL = 'redis://' BROKER_URL = 'redis://'
CELERY_RESULT_BACKEND = BROKER_URL CELERY_RESULT_BACKEND = BROKER_URL
PORTAL_LOG_CONFIG = False PORTAL_LOG_CONFIG = False
GIT_REPO_BASE = os.getenv('GIT_REPO_BASE', f"git@gitlab.local")
# pylint: enable=too-few-public-methods # pylint: enable=too-few-public-methods
......
...@@ -392,7 +392,7 @@ class Course(db.Model, EntityBase, NamedMixin): ...@@ -392,7 +392,7 @@ class Course(db.Model, EntityBase, NamedMixin):
.join(User.roles).filter((Role.id == role.id) & (Role.course == self)) \ .join(User.roles).filter((Role.id == role.id) & (Role.course == self)) \
.all() .all()
def get_users_filtered(self, groups: List['Group'], roles: List['Role']): def get_clients_filtered(self, groups: List['Group'], roles: List['Role']):
"""Gets all users in the course who are members of at least one of """Gets all users in the course who are members of at least one of
the provided groups and have at least one of the specified roles. the provided groups and have at least one of the specified roles.
...@@ -406,13 +406,13 @@ class Course(db.Model, EntityBase, NamedMixin): ...@@ -406,13 +406,13 @@ class Course(db.Model, EntityBase, NamedMixin):
(are in at least one group AND have at least one role). (are in at least one group AND have at least one role).
""" """
query = User.query.join(User.roles).filter(Role.course_id == self.id) query = Client.query.join(Client.roles).filter(Role.course_id == self.id)
if roles: if roles:
role_ids = [role.id for role in roles] role_ids = [role.id for role in roles]
query = query.filter(Role.id.in_(role_ids)) query = query.filter(Role.id.in_(role_ids))
if groups: if groups:
group_ids = [group.id for group in groups] group_ids = [group.id for group in groups]
query = query.join(User.groups).filter(Group.id.in_(group_ids)).filter( query = query.join(Client.groups).filter(Group.id.in_(group_ids)).filter(
Group.course_id == self.id) Group.course_id == self.id)
return query.all() return query.all()
......
...@@ -138,10 +138,10 @@ class CourseImport(CustomResource): ...@@ -138,10 +138,10 @@ class CourseImport(CustomResource):
return SCHEMAS.dump('course', copied_course) return SCHEMAS.dump('course', copied_course)
@courses_namespace.route('/<string:cid>/users') @courses_namespace.route('/<string:cid>/clients')
@courses_namespace.param('cid', 'Course id') @courses_namespace.param('cid', 'Course id')
@courses_namespace.response(404, 'Course not found') @courses_namespace.response(404, 'Course not found')
class CourseUsers(CustomResource): class CourseClients(CustomResource):
@jwt_required @jwt_required
# @courses_namespace.response(200, 'Users in the course', model=users_schema) # @courses_namespace.response(200, 'Users in the course', model=users_schema)
@courses_namespace.response(403, 'Not allowed to see users in the course') @courses_namespace.response(403, 'Not allowed to see users in the course')
...@@ -150,5 +150,5 @@ class CourseUsers(CustomResource): ...@@ -150,5 +150,5 @@ class CourseUsers(CustomResource):
self.permissions(course=course).require.permissions(['view_course_full']) self.permissions(course=course).require.permissions(['view_course_full'])
group_ids = request.args.getlist('group') group_ids = request.args.getlist('group')
role_ids = request.args.getlist('role') role_ids = request.args.getlist('role')
users = self.rest.courses(course).get_users_filtered(group_ids, role_ids) users = self.rest.courses(course).get_clients_filtered(group_ids, role_ids)
return SCHEMAS.dump('users', users) return SCHEMAS.dump('users', users)
...@@ -383,7 +383,7 @@ class Schemas: ...@@ -383,7 +383,7 @@ class Schemas:
'user_reduced': (*ALWAYS_ALLOWED, 'username', 'uco', 'email', 'name'), 'user_reduced': (*ALWAYS_ALLOWED, 'username', 'uco', 'email', 'name'),
'users': (*ALWAYS_ALLOWED, 'username', 'uco', 'email'), 'users': (*ALWAYS_ALLOWED, 'username', 'uco', 'email'),
'submissions': (*ALWAYS_ALLOWED, 'course', 'state', 'project', 'scheduled_for', 'user'), 'submissions': (*ALWAYS_ALLOWED, 'course', 'state', 'project', 'scheduled_for', 'user'),
'submission_state': (*ALWAYS_ALLOWED, 'state'), 'submission_state': (*ALWAYS_ALLOWED, 'state', 'parameters', 'scheduled_for'),
'roles': ENT_W_COURSE, 'roles': ENT_W_COURSE,
'groups': ENT_W_COURSE, 'groups': ENT_W_COURSE,
'projects': ENT_W_COURSE, 'projects': ENT_W_COURSE,
......
...@@ -76,14 +76,13 @@ class CourseService(GeneralService): ...@@ -76,14 +76,13 @@ class CourseService(GeneralService):
log.info(f"[UPDATE] Notes access token {self.course.log_name}: {token}") log.info(f"[UPDATE] Notes access token {self.course.log_name}: {token}")
return self.course return self.course
def get_users_filtered(self, groups: List[str], roles: List[str]) -> List[User]: def get_clients_filtered(self, groups: List[str], roles: List[str]) -> List[User]:
"""Get all users for course filtered """Get all users for course filtered
Args: Args:
groups(list): Group names list groups(list): Group names list
roles(list): Role names list roles(list): Role names list
Returns(List[User]): Returns(List[User]):
""" """
groups_entities = Group.query.filter(Group.id.in_(groups)).all() if groups else None
groups_entities = Group.query.filter(Group.id.in_(groups)).all() roles_entities = Role.query.filter(Role.id.in_(roles)).all() if roles else None
roles_entities = Role.query.filter(Role.id.in_(roles)).all() return self.course.get_clients_filtered(groups_entities, roles_entities)
return self.course.get_users_filtered(groups_entities, roles_entities)
...@@ -24,6 +24,10 @@ class GeneralService: ...@@ -24,6 +24,10 @@ class GeneralService:
self._rest_service: RestService = rest_service self._rest_service: RestService = rest_service
self._entity = None self._entity = None
@property
def flask_app(self) -> flask.Flask:
return flask.current_app
@property @property
def find(self): def find(self):
return self._rest_service.find return self._rest_service.find
......
...@@ -202,10 +202,12 @@ class SubmissionsService(GeneralService): ...@@ -202,10 +202,12 @@ class SubmissionsService(GeneralService):
def process_submission_params(self, params: dict, project: Project, user: User): def process_submission_params(self, params: dict, project: Project, user: User):
file_params = params.get('file_params') file_params = params.get('file_params')
file_params['from_dir'] = params.get('from_dir') or project.codename
source = file_params.get('source') source = file_params.get('source')
if source and source['type'] == 'git': if source and source['type'] == 'git':
source['url'] = source.get('url') or self.__get_default_git_url(project, user) url = source.get('url')
if not url:
source['url'] = self.__get_default_git_url(project, user)
file_params['from_dir'] = params.get('from_dir') or project.codename
return params return params
def __get_default_git_url(self, project: Project, user: User): def __get_default_git_url(self, project: Project, user: User):
......
...@@ -79,6 +79,19 @@ def test_read(client): ...@@ -79,6 +79,19 @@ def test_read(client):
rest_tools.assert_course(c, course) rest_tools.assert_course(c, course)
def test_read_course_users(client):
course = Course.query.filter_by(codename="testcourse2").first()
response = rest_tools.make_request(client, f"/courses/{course.id}/clients")
assert_response(response, 200)
users = rest_tools.extract_data(response)
course_users = set()
for role in course.roles:
course_users.update(role.clients)
assert users
assert len(users) == 4
assert len(course_users) == len(users)
def test_update(client): def test_update(client):
c = Course.query.filter_by(codename="testcourse1").first() c = Course.query.filter_by(codename="testcourse1").first()
request_dict = dict( request_dict = dict(
......
...@@ -3,6 +3,7 @@ from datetime import timedelta ...@@ -3,6 +3,7 @@ from datetime import timedelta
import pytest import pytest
from flask_jwt_extended import create_access_token from flask_jwt_extended import create_access_token
from mock import patch
from portal.database.models import Course, Project, User from portal.database.models import Course, Project, User
from portal.tools.time import current_time, strip_seconds from portal.tools.time import current_time, strip_seconds
...@@ -177,6 +178,7 @@ def request_dict() -> dict: ...@@ -177,6 +178,7 @@ def request_dict() -> dict:
} }
@pytest.mark.celery(result_backend='redis://')
def test_create_submission(client, request_dict): def test_create_submission(client, request_dict):
cpp = Course.query.filter_by(codename="testcourse1").first() cpp = Course.query.filter_by(codename="testcourse1").first()
p = cpp.projects[0] p = cpp.projects[0]
...@@ -198,6 +200,7 @@ def test_create_submission(client, request_dict): ...@@ -198,6 +200,7 @@ def test_create_submission(client, request_dict):
rest_tools.assert_submission_in(user_updated.submissions, new_submission) rest_tools.assert_submission_in(user_updated.submissions, new_submission)
@pytest.mark.celery(result_backend='redis://')
def test_create_submission_as_different_user(client, rest_service, request_dict): def test_create_submission_as_different_user(client, rest_service, request_dict):
cpp = rest_service.find.course("testcourse1") cpp = rest_service.find.course("testcourse1")
proj = cpp.projects[0] proj = cpp.projects[0]
...@@ -217,6 +220,7 @@ def test_create_submission_as_different_user(client, rest_service, request_dict) ...@@ -217,6 +220,7 @@ def test_create_submission_as_different_user(client, rest_service, request_dict)
rest_tools.assert_submission_in(user_updated.submissions, new_submission) rest_tools.assert_submission_in(user_updated.submissions, new_submission)
@pytest.mark.celery(result_backend='redis://')
def test_create_submission_as_student(client, ent_mocker, rest_service, request_dict): def test_create_submission_as_student(client, ent_mocker, rest_service, request_dict):
user, course, project = ent_mocker.create_user_in_course('testuser', role_type='student') user, course, project = ent_mocker.create_user_in_course('testuser', role_type='student')
path = f"/courses/{course.codename}/projects/{project.name}/submissions" path = f"/courses/{course.codename}/projects/{project.name}/submissions"
...@@ -229,6 +233,7 @@ def test_create_submission_as_student(client, ent_mocker, rest_service, request_ ...@@ -229,6 +233,7 @@ def test_create_submission_as_student(client, ent_mocker, rest_service, request_
assert new_submission['id'] assert new_submission['id']
@pytest.mark.celery(result_backend='redis://')
def test_create_submission_second_should_fail(client, ent_mocker, rest_service, request_dict): def test_create_submission_second_should_fail(client, ent_mocker, rest_service, request_dict):
user, course, project = ent_mocker.create_user_in_course('testuser', role_type='student') user, course, project = ent_mocker.create_user_in_course('testuser', role_type='student')
path = f"/courses/{course.codename}/projects/{project.name}/submissions" path = f"/courses/{course.codename}/projects/{project.name}/submissions"
...@@ -244,3 +249,36 @@ def test_create_submission_second_should_fail(client, ent_mocker, rest_service, ...@@ -244,3 +249,36 @@ def test_create_submission_second_should_fail(client, ent_mocker, rest_service,
credentials=user_credentials) credentials=user_credentials)
assert_response(response, code=429) assert_response(response, code=429)
@pytest.fixture()
def defaults_dict():
return {
"project_params": {},
"file_params": {
"source": {
"type": "git",
"branch": "master",
"checkout": "master"
}
}
}
@pytest.mark.celery(result_backend='redis://')
def test_create_submission_as_with_default_params(client, ent_mocker, rest_service, defaults_dict):
user, course, project = ent_mocker.create_user_in_course('testuser', role_type='student')
path = f"/courses/{course.codename}/projects/{project.name}/submissions"
user_credentials = get_user_credentials(user.username)
response = rest_tools.make_request(client, path, json=defaults_dict, method='post',
credentials=user_credentials)
assert_response(response, code=201)
new_submission = rest_tools.extract_data(response)
assert new_submission['id']
submission = rest_service.find.submission(new_submission['id'])
assert submission.project == project
assert submission.course == course
assert submission.user == user
assert submission.parameters['file_params']['from_dir'] == project.codename
gitlab_url = f'git@gitlab.local/{user.username}/{course.codename}'
assert submission.parameters['file_params']['source']['url'] == gitlab_url
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment