Commit d23f8053 authored by Barbora Kompišová's avatar Barbora Kompišová
Browse files

fixes, submission func

parent 569f3b2d
......@@ -245,6 +245,30 @@ class Course(db.Model, EntityBase):
return User.query.join(User.groups) \
.filter(( == & (Role.course == self)).all()
def get_users_filtered(self, groups: List['Group'], roles: List['Role']): # projects: List['Project']?
"""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.
groups: A list of groups. A user must be part of at least one to be included in the result.
roles: A list of roles. A user must be part of at least one to be included in the result.
Returns: Users in the course that satisfy constraints (are in at least one group AND have at least one role).
q = Course.query.join(Course.roles).join(Role.users).filter( ==
q2 = User.query.join(Role.users).join(Course.roles).filter(Role.course_id ==
q3 = User.query.join(User.roles).join(Role.course)
query = User.query.join(User.roles).filter(Role.course_id ==
if roles:
role_ids = [ for role in roles]
query = query.filter(
if groups:
group_ids = [ for group in groups]
query = query.join(User.groups).filter( ==
return query.all()
class ProjectState(enum.Enum):
......@@ -149,8 +149,8 @@ class SubmissionSchema(Schema):
state = EnumField(SubmissionState)
scheduled_for = fields.LocalDateTime()
parameters = fields.Dict()
project = fields.Nested(ProjectSchema, only=('id', 'name', '')) # check dot notation
user = fields.Nested(UserSchema, only='id') # id
project = fields.Nested(ProjectSchema, only=('id', 'name', '', 'course.codename'))
user = fields.Nested(UserSchema, only=('id', 'username', 'uco', 'name', 'email'))
class ReviewSchema(Schema):
import logging
from flask import Blueprint
from flask import Blueprint, request
from flask_jwt_extended import jwt_required
from flask_restful import Api, Resource
from import course_schema, courses_schema, course_import_schema, rest_helpers
from import course_schema, courses_schema, course_import_schema, rest_helpers, users_schema
from import delete_course, update_course, create_course, \
update_notes_token, copy_course, find_all_courses
update_notes_token, copy_course, find_all_courses, get_users_filtered
from portal.service.filters import filter_course_dump
from portal.service.general import find_course
from portal.service.errors import ForbiddenError
......@@ -141,10 +141,26 @@ class CourseImport(Resource):
config = data['config']
copy_course(source_course, course, config)
return course_schema.dump(course), 204
return course_schema.dump(course)[0], 204
class CourseUsers(Resource):
def get(self, cid):
client = find_client()
course = find_course(cid)
# authorization TODO
group_ids = request.args.getlist('group')
role_ids = request.args.getlist('role')
users = get_users_filtered(course, group_ids, role_ids)
# log.debug('filtered user list: ', users)
return users_schema.dump(users)[0], 200
courses_api.add_resource(CourseResource, '/<string:cid>')
courses_api.add_resource(CourseList, '')
courses_api.add_resource(CourseNotesToken, "/<string:cid>/notes_access_token")
courses_api.add_resource(CourseImport, "/<string:cid>/import")
courses_api.add_resource(CourseUsers, "/<string:cid>/users")
......@@ -72,10 +72,6 @@ class GroupsList(Resource):
def get(self, cid):
client = auth.find_client()
course = general.find_course(cid)
# authorization
permissions = ['read_groups', 'update_course', 'write_groups']
if not check_client(client=client, course=course, permissions=permissions):
raise ForbiddenError(
return groups_schema.dump(list_groups(course, client=client))
......@@ -137,15 +137,15 @@ class UserSubmissionList(Resource):
raise ForbiddenError(
course_id = request.args.get('course')
project_id = request.args.get('project')
project_ids = request.args.getlist('project') # musi brat zoznam projektov
if project_id and not course_id:
if project_ids and not course_id:
raise PortalAPIError(400,
f"Invalid filter combination at "
f"/get/users/{uid}/submissions: missing course id.")
submissions = find_submissions_filtered(user=user, course_id=course_id,
return submissions_schema.dump(submissions)[0], 200
import logging
from typing import List
from portal.database.models import Course
from portal.database.models import Course, Group, Role
from portal.service import general
from portal.service.groups import copy_group
from portal.service.projects import copy_project
......@@ -95,3 +96,13 @@ def update_notes_token(course: Course, token: str) -> Course:
def find_all_courses():
return Course.query.all()
def get_users_filtered(course: Course, groups: List[str], roles: List[str]):
# log.debug('group ids: ', str(len(groups)))
# log.debug('role ids: ', str(len(roles)))
groups_entities = Group.query.filter(
# log.debug('group entities size: ', str(len(groups_entities)))
roles_entities = Role.query.filter(
# log.debug('role entities size: ', str(len(roles_entities)))
return course.get_users_filtered(groups_entities, roles_entities)
......@@ -182,7 +182,7 @@ def import_group(data: dict, course: Course) -> Group:
def list_groups(course: Course, client):
if check_client(client=client, course=course, permissions=['view_course_full']):
return course.projects
return course.groups
elif check_client(client=client, course=course, permissions=['view_course_limited']):
return filters.filter_groups_from_course(course=course, user=client)
raise ForbiddenError(
......@@ -153,23 +153,23 @@ def find_reviews(user: User) -> List[Review]:
def find_submissions_filtered(user: User, course_id: str = None,
project_id: str = None) -> List[Submission]:
project_ids: List[str] = None) -> List[Submission]:
"""Get all submissions of a user, optionally filtered by course and project.
course_id(str): Course id (optional)
project_id(str): Project id (optional)
project_ids(List[str]): List of project ids (optional)
Returns(List[Submission]): submissions in the course and projects
submissions = Submission.query.filter_by(user=user)
# user.submissions cannot be used as the base query
if course_id:
submissions = submissions.join(Project)
if project_id:
if project_ids:
submissions = submissions.filter(
( == project_id) | ( == project_id))
( | (
submissions = submissions.join(Course).filter(
( == course_id) | (Course.codename == course_id))
return submissions
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