Skip to content

Commit

Permalink
Large restructure
Browse files Browse the repository at this point in the history
  • Loading branch information
danielecook committed May 6, 2020
1 parent d68ab21 commit 26eb9c6
Show file tree
Hide file tree
Showing 42 changed files with 560 additions and 570 deletions.
4 changes: 2 additions & 2 deletions .envrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export FLASK_APP=base/application.py
export FLASK_APP=main:app
export GAE_VERSION=development-`cat .travis.yml | grep 'VERSION_NUM=' | cut -f 2 -d '='`
export GOOGLE_APPLICATION_CREDENTIALS=env_config/client-secret.json
export PYTHONPATH=$(pwd)
Expand All @@ -10,4 +10,4 @@ export OAUTHLIB_RELAX_TOKEN_SCOPE=1
export OAUTHLIB_INSECURE_TRANSPORT=1

export PORT=8080 # For use with docker testing.
gcloud config configurations activate cendr
gcloud config configurations activate cendr
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[submodule "cendr-api-docs"]
path = cendr-api-docs
url = http://www.github.com/andersenlab/cendr-api-docs
244 changes: 122 additions & 122 deletions base/application.py
Original file line number Diff line number Diff line change
@@ -1,147 +1,147 @@
import os
import json
import yaml
import requests
from os.path import basename
from flask import Flask, render_template, jsonify
from flask_debugtoolbar import DebugToolbarExtension
from flask_caching import Cache
from flask_sqlalchemy import SQLAlchemy
from base.utils.data_utils import json_encoder
from base.config import config
from flask import Flask, render_template
from base.utils.text_utils import render_markdown
from base.constants import CENDR_VERSION, APP_CONFIG
from flaskext.markdown import Markdown
from werkzeug.middleware.proxy_fix import ProxyFix
from flaskext.markdown import Markdown

# Create
app = Flask(__name__,
static_url_path='/static')

app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)

# Add markdown
Markdown(app)

# Configuration - First load non-sensitive configuration info
app.config['json_encoder'] = json_encoder

# Load Credentials
# (BASE_VARS are the same regardless of whether we are debugging or in production)
BASE_VARS = yaml.load(open("env_config/base.yaml").read())
APP_CONFIG_VARS = yaml.load(open(f"env_config/{APP_CONFIG}.yaml").read())

app.config.update(BASE_VARS)
app.config.update(APP_CONFIG_VARS)

# Setup cache
cache = Cache(app, config={'CACHE_TYPE': 'base.utils.cache.datastore_cache'})

# Database
db_2 = SQLAlchemy(app)

# Set the json_encoder
app.json_encoder = json_encoder


def autoconvert(s):
for fn in (int, float):
try:
return fn(s)
except ValueError:
pass
return s


if os.getenv('HOME') == "/root":
"""
Running on server
"""
app.debug = False
from flask_sslify import SSLify
# Ignore leading slash of urls; skips must use start of path
sslify = SSLify(app)
elif app.config['DEBUG']:
app.debug = True
app.config['SECRET_KEY'] = "test"
toolbar = DebugToolbarExtension(app)


def gs_static(url, prefix='static'):
return f"https://storage.googleapis.com/elegansvariation.org/{prefix}/{url}"

from logzero import logger
from base.utils.data_utils import json_encoder

# Template filters
from base.utils.template_filters import *
from base.manage import init_db

# About Pages
# --------- #
# Routing #
# --------- #
from base.views.about import about_bp
app.register_blueprint(about_bp, url_prefix='/about')

# Strain Pages
from base.views.primary import primary_bp
from base.views.strains import strain_bp
app.register_blueprint(strain_bp, url_prefix='/strain')

# Order Pages
from base.views.order import order_bp
app.register_blueprint(order_bp, url_prefix='/order')

# Data Pages
from base.views.data import data_bp
app.register_blueprint(data_bp, url_prefix='/data')

# Mapping Pages -
from base.views.mapping import mapping_bp
app.register_blueprint(mapping_bp, url_prefix='')

# Gene Pages
from base.views.gene import gene_bp
app.register_blueprint(gene_bp, url_prefix='/gene')
from base.views.user import user_bp
from base.views.tools import tools_bp

# Main Pages - Homepage, Outreach, Contact
from base.views.primary import primary_bp
app.register_blueprint(primary_bp, url_prefix='')
# API
from base.views.api.api_strain import api_strain_bp
from base.views.api.api_gene import api_gene_bp
from base.views.api.api_variant import api_variant_bp

# User Pages
from base.views.user import user_bp
app.register_blueprint(user_bp, url_prefix='/user')
# Auth
from base.auth import (auth_bp,
google_bp,
github_bp)

# Tool Pages
from base.views.tools import tools_bp
app.register_blueprint(tools_bp, url_prefix='/tools')
# ---- End Routing ---- #

# Authentication
from base.auth import google_bp, github_bp #, dropbox_bp
app.register_blueprint(google_bp, url_prefix='/login')
app.register_blueprint(github_bp, url_prefix='/login')
# Extensions
from base.extensions import (markdown,
cache,
debug_toolbar,
sslify,
sqlalchemy)

# Template filters
from base.filters import (comma, format_release_filter)


def create_app(config=config):
"""Returns an initialized Flask application."""
app = Flask(__name__,
static_url_path='/static')

# Fix wsgi proxy
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
app.config.update(config)

register_commands(app)
register_blueprints(app)
register_template_filters(app)
register_extensions(app)
register_errorhandlers(app)
configure_jinja(app)

if os.getenv('HOME') == "/root":
# Running on server
app.debug = False
# Ignore leading slash of urls; skips must use start of path
sslify.init_app(app)
elif app.config['DEBUG']:
app.debug = True
app.config['SECRET_KEY'] = "test"
debug_toolbar(app)

return app


def register_commands(app):
"""Register custom commands for the Flask CLI."""
for command in [init_db]:
app.cli.command()(command)


def register_template_filters(app):
for t_filter in [comma, format_release_filter]:
app.template_filter()(t_filter)


def register_extensions(app):
markdown(app)
cache.init_app(app, config={'CACHE_TYPE': 'base.utils.cache.datastore_cache'})
sqlalchemy(app)


def register_blueprints(app):
"""Register blueprints with the Flask application."""
app.register_blueprint(primary_bp, url_prefix='')
app.register_blueprint(about_bp, url_prefix='/about')
app.register_blueprint(strain_bp, url_prefix='/strain')
app.register_blueprint(order_bp, url_prefix='/order')
app.register_blueprint(data_bp, url_prefix='/data')
app.register_blueprint(mapping_bp, url_prefix='')
app.register_blueprint(gene_bp, url_prefix='/gene')
app.register_blueprint(user_bp, url_prefix='/user')
app.register_blueprint(tools_bp, url_prefix='/tools')

# API
app.register_blueprint(api_strain_bp, url_prefix='/api')
app.register_blueprint(api_gene_bp, url_prefix='/api')
app.register_blueprint(api_variant_bp, url_prefix='/api')

# Auth
app.register_blueprint(auth_bp, url_prefix='')
app.register_blueprint(google_bp, url_prefix='/login')
app.register_blueprint(github_bp, url_prefix='/login')


# Inject globals
@app.context_processor
def inject():
"""
Used to inject variables that
need to be accessed globally
"""
return dict(version=CENDR_VERSION,
json=json,
list=list,
str=str,
int=int,
len=len,
gs_static=gs_static,
basename=basename,
render_markdown=render_markdown)
def gs_static(url, prefix='static'):
return f"https://storage.googleapis.com/elegansvariation.org/{prefix}/{url}"


@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html', page_title="Not found"), 404
def configure_jinja(app):
# Injects "contexts" into templates
@app.context_processor
def inject():
return dict(json=json,
list=list,
str=str,
int=int,
len=len,
gs_static=gs_static,
basename=basename,
render_markdown=render_markdown)


@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html', page_title="Not found"), 500
def register_errorhandlers(app):

def render_error(e):
return render_template("errors/%s.html" % e.code), e.code

from base.views.api import *
from base.manage import (init_db)
for e in [
requests.codes.INTERNAL_SERVER_ERROR,
requests.codes.NOT_FOUND,
requests.codes.UNAUTHORIZED
]:
app.errorhandler(e)(render_error)
17 changes: 10 additions & 7 deletions base/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
request,
flash,
Markup)
from base.application import app
from functools import wraps
from base.models2 import user_m
from base.models import user_ds
from base.utils.data_utils import unique_id
from slugify import slugify
from logzero import logger
Expand All @@ -20,14 +19,18 @@
from flask_dance.contrib.github import make_github_blueprint, github
from flask_dance.consumer import oauth_authorized

from flask import Blueprint
auth_bp = Blueprint('auth',
__name__,
template_folder='')

google_bp = make_google_blueprint(scope=["https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email"],
offline=True)
github_bp = make_github_blueprint(scope="user:email")
# dropbox_bp = make_dropbox_blueprint()


@app.route("/login/select", methods=['GET'])
@auth_bp.route("/login/select", methods=['GET'])
def choose_login(error=None):
# Relax scope for Google
if not session.get("login_referrer", "").endswith("/login/select"):
Expand All @@ -54,11 +57,11 @@ def authorized(blueprint, token):
user_info['github']['email'] = user_email
else:
flash("Error logging in!")
return redirect(url_for("choose_login"))
return redirect(url_for("auth.choose_login"))

# Create or get existing user.
logger.info(user_email)
user = user_m(user_email)
user = user_ds(user_email)
logger.debug(user)
logger.debug(user._exists)
if not user._exists:
Expand All @@ -84,11 +87,11 @@ def func(*args, **kwargs):
if not session.get('user'):
with app.app_context():
session['redirect_url'] = request.url
return redirect(url_for('choose_login'))
return redirect(url_for('auth.choose_login'))
return f(*args, **kwargs)
return func

@app.route('/logout')
@auth_bp.route('/logout')
def logout():
"""
Logs the user out.
Expand Down
52 changes: 52 additions & 0 deletions base/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Application Configuration
import os
import yaml
from base.utils.data_utils import json_encoder

# CeNDR Version
APP_CONFIG, CENDR_VERSION = os.environ['GAE_VERSION'].split("-", 1)
if APP_CONFIG not in ['development', 'master']:
APP_CONFIG = 'development'
CENDR_VERSION = CENDR_VERSION.replace("-", '.')

# BUILDS AND RELEASES
# (RELEASE, ANNOTATION_GENOME)
RELEASES = [("20180527", "WS263"),
("20170531", "WS258"),
("20160408", "WS245")]

# The most recent release
DATASET_RELEASE, WORMBASE_VERSION = RELEASES[0]

# SQLITE DATABASE
SQLITE_PATH = f"base/cendr.{WORMBASE_VERSION}.db"


def load_yaml(path):
return yaml.load(open(path), Loader=yaml.SafeLoader)


# CONFIG
def get_config(APP_CONFIG):
"""Load all configuration information including
constants defined above.
(BASE_VARS are the same regardless of whether we are debugging or in production)
"""
config = dict()
BASE_VARS = load_yaml("env_config/base.yaml")
APP_CONFIG_VARS = load_yaml(f"env_config/{APP_CONFIG}.yaml")
config.update(BASE_VARS)
config.update(APP_CONFIG_VARS)
# Configuration - First load non-sensitive configuration info
config['json_encoder'] = json_encoder
config.update({"CENDR_VERSION": CENDR_VERSION,
"APP_CONFIG": APP_CONFIG,
"DATASET_RELEASE": DATASET_RELEASE,
"WORMBASE_VERSION": WORMBASE_VERSION,
"RELEASES": RELEASES})
return config


# Generate the configuration
config = get_config(APP_CONFIG)
Loading

0 comments on commit 26eb9c6

Please sign in to comment.