Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Kontr 2.0
Portal API Backend
Commits
6b8f2b86
Verified
Commit
6b8f2b86
authored
Oct 06, 2018
by
Peter Stanko
Browse files
List of clients in the course
parent
6f057659
Changes
9
Hide whitespace changes
Inline
Side-by-side
portal/config.py
View file @
6b8f2b86
...
@@ -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
...
...
portal/database/models.py
View file @
6b8f2b86
...
@@ -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_
user
s_filtered
(
self
,
groups
:
List
[
'Group'
],
roles
:
List
[
'Role'
]):
def
get_
client
s_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
()
...
...
portal/rest/courses.py
View file @
6b8f2b86
...
@@ -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>/
user
s'
)
@
courses_namespace
.
route
(
'/<string:cid>/
client
s'
)
@
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
Course
User
s
(
CustomResource
):
class
Course
Client
s
(
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_
user
s_filtered
(
group_ids
,
role_ids
)
users
=
self
.
rest
.
courses
(
course
).
get_
client
s_filtered
(
group_ids
,
role_ids
)
return
SCHEMAS
.
dump
(
'users'
,
users
)
return
SCHEMAS
.
dump
(
'users'
,
users
)
portal/rest/schemas.py
View file @
6b8f2b86
...
@@ -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
,
...
...
portal/service/courses.py
View file @
6b8f2b86
...
@@ -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_
user
s_filtered
(
self
,
groups
:
List
[
str
],
roles
:
List
[
str
])
->
List
[
User
]:
def
get_
client
s_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
)
portal/service/general.py
View file @
6b8f2b86
...
@@ -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
...
...
portal/service/submissions.py
View file @
6b8f2b86
...
@@ -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
):
...
...
tests/rest/test_course.py
View file @
6b8f2b86
...
@@ -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
(
...
...
tests/rest/test_project.py
View file @
6b8f2b86
...
@@ -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
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment