2020-09-10 11:28:58 -04:00
|
|
|
import logging
|
|
|
|
import os
|
2020-10-02 15:16:28 -04:00
|
|
|
from functools import wraps
|
2020-09-10 11:28:58 -04:00
|
|
|
|
|
|
|
import connexion
|
|
|
|
import sentry_sdk
|
2020-10-02 15:16:28 -04:00
|
|
|
from flask import render_template, request, redirect, url_for, flash, abort
|
2020-09-23 12:43:58 -04:00
|
|
|
from flask_assets import Environment
|
2020-09-10 11:28:58 -04:00
|
|
|
from flask_cors import CORS
|
|
|
|
from flask_mail import Mail
|
|
|
|
from flask_marshmallow import Marshmallow
|
|
|
|
from flask_migrate import Migrate
|
2020-09-23 12:43:58 -04:00
|
|
|
from flask_paginate import Pagination, get_page_parameter
|
2020-09-10 11:28:58 -04:00
|
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
|
|
from sentry_sdk.integrations.flask import FlaskIntegration
|
2020-09-23 12:43:58 -04:00
|
|
|
from webassets import Bundle
|
2020-09-10 11:28:58 -04:00
|
|
|
|
2020-10-02 15:16:28 -04:00
|
|
|
|
2020-09-10 11:28:58 -04:00
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
|
|
|
# API, fully defined in api.yml
|
|
|
|
connexion_app = connexion.FlaskApp(__name__)
|
|
|
|
app = connexion_app.app
|
|
|
|
|
|
|
|
# Configuration
|
|
|
|
app.config.from_object('config.default')
|
|
|
|
if "TESTING" in os.environ and os.environ["TESTING"] == "true":
|
|
|
|
app.config.from_object('config.testing')
|
|
|
|
app.config.from_pyfile('../config/testing.py')
|
|
|
|
else:
|
|
|
|
app.config.root_path = app.instance_path
|
|
|
|
app.config.from_pyfile('config.py', silent=True)
|
|
|
|
|
|
|
|
# Mail settings
|
|
|
|
mail = Mail(app)
|
|
|
|
|
|
|
|
# Database
|
|
|
|
db = SQLAlchemy(app)
|
|
|
|
migrate = Migrate(app, db)
|
|
|
|
ma = Marshmallow(app)
|
|
|
|
|
2020-09-23 12:43:58 -04:00
|
|
|
# Asset management
|
|
|
|
url_map = app.url_map
|
|
|
|
try:
|
|
|
|
for rule in url_map.iter_rules('static'):
|
|
|
|
url_map._rules.remove(rule)
|
|
|
|
except ValueError:
|
|
|
|
# no static view was created yet
|
|
|
|
pass
|
|
|
|
app.add_url_rule(
|
|
|
|
app.static_url_path + '/<path:filename>',
|
|
|
|
endpoint='static', view_func=app.send_static_file)
|
|
|
|
assets = Environment(app)
|
|
|
|
assets.init_app(app)
|
|
|
|
assets.url = app.static_url_path
|
|
|
|
scss = Bundle(
|
|
|
|
'scss/app.scss',
|
|
|
|
filters='pyscss',
|
|
|
|
output='app.css'
|
|
|
|
)
|
|
|
|
assets.register('app_scss', scss)
|
|
|
|
|
2020-09-10 11:28:58 -04:00
|
|
|
from communicator import models
|
|
|
|
from communicator import api
|
2020-09-22 16:22:15 -04:00
|
|
|
from communicator import forms
|
2020-09-24 11:51:50 -04:00
|
|
|
from communicator import scheduler
|
2020-09-22 16:22:15 -04:00
|
|
|
|
2020-09-10 11:28:58 -04:00
|
|
|
connexion_app.add_api('api.yml', base_path='/v1.0')
|
|
|
|
|
|
|
|
# Convert list of allowed origins to list of regexes
|
|
|
|
origins_re = [r"^https?:\/\/%s(.*)" % o.replace('.', '\.') for o in app.config['CORS_ALLOW_ORIGINS']]
|
|
|
|
cors = CORS(connexion_app.app, origins=origins_re)
|
|
|
|
|
|
|
|
# Sentry error handling
|
2020-10-06 12:49:27 -04:00
|
|
|
if app.config['ENABLE_SENTRY']:
|
2020-09-10 11:28:58 -04:00
|
|
|
sentry_sdk.init(
|
2020-10-06 12:49:27 -04:00
|
|
|
dsn="https://048a9b3ac72f476a8c77b910ad4d7f84@o401361.ingest.sentry.io/5454621",
|
|
|
|
integrations=[FlaskIntegration()],
|
|
|
|
traces_sample_rate=1.0
|
2020-09-10 11:28:58 -04:00
|
|
|
)
|
2020-09-21 14:21:07 -04:00
|
|
|
|
2020-09-22 16:22:15 -04:00
|
|
|
### HTML Pages
|
|
|
|
BASE_HREF = app.config['APPLICATION_ROOT'].strip('/')
|
|
|
|
|
2020-10-02 15:16:28 -04:00
|
|
|
def superuser(f):
|
|
|
|
@wraps(f)
|
|
|
|
def decorated_function(*args, **kwargs):
|
|
|
|
from communicator.services.user_service import UserService
|
|
|
|
if not UserService().is_valid_user():
|
|
|
|
flash("You do not have permission to view that page", "warning")
|
2020-10-12 16:35:14 -04:00
|
|
|
logging.info("Permission Denied to user " + UserService().get_user_info())
|
2020-10-02 15:16:28 -04:00
|
|
|
abort(404)
|
|
|
|
return f(*args, **kwargs)
|
|
|
|
return decorated_function
|
|
|
|
|
2020-09-22 16:22:15 -04:00
|
|
|
|
2020-09-23 16:01:31 -04:00
|
|
|
@app.route('/', methods=['GET'])
|
2020-10-02 15:16:28 -04:00
|
|
|
@superuser
|
2020-09-22 16:22:15 -04:00
|
|
|
def index():
|
2020-09-23 12:43:58 -04:00
|
|
|
from communicator.models import Sample
|
|
|
|
from communicator.tables import SampleTable
|
2020-09-22 16:22:15 -04:00
|
|
|
# display results
|
2020-09-23 12:43:58 -04:00
|
|
|
page = request.args.get(get_page_parameter(), type=int, default=1)
|
|
|
|
samples = db.session.query(Sample).order_by(Sample.date.desc())
|
|
|
|
pagination = Pagination(page=page, total=samples.count(), search=False, record_name='samples')
|
|
|
|
|
|
|
|
table = SampleTable(samples.paginate(page,10,error_out=False).items)
|
2020-09-22 16:22:15 -04:00
|
|
|
return render_template(
|
|
|
|
'index.html',
|
2020-09-23 12:43:58 -04:00
|
|
|
table=table,
|
|
|
|
pagination=pagination,
|
2020-09-22 16:22:15 -04:00
|
|
|
base_href=BASE_HREF
|
|
|
|
)
|
|
|
|
|
|
|
|
@app.route('/invitation', methods=['GET', 'POST'])
|
2020-10-02 15:16:28 -04:00
|
|
|
@superuser
|
2020-09-22 16:22:15 -04:00
|
|
|
def send_invitation():
|
2020-09-23 17:00:51 -04:00
|
|
|
from communicator.models.invitation import Invitation
|
|
|
|
from communicator.tables import InvitationTable
|
|
|
|
|
2020-09-22 16:22:15 -04:00
|
|
|
form = forms.InvitationForm(request.form)
|
|
|
|
action = BASE_HREF + "/invitation"
|
|
|
|
title = "Send invitation to students"
|
2020-09-23 17:00:51 -04:00
|
|
|
if request.method == 'POST' and form.validate():
|
2020-09-22 16:22:15 -04:00
|
|
|
from communicator.services.notification_service import NotificationService
|
|
|
|
with NotificationService(app) as ns:
|
|
|
|
ns.send_invitations(form.date.data, form.location.data, form.emails.data)
|
2020-09-24 11:33:51 -04:00
|
|
|
return redirect(url_for('send_invitation'))
|
2020-09-23 17:00:51 -04:00
|
|
|
# display results
|
|
|
|
page = request.args.get(get_page_parameter(), type=int, default=1)
|
2020-09-24 11:33:51 -04:00
|
|
|
invites = db.session.query(Invitation).order_by(Invitation.date_sent.desc())
|
2020-09-23 17:00:51 -04:00
|
|
|
pagination = Pagination(page=page, total=invites.count(), search=False, record_name='samples')
|
|
|
|
|
|
|
|
table = InvitationTable(invites.paginate(page,10,error_out=False).items)
|
|
|
|
|
2020-09-22 16:22:15 -04:00
|
|
|
return render_template(
|
|
|
|
'form.html',
|
|
|
|
form=form,
|
2020-09-23 17:00:51 -04:00
|
|
|
table=table,
|
|
|
|
pagination=pagination,
|
2020-09-22 16:22:15 -04:00
|
|
|
action=action,
|
|
|
|
title=title,
|
|
|
|
description_map={},
|
|
|
|
base_href=BASE_HREF
|
2020-09-23 16:01:31 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
@app.route('/imported_files', methods=['GET'])
|
2020-10-02 15:16:28 -04:00
|
|
|
@superuser
|
2020-09-23 16:01:31 -04:00
|
|
|
def list_imported_files_from_ivy():
|
|
|
|
from communicator.models.ivy_file import IvyFile
|
|
|
|
from communicator.tables import IvyFileTable
|
|
|
|
|
|
|
|
# display results
|
|
|
|
page = request.args.get(get_page_parameter(), type=int, default=1)
|
|
|
|
files = db.session.query(IvyFile).order_by(IvyFile.date_added.desc())
|
|
|
|
pagination = Pagination(page=page, total=files.count(), search=False, record_name='samples')
|
|
|
|
|
|
|
|
table = IvyFileTable(files.paginate(page, 10, error_out=False).items)
|
|
|
|
return render_template(
|
|
|
|
'imported_files.html',
|
|
|
|
table=table,
|
|
|
|
pagination=pagination,
|
|
|
|
base_href=BASE_HREF
|
2020-09-22 16:22:15 -04:00
|
|
|
)
|
|
|
|
|
2020-09-23 14:43:24 -04:00
|
|
|
@app.route('/sso')
|
|
|
|
def sso():
|
2020-09-24 13:43:21 -04:00
|
|
|
from communicator.services.user_service import UserService
|
2020-09-24 13:36:46 -04:00
|
|
|
user = UserService().get_user_info()
|
2020-09-23 14:43:24 -04:00
|
|
|
response = ""
|
2020-09-24 13:36:46 -04:00
|
|
|
response += f"<h1>Current User: {user.display_name} ({user.uid})</h1>"
|
2020-09-23 14:43:24 -04:00
|
|
|
return response
|
2020-09-22 16:22:15 -04:00
|
|
|
|
2020-10-02 15:16:28 -04:00
|
|
|
@app.route('/debug-sentry')
|
|
|
|
def trigger_error():
|
|
|
|
division_by_zero = 1 / 0
|
|
|
|
|
2020-09-21 14:21:07 -04:00
|
|
|
# Access tokens
|
|
|
|
@app.cli.command()
|
|
|
|
def globus_token():
|
|
|
|
from communicator.services.ivy_service import IvyService
|
|
|
|
ivy_service = IvyService()
|
|
|
|
ivy_service.get_access_token()
|
|
|
|
|
2020-09-22 16:22:15 -04:00
|
|
|
|
2020-09-21 14:21:07 -04:00
|
|
|
@app.cli.command()
|
2020-10-01 11:25:12 -04:00
|
|
|
def count_files_in_ivy():
|
2020-09-21 14:21:07 -04:00
|
|
|
from communicator.services.ivy_service import IvyService
|
|
|
|
ivy_service = IvyService()
|
2020-10-01 11:25:12 -04:00
|
|
|
count = ivy_service.get_file_count_from_globus()
|
|
|
|
print(f"There are {count} files awaiting transfer")
|
2020-09-22 16:22:15 -04:00
|
|
|
|
2020-09-21 14:21:07 -04:00
|
|
|
@app.cli.command()
|
|
|
|
def transfer():
|
|
|
|
from communicator.services.ivy_service import IvyService
|
|
|
|
ivy_service = IvyService()
|
|
|
|
ivy_service.request_transfer()
|
|
|
|
|
2020-09-22 16:22:15 -04:00
|
|
|
|
2020-09-21 14:21:07 -04:00
|
|
|
@app.cli.command()
|
|
|
|
def delete():
|
|
|
|
from communicator.services.ivy_service import IvyService
|
|
|
|
ivy_service = IvyService()
|
|
|
|
ivy_service.delete_file()
|
2020-10-02 15:16:28 -04:00
|
|
|
|