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
370b1540
Unverified
Commit
370b1540
authored
Sep 16, 2018
by
Peter Stanko
Browse files
Clients refactor - username for user and name for worker are just proxy for codename
parent
964d92ba
Changes
11
Hide whitespace changes
Inline
Side-by-side
portal/database/models.py
View file @
370b1540
...
...
@@ -79,6 +79,7 @@ class Client(db.Model):
id
=
db
.
Column
(
db
.
String
(
length
=
36
),
default
=
lambda
:
str
(
uuid
.
uuid4
()),
primary_key
=
True
)
type
=
db
.
Column
(
db
.
Enum
(
ClientType
,
name
=
'ClientType'
),
nullable
=
False
)
codename
=
db
.
Column
(
db
.
String
(
30
),
unique
=
True
,
nullable
=
False
)
secrets
=
db
.
relationship
(
'Secret'
,
back_populates
=
'client'
,
uselist
=
True
,
cascade
=
"all, delete-orphan"
,
passive_deletes
=
True
)
...
...
@@ -196,7 +197,6 @@ class User(EntityBase, Client):
uuid
.
uuid4
()),
primary_key
=
True
)
uco
=
db
.
Column
(
db
.
Integer
)
email
=
db
.
Column
(
db
.
String
(
50
),
unique
=
True
,
nullable
=
False
)
username
=
db
.
Column
(
db
.
String
(
30
),
unique
=
True
,
nullable
=
False
)
name
=
db
.
Column
(
db
.
String
(
50
))
is_admin
=
db
.
Column
(
db
.
Boolean
,
default
=
False
)
# optional - after password change
...
...
@@ -210,6 +210,14 @@ class User(EntityBase, Client):
'polymorphic_identity'
:
ClientType
.
USER
,
}
@
hybrid_property
def
username
(
self
):
return
self
.
codename
@
username
.
setter
def
username
(
self
,
value
):
self
.
codename
=
value
def
is_self
(
self
,
eid
):
return
super
().
is_self
(
eid
)
or
self
.
username
==
eid
...
...
@@ -860,9 +868,8 @@ class Submission(db.Model, EntityBase):
uuid
.
uuid4
()),
primary_key
=
True
)
scheduled_for
=
db
.
Column
(
db
.
TIMESTAMP
(
timezone
=
True
))
parameters
=
db
.
Column
(
JSONEncodedDict
(),
nullable
=
True
)
state
=
db
.
Column
(
db
.
Enum
(
SubmissionState
,
name
=
'SubmissionState'
),
nullable
=
False
)
note
=
db
.
Column
(
db
.
Text
)
state
=
db
.
Column
(
db
.
Enum
(
SubmissionState
,
name
=
'SubmissionState'
),
nullable
=
False
)
note
=
db
.
Column
(
JSONEncodedDict
())
source_hash
=
db
.
Column
(
db
.
String
(
64
))
user_id
=
db
.
Column
(
db
.
String
(
36
),
db
.
ForeignKey
(
'user.id'
,
ondelete
=
'cascade'
),
nullable
=
False
)
...
...
@@ -1002,7 +1009,6 @@ class Worker(EntityBase, Client):
__tablename__
=
'worker'
id
=
db
.
Column
(
db
.
String
(
length
=
36
),
db
.
ForeignKey
(
'client.id'
),
default
=
lambda
:
str
(
uuid
.
uuid4
()),
primary_key
=
True
)
name
=
db
.
Column
(
db
.
String
(
30
),
nullable
=
False
,
unique
=
True
)
url
=
db
.
Column
(
db
.
String
(
250
),
nullable
=
False
)
tags
=
db
.
Column
(
db
.
Text
())
# set by a Worker at init
portal_secret
=
db
.
Column
(
db
.
String
(
64
))
# set by a Worker at init
...
...
@@ -1012,6 +1018,14 @@ class Worker(EntityBase, Client):
'polymorphic_identity'
:
ClientType
.
WORKER
,
}
@
hybrid_property
def
name
(
self
):
return
self
.
codename
@
name
.
setter
def
name
(
self
,
value
):
self
.
codename
=
value
def
is_self
(
self
,
eid
):
return
super
().
is_self
(
eid
)
or
self
.
name
==
eid
...
...
portal/rest/schemas.py
View file @
370b1540
...
...
@@ -51,8 +51,9 @@ class NestedCollection:
'Group'
:
(
'id'
,
'codename'
,
'course.id'
),
'Project'
:
(
'id'
,
'codename'
,
'course.id'
),
'Course'
:
(
'id'
,
'codename'
),
'User'
:
(
'id'
,
'username'
,
'uco'
),
'Client'
:
(
'id'
,
'type'
,
'name'
),
'User'
:
(
'id'
,
'username'
,
'uco'
,
'codename'
),
'Worker'
:
(
'id'
,
'codename'
,
'name'
),
'Client'
:
(
'id'
,
'type'
,
'name'
,
'codename'
),
'Component'
:
(
'id'
,
'name'
,
'type'
),
'Submission'
:
(
'id'
,
'state'
,
'user.id'
,
'user.username'
,
'project.id'
,
'project.codename'
,
...
...
@@ -92,6 +93,7 @@ class UserSchema(BaseSchema, Schema):
email
=
fields
.
Email
(
required
=
True
)
username
=
fields
.
Str
(
required
=
True
)
name
=
fields
.
Str
()
codename
=
fields
.
Str
()
type
=
fields
.
Str
()
is_admin
=
fields
.
Bool
(
default
=
False
,
missing
=
False
)
submissions
=
NESTED
[
'submissions'
]
...
...
@@ -282,6 +284,7 @@ class WorkerSchema(BaseSchema, Schema):
"""Component Schema
"""
name
=
fields
.
Str
()
codename
=
fields
.
Str
(
allow_none
=
True
)
type
=
fields
.
Str
()
url
=
fields
.
Str
(
allow_none
=
True
)
tags
=
fields
.
Str
(
allow_none
=
True
)
...
...
portal/service/auth.py
View file @
370b1540
...
...
@@ -7,9 +7,7 @@ from flask_jwt_extended import get_jwt_identity
from
portal
import
gitlab_factory
from
portal.database.models
import
Client
from
portal.service.errors
import
IncorrectCredentialsError
,
InvalidGitlabAccessTokenError
,
\
PortalAPIError
,
UnauthorizedError
from
portal.service.general
import
find_user
,
find_worker
from
portal.service
import
general
,
errors
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -24,13 +22,13 @@ def login_gitlab(identifier: str, secret: str) -> Client:
Returns(User): the authenticated user
"""
if
secret
is
None
:
raise
PortalAPIError
(
400
,
'No gitlab access token found.'
)
raise
errors
.
PortalAPIError
(
400
,
'No gitlab access token found.'
)
validate_gitlab_token
(
secret
,
username
=
identifier
)
user
=
find_user
(
identifier
,
throws
=
False
)
user
=
general
.
find_user
(
identifier
,
throws
=
False
)
if
user
is
None
:
raise
InvalidGitlabAccessTokenError
()
raise
errors
.
InvalidGitlabAccessTokenError
()
return
user
...
...
@@ -43,14 +41,14 @@ def login_username_password(identifier: str, secret: str) -> Client:
Returns(Client): the authenticated user
"""
user
=
find_user
(
identifier
,
throws
=
False
)
user
=
general
.
find_user
(
identifier
,
throws
=
False
)
if
user
is
None
or
secret
is
None
:
raise
IncorrectCredentialsError
()
raise
errors
.
IncorrectCredentialsError
()
if
user
.
verify_password
(
password
=
secret
):
return
user
raise
IncorrectCredentialsError
()
raise
errors
.
IncorrectCredentialsError
()
def
login_secret
(
identifier
:
str
,
secret
:
str
)
->
Client
:
...
...
@@ -66,7 +64,7 @@ def login_secret(identifier: str, secret: str) -> Client:
client
=
__find_client_helper
(
identifier
)
if
client
.
verify_secret
(
secret
):
return
client
raise
UnauthorizedError
(
f
"[LOGIN] Invalid secret."
)
raise
errors
.
UnauthorizedError
(
f
"[LOGIN] Invalid secret."
)
def
validate_gitlab_token
(
token
:
str
,
username
:
str
,
throws
:
bool
=
True
):
...
...
@@ -82,7 +80,7 @@ def validate_gitlab_token(token: str, username: str, throws: bool = True):
user
=
client
.
user
if
user
.
username
!=
username
:
if
throws
:
raise
InvalidGitlabAccessTokenError
()
raise
errors
.
InvalidGitlabAccessTokenError
()
return
False
return
True
...
...
@@ -93,10 +91,8 @@ def find_client() -> Client:
def
__find_client_helper
(
identifier
:
str
)
->
Client
:
log
.
debug
(
f
"[LOGIN] Finding
permissions
using identifier:
{
identifier
}
"
)
client
=
find_user
(
identifier
,
throws
=
False
)
log
.
debug
(
f
"[LOGIN] Finding
client
using identifier:
{
identifier
}
"
)
client
=
general
.
find_client
(
identifier
,
throws
=
False
)
if
not
client
:
client
=
find_worker
(
identifier
,
throws
=
False
)
if
not
client
:
raise
UnauthorizedError
(
f
"[LOGIN] Unknown permissions identifier
{
identifier
}
."
)
raise
errors
.
UnauthorizedError
(
f
"[LOGIN] Unknown client identifier
{
identifier
}
."
)
return
client
portal/service/errors.py
View file @
370b1540
...
...
@@ -108,7 +108,7 @@ class UnauthorizedError(PortalAPIError):
class
ForbiddenError
(
PortalAPIError
):
# could use a resource identification (like 404)
def
__init__
(
self
,
client
=
None
,
note
=
None
):
user_message
=
f
"Forbidden for
{
permissions
.
type
}
:
{
permissions
.
id
}
!"
if
client
else
\
user_message
=
f
"Forbidden for
{
client
.
type
}
:
{
client
.
id
}
(
{
client
.
codename
}
)
!"
if
client
else
\
'Forbidden action.'
message
=
dict
(
uid
=
client
.
id
,
message
=
user_message
)
if
note
:
...
...
portal/service/general.py
View file @
370b1540
...
...
@@ -78,8 +78,7 @@ def find_resource(identifier: str, resource: str, query, throws: bool = True):
raise
ResourceNotFoundError
(
resource
=
resource
,
res_id
=
identifier
)
else
:
return
None
log
.
debug
(
f
"[FIND] Found
{
resource
.
capitalize
()
}
for identifier [
{
identifier
}
]:
{
instance
}
"
)
log
.
debug
(
f
"[FIND] Found
{
resource
.
capitalize
()
}
for identifier [
{
identifier
}
]:
{
instance
}
"
)
return
instance
...
...
@@ -252,17 +251,12 @@ def find_client(identifier: str, throws=False, client_type=None) -> Client:
Returns(Client): User entity instance
"""
query
=
Client
.
query
.
filter
(
Client
.
id
==
identifier
)
if
client_type
==
'user'
:
query
=
User
.
query
.
filter
((
User
.
id
==
identifier
)
|
(
User
.
username
==
identifier
))
elif
client_type
==
'worker'
:
query
=
Worker
.
query
.
filter
((
Worker
.
id
==
identifier
)
|
(
Worker
.
name
==
identifier
))
register
=
dict
(
user
=
User
,
client
=
Client
,
worker
=
Worker
)
klass
=
register
.
get
(
client_type
)
or
Client
query
=
klass
.
query
.
filter
((
klass
.
id
==
identifier
)
|
(
klass
.
codename
==
identifier
))
return
find_resource
(
resource
=
'permissions
'
,
resource
=
client_type
or
'client
'
,
identifier
=
identifier
,
query
=
query
,
throws
=
throws
...
...
@@ -298,4 +292,4 @@ def find_client_owner(client: Client) -> Union[User, Worker]:
return
find_user
(
client
.
id
)
if
client
.
type
==
ClientType
.
WORKER
:
return
find_worker
(
client
.
id
)
raise
UnauthorizedError
(
f
"[LOGIN] Unknown
permissions type
{
permissions
.
type
}
."
)
raise
UnauthorizedError
(
f
"[LOGIN] Unknown
client type
{
client
.
type
}
."
)
portal/service/permissions.py
View file @
370b1540
...
...
@@ -5,7 +5,7 @@ Permissions service
import
logging
from
typing
import
Union
from
portal.database.models
import
ClientType
,
Course
,
Role
,
User
,
Worker
from
portal.database.models
import
ClientType
,
Course
,
Role
,
Submission
,
User
,
Worker
from
portal.service
import
auth
,
general
from
portal.service.errors
import
ForbiddenError
...
...
@@ -35,9 +35,9 @@ class PermissionServiceCheck:
return
False
def
permissions
(
self
,
permissions
)
->
bool
:
log
.
debug
(
f
"[PERM] Client
{
self
.
service
.
client
.
id
}
in course "
f
"
{
self
.
service
.
course
.
codename
}
:
{
permissions
}
"
)
client
=
self
.
service
.
client
log
.
debug
(
f
"[PERM] Client
{
client
.
id
}
(
{
client
.
codename
}
)
in course "
f
"
\
"
{
self
.
service
.
course
.
codename
}
\"
:
{
permissions
}
"
)
if
self
.
sysadmin
():
return
True
...
...
@@ -48,28 +48,53 @@ class PermissionServiceCheck:
res
=
any
(
_resolve_permissions
(
conjunction
,
effective_permissions
)
for
conjunction
in
permissions
)
log
.
debug
(
f
"[PERM]
{
permissions
}
for
{
self
.
service
.
client
.
id
}
:
{
res
}
"
)
log
.
debug
(
f
"[PERM]
{
permissions
}
for
{
client
.
id
}
(
{
client
.
codename
}
)
:
{
res
}
"
)
return
res
def
any_check
(
self
,
*
params
)
->
bool
:
return
any
(
params
)
def
view_course_full
(
self
)
->
bool
:
return
self
.
permissions
([
'view_course_full'
])
def
view_course_limited
(
self
)
->
bool
:
return
self
.
permissions
([
'view_course_limited'
])
def
view_course_any
(
self
)
->
bool
:
return
self
.
permissions
([
'view_course_limited'
,
'view_course_full'
])
def
read_submissions_all
(
self
)
->
bool
:
return
self
.
permissions
([
'read_submissions_all'
])
def
read_submissions_group
(
self
,
submission
:
Submission
)
->
bool
:
return
self
.
read_submissions_all
()
or
\
self
.
service
.
submission_access_group
(
submission
,
[
'read_submissions_groups'
])
def
read_submissions_own
(
self
,
submission
:
Submission
)
->
bool
:
return
self
.
read_submissions_all
()
or
\
self
.
permissions
([
'read_submissions_own'
])
and
\
submission
.
user
==
self
.
service
.
client_owner
class
PermissionServiceRequire
:
def
__init__
(
self
,
service
:
'PermissionsService'
):
self
.
service
=
service
@
property
def
_check
(
self
)
->
PermissionServiceCheck
:
return
self
.
service
.
check
def
sysadmin_or_self
(
self
,
eid
):
self
.
any_check
(
self
.
service
.
check
.
sysadmin_or_self
(
eid
))
self
.
any_check
(
self
.
_
check
.
sysadmin_or_self
(
eid
))
def
sysadmin
(
self
):
self
.
any_check
(
self
.
service
.
check
.
sysadmin
())
self
.
any_check
(
self
.
_
check
.
sysadmin
())
def
permissions
(
self
,
permissions
):
self
.
any_check
(
self
.
service
.
check
.
permissions
(
permissions
))
self
.
any_check
(
self
.
_
check
.
permissions
(
permissions
))
def
any_check
(
self
,
*
checks
):
if
not
self
.
service
.
check
.
any_check
(
*
checks
):
if
not
self
.
_
check
.
any_check
(
*
checks
):
raise
ForbiddenError
(
self
.
service
.
client
)
def
update_course
(
self
):
...
...
@@ -85,45 +110,42 @@ class PermissionServiceRequire:
self
.
permissions
([
'update_course'
,
'write_groups'
])
def
view_course
(
self
):
self
.
permissions
([
'view_course_full'
,
'
view_course_
limited'
]
)
self
.
_check
.
view_course_
any
(
)
def
belongs_to_group
(
self
,
group
):
checks
=
[
self
.
service
.
check
.
permissions
([
'
view_course_full
'
]
),
(
self
.
service
.
check
.
permissions
([
'
view_course_limited
'
]
)
self
.
_check
.
view_course_full
(
),
(
self
.
_check
.
view_course_limited
(
)
and
self
.
service
.
client_owner
in
group
.
users
)
]
self
.
any_check
(
*
checks
)
def
belongs_to_role
(
self
,
role
:
Role
):
checks
=
[
self
.
service
.
check
.
permissions
([
'
view_course_full
'
]
),
(
self
.
service
.
check
.
permissions
([
'
view_course_limited
'
]
)
self
.
_check
.
view_course_full
(
),
(
self
.
_check
.
view_course_limited
(
)
and
self
.
service
.
client_owner
in
role
.
clients
)
]
self
.
any_check
(
*
checks
)
def
read_submission
(
self
,
submission
):
checks
=
[
self
.
service
.
check
.
permissions
([
'read_submissions_all'
]),
self
.
service
.
submission_access_group
(
submission
,
[
'read_submissions_groups'
]),
(
self
.
service
.
check
.
permissions
([
'read_submissions_own'
])
and
submission
.
user
==
self
.
service
.
client_owner
)
self
.
_check
.
read_submissions_group
(
submission
),
self
.
_check
.
read_submissions_own
(
submission
=
submission
)
]
self
.
any_check
(
*
checks
)
def
read_submission_group
(
self
,
submission
):
checks
=
[
self
.
service
.
check
.
permissions
([
'read_submissions_all'
]),
self
.
service
.
submission_access_group
(
submission
,
[
'read_submissions_groups'
])
self
.
_check
.
read_submissions_group
(
submission
=
submission
)
]
self
.
any_check
(
*
checks
)
def
write_review_for_submission
(
self
,
submission
):
checks
=
[
self
.
service
.
check
.
permissions
([
'write_reviews_all'
]),
self
.
_
check
.
permissions
([
'write_reviews_all'
]),
self
.
service
.
submission_access_group
(
submission
,
[
'write_reviews_group'
]),
(
self
.
service
.
check
.
permissions
([
'write_reviews_own'
])
and
(
self
.
_
check
.
permissions
([
'write_reviews_own'
])
and
submission
.
user
==
self
.
service
.
client_owner
)
]
self
.
any_check
(
*
checks
)
...
...
@@ -133,7 +155,7 @@ class PermissionServiceRequire:
self
.
permissions
([
'create_submissions_other'
])
user_service
=
PermissionsService
(
course
=
self
.
service
.
course
,
client
=
user
)
user_service
.
require
.
permissions
(
'create_submissions'
)
user_service
.
require
.
permissions
(
[
'create_submissions'
]
)
def
course_access_token
(
self
):
self
.
permissions
([
'handle_notes_access_token'
])
...
...
@@ -207,7 +229,7 @@ class PermissionsService:
if
not
key
.
startswith
(
"_"
)
and
key
not
in
FILTER_PERMISSION_ATTRS
:
result
[
key
]
=
result
.
get
(
key
)
or
value
log
.
debug
(
f
"[PERM] Effective permissions:
{
self
.
permissions
.
id
}
"
f
"[PERM] Effective permissions:
{
self
.
client
.
id
}
"
f
"in course
{
course
.
codename
}
:
{
result
}
"
)
return
result
...
...
portal/service/roles.py
View file @
370b1540
...
...
@@ -138,7 +138,7 @@ class RoleService:
return
clients
def
add_client
(
self
,
client
:
Client
):
"""Adds single
permissions
to the role
"""Adds single
client
to the role
Args:
client(Client): Client instance
Returns:
...
...
@@ -146,14 +146,14 @@ class RoleService:
if
client
not
in
self
.
role
.
clients
:
self
.
role
.
clients
.
append
(
client
)
write_entity
(
self
.
role
)
log
.
info
(
f
"[ADD] Client
{
permissions
.
id
}
to role "
log
.
info
(
f
"[ADD] Client
{
client
.
id
}
to role "
f
"
{
self
.
role
.
id
}
in course
{
self
.
role
.
course
.
id
}
."
)
else
:
log
.
info
(
f
"[ADD] Client
{
permissions
.
id
}
is already "
log
.
info
(
f
"[ADD] Client
{
client
.
id
}
is already "
f
"in role
{
self
.
role
.
id
}
in course
{
self
.
role
.
course
.
id
}
: no change."
)
def
remove_client
(
self
,
client
:
Client
)
->
Role
:
"""Removes single
permissions
from the role
"""Removes single
client
from the role
Args:
role(Role): Role instance
client(Client): Client instance
...
...
@@ -164,10 +164,10 @@ class RoleService:
self
.
role
.
clients
.
remove
(
client
)
write_entity
(
self
.
role
)
except
ValueError
:
raise
PortalAPIError
(
400
,
message
=
f
"Could not remove
permissions
{
permissions
.
id
}
"
raise
PortalAPIError
(
400
,
message
=
f
"Could not remove
client
{
client
.
id
}
"
f
"from role
{
self
.
role
.
id
}
in course
{
course
.
id
}
: "
f
"role does not contain
permissions
."
)
log
.
info
(
f
"[REMOVE] Client
{
permissions
.
id
}
from role "
f
"role does not contain
client
."
)
log
.
info
(
f
"[REMOVE] Client
{
client
.
id
}
from role "
f
"
{
self
.
role
.
id
}
in course
{
course
.
id
}
."
)
return
self
.
role
...
...
portal/service/submissions.py
View file @
370b1540
...
...
@@ -140,12 +140,12 @@ class SubmissionsService(object):
new_state
=
data
[
'state'
]
if
isinstance
(
client
,
User
)
and
new_state
!=
SubmissionState
.
CANCELLED
:
raise
errors
.
ForbiddenError
(
client
,
note
=
f
"User
{
permissions
.
id
}
cannot update "
note
=
f
"User
{
client
.
id
}
cannot update "
f
"state to other than CANCELLED."
)
self
.
submission
.
change_state
(
new_state
)
write_entity
(
self
.
submission
)
log
.
info
(
f
"[UPDATE] Submission state
{
self
.
submission
.
id
}
"
f
"by
{
permissions
.
id
}
to
{
self
.
submission
.
state
}
"
)
f
"by
{
client
.
id
}
to
{
self
.
submission
.
state
}
"
)
return
self
.
submission
def
cancel_submission
(
self
):
...
...
tests/rest/test_client.py
View file @
370b1540
...
...
@@ -24,7 +24,7 @@ def worker_credentials():
def
test_client_detail_using_student_cred
(
client
,
student_credentials
):
path
=
f
'/
permissions
'
path
=
f
'/
client
'
response
=
utils
.
make_request
(
client
,
path
,
'get'
,
credentials
=
student_credentials
)
print
(
f
"Response:
{
response
.
data
}
"
)
...
...
@@ -36,7 +36,7 @@ def test_client_detail_using_student_cred(client, student_credentials):
def
test_client_detail_using_executor_cred
(
client
,
worker_credentials
):
path
=
f
'/
permissions
'
path
=
f
'/
client
'
response
=
utils
.
make_request
(
client
,
path
,
'get'
,
credentials
=
worker_credentials
)
print
(
f
"Response:
{
response
.
data
}
"
)
...
...
tests/rest/test_project.py
View file @
370b1540
import
json
from
datetime
import
timedelta
from
flask_jwt_extended
import
create_access_token
from
portal.database.models
import
Course
,
Project
,
User
...
...
@@ -31,7 +32,7 @@ def test_create(client):
"name"
:
"new_project"
,
'codename'
:
'new-project'
,
'description'
:
'ultimate project blah'
}
}
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
cpp
.
codename
}
/projects"
,
method
=
'post'
,
data
=
request_json
,
...
...
@@ -66,7 +67,7 @@ def test_update(client):
p_name
=
p
.
name
request_dict
=
dict
(
name
=
"new project name"
,
)
)
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
cpp
.
codename
}
/projects/
{
p
.
name
}
"
,
data
=
request_json
,
method
=
'put'
,
...
...
@@ -118,7 +119,7 @@ def test_config_update(client):
test_files_source
=
"new source"
,
pre_submit_script
=
"a python script"
,
submissions_allowed_to
=
new_time
)
)
request_json
=
json
.
dumps
(
request_dict
,
cls
=
utils
.
DateTimeEncoder
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
cpp
.
codename
}
/projects/
{
p
.
name
}
/config"
,
...
...
@@ -183,9 +184,9 @@ def test_create_submission(client):
"url"
:
"https://gitlab.fi.muni.cz/xkompis/test-hello-world.git"
,
"branch"
:
"master"
,
"checkout"
:
"master"
}
}
}
}
request_json
=
json
.
dumps
(
request_dict
,
cls
=
utils
.
DateTimeEncoder
)
path
=
f
"/courses/
{
cpp
.
codename
}
/projects/
{
p
.
name
}
/submissions"
...
...
@@ -203,3 +204,36 @@ def test_create_submission(client):
assert
len
(
p_updated
.
submissions
)
==
p_submissions
+
1
utils
.
assert_submission_in
(
p_updated
.
submissions
,
new_submission
)
utils
.
assert_submission_in
(
user_updated
.
submissions
,
new_submission
)
def
test_create_submission_as_different_user
(
client
):
cpp
=
Course
.
query
.
filter_by
(
codename
=
"testcourse1"
).
first
()
p
=
cpp
.
projects
[
0
]
p_submissions
=
len
(
p
.
submissions
)
request_dict
=
{
"project_params"
:
"data for Kontr"
,
"file_params"
:
{
"source"
:
{
"type"
:
"git"
,
"url"
:
"https://gitlab.fi.muni.cz/xkompis/test-hello-world.git"
,
"branch"
:
"master"
,
"checkout"
:
"master"
}
}
}
request_json
=
json
.
dumps
(
request_dict
,
cls
=
utils
.
DateTimeEncoder
)
path
=
f
"/courses/
{
cpp
.
codename
}
/projects/
{
p
.
name
}
/submissions?user=student1"
response
=
utils
.
make_request
(
client
,
path
,
data
=
request_json
,
method
=
'post'
)
assert
response
.
status_code
==
201
assert
response
.
mimetype
==
'application/json'
new_submission
=
utils
.
extract_data
(
response
)
p_updated
=
Project
.
query
.
filter
(
Project
.
course_id
==
cpp
.
id
).
filter_by
(
name
=
p
.
name
).
first
()
user_updated
=
User
.
query
.
filter_by
(
username
=
"student1"
).
first
()
assert
len
(
p_updated
.
submissions
)
==
p_submissions
+
1
utils
.
assert_submission_in
(
p_updated
.
submissions
,
new_submission
)
utils
.
assert_submission_in
(
user_updated
.
submissions
,
new_submission
)
tests/rest/test_role.py
View file @
370b1540
...
...
@@ -27,7 +27,7 @@ def test_create(client):
"name"
:
"new role"
,
'codename'
:
'new-role'
,
"description"
:
"new role desc"
}
}
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
cpp
.
codename
}
/roles"
,
data
=
request_json
,
headers
=
{
"content-type"
:
"application/json"
},
method
=
'post'
)
...
...
@@ -63,7 +63,7 @@ def test_update(client):
request_dict
=
dict
(
name
=
"new role name"
,
description
=
"new role desc"
,
)
)
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
cpp
.
codename
}
/roles/
{
r
.
name
}
"
,
data
=
request_json
,
...
...
@@ -118,7 +118,7 @@ def test_users_update_add(client):
request_dict
=
dict
(
add
=
[
user
.
id
]
)
)
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
c
.
codename
}
/roles/
{
r
.
name
}
/clients"
,
data
=
request_json
,
...
...
@@ -143,7 +143,7 @@ def test_users_update_add_duplicate(client):
request_dict
=
dict
(
add
=
[
user
.
id
]
)
)
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
c
.
codename
}
/roles/
{
r
.
name
}
/clients"
,
data
=
request_json
,
...
...
@@ -168,7 +168,7 @@ def test_users_update_remove(client):
request_dict
=
dict
(
remove
=
[
user
.
id
]
)
)
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
c
.
codename
}
/roles/
{
r
.
name
}
/clients"
,
data
=
request_json
,
...
...
@@ -193,7 +193,7 @@ def test_users_update_remove_user_not_in(client):
request_dict
=
dict
(
remove
=
[
user
.
id
]
)
)
request_json
=
json
.
dumps
(
request_dict
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
c
.
codename
}
/roles/
{
r
.
name
}
/clients"
,
data
=
request_json
,
...
...
@@ -305,7 +305,7 @@ def test_permissions_update(client):
view_course_full
=
True
,
write_roles
=
True
,
read_submissions_all
=
True
)
)
request_json
=
json
.
dumps
(
request_dict
,
cls
=
utils
.
DateTimeEncoder
)
response
=
utils
.
make_request
(
client
,
f
"/courses/
{
cpp
.
codename
}
/roles/
{
r
.
name
}
/permissions"
,
...
...
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