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
bf102b33
Verified
Commit
bf102b33
authored
Oct 01, 2018
by
Peter Stanko
Browse files
Submission create check - test + fixes
parent
a6bd7ff8
Pipeline
#14175
failed with stage
in 7 minutes and 58 seconds
Changes
21
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
management/data/__init__.py
View file @
bf102b33
...
...
@@ -107,10 +107,9 @@ class DataManagement(object):
course
=
self
.
rest
.
find
.
course
(
course
)
role
=
self
.
creator
.
scaffold_project
(
course
,
name
)
self
.
db
.
session
.
commit
()
log
.
debug
(
f
'[DATA] Created ro
le
:
{
role
.
log_name
}
'
)
log
.
debug
(
f
'[DATA] Created
p
ro
ject
:
{
role
.
log_name
}
'
)
return
role
def
create_role
(
self
,
course_name
:
str
,
role_type
:
str
,
name
:
str
)
->
Role
:
"""Creates role in the course based on type
Args:
...
...
management/data/shared.py
View file @
bf102b33
...
...
@@ -4,12 +4,14 @@ Factory to create sample data
import
random
import
string
from
datetime
import
timedelta
from
flask_sqlalchemy
import
SQLAlchemy
from
portal
import
logger
from
portal.database.models
import
Course
,
Group
,
Project
,
ReviewItem
,
Role
,
Submission
,
User
,
\
Worker
from
portal.tools
import
time
log
=
logger
.
get_logger
(
__name__
)
...
...
@@ -176,5 +178,18 @@ class DataFactory(object):
permissions
=
permissions
)
return
role
def
scaffold_project
(
self
,
course
,
name
):
return
self
.
create_project
(
course
=
course
,
name
=
name
,
codename
=
name
)
def
scaffold_project
(
self
,
course
:
Course
,
name
:
str
):
project_config
=
dict
(
file_whitelist
=
"*.*"
,
test_files_source
=
'https://gitlab.fi.muni.cz/grp-kontr2/testing/hello-test-files'
,
test_files_subdir
=
''
,
pre_submit_script
=
"python for kontr pre"
,
post_submit_script
=
"python for kontr post"
,
submission_scheduler_config
=
"python for sub Q"
,
submission_parameters
=
"{
\"
type
\"
:
\"
text
\"
}"
,
submissions_allowed_from
=
time
.
current_time
()
-
timedelta
(
days
=
1
),
submissions_allowed_to
=
time
.
current_time
()
+
timedelta
(
days
=
10
),
archive_from
=
time
.
current_time
()
+
timedelta
(
days
=
30
)
)
return
self
.
create_project
(
course
=
course
,
name
=
name
,
config
=
project_config
)
portal/database/mixins.py
View file @
bf102b33
"""
A collection of Mixins specifying common behaviour and attributes of database entities.
"""
import
datetime
from
sqlalchemy.ext.hybrid
import
hybrid_property
from
portal
import
db
...
...
portal/rest/projects.py
View file @
bf102b33
...
...
@@ -3,6 +3,7 @@ from flask_jwt_extended import jwt_required
from
flask_restplus
import
Namespace
from
portal
import
logger
from
portal.database.models
import
ClientType
from
portal.rest
import
rest_helpers
from
portal.rest.custom_resource
import
CustomResource
from
portal.rest.schemas
import
SCHEMAS
...
...
@@ -170,7 +171,10 @@ class ProjectSubmissions(CustomResource):
# check if a new submission can be created by this user in this project
project
=
self
.
find
.
project
(
course
,
pid
)
self
.
rest
.
projects
(
project
).
check_submission_create
(
client
=
user
)
if
client
.
type
==
ClientType
.
USER
:
client_instance
=
self
.
find
.
user
(
client
.
id
)
if
not
client_instance
.
is_admin
:
self
.
rest
.
projects
(
project
).
check_submission_create
(
client
=
user
)
data
=
rest_helpers
.
parse_request_data
(
schema
=
SCHEMAS
.
submission_create
,
action
=
'create'
,
resource
=
'submission'
...
...
@@ -179,11 +183,7 @@ class ProjectSubmissions(CustomResource):
# data for Kontr processing
service
=
self
.
rest
.
submissions
()
new_submission
=
service
.
create_submission
(
user
=
user
,
project
=
project
,
submission_params
=
data
)
new_submission
=
service
.
create
(
user
=
user
,
project
=
project
,
submission_params
=
data
)
return
SCHEMAS
.
dump
(
'submission'
,
new_submission
),
201
...
...
@@ -201,7 +201,3 @@ class ProjectTestFiles(CustomResource):
service
=
self
.
rest
.
storage
(
project
=
project
)
storage_entity
=
service
.
get_test_files_entity_from_storage
()
return
service
.
send_file_or_zip
(
storage_entity
)
portal/service/errors.py
View file @
bf102b33
...
...
@@ -4,6 +4,8 @@ Errors in the service layer
import
json
from
typing
import
Union
from
portal.database
import
Project
,
User
class
PortalError
(
Exception
):
"""Base exception class
...
...
@@ -96,7 +98,7 @@ class ResourceNotFoundError(PortalAPIError):
class
UnauthorizedError
(
PortalAPIError
):
def
__init__
(
self
,
note
=
None
):
message
=
dict
(
message
=
f
"You are not authorized."
,)
message
=
dict
(
message
=
f
"You are not authorized."
,
)
if
note
:
message
[
'note'
]
=
note
...
...
@@ -144,3 +146,12 @@ class SubmissionRefusedError(PortalAPIError):
class
WorkerNotAvailable
(
PortalError
):
def
__init__
(
self
,
message
:
str
=
None
):
self
.
message
=
message
or
"Worker is not available"
class
SubmissionDiffTimeError
(
PortalAPIError
):
def
__init__
(
self
,
project
:
Project
,
diff_time
,
user
:
User
=
None
):
log_user
=
f
'by
{
user
.
log_name
}
'
if
user
else
''
message
=
f
"Submission cannot be created for
{
project
.
log_name
}
,
{
log_user
}
"
\
f
"you can create submission in
{
diff_time
}
."
super
().
__init__
(
code
=
429
,
message
=
message
)
portal/service/projects.py
View file @
bf102b33
"""
Projects service
"""
import
datetime
import
logging
from
datetime
import
timedelta
from
typing
import
List
from
flask_sqlalchemy
import
BaseQuery
from
portal
import
storage
from
portal.async_celery
import
tasks
from
portal.database.models
import
ClientType
,
Course
,
Project
,
ProjectConfig
,
ProjectState
,
\
Submission
,
SubmissionState
,
User
...
...
@@ -14,7 +16,6 @@ from portal.service import errors, filters
from
portal.service.errors
import
ForbiddenError
from
portal.service.general
import
GeneralService
,
get_new_name
from
portal.tools
import
time
from
portal
import
storage
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -130,16 +131,40 @@ class ProjectService(GeneralService):
def
check_submission_create
(
self
,
client
=
None
):
client
=
client
or
self
.
client
if
client
.
type
==
ClientType
.
USER
:
user
=
self
.
find
.
user
(
client
.
id
)
# TODO: Might be good to add check whether it is in DEBUG Mode
if
user
.
is_admin
:
return
True
if
client
.
type
!=
ClientType
.
USER
:
raise
errors
.
SubmissionRefusedError
(
f
"Worker cannot create submission."
)
user
=
self
.
find
.
user
(
client
.
id
)
# TODO: Might be good to add check whether it is in DEBUG Mode
if
user
.
is_admin
:
return
True
if
self
.
project
.
state
(
timestamp
=
time
.
current_time
())
!=
ProjectState
.
ACTIVE
:
raise
errors
.
SubmissionRefusedError
(
f
"Project
{
self
.
project
.
name
}
not active."
)
raise
errors
.
SubmissionRefusedError
(
f
"Project
{
self
.
project
.
log_
name
}
not active."
)
if
not
ProjectService
(
self
.
project
).
can_create_submission
(
client
):
raise
errors
.
SubmissionRefusedError
(
f
"Submission in project
{
self
.
project
.
name
}
already active."
)
f
"Submission in project
{
self
.
project
.
log_name
}
already active."
)
self
.
_check_latest_submission
(
user
)
return
True
def
_check_latest_submission
(
self
,
user
:
User
):
latest_submission
=
self
.
get_latest_submission
(
user
)
if
not
latest_submission
:
return
True
latest_time
=
latest_submission
.
created_at
now_time
=
datetime
.
datetime
.
utcnow
()
diff_time
=
now_time
-
latest_time
delta
=
timedelta
(
minutes
=
30
)
# TODO this should be configurable @mdujava
log
.
info
(
f
"Submission for project
{
self
.
project
.
log_name
}
by user
{
user
.
log_name
}
,"
f
" time delta:
{
diff_time
}
<
{
delta
}
=
{
diff_time
<
delta
}
"
)
if
diff_time
<
delta
:
log
.
debug
(
f
"Submission for
{
self
.
project
.
log_name
}
by
{
user
.
log_name
}
"
f
"rejected based on the time delta:
{
diff_time
}
"
)
raise
errors
.
SubmissionDiffTimeError
(
self
.
project
,
diff_time
,
user
=
user
)
return
True
def
get_latest_submission
(
self
,
user
)
->
Submission
:
return
Submission
.
query
.
filter
((
Submission
.
user
==
user
)
&
(
Submission
.
project
==
self
.
project
))
\
.
order_by
(
Submission
.
created_at
.
desc
()).
first
()
def
find_all
(
self
,
course
:
Course
)
->
list
:
"""List of all projects
...
...
@@ -154,7 +179,8 @@ class ProjectService(GeneralService):
return
filters
.
filter_projects_from_course
(
course
=
course
,
user
=
perm_service
.
client
)
raise
ForbiddenError
(
perm_service
.
client
)
def
update_project_test_files
(
self
):
""" Sends a request to Storage to update the project's test_files to the newest version.
"""
tasks
.
update_project_test_files
.
delay
(
self
.
project
.
course
.
id
,
self
.
project
.
id
)
\ No newline at end of file
def
update_project_test_files
(
self
):
""" Sends a request to Storage to update the project's test_files to the newest version.
"""
tasks
.
update_project_test_files
.
delay
(
self
.
project
.
course
.
id
,
self
.
project
.
id
)
portal/service/submissions.py
View file @
bf102b33
...
...
@@ -3,7 +3,6 @@ Submissions service
"""
import
logging
import
time
from
pathlib
import
Path
from
typing
import
List
,
Union
...
...
@@ -50,7 +49,7 @@ class SubmissionsService(GeneralService):
allowed
=
[]
return
self
.
update_entity
(
entity
,
data
,
allowed
=
allowed
)
def
create
_submission
(
self
,
user
:
User
,
project
:
Project
,
submission_params
:
dict
):
def
create
(
self
,
user
:
User
,
project
:
Project
,
submission_params
:
dict
):
"""Creates a new submission in the database and downloads its files.
Zip and git sources are processed differently.
...
...
tests/rest/
uti
ls.py
→
tests/rest/
rest_too
ls.py
View file @
bf102b33
import
json
import
json
as
json_parser
from
datetime
import
datetime
import
flask
from
flask
import
Response
from
flask.testing
import
FlaskClient
...
...
@@ -8,11 +10,24 @@ from portal import logger
from
portal.database.models
import
Course
,
Group
,
Project
,
ProjectConfig
,
Review
,
ReviewItem
,
Role
,
\
Submission
,
User
,
Worker
DEFAULT_USER_CREDENTIALS
=
json
.
dumps
({
"type"
:
"username_password"
,
"identifier"
:
"admin"
,
"secret"
:
"789789"
})
def
get_user_credentials
(
username
,
password
=
'123456'
):
return
json
.
dumps
({
"type"
:
"username_password"
,
"identifier"
:
username
,
"secret"
:
password
})
def
get_user_secret
(
username
,
secret
):
return
json
.
dumps
({
"type"
:
"secret"
,
"identifier"
:
username
,
"secret"
:
secret
})
DEFAULT_USER_CREDENTIALS
=
get_user_credentials
(
'admin'
,
'789789'
)
log
=
logger
.
get_logger
(
__name__
)
...
...
@@ -26,7 +41,8 @@ def extract_data(response: Response) -> dict:
def
make_request
(
client
:
FlaskClient
,
url
:
str
,
method
:
str
=
'get'
,
credentials
:
str
=
None
,
headers
:
dict
=
None
,
data
:
str
=
None
)
->
Response
:
credentials
:
str
=
None
,
headers
:
dict
=
None
,
data
:
str
=
None
,
json
:
dict
=
None
)
->
Response
:
""" Creates an authenticated request to an endpoint.
Args:
...
...
@@ -47,6 +63,8 @@ def make_request(client: FlaskClient, url: str, method: str = 'get',
full_url
=
API_PREFIX
+
url
log
.
debug
(
f
"[REQ] (
{
method
}
) -
\"
{
full_url
}
\"
"
)
request_method
=
getattr
(
client
,
method
)
if
json
is
not
None
and
data
is
None
:
data
=
json_parser
.
dumps
(
json
)
return
request_method
(
full_url
,
headers
=
headers
,
data
=
data
,
follow_redirects
=
True
)
...
...
@@ -55,6 +73,7 @@ def __get_access_token(client, credentials):
log
.
debug
(
f
"[REQ] Login credentials:
{
credentials
}
"
)
login_resp
=
client
.
post
(
f
"
{
API_PREFIX
}
/auth/login"
,
data
=
credentials
,
headers
=
{
"content-type"
:
"application/json"
})
log
.
debug
(
f
"[RESP]
{
login_resp
}
"
)
resp_data
=
json
.
loads
(
str
(
login_resp
.
get_data
().
decode
(
"utf-8"
)))
return
resp_data
[
'access_token'
]
...
...
@@ -259,3 +278,8 @@ class DateTimeEncoder(json.JSONEncoder):
return
o
.
isoformat
()
return
json
.
JSONEncoder
.
default
(
self
,
o
)
def
assert_response
(
response
:
flask
.
Response
,
code
=
200
,
content_type
=
'application/json'
):
assert
response
.
status_code
==
code
assert
response
.
mimetype
==
content_type
tests/rest/test_clients.py
View file @
bf102b33
...
...
@@ -3,7 +3,7 @@ import json
import
pytest
from
portal.database.models
import
Client
,
Secret
from
tests.rest
import
uti
ls
from
tests.rest
import
rest_too
ls
@
pytest
.
fixture
...
...
@@ -26,7 +26,7 @@ def worker_credentials():
def
test_client_detail_using_student_cred
(
client
,
student_credentials
):
path
=
f
'/client'
response
=
uti
ls
.
make_request
(
response
=
rest_too
ls
.
make_request
(
client
,
path
,
'get'
,
credentials
=
student_credentials
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
'application/json'
...
...
@@ -37,7 +37,7 @@ def test_client_detail_using_student_cred(client, student_credentials):
def
test_client_detail_using_executor_cred
(
client
,
worker_credentials
):
path
=
f
'/client'
response
=
uti
ls
.
make_request
(
response
=
rest_too
ls
.
make_request
(
client
,
path
,
'get'
,
credentials
=
worker_credentials
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
'application/json'
...
...
@@ -49,10 +49,10 @@ def test_client_detail_using_executor_cred(client, worker_credentials):
def
test_create_secret
(
client
):
instance
=
Client
.
query
.
filter_by
(
codename
=
"executor"
).
first
()
request_dict
=
dict
(
name
=
"new_secret"
)
response
=
uti
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets'
,
headers
=
{
"content-type"
:
"application/json"
},
data
=
json
.
dumps
(
request_dict
),
method
=
'post'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets'
,
headers
=
{
"content-type"
:
"application/json"
},
data
=
json
.
dumps
(
request_dict
),
method
=
'post'
)
assert
response
.
status_code
==
201
assert
response
.
mimetype
==
'application/json'
...
...
@@ -67,22 +67,22 @@ def test_create_secret(client):
def
test_list_secret
(
client
):
instance
=
Client
.
query
.
filter_by
(
codename
=
"executor"
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'get'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'get'
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
'application/json'
secrets
=
uti
ls
.
extract_data
(
response
)
secrets
=
rest_too
ls
.
extract_data
(
response
)
assert
len
(
secrets
)
==
1
def
test_delete_secret
(
client
):
worker
=
Client
.
query
.
filter_by
(
codename
=
"executor"
).
first
()
secret
=
Secret
.
query
.
filter_by
(
client
=
worker
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
'/clients/
{
worker
.
id
}
/secrets/
{
secret
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'delete'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/clients/
{
worker
.
id
}
/secrets/
{
secret
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'delete'
)
assert
response
.
status_code
==
204
...
...
@@ -92,13 +92,13 @@ def test_delete_secret(client):
def
test_read_secret
(
client
):
instance
=
Client
.
query
.
filter_by
(
codename
=
"executor"
).
first
()
secret
=
Secret
.
query
.
filter_by
(
client
=
instance
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets/
{
secret
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'get'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets/
{
secret
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'get'
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
'application/json'
response_secret
=
uti
ls
.
extract_data
(
response
)
response_secret
=
rest_too
ls
.
extract_data
(
response
)
assert
response_secret
[
'id'
]
==
secret
.
id
assert
response_secret
[
'name'
]
==
secret
.
name
...
...
@@ -109,10 +109,10 @@ def test_update_secret(client):
instance
=
Client
.
query
.
filter_by
(
codename
=
"executor"
).
first
()
request_dict
=
dict
(
name
=
"new_name"
)
secret
=
Secret
.
query
.
filter_by
(
client
=
instance
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets/
{
secret
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
data
=
json
.
dumps
(
request_dict
),
method
=
'put'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/clients/
{
instance
.
id
}
/secrets/
{
secret
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
data
=
json
.
dumps
(
request_dict
),
method
=
'put'
)
assert
response
.
status_code
==
204
updated_secret
=
Secret
.
query
.
filter_by
(
client
=
instance
).
first
()
...
...
tests/rest/test_course.py
View file @
bf102b33
...
...
@@ -3,19 +3,19 @@ import json
from
portal.database.models
import
Course
from
portal.service
import
courses
,
general
from
portal.service.courses
import
CourseService
from
.
import
uti
ls
from
.
import
rest_too
ls
def
test_list
(
client
):
response
=
uti
ls
.
make_request
(
client
,
'/courses'
,
method
=
'get'
)
response
=
rest_too
ls
.
make_request
(
client
,
'/courses'
,
method
=
'get'
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
'application/json'
courses_response
=
uti
ls
.
extract_data
(
response
)
courses_response
=
rest_too
ls
.
extract_data
(
response
)
assert
len
(
courses_response
)
==
2
db_courses
=
Course
.
query
.
all
()
uti
ls
.
assert_course_in
(
db_courses
,
courses_response
[
0
])
uti
ls
.
assert_course_in
(
db_courses
,
courses_response
[
1
])
rest_too
ls
.
assert_course_in
(
db_courses
,
courses_response
[
0
])
rest_too
ls
.
assert_course_in
(
db_courses
,
courses_response
[
1
])
def
test_create
(
client
):
...
...
@@ -26,16 +26,16 @@ def test_create(client):
db_courses_number
=
len
(
Course
.
query
.
all
())
request_json
=
json
.
dumps
(
request_dict
)
response
=
uti
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
response
=
rest_too
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
assert
response
.
status_code
==
201
assert
response
.
mimetype
==
'application/json'
resp_new_course
=
uti
ls
.
extract_data
(
response
)
resp_new_course
=
rest_too
ls
.
extract_data
(
response
)
db_courses
=
Course
.
query
.
all
()
assert
len
(
db_courses
)
==
db_courses_number
+
1
uti
ls
.
assert_course_in
(
db_courses
,
resp_new_course
)
rest_too
ls
.
assert_course_in
(
db_courses
,
resp_new_course
)
def
test_create_extra_key
(
client
):
...
...
@@ -47,16 +47,16 @@ def test_create_extra_key(client):
db_courses_number
=
len
(
Course
.
query
.
all
())
request_json
=
json
.
dumps
(
request_dict
)
response
=
uti
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
response
=
rest_too
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
assert
response
.
status_code
==
201
assert
response
.
mimetype
==
'application/json'
resp_new_course
=
uti
ls
.
extract_data
(
response
)
resp_new_course
=
rest_too
ls
.
extract_data
(
response
)
db_courses
=
Course
.
query
.
all
()
assert
len
(
db_courses
)
==
db_courses_number
+
1
uti
ls
.
assert_course_in
(
db_courses
,
resp_new_course
)
rest_too
ls
.
assert_course_in
(
db_courses
,
resp_new_course
)
def
test_create_missing_name
(
client
):
...
...
@@ -64,9 +64,9 @@ def test_create_missing_name(client):
db_courses_number
=
len
(
Course
.
query
.
all
())
request_json
=
json
.
dumps
(
request_dict
)
response
=
uti
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
response
=
rest_too
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
assert
response
.
status_code
==
400
assert
response
.
mimetype
==
'application/json'
assert
len
(
Course
.
query
.
all
())
==
db_courses_number
...
...
@@ -80,9 +80,9 @@ def test_create_invalid_value(client):
db_courses_number
=
len
(
Course
.
query
.
all
())
request_json
=
json
.
dumps
(
request_dict
)
response
=
uti
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
response
=
rest_too
ls
.
make_request
(
client
,
'/courses'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
assert
response
.
status_code
==
400
assert
response
.
mimetype
==
'application/json'
assert
len
(
Course
.
query
.
all
())
==
db_courses_number
...
...
@@ -90,13 +90,13 @@ def test_create_invalid_value(client):
def
test_read
(
client
):
c
=
Course
.
query
.
filter_by
(
codename
=
"testcourse1"
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
"/courses/
{
c
.
id
}
"
,
method
=
'get'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
"/courses/
{
c
.
id
}
"
,
method
=
'get'
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
'application/json'
course
=
uti
ls
.
extract_data
(
response
)
course
=
rest_too
ls
.
extract_data
(
response
)
uti
ls
.
assert_course
(
c
,
course
)
rest_too
ls
.
assert_course
(
c
,
course
)
def
test_update
(
client
):
...
...
@@ -106,8 +106,8 @@ def test_update(client):
codename
=
"testcourse1_new"
,
)
request_json
=
json
.
dumps
(
request_dict
)
response
=
uti
ls
.
make_request
(
client
,
f
'/courses/
{
c
.
id
}
'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/courses/
{
c
.
id
}
'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
assert
response
.
status_code
==
204
assert
response
.
mimetype
==
'application/json'
...
...
@@ -119,9 +119,9 @@ def test_update(client):
def
test_delete
(
client
):
c
=
Course
.
query
.
filter_by
(
codename
=
"testcourse2"
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
'/courses/
{
c
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'delete'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/courses/
{
c
.
id
}
'
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'delete'
)
assert
response
.
status_code
==
204
assert
response
.
mimetype
==
'application/json'
...
...
@@ -131,20 +131,20 @@ def test_delete(client):
def
test_notes_token_read
(
client
):
c
=
Course
.
query
.
filter_by
(
codename
=
"testcourse2"
).
first
()
response
=
uti
ls
.
make_request
(
response
=
rest_too
ls
.
make_request
(
client
,
f
"/courses/
{
c
.
id
}
/notes_access_token"
,
method
=
'get'
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
'application/json'
data
=
uti
ls
.
extract_data
(
response
)
data
=
rest_too
ls
.
extract_data
(
response
)
assert
data
==
"testcourse2_token"
def
test_notes_token_create
(
client
):
c
=
Course
.
query
.
filter_by
(
codename
=
"testcourse2"
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
"/courses/
{
c
.
id
}
/notes_access_token"
,
data
=
json
.
dumps
({
"token"
:
"new_token"
}),
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
"/courses/
{
c
.
id
}
/notes_access_token"
,
data
=
json
.
dumps
({
"token"
:
"new_token"
}),
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
assert
response
.
status_code
==
204
assert
response
.
mimetype
==
'application/json'
...
...
@@ -154,9 +154,9 @@ def test_notes_token_create(client):
def
test_notes_token_update
(
client
):
c
=
Course
.
query
.
filter_by
(
codename
=
"testcourse1"
).
first
()
response
=
uti
ls
.
make_request
(
client
,
f
"/courses/
{
c
.
id
}
/notes_access_token"
,
data
=
json
.
dumps
({
"token"
:
"new_token"
}),
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
"/courses/
{
c
.
id
}
/notes_access_token"
,
data
=
json
.
dumps
({
"token"
:
"new_token"
}),
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
assert
response
.
status_code
==
204
assert
response
.
mimetype
==
'application/json'
...
...
@@ -177,10 +177,10 @@ def test_copy_from_course(rest_service, client):
}
request_json
=
json
.
dumps
(
request_dict
)
response
=
uti
ls
.
make_request
(
client
,
f
'/courses/
{
target
.
codename
}
/import'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
response
=
rest_too
ls
.
make_request
(
client
,
f
'/courses/
{
target
.
codename
}
/import'
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'put'
)
assert
response
.
status_code
==
200
assert
response
.
mimetype
==
"application/json"
...
...
tests/rest/test_group.py
View file @
bf102b33
import
json
from
portal.database.models
import
Course
,
Group
,
Role
,
User
from