Skip to content

Commit 0936e0a

Browse files
committed
added app dir and populate_db.py
1 parent 06064a6 commit 0936e0a

File tree

332 files changed

+88053
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

332 files changed

+88053
-0
lines changed

app/__init__.py

+269
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
from celery.signals import after_task_publish
2+
import logging
3+
import os.path
4+
from envparse import env
5+
6+
import sys
7+
from flask import Flask, json, make_response
8+
from flask_celeryext import FlaskCeleryExt
9+
from app.settings import get_settings, get_setts
10+
from flask_migrate import Migrate, MigrateCommand
11+
from flask_script import Manager
12+
from flask_login import current_user
13+
from flask_jwt_extended import JWTManager
14+
from flask_limiter import Limiter
15+
from datetime import timedelta
16+
from flask_cors import CORS
17+
from flask_rest_jsonapi.errors import jsonapi_errors
18+
from flask_rest_jsonapi.exceptions import JsonApiException
19+
from healthcheck import HealthCheck
20+
from apscheduler.schedulers.background import BackgroundScheduler
21+
from elasticsearch_dsl.connections import connections
22+
from pytz import utc
23+
24+
import sqlalchemy as sa
25+
26+
import stripe
27+
from app.settings import get_settings
28+
from app.models import db
29+
from app.api.helpers.jwt import jwt_user_loader
30+
from app.api.helpers.cache import cache
31+
from werkzeug.middleware.profiler import ProfilerMiddleware
32+
from app.views import BlueprintsManager
33+
from app.api.helpers.auth import AuthManager, is_token_blacklisted
34+
from app.api.helpers.scheduled_jobs import send_after_event_mail, send_event_fee_notification, \
35+
send_event_fee_notification_followup, change_session_state_on_event_completion, \
36+
expire_pending_tickets, send_monthly_event_invoice, event_invoices_mark_due
37+
from app.models.event import Event
38+
from app.models.role_invite import RoleInvite
39+
from app.views.healthcheck import health_check_celery, health_check_db, health_check_migrations, check_migrations
40+
from app.views.elastic_search import client
41+
from app.views.elastic_cron_helpers import sync_events_elasticsearch, cron_rebuild_events_elasticsearch
42+
from app.views.redis_store import redis_store
43+
from app.views.celery_ import celery
44+
from app.templates.flask_ext.jinja.filters import init_filters
45+
import sentry_sdk
46+
from sentry_sdk.integrations.flask import FlaskIntegration
47+
48+
49+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
50+
51+
static_dir = os.path.dirname(os.path.dirname(__file__)) + "/static"
52+
template_dir = os.path.dirname(__file__) + "/templates"
53+
app = Flask(__name__, static_folder=static_dir, template_folder=template_dir)
54+
limiter = Limiter(app)
55+
env.read_envfile()
56+
57+
58+
class ReverseProxied(object):
59+
"""
60+
ReverseProxied flask wsgi app wrapper from http://stackoverflow.com/a/37842465/1562480 by aldel
61+
"""
62+
63+
def __init__(self, app):
64+
self.app = app
65+
66+
def __call__(self, environ, start_response):
67+
scheme = environ.get('HTTP_X_FORWARDED_PROTO')
68+
if scheme:
69+
environ['wsgi.url_scheme'] = scheme
70+
if os.getenv('FORCE_SSL', 'no') == 'yes':
71+
environ['wsgi.url_scheme'] = 'https'
72+
return self.app(environ, start_response)
73+
74+
75+
app.wsgi_app = ReverseProxied(app.wsgi_app)
76+
77+
app_created = False
78+
79+
80+
def create_app():
81+
global app_created
82+
if not app_created:
83+
BlueprintsManager.register(app)
84+
Migrate(app, db)
85+
86+
app.config.from_object(env('APP_CONFIG', default='config.ProductionConfig'))
87+
db.init_app(app)
88+
_manager = Manager(app)
89+
_manager.add_command('db', MigrateCommand)
90+
91+
if app.config['CACHING']:
92+
cache.init_app(app, config={'CACHE_TYPE': 'simple'})
93+
else:
94+
cache.init_app(app, config={'CACHE_TYPE': 'null'})
95+
96+
stripe.api_key = 'SomeStripeKey'
97+
app.secret_key = 'super secret key'
98+
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
99+
app.config['FILE_SYSTEM_STORAGE_FILE_VIEW'] = 'static'
100+
101+
app.logger.addHandler(logging.StreamHandler(sys.stdout))
102+
app.logger.setLevel(logging.ERROR)
103+
104+
# set up jwt
105+
app.config['JWT_HEADER_TYPE'] = 'JWT'
106+
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(days=1)
107+
app.config['JWT_REFRESH_TOKEN_EXPIRES'] = timedelta(days=365)
108+
app.config['JWT_ERROR_MESSAGE_KEY'] = 'error'
109+
app.config['JWT_TOKEN_LOCATION'] = ['cookies', 'headers']
110+
app.config['JWT_REFRESH_COOKIE_PATH'] = '/v1/auth/token/refresh'
111+
app.config['JWT_SESSION_COOKIE'] = False
112+
app.config['JWT_BLACKLIST_ENABLED'] = True
113+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['refresh']
114+
_jwt = JWTManager(app)
115+
_jwt.user_loader_callback_loader(jwt_user_loader)
116+
_jwt.token_in_blacklist_loader(is_token_blacklisted)
117+
118+
# setup celery
119+
app.config['CELERY_BROKER_URL'] = app.config['REDIS_URL']
120+
app.config['CELERY_RESULT_BACKEND'] = app.config['CELERY_BROKER_URL']
121+
app.config['CELERY_ACCEPT_CONTENT'] = ['json', 'application/text']
122+
123+
CORS(app, resources={r"/*": {"origins": "*"}})
124+
AuthManager.init_login(app)
125+
126+
if app.config['TESTING'] and app.config['PROFILE']:
127+
# Profiling
128+
app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[30])
129+
130+
# development api
131+
with app.app_context():
132+
from app.api.admin_statistics_api.events import event_statistics
133+
from app.api.auth import auth_routes
134+
from app.api.attendees import attendee_misc_routes
135+
from app.api.bootstrap import api_v1
136+
from app.api.celery_tasks import celery_routes
137+
from app.api.event_copy import event_copy
138+
from app.api.exports import export_routes
139+
from app.api.imports import import_routes
140+
from app.api.uploads import upload_routes
141+
from app.api.users import user_misc_routes
142+
from app.api.orders import order_misc_routes
143+
from app.api.role_invites import role_invites_misc_routes
144+
from app.api.auth import ticket_blueprint, authorised_blueprint
145+
from app.api.admin_translations import admin_blueprint
146+
from app.api.orders import alipay_blueprint
147+
from app.api.settings import admin_misc_routes
148+
149+
app.register_blueprint(api_v1)
150+
app.register_blueprint(event_copy)
151+
app.register_blueprint(upload_routes)
152+
app.register_blueprint(export_routes)
153+
app.register_blueprint(import_routes)
154+
app.register_blueprint(celery_routes)
155+
app.register_blueprint(auth_routes)
156+
app.register_blueprint(event_statistics)
157+
app.register_blueprint(user_misc_routes)
158+
app.register_blueprint(attendee_misc_routes)
159+
app.register_blueprint(order_misc_routes)
160+
app.register_blueprint(role_invites_misc_routes)
161+
app.register_blueprint(ticket_blueprint)
162+
app.register_blueprint(authorised_blueprint)
163+
app.register_blueprint(admin_blueprint)
164+
app.register_blueprint(alipay_blueprint)
165+
app.register_blueprint(admin_misc_routes)
166+
167+
sa.orm.configure_mappers()
168+
169+
if app.config['SERVE_STATIC']:
170+
app.add_url_rule('/static/<path:filename>',
171+
endpoint='static',
172+
view_func=app.send_static_file)
173+
174+
# sentry
175+
if not app_created and 'SENTRY_DSN' in app.config:
176+
sentry_sdk.init(app.config['SENTRY_DSN'], integrations=[FlaskIntegration()])
177+
178+
# redis
179+
redis_store.init_app(app)
180+
181+
# elasticsearch
182+
if app.config['ENABLE_ELASTICSEARCH']:
183+
client.init_app(app)
184+
connections.add_connection('default', client.elasticsearch)
185+
with app.app_context():
186+
try:
187+
cron_rebuild_events_elasticsearch.delay()
188+
except Exception:
189+
pass
190+
191+
app_created = True
192+
return app, _manager, db, _jwt
193+
194+
195+
current_app, manager, database, jwt = create_app()
196+
init_filters(app)
197+
198+
199+
# http://stackoverflow.com/questions/26724623/
200+
@app.before_request
201+
def track_user():
202+
if current_user.is_authenticated:
203+
current_user.update_lat()
204+
205+
206+
def make_celery(app=None):
207+
app = app or create_app()[0]
208+
celery.conf.update(app.config)
209+
ext = FlaskCeleryExt(app)
210+
return ext.celery
211+
212+
213+
# Health-check
214+
health = HealthCheck(current_app, "/health-check")
215+
health.add_check(health_check_celery)
216+
health.add_check(health_check_db)
217+
with current_app.app_context():
218+
current_app.config['MIGRATION_STATUS'] = check_migrations()
219+
health.add_check(health_check_migrations)
220+
221+
222+
# http://stackoverflow.com/questions/9824172/find-out-whether-celery-task-exists
223+
@after_task_publish.connect
224+
def update_sent_state(sender=None, headers=None, **kwargs):
225+
# the task may not exist if sent using `send_task` which
226+
# sends tasks by name, so fall back to the default result backend
227+
# if that is the case.
228+
task = celery.tasks.get(sender)
229+
backend = task.backend if task else celery.backend
230+
backend.store_result(headers['id'], None, 'WAITING')
231+
232+
233+
# register celery tasks. removing them will cause the tasks to not function. so don't remove them
234+
# it is important to register them after celery is defined to resolve circular imports
235+
236+
from .api.helpers import tasks
237+
238+
# import helpers.tasks
239+
240+
241+
scheduler = BackgroundScheduler(timezone=utc)
242+
# scheduler.add_job(send_mail_to_expired_orders, 'interval', hours=5)
243+
# scheduler.add_job(empty_trash, 'cron', hour=5, minute=30)
244+
if app.config['ENABLE_ELASTICSEARCH']:
245+
scheduler.add_job(sync_events_elasticsearch, 'interval', minutes=60)
246+
scheduler.add_job(cron_rebuild_events_elasticsearch, 'cron', day=7)
247+
248+
scheduler.add_job(send_after_event_mail, 'cron', hour=5, minute=30)
249+
scheduler.add_job(send_event_fee_notification, 'cron', day=1)
250+
scheduler.add_job(send_event_fee_notification_followup, 'cron', day=1, month='1-12')
251+
scheduler.add_job(change_session_state_on_event_completion, 'cron', hour=5, minute=30)
252+
scheduler.add_job(expire_pending_tickets, 'cron', minute=45)
253+
scheduler.add_job(send_monthly_event_invoice, 'cron', day=1, month='1-12')
254+
scheduler.add_job(event_invoices_mark_due, 'cron', hour=5)
255+
scheduler.start()
256+
257+
258+
@app.errorhandler(500)
259+
def internal_server_error(error):
260+
if current_app.config['PROPOGATE_ERROR'] is True:
261+
exc = JsonApiException({'pointer': ''}, str(error))
262+
else:
263+
exc = JsonApiException({'pointer': ''}, 'Unknown error')
264+
return make_response(json.dumps(jsonapi_errors([exc.to_dict()])), exc.status,
265+
{'Content-Type': 'application/vnd.api+json'})
266+
267+
268+
if __name__ == '__main__':
269+
current_app.run()

0 commit comments

Comments
 (0)