-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Aurélien Bompard <[email protected]>
- Loading branch information
Showing
22 changed files
with
484 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# SPDX-FileCopyrightText: Contributors to the Fedora Project | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
from {{ cookiecutter.pkg_name }}.app import create_app | ||
|
||
|
||
application = create_app() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# SPDX-FileCopyrightText: Contributors to the Fedora Project | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
TESTING = True | ||
DEBUG = True | ||
WTF_CSRF_ENABLED = False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# SPDX-FileCopyrightText: Contributors to the Fedora Project | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
from flask import current_app | ||
from sqlalchemy_helpers.manager import DatabaseStatus | ||
|
||
from {{ cookiecutter.pkg_name }}.database import db | ||
|
||
|
||
def test_healthz_liveness(client): | ||
"""Test the /healthz/live check endpoint""" | ||
response = client.get("/healthz/live") | ||
assert response.status_code == 200 | ||
assert response.json == {"status": 200, "title": "OK"} | ||
|
||
|
||
def test_healthz_readiness_ok(client): | ||
"""Test the /healthz/ready check endpoint""" | ||
response = client.get("/healthz/ready") | ||
print(response.data) | ||
assert response.status_code == 200 | ||
assert response.json == {"status": 200, "title": "OK"} | ||
|
||
|
||
def test_healthz_readiness_unavailable(client, mocker, tmpdir): | ||
"""Test the /healthz/ready check endpoint when the DB is not ready""" | ||
db.manager.drop() | ||
mocker.patch.dict( | ||
current_app.config, {"SQLALCHEMY_DATABASE_URI": f"sqlite:///{tmpdir}/new.db"} | ||
) | ||
response = client.get("/healthz/ready") | ||
assert response.status_code == 503 | ||
assert response.json == {"status": 503, "title": "Can't connect to the database"} | ||
|
||
|
||
def test_healthz_readiness_needs_upgrade(client, mocker): | ||
"""Test the /healthz/ready check endpoint when the DB schema is old""" | ||
mocker.patch.object( | ||
db.manager, "get_status", return_value=DatabaseStatus.UPGRADE_AVAILABLE | ||
) | ||
response = client.get("/healthz/ready") | ||
assert response.status_code == 503 | ||
assert response.json == { | ||
"status": 503, | ||
"title": "The database schema needs to be updated", | ||
} | ||
|
||
|
||
def test_healthz_readiness_exception(client, mocker): | ||
"""Test the /healthz/ready check endpoint when the DB is wrong""" | ||
mocker.patch.dict( | ||
current_app.config, {"SQLALCHEMY_DATABASE_URI": "sqlite:////does/not/exist"} | ||
) | ||
response = client.get("/healthz/ready") | ||
assert response.status_code == 503 | ||
assert response.json["status"] == 503 | ||
assert response.json["title"].startswith( | ||
"Can't get the database status: (sqlite3.OperationalError) " | ||
"unable to open database file" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# SPDX-FileCopyrightText: Contributors to the Fedora Project | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
from bs4 import BeautifulSoup | ||
|
||
from {{ cookiecutter.pkg_name }}.database import db | ||
from {{ cookiecutter.pkg_name }}.models import User | ||
|
||
|
||
def test_root(client): | ||
"""Test the root page""" | ||
response = client.get("/") | ||
assert response.status_code == 200 | ||
page = BeautifulSoup(response.data, "html.parser") | ||
assert page.title | ||
assert page.title.string is not None | ||
assert "{{ cookiecutter.name }}" in page.title.string | ||
|
||
|
||
def test_profile(client): | ||
"""Test the profile page""" | ||
user = User(name="testuser", full_name="Test User", timezone="Europe/Paris") | ||
db.session.add(user) | ||
db.session.flush() | ||
response = client.get(f"/user/{user.id}") | ||
assert response.status_code == 200 | ||
page = BeautifulSoup(response.data, "html.parser") | ||
assert page.title | ||
assert page.title.string is not None | ||
assert "{{ cookiecutter.name }}" in page.title.string | ||
content = page.select_one("#profile") | ||
assert content is not None | ||
assert "Full Name: Test User" in list(content.stripped_strings) | ||
assert "Timezone: Europe/Paris" in list(content.stripped_strings) |
90 changes: 90 additions & 0 deletions
90
{{ cookiecutter.slug }}/{{ cookiecutter.pkg_name }}/app.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# SPDX-FileCopyrightText: Contributors to the Fedora Project | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
import os | ||
from logging.config import dictConfig | ||
|
||
import flask_talisman | ||
from flask import Flask | ||
from flask_healthz import healthz | ||
from flask_wtf.csrf import CSRFProtect | ||
from whitenoise import WhiteNoise | ||
|
||
{% if cookiecutter.with_i18n -%} | ||
from {{ cookiecutter.pkg_name }} import l10n | ||
{%- endif %} | ||
from {{ cookiecutter.pkg_name }}.database import db | ||
from {{ cookiecutter.pkg_name }}.utils import import_all | ||
from {{ cookiecutter.pkg_name }}.views import blueprint | ||
|
||
|
||
# Forms | ||
csrf = CSRFProtect() | ||
|
||
# Security headers | ||
talisman = flask_talisman.Talisman() | ||
|
||
|
||
def create_app(config=None): | ||
"""See https://flask.palletsprojects.com/en/1.1.x/patterns/appfactories/""" | ||
|
||
app = Flask(__name__) | ||
|
||
# Load default configuration | ||
app.config.from_object("{{ cookiecutter.pkg_name }}.defaults") | ||
|
||
# Load the optional configuration file | ||
if "FLASK_CONFIG" in os.environ: | ||
app.config.from_envvar("FLASK_CONFIG") | ||
|
||
# Load the config passed as argument | ||
app.config.update(config or {}) | ||
|
||
if app.config.get("TEMPLATES_AUTO_RELOAD"): | ||
app.jinja_env.auto_reload = True | ||
|
||
# Logging | ||
if app.config.get("LOGGING"): | ||
dictConfig(app.config["LOGGING"]) | ||
|
||
# Extensions | ||
{%- if cookiecutter.with_i18n %} | ||
l10n.babel.init_app(app, locale_selector=l10n.pick_locale, timezone_selector=l10n.get_timezone) | ||
app.before_request(l10n.store_locale) | ||
app.jinja_env.add_extension("jinja2.ext.i18n") | ||
{%- endif %} | ||
csrf.init_app(app) | ||
|
||
# Database | ||
db.init_app(app) | ||
|
||
# Security | ||
talisman.init_app( | ||
app, | ||
force_https=app.config.get("SESSION_COOKIE_SECURE", True), | ||
session_cookie_secure=app.config.get("SESSION_COOKIE_SECURE", True), | ||
frame_options=flask_talisman.DENY, | ||
referrer_policy="same-origin", | ||
content_security_policy={ | ||
"default-src": ["'self'", "apps.fedoraproject.org"], | ||
"script-src": [ | ||
# https://csp.withgoogle.com/docs/strict-csp.html#example | ||
"'strict-dynamic'", | ||
], | ||
# "img-src": ["'self'", "seccdn.libravatar.org"], | ||
}, | ||
content_security_policy_nonce_in=["script-src"], | ||
) | ||
|
||
# Register views | ||
import_all("{{ cookiecutter.pkg_name }}.views") | ||
app.register_blueprint(blueprint) | ||
app.register_blueprint(healthz, url_prefix="/healthz") | ||
|
||
# Static files | ||
app.wsgi_app = WhiteNoise( | ||
app.wsgi_app, root=f"{app.root_path}/static/", prefix="static/" | ||
) | ||
|
||
return app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
{{ cookiecutter.slug }}/{{ cookiecutter.pkg_name }}/defaults.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# SPDX-FileCopyrightText: Contributors to the Fedora Project | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
# This file contains the default configuration values | ||
|
||
TEMPLATES_AUTO_RELOAD = False | ||
SESSION_COOKIE_HTTPONLY = True | ||
SESSION_COOKIE_SECURE = True | ||
|
||
SQLALCHEMY_TRACK_MODIFICATIONS = False | ||
SQLALCHEMY_DATABASE_URI = "sqlite:///../{{ cookiecutter.slug }}.db" | ||
|
||
HEALTHZ = { | ||
"live": "{{ cookiecutter.pkg_name }}.utils.healthz.liveness", | ||
"ready": "{{ cookiecutter.pkg_name }}.utils.healthz.readiness", | ||
} |
Oops, something went wrong.