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
59f2ce4b
Unverified
Commit
59f2ce4b
authored
Sep 21, 2018
by
Peter Stanko
Browse files
Full refactor of the service layer
parent
302dfef3
Pipeline
#13268
passed with stage
in 13 minutes and 9 seconds
Changes
38
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
management/data/__init__.py
View file @
59f2ce4b
...
...
@@ -8,8 +8,7 @@ from management.data.data_dev import init_dev_data
from
management.data.data_prod
import
init_prod_data
from
management.data.data_test
import
init_test_data
from
portal.database.models
import
Course
,
Role
,
Secret
,
Submission
,
SubmissionState
,
User
from
portal.service
import
general
from
portal.service.general
import
write_entity
from
portal.service.rest
import
RestService
from
portal.tools
import
time
...
...
@@ -23,6 +22,7 @@ class DataManagement(object):
self
.
app
=
app
self
.
db
=
db
self
.
creator
=
shared
.
DataFactory
(
self
.
db
)
self
.
rest
=
RestService
()
def
reset_db
(
self
):
"""Resets the database
...
...
@@ -43,14 +43,14 @@ class DataManagement(object):
else
:
init_dev_data
(
db
=
self
.
db
,
app
=
self
.
app
)
def
delete_user
(
self
,
name
):
def
delete_user
(
self
,
name
:
str
):
"""Deletes user
Args:
name(str): name of the user
"""
with
self
.
app
.
app_context
():
user
=
general
.
find_user
(
name
)
general
.
delete_entity
(
user
)
user
=
self
.
rest
.
users
.
find
(
name
)
self
.
rest
.
users
(
user
).
delete
(
)
def
update_users_password
(
self
,
name
:
str
,
password
:
str
)
->
User
:
"""Updates user's password
...
...
@@ -60,7 +60,7 @@ class DataManagement(object):
Returns(User): Updated user
"""
with
self
.
app
.
app_context
():
user
=
general
.
find
_
user
(
name
)
user
=
self
.
rest
.
find
.
user
(
name
)
user
.
set_password
(
password
=
password
)
self
.
db
.
session
.
add
(
user
)
self
.
db
.
session
.
commit
()
...
...
@@ -105,7 +105,7 @@ class DataManagement(object):
Returns(Role): Created role
"""
with
self
.
app
.
app_context
():
course
=
general
.
find
_
course
(
course_name
)
course
=
self
.
rest
.
find
.
course
(
course_name
)
role
=
self
.
creator
.
scaffold_role
(
course
,
role_type
=
role_type
,
name
=
name
)
self
.
db
.
session
.
commit
()
...
...
@@ -118,17 +118,17 @@ class DataManagement(object):
def
activate_project
(
self
,
course
:
str
,
project
:
str
):
with
self
.
app
.
app_context
():
course
=
general
.
find
_
course
(
course
)
project
=
general
.
find
_
project
(
course
,
project
)
course
=
self
.
rest
.
find
.
course
(
course
)
project
=
self
.
rest
.
find
.
project
(
course
,
project
)
days_allow_to
=
time
.
current_time
()
+
datetime
.
timedelta
(
days
=
1000
)
project
.
config
.
archive_from
=
None
project
.
config
.
submissions_allowed_to
=
days_allow_to
write_entity
(
project
)
self
.
rest
.
projects
.
write_entity
(
project
)
return
project
def
list_projects
(
self
,
course
:
str
):
with
self
.
app
.
app_context
():
course
=
general
.
find
_
course
(
course
)
course
=
self
.
rest
.
find
.
course
(
course
)
for
project
in
course
.
projects
:
print
(
f
"
{
project
.
name
}
:
{
project
.
description
}
"
)
...
...
@@ -146,14 +146,14 @@ class DataManagement(object):
with
self
.
app
.
app_context
():
for
submission
in
Submission
.
query
.
all
():
submission
.
change_state
(
SubmissionState
.
CANCELLED
)
write_entity
(
submission
)
self
.
rest
.
submissions
.
write_entity
(
submission
)
self
.
db
.
session
.
commit
()
def
cancel_submission
(
self
,
sid
):
with
self
.
app
.
app_context
():
submission
=
general
.
find
_
submission
(
sid
)
submission
=
self
.
rest
.
find
.
submission
(
sid
)
submission
.
change_state
(
SubmissionState
.
CANCELLED
)
write_entity
(
submission
)
self
.
rest
.
submissions
.
write_entity
(
submission
)
self
.
db
.
session
.
commit
()
def
clean_all_submissions
(
self
):
...
...
portal/async_celery/submission_processor.py
View file @
59f2ce4b
...
...
@@ -6,7 +6,6 @@ from storage import UploadedEntity
import
portal.tools.worker_client
from
portal
import
logger
,
tools
from
portal.database
import
Project
,
Submission
,
SubmissionState
,
Worker
from
portal.service
import
general
log
=
logger
.
get_logger
(
__name__
)
...
...
@@ -15,6 +14,8 @@ class SubmissionProcessor:
def
__init__
(
self
,
submission
:
Submission
,
params
:
dict
=
None
):
self
.
_submission
=
submission
self
.
_params
=
params
from
portal.service.rest
import
RestService
self
.
_rest
=
RestService
()
@
property
def
submission
(
self
)
->
Submission
:
...
...
@@ -43,7 +44,7 @@ class SubmissionProcessor:
self
.
submission
.
state
=
state
self
.
submission
.
async_task_id
=
None
general
.
write_entity
(
self
.
submission
)
self
.
_rest
.
submissions
.
write_entity
(
self
.
submission
)
def
submission_enqueue_ended
(
self
):
log
.
info
(
f
"[ASYNC] Submission enqueue ended
{
self
.
submission
.
log_name
}
:
{
self
.
submission
}
"
)
...
...
portal/async_celery/tasks.py
View file @
59f2ce4b
...
...
@@ -3,20 +3,21 @@ from storage import UploadedEntity
from
portal
import
storage
from
portal.async_celery
import
celery_app
,
submission_processor
from
portal.service.general
import
find_course
,
find_project
,
find_submission
,
write_entity
log
=
get_task_logger
(
__name__
)
@
celery_app
.
task
(
name
=
'upload-submission-to-storage'
)
def
process_submission
(
new_submission_id
:
str
):
new_submission
=
find_submission
(
new_submission_id
)
from
portal.service.rest
import
RestService
rest_service
=
RestService
()
new_submission
=
rest_service
.
find
.
submission
(
new_submission_id
)
project
=
new_submission
.
project
course
=
project
.
course
if
not
project
.
config
.
test_files_commit_hash
:
log
.
warning
(
f
"Project test files not found:
{
project
.
log_name
}
"
)
update_project_test_files
(
course_id
=
course
.
id
,
project_id
=
project
.
id
)
new_submission
=
find
_
submission
(
new_submission_id
)
new_submission
=
rest_service
.
find
.
submission
(
new_submission_id
)
processor
=
submission_processor
.
SubmissionProcessor
(
new_submission
)
processor
.
process_submission
()
...
...
@@ -24,7 +25,9 @@ def process_submission(new_submission_id: str):
@
celery_app
.
task
(
name
=
'upload-results-to-storage'
)
def
upload_results_to_storage
(
new_submission_id
:
str
,
path
:
str
):
path
=
str
(
path
)
new_submission
=
find_submission
(
new_submission_id
)
from
portal.service.rest
import
RestService
rest_service
=
RestService
()
new_submission
=
rest_service
.
find
.
submission
(
new_submission_id
)
processor
=
submission_processor
.
SubmissionProcessor
(
new_submission
)
file_params
=
dict
(
source
=
dict
(
url
=
path
,
type
=
'zip'
))
processor
.
upload_result
(
path
=
path
,
file_params
=
file_params
)
...
...
@@ -32,23 +35,31 @@ def upload_results_to_storage(new_submission_id: str, path: str):
@
celery_app
.
task
(
name
=
'clone-submission-files'
)
def
clone_submission_files
(
source_id
:
str
,
target_id
:
str
):
source
=
find_submission
(
source_id
)
target
=
find_submission
(
target_id
)
from
portal.service.rest
import
RestService
rest_service
=
RestService
()
source
=
rest_service
.
find
.
submission
(
source_id
)
target
=
rest_service
.
find
.
submission
(
target_id
)
processor
=
submission_processor
.
SubmissionProcessor
(
source
)
processor
.
clone
(
target
)
@
celery_app
.
task
(
name
=
'start-processing-submission'
)
def
start_processing_submission
(
submission_id
:
str
,
submission_params
):
submission
=
find_submission
(
submission_id
)
from
portal.service.rest
import
RestService
rest_service
=
RestService
()
submission
=
rest_service
.
find
.
submission
(
submission_id
)
processor
=
submission_processor
.
SubmissionProcessor
(
submission
,
submission_params
)
processor
.
send_to_worker
()
@
celery_app
.
task
(
name
=
'update-project-test-files'
)
def
update_project_test_files
(
course_id
:
str
,
project_id
:
str
):
course
=
find_course
(
course_id
)
project
=
find_project
(
course
,
project_id
)
from
portal.service.rest
import
RestService
rest_service
=
RestService
()
course
=
rest_service
.
find
.
course
(
course_id
)
project
=
rest_service
.
find
.
project
(
course
,
project_id
)
log
.
info
(
f
"[ASYNC] Updating test files for project:
{
project
.
log_name
}
"
)
params
=
{
'from_dir'
:
project
.
config
.
test_files_subdir
,
...
...
@@ -60,4 +71,4 @@ def update_project_test_files(course_id: str, project_id: str):
updated_entity
:
UploadedEntity
=
storage
.
test_files
.
update
(
entity_id
=
project
.
id
,
**
params
)
project
.
config
.
test_files_commit_hash
=
updated_entity
.
version
log
.
debug
(
f
"Updated project config
{
project
.
log_name
}
:
{
project
.
config
}
"
)
write_entity
(
project
.
config
)
rest_service
.
projects
.
write_entity
(
project
.
config
)
portal/rest/client.py
View file @
59f2ce4b
from
flask_jwt_extended
import
jwt_required
from
flask_restplus
import
Namespace
,
Resource
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
from
portal.service
import
permissions
,
general
from
portal.service.secrets
import
create_secret
,
delete_secret
client_namespace
=
Namespace
(
'client'
)
clients_namespace
=
Namespace
(
'clients'
)
...
...
@@ -15,12 +14,11 @@ log = logger.get_logger(__name__)
@
client_namespace
.
route
(
''
)
class
ClientController
(
Resource
):
class
ClientController
(
Custom
Resource
):
@
jwt_required
# @users_namespace.response(200, 'List of users', model=users_schema)
def
get
(
self
):
perm_service
=
permissions
.
PermissionsService
()
client
=
perm_service
.
client_owner
client
=
self
.
permissions
.
client_owner
schema
=
SCHEMAS
.
user
()
if
client
.
type
==
ClientType
.
USER
else
SCHEMAS
.
worker
()
return
schema
.
dump
(
client
)[
0
],
200
...
...
@@ -28,21 +26,21 @@ class ClientController(Resource):
@
clients_namespace
.
route
(
'/<string:cid>/secrets'
)
@
clients_namespace
.
param
(
'wid'
,
"Client's id"
)
@
clients_namespace
.
response
(
404
,
'Client not found'
)
class
ClientSecretsController
(
Resource
):
class
ClientSecretsController
(
Custom
Resource
):
@
jwt_required
@
clients_namespace
.
response
(
200
,
'List client secrets'
)
def
get
(
self
,
cid
:
str
):
permissions
.
P
ermissions
Service
()
.
require
.
sysadmin_or_self
(
cid
)
client
=
general
.
find
_
client
(
cid
)
self
.
p
ermissions
.
require
.
sysadmin_or_self
(
cid
)
client
=
self
.
rest
.
find
.
client
(
cid
)
return
SCHEMAS
.
dump
(
'secrets'
,
client
.
secrets
)
@
jwt_required
# @workers_namespace.response(201, 'Created worker secret', model=secret_schema)
def
post
(
self
,
cid
:
str
):
permissions
.
P
ermissions
Service
()
.
require
.
sysadmin_or_self
(
cid
)
self
.
p
ermissions
.
require
.
sysadmin_or_self
(
cid
)
data
=
rest_helpers
.
parse_request_data
(
action
=
'create'
,
resource
=
'secret'
)
client
=
general
.
find
_
client
(
cid
)
new_secret
,
value
=
create_
secret
(
client
,
**
data
)
client
=
self
.
find
.
client
(
cid
)
new_secret
,
value
=
self
.
rest
.
secret
s
(
client
=
client
).
create
(
**
data
)
return
{
'id'
:
new_secret
.
id
,
'value'
:
value
},
201
...
...
@@ -50,35 +48,33 @@ class ClientSecretsController(Resource):
@
clients_namespace
.
param
(
'wid'
,
"Client's id"
)
@
clients_namespace
.
param
(
'sid'
,
"Secret id"
)
@
clients_namespace
.
response
(
404
,
'Client not found'
)
class
ClientSecretController
(
Resource
):
class
ClientSecretController
(
Custom
Resource
):
@
jwt_required
@
clients_namespace
.
response
(
200
,
'Client secret detail'
)
def
get
(
self
,
cid
:
str
,
sid
:
str
):
permissions
.
P
ermissions
Service
()
.
require
.
sysadmin
(
)
client
=
general
.
find
_
client
(
cid
)
secret
=
general
.
find
_
secret
(
client
,
sid
)
self
.
rest
.
p
ermissions
.
require
.
sysadmin
_or_self
(
cid
)
client
=
self
.
rest
.
find
.
client
(
cid
)
secret
=
self
.
rest
.
find
.
secret
(
client
,
sid
)
return
SCHEMAS
.
dump
(
'secret'
,
secret
)
@
jwt_required
@
clients_namespace
.
response
(
204
,
'Client secret deleted'
)
def
delete
(
self
,
cid
:
str
,
sid
:
str
):
permissions
.
PermissionsService
().
require
.
sysadmin_or_self
(
cid
)
worker
=
general
.
find_client
(
cid
)
delete_secret
(
worker
,
sid
)
self
.
rest
.
permissions
.
require
.
sysadmin_or_self
(
cid
)
client
=
self
.
find
.
client
(
cid
)
secret
=
self
.
find
.
secret
(
client
,
sid
)
self
.
rest
.
secrets
(
secret
).
delete
()
return
''
,
204
@
jwt_required
@
clients_namespace
.
response
(
204
,
'Client secret updated'
)
@
clients_namespace
.
response
(
403
,
'Not allowed to update client secret'
)
def
put
(
self
,
cid
:
str
,
sid
:
str
):
permissions
.
P
ermissions
Service
()
.
require
.
sysadmin_or_self
(
cid
)
self
.
rest
.
p
ermissions
.
require
.
sysadmin_or_self
(
cid
)
data
=
rest_helpers
.
parse_request_data
(
action
=
'update'
,
resource
=
'secret'
,
partial
=
True
)
client
=
general
.
find
_
client
(
cid
)
secret
=
general
.
find
_
secret
(
client
,
sid
)
general
.
update_entity
(
secret
,
data
,
[
'name'
,
'expires_at'
]
)
client
=
self
.
find
.
client
(
cid
)
secret
=
self
.
find
.
secret
(
client
,
sid
)
self
.
rest
.
secrets
(
secret
).
update
(
**
data
)
return
''
,
204
portal/rest/courses.py
View file @
59f2ce4b
from
flask
import
request
from
flask_jwt_extended
import
jwt_required
from
flask_restplus
import
Namespace
,
Resource
from
flask_restplus
import
Namespace
from
portal
import
logger
from
portal.rest
import
rest_helpers
from
portal.rest.custom_resource
import
CustomResource
from
portal.rest.schemas
import
SCHEMAS
from
portal.service
import
permissions
from
portal.service.auth
import
find_client
from
portal.service.courses
import
CourseService
from
portal.service.errors
import
ForbiddenError
,
PortalAPIError
from
portal.service.filters
import
filter_course_dump
from
portal.service.general
import
find_course
courses_namespace
=
Namespace
(
'courses'
)
log
=
logger
.
get_logger
(
__name__
)
@
courses_namespace
.
route
(
''
)
class
CourseList
(
Resource
):
class
CourseList
(
Custom
Resource
):
@
jwt_required
# @courses_namespace.response(200, 'Courses list', model=courses_schema)
@
courses_namespace
.
response
(
403
,
'Not allowed to see courses'
)
def
get
(
self
):
# authorization
permissions
.
P
ermissions
Service
()
.
require
.
sysadmin
()
self
.
p
ermissions
.
require
.
sysadmin
()
courses_list
=
CourseService
()
.
find_all
_courses
()
courses_list
=
self
.
rest
.
courses
.
find_all
()
return
SCHEMAS
.
dump
(
'courses'
,
courses_list
)
@
jwt_required
# @courses_namespace.response(200, 'Created course', model=course_schema)
# @courses_namespace.response(403, 'Not allowed to create course', model=course_schema)
def
post
(
self
):
permissions
.
P
ermissions
Service
()
.
require
.
sysadmin
()
self
.
p
ermissions
.
require
.
sysadmin
()
data
=
rest_helpers
.
parse_request_data
(
resource
=
'course'
,
action
=
'create'
)
new_course
=
CourseService
().
create_cours
e
(
**
data
)
new_course
=
self
.
rest
.
courses
.
creat
e
(
**
data
)
return
SCHEMAS
.
dump
(
'course'
,
new_course
),
201
@
courses_namespace
.
route
(
'/<string:cid>'
)
@
courses_namespace
.
param
(
'cid'
,
'Course id'
)
@
courses_namespace
.
response
(
404
,
'Course not found'
)
class
CourseResource
(
Resource
):
class
CourseResource
(
Custom
Resource
):
@
jwt_required
# @courses_namespace.response(200, 'Course found', model=course_schema)
@
courses_namespace
.
response
(
403
,
'Not allowed to see course'
)
def
get
(
self
,
cid
:
str
):
client
=
find_
client
()
course
=
find
_
course
(
cid
)
client
=
self
.
rest
.
auth
.
client
course
=
self
.
rest
.
find
.
course
(
cid
)
# authorization
perm_service
=
permissions
.
P
ermissions
Service
(
course
=
course
)
perm_service
=
self
.
p
ermissions
(
course
=
course
)
if
perm_service
.
check
.
permissions
([
'view_course_full'
]):
return
SCHEMAS
.
dump
(
'course'
,
course
)
...
...
@@ -67,36 +64,36 @@ class CourseResource(Resource):
@
courses_namespace
.
response
(
204
,
'Course deleted'
)
@
courses_namespace
.
response
(
403
,
'Not allowed to delete course'
)
def
delete
(
self
,
cid
:
str
):
permissions
.
P
ermissions
Service
()
.
require
.
sysadmin
()
course
=
find
_
course
(
cid
)
CourseService
(
course
=
course
).
delete
_course
()
self
.
p
ermissions
.
require
.
sysadmin
()
course
=
self
.
rest
.
find
.
course
(
cid
)
self
.
rest
.
course
s
(
course
).
delete
()
return
''
,
204
@
jwt_required
@
courses_namespace
.
response
(
204
,
'Course updated'
)
@
courses_namespace
.
response
(
403
,
'Not allowed to update course'
)
def
put
(
self
,
cid
:
str
):
course
=
find
_
course
(
cid
)
course
=
self
.
rest
.
find
.
course
(
cid
)
# authorization
permissions
.
P
ermissions
Service
(
course
=
course
).
require
.
update_course
()
self
.
p
ermissions
(
course
=
course
).
require
.
update_course
()
data
=
rest_helpers
.
parse_request_data
(
action
=
'update'
,
resource
=
'course'
,
partial
=
True
)
CourseService
(
course
=
course
).
update
_course
(
data
)
self
.
rest
.
course
s
(
course
).
update
(
**
data
)
return
''
,
204
@
courses_namespace
.
route
(
'/<string:cid>/notes_access_token'
)
@
courses_namespace
.
param
(
'cid'
,
'Course id'
)
@
courses_namespace
.
response
(
404
,
'Course not found'
)
class
CourseNotesToken
(
Resource
):
class
CourseNotesToken
(
Custom
Resource
):
@
jwt_required
@
courses_namespace
.
response
(
403
,
'Not allowed to manipulate with course
\'
s notes access token'
)
@
courses_namespace
.
response
(
200
,
'Course notes token'
)
def
get
(
self
,
cid
):
course
=
find
_
course
(
cid
)
course
=
self
.
find
.
course
(
cid
)
# authorization
permissions
.
P
ermissions
Service
(
course
=
course
).
require
.
course_access_token
()
self
.
p
ermissions
(
course
=
course
).
require
.
course_access_token
()
return
course
.
notes_access_token
@
jwt_required
...
...
@@ -104,54 +101,54 @@ class CourseNotesToken(Resource):
@
courses_namespace
.
response
(
403
,
'Not allowed to update course
\'
s notes access token'
)
def
put
(
self
,
cid
):
course
=
find
_
course
(
cid
)
course
=
self
.
find
.
course
(
cid
)
# authorization
permissions
.
P
ermissions
Service
(
course
=
course
).
require
.
course_access_token
()
self
.
p
ermissions
(
course
=
course
).
require
.
course_access_token
()
json_data
=
rest_helpers
.
require_data
(
action
=
'update_notes_token'
,
resource
=
'course'
)
CourseService
(
course
=
course
).
update_notes_token
(
json_data
[
'token'
])
self
.
rest
.
course
s
(
course
).
update_notes_token
(
json_data
[
'token'
])
return
''
,
204
@
courses_namespace
.
route
(
'/<string:cid>/import'
)
@
courses_namespace
.
param
(
'cid'
,
'Course id'
)
@
courses_namespace
.
response
(
404
,
'Course not found'
)
class
CourseImport
(
Resource
):
class
CourseImport
(
Custom
Resource
):
@
jwt_required
# @courses_namespace.response(200, 'Course has been imported', model=course_schema)
@
courses_namespace
.
response
(
403
,
'Not allowed to import course'
)
@
courses_namespace
.
response
(
400
,
'Cannot import course to itself.'
)
def
put
(
self
,
cid
:
str
):
course
=
find
_
course
(
cid
)
course
=
self
.
find
.
course
(
cid
)
# authorization
permissions
.
P
ermissions
Service
(
course
=
course
).
require
.
update_course
()
self
.
p
ermissions
(
course
=
course
).
require
.
update_course
()
data
=
rest_helpers
.
parse_request_data
(
schema
=
SCHEMAS
.
course_import
,
action
=
'import'
,
resource
=
'course'
)
source_course
=
find
_
course
(
data
[
'source_course'
])
source_course
=
self
.
find
.
course
(
data
[
'source_course'
])
if
source_course
==
course
:
raise
PortalAPIError
(
400
,
f
'[IMPORT] Cannot import course to itself. (id:
{
cid
}
)'
)
config
=
data
[
'config'
]
copied_course
=
CourseService
(
course
=
course
).
copy_course
(
course
,
config
)
copied_course
=
self
.
rest
.
course
s
(
course
).
copy_course
(
course
,
config
)
return
SCHEMAS
.
dump
(
'course'
,
copied_course
)
@
courses_namespace
.
route
(
'/<string:cid>/users'
)
@
courses_namespace
.
param
(
'cid'
,
'Course id'
)
@
courses_namespace
.
response
(
404
,
'Course not found'
)
class
CourseUsers
(
Resource
):
class
CourseUsers
(
Custom
Resource
):
@
jwt_required
# @courses_namespace.response(200, 'Users in the course', model=users_schema)
@
courses_namespace
.
response
(
403
,
'Not allowed to see users in the course'
)
def
get
(
self
,
cid
):
course
=
find
_
course
(
cid
)
permissions
.
P
ermissions
Service
(
course
=
course
).
require
.
permissions
([
'view_course_full'
])
course
=
self
.
find
.
course
(
cid
)
self
.
p
ermissions
(
course
=
course
).
require
.
permissions
([
'view_course_full'
])
group_ids
=
request
.
args
.
getlist
(
'group'
)
role_ids
=
request
.
args
.
getlist
(
'role'
)
users
=
CourseService
(
course
=
course
).
get_users_filtered
(
group_ids
,
role_ids
)
users
=
self
.
rest
.
course
s
(
course
).
get_users_filtered
(
group_ids
,
role_ids
)
return
SCHEMAS
.
dump
(
'users'
,
users
)
portal/rest/custom_resource.py
0 → 100644
View file @
59f2ce4b
from
flask_restplus
import
Resource
from
portal.service.find
import
FindService
from
portal.service.permissions
import
PermissionsService
from
portal.service.rest
import
RestService
class
CustomResource
(
Resource
):
@
property
def
rest
(
self
)
->
RestService
:
if
not
hasattr
(
self
,
'__rest_service'
):
setattr
(
self
,
'__rest_service'
,
RestService
())
return
getattr
(
self
,
'__rest_service'
)
@
property
def
find
(
self
)
->
FindService
:
return
self
.
rest
.
find
@
property
def
permissions
(
self
)
->
PermissionsService
:
return
self
.
rest
.
permissions
portal/rest/gitlab.py
View file @
59f2ce4b
from
typing
import
Union
from
flask
import
Flask
,
Response
,
make_response
,
redirect
,
request
,
session
from
flask_oauthlib.client
import
OAuth
,
OAuthRemoteApp
from
flask_restplus
import
Namespace
,
Resource
from
flask_restplus
import
Namespace
from
portal
import
oauth
,
logger
from
portal
import
logger
,
oauth
from
portal.rest
import
rest_api
from
portal.service
import
general
from
portal.service.users
import
UserService
from
portal.rest.custom_resource
import
CustomResource
log
=
logger
.
get_logger
(
__name__
)
...
...
@@ -20,7 +20,7 @@ def extract_user_info(me: dict) -> dict:
name
=
me
[
'name'
],
username
=
me
[
'username'
],
email
=
me
[
'email'
]
)
)
def
gitlab_enabled
(
app
:
Flask
)
->
bool
:
...
...
@@ -46,14 +46,14 @@ def create_gitlab_app(oauth_app: OAuth) -> Union[OAuthRemoteApp, None]:
access_token_method
=
'POST'
,
consumer_key
=
client_id
,
consumer_secret
=
client_secret
)
)
gitlab
=
create_gitlab_app
(
oauth_app
=
oauth
)
@
oauth_namespace
.
route
(
'/login'
)
class
OAuthLogin
(
Resource
):
class
OAuthLogin
(
Custom
Resource
):
def
get
(
self
):
if
not
gitlab
:
return
{
'message'
:
'Gitlab OAuth is not enabled'
},
404
...
...
@@ -64,20 +64,48 @@ class OAuthLogin(Resource):
return
gitlab
.
authorize
(
callback
=
callback
)
@
oauth_namespace
.
route
(
'/login/authorized'
)
class
OAuthLoginAuthorized
(
CustomResource
):
def
get
(
self
):
if
not
gitlab
:
return
{
'message'
:
'Gitlab OAuth is not enabled'
},
404
resp
=
gitlab
.
authorized_response
()
if
resp
is
None
:
return
'Access denied: reason=%s error=%s'
%
(
request
.
args
[
'error'
],
request
.
args
[
'error_description'
]
)
token
=
extract_token
(
resp
)
login
=
login_to_gitlab_with_token
(
token
)
log
.
debug
(
f
"[GITLAB] Gitlab Login response:
{
login
}
"
)
return
login
@
gitlab
.
tokengetter
def
get_gitlab_oauth_token
():
token
=
session
.
get
(
'gitlab_token'
)
return
token
def
user_oauth_register
(
user_info
):
new_user
=
UserService
().
create_user
(
from
portal.service.rest
import
RestService
rest
=
RestService
()
new_user
=
rest
.
users
.
create
(
uco
=
None
,
username
=
user_info
[
'username'
],
name
=
user_info
[
'name'
],
email
=
user_info
[
'email'
],
is_admin
=
False
)
)
log
.
debug
(
f
"[GITLAB] Created user=
{
new_user
}
"
)
return
new_user
def
user_login
(
user_info
)
->
Response
:
user
=
general
.
find_user
(
user_info
[
'username'
],
throws
=
False
)