diff --git a/pyproject.toml b/pyproject.toml
index 61b25b5..768f33d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -19,6 +19,7 @@ pyyaml = "^6.0.2"
nanoid = "^2.0.0"
# grung-db = {git = "https://git.evilchi.li/evilchili/grung-db.git"}
grung-db = {git = "file:///home/greg/dev/grung-db/"}
+flask-session = "^0.8.0"
[tool.poetry.group.dev.dependencies]
pytest = "*"
diff --git a/src/ttfrog/app.py b/src/ttfrog/app.py
index bde176c..b337b88 100644
--- a/src/ttfrog/app.py
+++ b/src/ttfrog/app.py
@@ -4,9 +4,9 @@ from pathlib import Path
from types import SimpleNamespace
from dotenv import dotenv_values
-from flask import Flask
+from flask import Flask, session
+from flask_session import Session
from grung.db import GrungDB
-from grung.exceptions import UniqueConstraintError
from tinydb.storages import MemoryStorage
from ttfrog import schema
@@ -78,6 +78,7 @@ VIEW_URI=/
config=config_file,
data_root=data_root,
database=data_root / f"{self.config.NAME}.json",
+ sessions=data_root / "session_cache"
)
def initialize(self, db: GrungDB = None, force: bool = False) -> None:
@@ -99,6 +100,11 @@ VIEW_URI=/
self.web.config["SEND_FILE_MAX_AGE_DEFAULT"] = 0
self.web.config["DEBUG"] = True
+ self.web.config["SESSION_TYPE"] = "filesystem"
+ self.web.config["SESSION_REFRESH_EACH_REQUEST"] = True
+ self.web.config["SESSION_FILE_DIR"] = self.path.sessions
+ Session(self.web)
+
self._initialized = True
def check_state(self) -> None:
diff --git a/src/ttfrog/forms.py b/src/ttfrog/forms.py
index cfa0e72..9159c8f 100644
--- a/src/ttfrog/forms.py
+++ b/src/ttfrog/forms.py
@@ -5,6 +5,8 @@ from grung.types import BackReference, Collection, Pointer, Record
from ttfrog import schema
+from flask import g
+
READ_ONLY_FIELD_TYPES = [Collection, Pointer, BackReference]
@@ -30,6 +32,7 @@ class Form:
continue
self.record[key] = value
+ self.record.author = g.user
return self.record
diff --git a/src/ttfrog/themes/default/base.html b/src/ttfrog/themes/default/base.html
index 6da2643..ddeafef 100644
--- a/src/ttfrog/themes/default/base.html
+++ b/src/ttfrog/themes/default/base.html
@@ -22,6 +22,8 @@
{% block menu %}{% endblock %}
+ Last Edited By: {{ page.author.name }}
+
{% for message in get_flashed_messages() %}
diff --git a/src/ttfrog/web.py b/src/ttfrog/web.py
index 42acfc4..83821a1 100644
--- a/src/ttfrog/web.py
+++ b/src/ttfrog/web.py
@@ -1,4 +1,4 @@
-from flask import Response, render_template, request
+from flask import Response, render_template, request, redirect, url_for, session, g
from tinydb import where
from ttfrog import app, schema, forms
@@ -81,11 +81,26 @@ def index():
return rendered(get_page(create_okay=False))
+@app.web.route("/login")
+def login():
+ app.web.session_interface.regenerate(session)
+ g.user = app.db.User.search(where("name") == "admin")[0]
+ session['user_id'] = g.user.doc_id
+ return redirect(url_for("index"))
+
+
+@app.web.route("/logout")
+def logout():
+ if 'user_id' in session:
+ del session['user_id']
+ del g.user
+
+
@app.web.route(f"{app.config.VIEW_URI}//", methods=["GET"])
@app.web.route(f"{app.config.VIEW_URI}/", methods=["GET"], defaults={'table': 'Page'})
def view(table, path):
parent = get_parent(table, relative_uri())
- return rendered(get_page(request.path, table=table, create_okay=parent.doc_id is not None))
+ return rendered(get_page(request.path, table=table, create_okay=parent and parent.doc_id is not None))
@app.web.route(f"{app.config.VIEW_URI}//", methods=["POST"])
@@ -110,6 +125,14 @@ def edit(table, path):
return rendered(app.add_member(parent, save_data))
+@app.web.before_request
+def before_request():
+ if 'user_id' in session:
+ g.user = app.db.User.get(doc_id=session['user_id'])
+ elif request.endpoint != 'login':
+ return redirect(url_for('login'))
+
+
@app.web.after_request
def add_header(r):
r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate, public, max-age=0"