Introduce flask_arrest, fix dotenv loading (Apache), and new template macro "nl.jinja2"

This commit is contained in:
Yusur 2023-12-12 10:10:20 +01:00
parent 910e01b691
commit acf918f656
10 changed files with 80 additions and 118 deletions

4
.gitignore vendored
View file

@ -7,8 +7,8 @@ site-*.conf
run_8180.py run_8180.py
.env .env
alembic.ini alembic.ini
venv/ venv
venv-*/ venv-*
.venv .venv
env env

View file

@ -20,7 +20,7 @@ suitable as a community or team knowledge base.
## Requirements ## Requirements
+ **Python** 3.6+. + **Python** 3.6+.
+ **Flask** web framework (and Flask-Login / Flask-WTF extensions). + **Flask** web framework (and Flask-Login / Flask-WTF / Flask-Arrest extensions).
+ **Peewee** ORM. + **Peewee** ORM.
+ **Markdown** for page rendering. + **Markdown** for page rendering.
+ **Python-I18n**. + **Python-I18n**.

22
app.py
View file

@ -17,6 +17,7 @@ from flask import (
render_template, send_from_directory) render_template, send_from_directory)
from flask_login import LoginManager, login_user, logout_user, current_user, login_required from flask_login import LoginManager, login_user, logout_user, current_user, login_required
from flask_wtf import CSRFProtect from flask_wtf import CSRFProtect
#from flask_arrest import RestBlueprint, serialize_response
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.routing import BaseConverter from werkzeug.routing import BaseConverter
from peewee import * from peewee import *
@ -46,9 +47,9 @@ PING_RE = r'(?<!\w)@(' + USERNAME_RE + r')'
#### GENERAL CONFIG #### #### GENERAL CONFIG ####
dotenv.load_dotenv() dotenv.load_dotenv(os.path.join(APP_BASE_DIR, '.env'))
CONFIG_FILE = os.getenv('SALVI_CONF', APP_BASE_DIR + '/site.conf') CONFIG_FILE = os.getenv('SALVI_CONF', os.path.join(APP_BASE_DIR, 'site.conf'))
# security check: one may specify only configuration files INSIDE # security check: one may specify only configuration files INSIDE
# the code directory. # the code directory.
@ -96,7 +97,6 @@ def render_paginated_template(template_name, query_name, **kwargs):
template_name, template_name,
page_n = page, page_n = page,
total_count = query.count(), total_count = query.count(),
min=min,
**kwargs **kwargs
) )
@ -143,12 +143,6 @@ class BaseModel(Model):
class Meta: class Meta:
database = database database = database
# Used for PagePolicy
def _passphrase_hash(pp):
pp_bin = pp.encode('utf-8')
h = str(len(pp_bin)) + ':' + hashlib.sha256(pp_bin).hexdigest()
return h
class User(BaseModel): class User(BaseModel):
username = CharField(32, unique=True) username = CharField(32, unique=True)
email = CharField(256, null=True) email = CharField(256, null=True)
@ -325,6 +319,12 @@ class Page(BaseModel):
pass pass
return ", ".join(kw) return ", ".join(kw)
#def ldjson(self):
# return {
# "@context": "https://www.w3.org/ns/activitystreams",
#
# }
class PageText(BaseModel): class PageText(BaseModel):
content = BlobField() content = BlobField()
@ -657,13 +657,13 @@ def _before_request():
@app.context_processor @app.context_processor
def _inject_variables(): def _inject_variables():
return { return {
'T': partial(get_string, _get_lang()), 'T': partial(get_string, _get_lang()),
'app_name': os.getenv("APP_NAME") or _getconf('site', 'title'), 'app_name': os.getenv("APP_NAME") or _getconf('site', 'title'),
'strong': lambda x:Markup('<strong>{0}</strong>').format(x), 'strong': lambda x:Markup('<strong>{0}</strong>').format(x),
'app_version': __version__, 'app_version': __version__,
'material_icons_url': _getconf('site', 'material_icons_url') 'material_icons_url': _getconf('site', 'material_icons_url'),
'min': min
} }
@login_manager.user_loader @login_manager.user_loader

View file

@ -4,3 +4,5 @@ markdown
flask-login flask-login
flask-wtf flask-wtf
python-i18n python-i18n
flask-arrest
python-dotenv

View file

@ -13,8 +13,11 @@
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
{% endif %} {% endif %}
{% block json_info %}{% endblock %} {% block json_info %}{% endblock %}
{% block ldjson %}{% endblock %}
</head> </head>
<body {% if request.cookies.get('dark') == '1' %}class="dark"{% endif %}> <body {% if request.cookies.get('dark') == '1' -%}
class="dark"
{%- endif %}>
<div id="__top"></div> <div id="__top"></div>
<header class="header"> <header class="header">
<span class="header-app-name"><a href="/">{{ app_name }}</a></span> <span class="header-app-name"><a href="/">{{ app_name }}</a></span>

View file

@ -15,33 +15,9 @@
<h2>{{ T('latest-notes') }}</h2> <h2>{{ T('latest-notes') }}</h2>
<br style="clear:both"> <br style="clear:both">
<ul class="nl-list">
{% for n in new_notes %} {% from "macros/nl.jinja2" import nl_list with context %}
<li> {{ nl_list(new_notes) }}
<a href="{{ n.get_url() }}" class="nl-title">{{ n.title }}</a>
<p class="nl-desc">{{ n.short_desc() }}</p>
{% if n.tags %}
<p class="nl-tags">
<span class="material-icons">tag</span>
{{ T('tags') }}:
{% for tag in n.tags %}
{% set tn = tag.name %}
<a href="/tags/{{ tn }}/" class="nl-tag">#{{ tn }}</a>
{% endfor %}
</p>
{% endif %}
{% if n.calendar %}
<p class="nl-calendar">
<span class="material-icons">calendar_today</span>
<a href="/calendar/{{ n.calendar.year }}/{{ n.calendar.month }}">
<time datetime="{{ n.calendar.isoformat() }}">{{ n.calendar.strftime('%B %-d, %Y') }}</time>
</a>
</p>
{% endif %}
</li>
{% endfor %}
<li class="nl-next"><a href="/p/most_recent/">{{ T('show-all') }}</a></li>
</ul>
</article> </article>

View file

@ -4,39 +4,7 @@
<article> <article>
<h1 id="firstHeading">Notes by date</h1> <h1 id="firstHeading">Notes by date</h1>
<p class="nl-pagination">Showing results <strong>{{ page_n * 20 - 19 }}</strong> to <strong>{{ min(page_n * 20, total_count) }}</strong> of <strong>{{ total_count }}</strong> total.</p> {% from "macros/nl.jinja2" import nl_list with context %}
{{ nl_list(notes, page_n=page_n, total_count=total_count) }}
<ul class="nl-list">
{% if page_n > 1 %}
<li class="nl-prev"><a href="/p/most_recent/{{ page_n - 1 }}">&laquo; Previous page</a></li>
{% endif %}
{% for n in notes %}
<li>
<a href="{{ n.get_url() }}" class="nl-title">{{ n.title }}</a>
<p class="nl-desc">{{ n.short_desc() }}</p>
{% if n.tags %}
<p class="nl-tags">
<span class="material-icons">tag</span>
{{ T('tags') }}:
{% for tag in n.tags %}
{% set tn = tag.name %}
<a href="/tags/{{ tn }}/" class="nl-tag">#{{ tn }}</a>
{% endfor %}
</p>
{% endif %}
{% if n.calendar %}
<p class="nl-calendar">
<span class="material-icons">calendar_today</span>
<a href="/calendar/{{ n.calendar.year }}/{{ n.calendar.month }}">
<time datetime="{{ n.calendar.isoformat() }}">{{ n.calendar.strftime('%B %-d, %Y') }}</time>
</a>
</p>
{% endif %}
</li>
{% endfor %}
{% if page_n <= total_count // 20 %}
<li class="nl-next"><a href="/p/most_recent/{{ page_n + 1 }}/">Next page &raquo;</a></li>
{% endif %}
</ul>
</article> </article>
{% endblock %} {% endblock %}

View file

@ -8,42 +8,8 @@
<div class="preview-subtitle">{{ T('notes-tagged') }}</div> <div class="preview-subtitle">{{ T('notes-tagged') }}</div>
{% if total_count > 0 %} {% if total_count > 0 %}
<p class="nl-pagination">Showing results <strong>{{ page_n * 20 - 19 }}</strong> to <strong>{{ min(page_n * 20, total_count) }}</strong> of <strong>{{ total_count }}</strong> total.</p> {% from "macros/nl.jinja2" import nl_list with context %}
{{ nl_list(l, page_n=page_n, total_count=total_count, hl_tags=(tagname,)) }}
<ul class="nl-list">
{% if page_n > 1 %}
<li class="nl-prev"><a href="/tags/{{ tagname }}/{{ page_n - 1 }}/">&laquo; Previous page</a></li>
{% endif %}
{% for n in tagged_notes %}
<li>
<a href="{{ n.get_url() }}" class="nl-title">{{ n.title }}</a>
<p class="nl-desc">{{ n.short_desc() }}</p>
<p class="nl-tags">
<span class="material-icons">tag</span>
{{ T('tags') }}:
{% for tag in n.tags %}
{% set tn = tag.name %}
{% if tn == tagname %}
<strong class="nl-tag-hl">#{{ tn }}</strong>
{% else %}
<a href="/tags/{{ tn }}/" class="nl-tag">#{{ tn }}</a>
{% endif %}
{% endfor %}
{% if n.calendar %}
<p class="nl-calendar">
<span class="material-icons">calendar_today</span>
<a href="/calendar/{{ n.calendar.year }}/{{ n.calendar.month }}">
<time datetime="{{ n.calendar.isoformat() }}">{{ n.calendar.strftime('%B %-d, %Y') }}</time>
</a>
</p>
{% endif %}
</p>
</li>
{% endfor %}
{% if page_n < total_count // 20 %}
<li class="nl-next"><a href="/tags/{{ tagname }}/{{ page_n + 1 }}/">Next page &raquo;</a></li>
{% endif %}
</ul>
{% else %} {% else %}
<p class="nl-placeholder">{{ T('notes-tagged-empty') }}</p> <p class="nl-placeholder">{{ T('notes-tagged-empty') }}</p>
{% endif %} {% endif %}

View file

@ -0,0 +1,50 @@
{% macro nl_list(l, page_n=None, total_count=None, hl_tags=(), other_url='p/most_recent') %}
{% if page_n and total_count %}
<p class="nl-pagination">
Showing results <strong>{{ page_n * 20 - 19 }}</strong> to <strong>{{ min(page_n * 20, total_count) }}</strong>
of <strong>{{ total_count }}</strong> total.</p>
{% endif %}
<ul class="nl-list">
{% if page_n and page_n > 1 %}
<li class="nl-prev"><a href="/{{ other_url }}/?page={{ page_n - 1 }}">&laquo; Previous page</a></li>
{% endif %}
{% for n in l %}
<li>
<a href="{{ n.get_url() }}" class="nl-title">{{ n.title }}</a>
<p class="nl-desc">{{ n.short_desc() }}</p>
{% if n.tags %}
<p class="nl-tags">
<span class="material-icons">tag</span>
{{ T('tags') }}:
{% for tag in n.tags %}
{% set tn = tag.name %}
{% if tn in hl_tags %}
<strong class="nl-tag-hl">#{{ tn }}</strong>
{% else %}
<a href="/tags/{{ tn }}/" class="nl-tag">#{{ tn }}</a>
{% endif %}
{% endfor %}
</p>
{% endif %}
{% if n.calendar %}
<p class="nl-calendar">
<span class="material-icons">calendar_today</span>
<a href="/calendar/{{ n.calendar.year }}/{{ n.calendar.month }}">
<time datetime="{{ n.calendar.isoformat() }}">{{ n.calendar.strftime('%B %-d, %Y') }}</time>
</a>
</p>
{% endif %}
</li>
{% endfor %}
{% if page_n is none %}
<li class="nl-next"><a href="/{{ other_url }}/">{{ T('show-all') }}</a></li>
{% elif page_n <= total_count // 20 %}
<li class="nl-next"><a href="/{{ other_url }}/?page={{ page_n + 1 }}">Next page &raquo;</a></li>
{% endif %}
</ul>
{% endmacro %}

View file

@ -21,11 +21,8 @@
{% if results %} {% if results %}
<h2>Search results for <em>{{ q }}</em></h2> <h2>Search results for <em>{{ q }}</em></h2>
<ul class="nl-list"> {% from "macros/nl.jinja2" import nl_list with context %}
{% for n in results %} {{ nl_list(l, other_url=None) }}
<li>{% include "includes/nl_item.jinja2" %}</li>
{% endfor %}
</ul>
{% elif q %} {% elif q %}
<h2>{{ T('search-no-results') }} <em>{{ q }}</em></h2> <h2>{{ T('search-no-results') }} <em>{{ q }}</em></h2>
{% else %} {% else %}