2020-06-16 16:26:25 +00:00
|
|
|
# Admin app
|
2020-06-17 21:11:15 +00:00
|
|
|
import json
|
2020-06-16 16:26:25 +00:00
|
|
|
|
|
|
|
from flask import url_for
|
|
|
|
from flask_admin import Admin
|
2020-07-15 13:00:25 +00:00
|
|
|
from flask_admin.actions import action
|
2020-06-16 16:26:25 +00:00
|
|
|
from flask_admin.contrib import sqla
|
|
|
|
from flask_admin.contrib.sqla import ModelView
|
2020-07-15 13:00:25 +00:00
|
|
|
from github import Github, UnknownObjectException
|
2020-07-17 15:49:47 +00:00
|
|
|
from sqlalchemy import desc
|
2020-06-16 16:26:25 +00:00
|
|
|
from werkzeug.utils import redirect
|
2020-06-17 21:11:15 +00:00
|
|
|
from jinja2 import Markup
|
2020-06-16 16:26:25 +00:00
|
|
|
|
|
|
|
from crc import db, app
|
|
|
|
from crc.api.user import verify_token, verify_token_admin
|
|
|
|
from crc.models.approval import ApprovalModel
|
2020-07-15 13:00:25 +00:00
|
|
|
from crc.models.file import FileModel, FileDataModel
|
|
|
|
from crc.models.stats import TaskEventModel
|
2020-06-16 16:26:25 +00:00
|
|
|
from crc.models.study import StudyModel
|
|
|
|
from crc.models.user import UserModel
|
|
|
|
from crc.models.workflow import WorkflowModel
|
|
|
|
|
|
|
|
|
|
|
|
class AdminModelView(sqla.ModelView):
|
|
|
|
can_create = False
|
|
|
|
can_edit = False
|
|
|
|
can_delete = False
|
|
|
|
page_size = 50 # the number of entries to display on the list view
|
|
|
|
column_exclude_list = ['bpmn_workflow_json', ]
|
|
|
|
column_display_pk = True
|
|
|
|
can_export = True
|
|
|
|
|
|
|
|
def is_accessible(self):
|
|
|
|
return verify_token_admin()
|
|
|
|
|
|
|
|
def inaccessible_callback(self, name, **kwargs):
|
|
|
|
# redirect to login page if user doesn't have access
|
|
|
|
return redirect(url_for('home'))
|
|
|
|
|
2020-07-15 13:00:25 +00:00
|
|
|
|
2020-06-16 16:26:25 +00:00
|
|
|
class UserView(AdminModelView):
|
|
|
|
column_filters = ['uid']
|
|
|
|
|
2020-07-15 13:00:25 +00:00
|
|
|
|
2020-06-16 16:26:25 +00:00
|
|
|
class StudyView(AdminModelView):
|
|
|
|
column_filters = ['id', 'primary_investigator_id']
|
|
|
|
column_searchable_list = ['title']
|
|
|
|
|
2020-07-15 13:00:25 +00:00
|
|
|
|
2020-06-16 16:26:25 +00:00
|
|
|
class ApprovalView(AdminModelView):
|
|
|
|
column_filters = ['study_id', 'approver_uid']
|
|
|
|
|
2020-07-15 13:00:25 +00:00
|
|
|
|
2020-06-16 16:26:25 +00:00
|
|
|
class WorkflowView(AdminModelView):
|
|
|
|
column_filters = ['study_id', 'id']
|
|
|
|
|
2020-07-15 13:00:25 +00:00
|
|
|
|
2020-06-16 16:26:25 +00:00
|
|
|
class FileView(AdminModelView):
|
2020-07-15 13:00:25 +00:00
|
|
|
column_filters = ['workflow_id', 'type']
|
|
|
|
|
|
|
|
@action('publish', 'Publish', 'Are you sure you want to publish this file(s)?')
|
|
|
|
def action_publish(self, ids):
|
2020-07-17 18:10:55 +00:00
|
|
|
# TODO: Replace docs repo
|
|
|
|
gh_token = app.config['GITHUB_TOKEN']
|
2020-07-17 15:49:47 +00:00
|
|
|
_github = Github(gh_token)
|
2020-07-15 13:00:25 +00:00
|
|
|
repo = _github.get_user().get_repo('crispy-fiesta')
|
|
|
|
|
|
|
|
for file_id in ids:
|
|
|
|
file_data_model = FileDataModel.query.filter_by(file_model_id=file_id).first()
|
|
|
|
try:
|
|
|
|
repo_file = repo.get_contents(file_data_model.file_model.name)
|
|
|
|
except UnknownObjectException:
|
|
|
|
repo.create_file(
|
|
|
|
path=file_data_model.file_model.name,
|
|
|
|
message=f'Creating {file_data_model.file_model.name}',
|
|
|
|
content=file_data_model.data
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
updated = repo.update_file(
|
|
|
|
path=repo_file.path,
|
|
|
|
message=f'Updating {file_data_model.file_model.name}',
|
|
|
|
content=file_data_model.data,
|
|
|
|
sha=repo_file.sha
|
|
|
|
)
|
|
|
|
|
|
|
|
@action('update', 'Update', 'Are you sure you want to update this file(s)?')
|
|
|
|
def action_update(self, ids):
|
2020-07-17 18:10:55 +00:00
|
|
|
gh_token = app.config['GITHUB_TOKEN']
|
2020-07-17 15:49:47 +00:00
|
|
|
_github = Github(gh_token)
|
2020-07-15 13:00:25 +00:00
|
|
|
repo = _github.get_user().get_repo('crispy-fiesta')
|
|
|
|
|
|
|
|
for file_id in ids:
|
2020-07-17 15:49:47 +00:00
|
|
|
file_data_model = FileDataModel.query.filter_by(
|
|
|
|
file_model_id=file_id
|
|
|
|
).order_by(
|
|
|
|
desc(FileDataModel.version)
|
|
|
|
).first()
|
2020-07-15 13:00:25 +00:00
|
|
|
try:
|
|
|
|
repo_file = repo.get_contents(file_data_model.file_model.name)
|
|
|
|
except UnknownObjectException:
|
|
|
|
# Add message indicating file is not in the repo
|
|
|
|
pass
|
|
|
|
else:
|
2020-07-17 15:49:47 +00:00
|
|
|
file_data_model.data = repo_file.decoded_content
|
|
|
|
self.session.add(file_data_model)
|
|
|
|
self.session.commit()
|
2020-07-15 13:00:25 +00:00
|
|
|
|
2020-06-16 16:26:25 +00:00
|
|
|
|
2020-06-17 21:11:15 +00:00
|
|
|
def json_formatter(view, context, model, name):
|
|
|
|
value = getattr(model, name)
|
|
|
|
json_value = json.dumps(value, ensure_ascii=False, indent=2)
|
2020-07-15 13:00:25 +00:00
|
|
|
return Markup(f'<pre>{json_value}</pre>')
|
2020-06-17 21:11:15 +00:00
|
|
|
|
|
|
|
class TaskEventView(AdminModelView):
|
|
|
|
column_filters = ['workflow_id', 'action']
|
2020-06-19 12:22:53 +00:00
|
|
|
column_list = ['study_id', 'user_id', 'workflow_id', 'action', 'task_title', 'form_data', 'date']
|
2020-06-17 21:11:15 +00:00
|
|
|
column_formatters = {
|
2020-06-19 12:22:53 +00:00
|
|
|
'form_data': json_formatter,
|
2020-06-17 21:11:15 +00:00
|
|
|
}
|
|
|
|
|
2020-07-15 13:00:25 +00:00
|
|
|
|
2020-06-16 16:26:25 +00:00
|
|
|
admin = Admin(app)
|
|
|
|
|
|
|
|
admin.add_view(StudyView(StudyModel, db.session))
|
|
|
|
admin.add_view(ApprovalView(ApprovalModel, db.session))
|
|
|
|
admin.add_view(UserView(UserModel, db.session))
|
|
|
|
admin.add_view(WorkflowView(WorkflowModel, db.session))
|
|
|
|
admin.add_view(FileView(FileModel, db.session))
|
2020-06-17 21:11:15 +00:00
|
|
|
admin.add_view(TaskEventView(TaskEventModel, db.session))
|