~homeworkprod/byceps

ref: 35b259078a130b07669525ee1effd0a05d45564b byceps/byceps/application.py -rw-r--r-- 7.1 KiB
35b25907 — Jochen Kupperschmidt Qualify access to static URL prefix constants via module 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
"""
byceps.application
~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2019 Jochen Kupperschmidt
:License: Modified BSD, see LICENSE for details.
"""

from pathlib import Path

from flask import Flask, redirect
import jinja2

from .blueprints.snippet.init import add_routes_for_snippets
from . import config, config_defaults
from .database import db
from . import email
from .redis import redis
from .util.framework.blueprint import register_blueprint
from .util.l10n import set_locale
from .util import templatefilters


def create_app(config_filename):
    """Create the actual Flask application."""
    app = Flask(__name__)

    app.config.from_object(config_defaults)
    app.config.from_pyfile(str(config_filename))

    # Throw an exception when an undefined name is referenced in a template.
    app.jinja_env.undefined = jinja2.StrictUndefined

    # Set the locale.
    set_locale(app.config['LOCALE'])  # Fail if not configured.

    # Initialize database.
    db.init_app(app)

    # Initialize Redis connection.
    redis.init_app(app)

    email.init_app(app)

    config.init_app(app)

    _register_blueprints(app)

    templatefilters.register(app)

    _add_static_file_url_rules(app)

    return app


def _register_blueprints(app):
    """Register blueprints depending on the configuration."""
    for name, url_prefix in _get_blueprints(app):
        register_blueprint(app, name, url_prefix)


def _get_blueprints(app):
    """Yield blueprints to register on the application."""
    yield from [
        ('authentication',          '/authentication'               ),
        ('authorization',           None                            ),
        ('core',                    '/core'                         ),
        ('healthcheck',             '/health'                       ),
        ('shop.orders.email',       None                            ),
        ('user',                    '/users'                        ),
        ('user_avatar',             '/users'                        ),
    ]

    current_mode = config.get_site_mode(app)
    if current_mode.is_public():
        yield from [
            ('attendance',              '/attendance'               ),
            ('board',                   '/board'                    ),
            ('news',                    '/news'                     ),
            ('newsletter',              '/newsletter'               ),
            ('orga_team',               '/orgas'                    ),
            ('party',                   None                        ),
            ('seating',                 '/seating'                  ),
            ('shop.orders',             '/shop/orders'              ),
            ('shop_order',              '/shop'                     ),
            ('snippet',                 '/snippets'                 ),
            ('terms',                   '/terms'                    ),
            ('ticketing',               '/tickets'                  ),
            ('tourney.avatar',          '/tourney/avatars'          ),
            ('tourney.match',           '/tourney/matches'          ),
            ('user_badge',              '/user_badges'              ),
            ('user_group',              '/user_groups'              ),
            ('user_message',            '/user_messages'            ),
        ]
    elif current_mode.is_admin():
        yield from [
            ('admin_dashboard',         '/admin/dashboard'          ),
            ('authorization_admin',     '/admin/authorization'      ),
            ('board_admin',             '/admin/board'              ),
            ('brand_admin',             '/admin/brands'             ),
            ('core_admin',              '/admin/core'               ),
            ('news_admin',              '/admin/news'               ),
            ('newsletter_admin',        '/admin/newsletter'         ),
            ('orga_admin',              '/admin/orgas'              ),
            ('orga_presence',           '/admin/presence'           ),
            ('orga_team_admin',         '/admin/orga_teams'         ),
            ('party_admin',             '/admin/parties'            ),
            ('seating_admin',           '/admin/seating'            ),
            ('shop.admin',              None                        ),
            ('shop.article_admin',      '/admin/shop/articles'      ),
            ('shop.order_admin',        '/admin/shop/orders'        ),
            ('shop.shipping_admin',     '/admin/shop/shipping'      ),
            ('shop.shop_admin',         '/admin/shop/shop'          ),
            ('site_admin',              '/admin/sites'              ),
            ('snippet_admin',           '/admin/snippets'           ),
            ('terms_admin',             '/admin/terms'              ),
            ('ticketing_admin',         '/admin/ticketing'          ),
            ('ticketing.checkin',       '/admin/ticketing/checkin'  ),
            ('tourney.admin',           '/admin/tourney'            ),
            ('user_admin',              '/admin/users'              ),
            ('user_badge_admin',        '/admin/user_badges'        ),
        ]

    if app.config['METRICS_ENABLED']:
        yield from [
            ('metrics',                 '/metrics'                  ),
        ]

    if app.debug:
        yield from [
            ('style_guide',             '/style_guide'              ),
        ]


def _add_static_file_url_rules(app):
    """Add URL rules to for static files."""
    for rule_prefix, endpoint in [
        (config.STATIC_URL_PREFIX_GLOBAL, 'global_file'),
        (config.STATIC_URL_PREFIX_BRAND, 'brand_file'),
        (config.STATIC_URL_PREFIX_PARTY, 'party_file'),
        (config.STATIC_URL_PREFIX_SITE, 'site_file'),
    ]:
        rule = rule_prefix + '/<path:filename>'
        app.add_url_rule(rule,
                         endpoint=endpoint,
                         methods=['GET'],
                         build_only=True)


def init_app(app):
    """Initialize the application after is has been created."""
    with app.app_context():
        _set_url_root_path(app)

        site_mode = config.get_site_mode()
        if site_mode.is_public():
            party_id = config.get_current_party_id()

            # Mount snippets.
            add_routes_for_snippets(party_id)

            # Incorporate template overrides for the configured site ID.
            site_id = config.get_current_site_id()
            app.template_folder = str(Path('..') / 'sites' / site_id / 'template_overrides')
        elif site_mode.is_admin() and app.config['RQ_DASHBOARD_ENABLED']:
            import rq_dashboard
            app.register_blueprint(rq_dashboard.blueprint,
                                   url_prefix='/admin/rq')


def _set_url_root_path(app):
    """Set an optional URL path to redirect to from the root URL path (`/`).

    Important: Don't specify the target with a leading slash unless you
    really mean the root of the host.
    """
    target_url = app.config['ROOT_REDIRECT_TARGET']
    if target_url is None:
        return

    status_code = app.config['ROOT_REDIRECT_STATUS_CODE']

    def _redirect():
        return redirect(target_url, status_code)

    app.add_url_rule('/', endpoint='root', view_func=_redirect)