Commit 32bfe777 authored by Robin Sonnabend's avatar Robin Sonnabend
Browse files

Improve server.py code quality

Also fixes some latent bugs
parent 4bd3d253
......@@ -48,6 +48,10 @@ class DatabaseModel(db.Model):
columns.append("{}={}".format(column_name, value))
return "{}({})".format(self.__class__.__name__, ", ".join(columns))
@classmethod
def first_by_id(cls, instance_id):
return cls.query.filter_by(id=instance_id).first()
class ProtocolType(DatabaseModel):
__tablename__ = "protocoltypes"
__model_name__ = "protocoltype"
......@@ -235,6 +239,11 @@ class Protocol(DatabaseModel):
or self.protocoltype.has_private_view_right(user)
)
def get_visible_content(self, user):
if self.has_private_view_right(user):
return self.content_private
return self.content_public
def is_done(self):
return self.done
......
......@@ -2,34 +2,58 @@
import locale
locale.setlocale(locale.LC_TIME, "de_DE.utf8")
from flask import Flask, g, current_app, request, session, flash, redirect, url_for, abort, render_template, Response, send_file as flask_send_file, Markup
from flask import (
Flask, request, session, flash, redirect,
url_for, abort, render_template, Response, Markup)
from werkzeug.utils import secure_filename
from flask_script import Manager, prompt
from flask_migrate import Migrate, MigrateCommand
#from flask_socketio import SocketIO
from celery import Celery
from sqlalchemy import or_, and_
from sqlalchemy import or_
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.interval import IntervalTrigger
import atexit
import feedgen.feed
import icalendar
from io import StringIO, BytesIO
from io import BytesIO
import os
from datetime import datetime, time, timedelta
from datetime import datetime, timedelta
import math
import mimetypes
import subprocess
from dateutil import tz
import config
from shared import db, date_filter, datetime_filter, date_filter_long, date_filter_short, time_filter, time_filter_short, user_manager, security_manager, current_user, check_login, login_required, group_required, class_filter, needs_date_test, todostate_name_filter, code_filter, indent_tab_filter
from utils import is_past, mail_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text, split_terms, optional_int_arg, fancy_join, footnote_hash
from decorators import db_lookup, require_public_view_right, require_private_view_right, require_modify_right, require_publish_right, require_admin_right
from models.database import ProtocolType, Protocol, DefaultTOP, TOP, LocalTOP, Document, Todo, Decision, MeetingReminder, Error, TodoMail, DecisionDocument, TodoState, Meta, DefaultMeta, DecisionCategory, Like
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, generate_protocol_form, TopForm, LocalTopForm, SearchForm, DecisionSearchForm, ProtocolSearchForm, TodoSearchForm, NewProtocolFileUploadForm, NewTodoForm, TodoForm, TodoMailForm, DefaultMetaForm, MetaForm, MergeTodosForm, DecisionCategoryForm, DocumentEditForm
from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable, TodoTable, ErrorTable, TodoMailsTable, DefaultMetasTable, DecisionCategoriesTable
from shared import (
db, date_filter, datetime_filter, date_filter_long,
date_filter_short, time_filter, time_filter_short, user_manager,
security_manager, current_user, check_login, login_required,
class_filter, needs_date_test, todostate_name_filter,
code_filter, indent_tab_filter)
from utils import (
get_first_unused_int, get_etherpad_text, split_terms, optional_int_arg,
fancy_join, footnote_hash, get_git_revision, get_max_page_length_exp,
get_internal_filename)
from decorators import (
db_lookup,
require_private_view_right, require_modify_right, require_publish_right,
require_admin_right)
from models.database import (
ProtocolType, Protocol, DefaultTOP, TOP, LocalTOP,
Document, Todo, Decision, MeetingReminder, Error, TodoMail,
DecisionDocument, TodoState, DefaultMeta, DecisionCategory, Like)
from views.forms import (
LoginForm, ProtocolTypeForm, DefaultTopForm,
MeetingReminderForm, NewProtocolForm, DocumentUploadForm,
KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm,
generate_protocol_form, TopForm, LocalTopForm,
DecisionSearchForm, ProtocolSearchForm, TodoSearchForm,
NewProtocolFileUploadForm, NewTodoForm, TodoForm, TodoMailForm,
DefaultMetaForm, MergeTodosForm, DecisionCategoryForm,
DocumentEditForm)
from views.tables import (
ProtocolsTable, ProtocolTypesTable,
ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable,
TodosTable, DocumentsTable, DecisionsTable, TodoTable, ErrorTable,
TodoMailsTable, DefaultMetasTable, DecisionCategoriesTable)
from legacy import import_old_todos, import_old_protocols, import_old_todomails
import back
......@@ -40,16 +64,14 @@ migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command("db", MigrateCommand)
def make_celery(app, config):
celery = Celery(app.import_name, broker=config.CELERY_BROKER_URL)
celery.conf.update(app.config)
return celery
celery = make_celery(app, config)
#def make_socketio(app, config):
# socketio = SocketIO(app)
# return socketio
#socketio = make_socketio(app, config)
celery = make_celery(app, config)
app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True
......@@ -59,7 +81,6 @@ app.jinja_env.filters["timify"] = time_filter
app.jinja_env.filters["timify_short"] = time_filter_short
app.jinja_env.filters["datify_short"] = date_filter_short
app.jinja_env.filters["datify_long"] = date_filter_long
#app.jinja_env.filters["url_complete"] = url_manager.complete
app.jinja_env.filters["class"] = class_filter
app.jinja_env.filters["todo_get_name"] = todostate_name_filter
app.jinja_env.filters["code"] = code_filter
......@@ -73,7 +94,7 @@ additional_templates = getattr(config, "LATEX_LOCAL_TEMPLATES", None)
if additional_templates is not None and os.path.isdir(additional_templates):
if additional_templates not in app.jinja_loader.searchpath:
app.jinja_loader.searchpath.append(additional_templates)
import tasks
......@@ -84,32 +105,20 @@ app.jinja_env.globals.update(min=min)
app.jinja_env.globals.update(max=max)
app.jinja_env.globals.update(dir=dir)
app.jinja_env.globals.update(now=datetime.now)
app.jinja_env.globals["git_revision"] = get_git_revision()
def get_git_revision():
gitlab_url = "https://git.fsmpi.rwth-aachen.de/protokollsystem/proto3"
commit_hash = subprocess.check_output(["git", "log", "-g", "-1", "--pretty=%H"]).decode("UTF-8").strip()
timestamp = int(subprocess.check_output(["git", "log", "-g", "-1", "--pretty=%at"]).strip())
commit_date = datetime.fromtimestamp(timestamp)
return {"url": gitlab_url, "hash": commit_hash, "date": commit_date}
try:
app.jinja_env.globals["git_revision"] = get_git_revision()
except:
pass
# blueprints here
@manager.command
def import_legacy():
"""Import the old todos and protocols from an sql dump"""
filename = prompt("SQL-file")
#filename = "legacy.sql"
with open(filename, "rb") as sqlfile:
content = sqlfile.read().decode("utf-8")
import_old_todos(content)
import_old_protocols(content)
import_old_todomails(content)
@manager.command
def recompile_all():
for protocol in sorted(Protocol.query.all(), key=lambda p: p.date):
......@@ -117,8 +126,9 @@ def recompile_all():
print(protocol.get_short_identifier())
tasks.parse_protocol(protocol)
@manager.command
def merge_todos():
def merge_duplicate_todos():
todo_by_id = {}
todos = Todo.query.all()
for todo in todos:
......@@ -139,34 +149,42 @@ def merge_todos():
else:
todo_by_id[todo_id] = todo
@manager.command
def runserver():
app.run()
make_scheduler()
# cause uwsgi currently has a bug
def send_file(file_like, cache_timeout, as_attachment, attachment_filename):
"""
Replaces flask.send_file since that uses an uwsgi function that is buggy.
"""
mimetype, _ = mimetypes.guess_type(attachment_filename)
response = Response(file_like.read(), mimetype)
if as_attachment:
response.headers["Content-Disposition"] = 'attachment; filename="{}"'.format(attachment_filename)
response.headers["Content-Disposition"] = (
'attachment; filename="{}"'.format(attachment_filename))
content_type = mimetype
if mimetype.startswith("text/"):
content_type = "{}; charset=utf-8".format(content_type)
response.headers["Content-Type"] = content_type
response.headers["Cache-Control"] = "public, max-age={}".format(cache_timeout)
response.headers["Cache-Control"] = (
"public, max-age={}".format(cache_timeout))
response.headers["Connection"] = "close"
return response
@app.route("/")
@back.anchor
def index():
user = current_user()
protocols = [
protocol for protocol in Protocol.query.all()
if protocol.protocoltype.has_public_view_right(user,
check_networks=False)
if protocol.protocoltype.has_public_view_right(
user, check_networks=False)
]
def _protocol_sort_key(protocol):
if protocol.date is not None:
return protocol.date
......@@ -185,8 +203,10 @@ def index():
[
protocol for protocol in protocols
if protocol.done and protocol.public
and (protocol.has_private_view_right(user)
or protocol.protocoltype.has_public_view_right(user, check_networks=False))
and (
protocol.has_private_view_right(user)
or protocol.protocoltype.has_public_view_right(
user, check_networks=False))
],
key=_protocol_sort_key,
reverse=True
......@@ -197,7 +217,8 @@ def index():
if len(finished_protocols) > 0:
protocol = finished_protocols[0]
show_private = protocol.has_private_view_right(user)
has_public_view_right = protocol.protocoltype.has_public_view_right(user)
has_public_view_right = (
protocol.protocoltype.has_public_view_right(user))
todos = None
if check_login():
todos = [
......@@ -207,16 +228,23 @@ def index():
]
user_todos = [
todo for todo in todos
if user.username.lower() in list(map(str.strip, todo.who.lower().split(",")))
if user.username.lower()
in list(map(str.strip, todo.who.lower().split(",")))
]
if len(user_todos) > 0:
todos = user_todos
def _todo_sort_key(todo):
protocol = todo.get_first_protocol()
return protocol.date if protocol is not None and protocol.date is not None else datetime.now().date()
if protocol is not None and protocol.date is not None:
return protocol.date
return datetime.now().date()
todos = sorted(todos, key=_todo_sort_key, reverse=True)
todos_table = TodosTable(todos) if todos is not None else None
return render_template("index.html", open_protocols=open_protocols, protocol=protocol, todos=todos, show_private=show_private, has_public_view_right=has_public_view_right)
return render_template(
"index.html", open_protocols=open_protocols,
protocol=protocol, todos=todos, show_private=show_private,
has_public_view_right=has_public_view_right)
@app.route("/documentation")
@back.anchor
......@@ -224,22 +252,26 @@ def index():
def documentation():
todostates = list(TodoState)
name_to_state = TodoState.get_name_to_state()
return render_template("documentation.html", todostates=todostates, name_to_state=name_to_state)
return render_template(
"documentation.html", todostates=todostates,
name_to_state=name_to_state)
@app.route("/types/list")
@back.anchor
@login_required
def list_types():
is_logged_in = check_login()
user = current_user()
types = [
protocoltype for protocoltype in ProtocolType.query.all()
if (protocoltype.has_private_view_right(user)
or protocoltype.has_public_view_right(user)
or protocoltype.is_public)]
or protocoltype.has_public_view_right(user)
or protocoltype.is_public)]
types = sorted(types, key=lambda t: t.short_name)
types_table = ProtocolTypesTable(types)
return render_template("types-list.html", types=types, types_table=types_table)
return render_template(
"types-list.html", types=types, types_table=types_table)
@app.route("/type/new", methods=["GET", "POST"])
@login_required
......@@ -248,16 +280,19 @@ def new_type():
if form.validate_on_submit():
user = current_user()
if form.private_group.data not in user.groups:
flash("Du kannst keinen internen Protokolltypen anlegen, zu dem du selbst keinen Zugang hast.", "alert-error")
flash("Du kannst keinen internen Protokolltypen anlegen, "
"zu dem du selbst keinen Zugang hast.", "alert-error")
else:
protocoltype = ProtocolType()
form.populate_obj(protocoltype)
db.session.add(protocoltype)
db.session.commit()
flash("Der Protokolltyp {} wurde angelegt.".format(protocoltype.name), "alert-success")
flash("Der Protokolltyp {} wurde angelegt.".format(
protocoltype.name), "alert-success")
return back.redirect("list_types")
return render_template("type-new.html", form=form)
@app.route("/type/edit/<int:protocoltype_id>", methods=["GET", "POST"])
@login_required
@db_lookup(ProtocolType)
......@@ -267,12 +302,15 @@ def edit_type(protocoltype):
form = ProtocolTypeForm(obj=protocoltype)
if form.validate_on_submit():
if form.private_group.data not in user.groups:
flash("Du kannst keinen internen Protokolltypen anlegen, zu dem du selbst keinen Zugang hast.", "alert-error")
flash("Du kannst keinen internen Protokolltypen anlegen, "
"zu dem du selbst keinen Zugang hast.", "alert-error")
else:
form.populate_obj(protocoltype)
db.session.commit()
return back.redirect("show_type", protocoltype_id=protocoltype.id)
return render_template("type-edit.html", form=form, protocoltype=protocoltype)
return render_template(
"type-edit.html", form=form, protocoltype=protocoltype)
@app.route("/type/show/<int:protocoltype_id>")
@back.anchor
......@@ -281,25 +319,36 @@ def edit_type(protocoltype):
@require_private_view_right()
def show_type(protocoltype):
protocoltype_table = ProtocolTypeTable(protocoltype)
default_tops_table = DefaultTOPsTable(protocoltype.default_tops, protocoltype)
reminders_table = MeetingRemindersTable(protocoltype.reminders, protocoltype)
default_tops_table = DefaultTOPsTable(
protocoltype.default_tops, protocoltype)
reminders_table = MeetingRemindersTable(
protocoltype.reminders, protocoltype)
metas_table = DefaultMetasTable(protocoltype.metas, protocoltype)
categories_table = DecisionCategoriesTable(protocoltype.decisioncategories, protocoltype)
return render_template("type-show.html", protocoltype=protocoltype, protocoltype_table=protocoltype_table, default_tops_table=default_tops_table, metas_table=metas_table, reminders_table=reminders_table, mail_active=config.MAIL_ACTIVE, categories_table=categories_table)
categories_table = DecisionCategoriesTable(
protocoltype.decisioncategories, protocoltype)
return render_template(
"type-show.html", protocoltype=protocoltype,
protocoltype_table=protocoltype_table,
default_tops_table=default_tops_table, metas_table=metas_table,
reminders_table=reminders_table, mail_active=config.MAIL_ACTIVE,
categories_table=categories_table)
@app.route("/type/delete/<int:protocoltype_id>")
@login_required
@group_required(config.ADMIN_GROUP)
@db_lookup(ProtocolType)
@require_admin_right()
@require_modify_right()
def delete_type(protocoltype):
name = protocoltype.name
db.session.delete(protocoltype)
db.session.delete(protocoltype)
db.session.commit()
flash("Der Protokolltype {} wurde gelöscht.".format(name), "alert-success")
return back.redirect("list_types")
@app.route("/type/reminders/new/<int:protocoltype_id>", methods=["GET", "POST"])
@app.route("/type/reminders/new/<int:protocoltype_id>",
methods=["GET", "POST"])
@login_required
@db_lookup(ProtocolType)
@require_modify_right()
......@@ -311,9 +360,12 @@ def new_reminder(protocoltype):
db.session.add(meetingreminder)
db.session.commit()
return back.redirect("show_type", protocoltype_id=protocoltype.id)
return render_template("reminder-new.html", form=form, protocoltype=protocoltype)
return render_template(
"reminder-new.html", form=form, protocoltype=protocoltype)
@app.route("/type/reminder/edit/<int:meetingreminder_id>", methods=["GET", "POST"])
@app.route("/type/reminder/edit/<int:meetingreminder_id>",
methods=["GET", "POST"])
@login_required
@db_lookup(MeetingReminder)
@require_modify_right()
......@@ -322,8 +374,11 @@ def edit_reminder(meetingreminder):
if form.validate_on_submit():
form.populate_obj(meetingreminder)
db.session.commit()
return back.redirect("show_type", protocoltype_id=protocoltype.id)
return render_template("reminder-edit.html", form=form, meetingreminder=meetingreminder)
return back.redirect(
"show_type", protocoltype_id=meetingreminder.protocoltype.id)
return render_template(
"reminder-edit.html", form=form, meetingreminder=meetingreminder)
@app.route("/type/reminder/delete/<int:meetingreminder_id>")
@login_required
......@@ -335,6 +390,7 @@ def delete_reminder(meetingreminder):
db.session.commit()
return back.redirect("show_type", protocoltype_id=protocoltype.id)
@app.route("/type/tops/new/<int:protocoltype_id>", methods=["GET", "POST"])
@login_required
@db_lookup(ProtocolType)
......@@ -348,15 +404,20 @@ def new_default_top(protocoltype):
db.session.commit()
for protocol in protocoltype.protocols:
if not protocol.done:
localtop = LocalTOP(protocol_id=protocol.id,
localtop = LocalTOP(
protocol_id=protocol.id,
defaulttop_id=defaulttop.id, description="")
db.session.add(localtop)
db.session.commit()
flash("Der Standard-TOP {} wurde für dem Protokolltyp {} hinzugefügt.".format(defaulttop.name, protocoltype.name), "alert-success")
flash("Der Standard-TOP {} wurde für dem Protokolltyp {} hinzugefügt."
.format(defaulttop.name, protocoltype.name), "alert-success")
return back.redirect()
return render_template("default-top-new.html", form=form, protocoltype=protocoltype)
return render_template(
"default-top-new.html", form=form, protocoltype=protocoltype)
@app.route("/type/tops/edit/<int:protocoltype_id>/<int:defaulttop_id>", methods=["GET", "POST"])
@app.route("/type/tops/edit/<int:protocoltype_id>/<int:defaulttop_id>",
methods=["GET", "POST"])
@login_required
@db_lookup(ProtocolType, DefaultTOP)
@require_modify_right()
......@@ -366,7 +427,10 @@ def edit_default_top(protocoltype, defaulttop):
form.populate_obj(defaulttop)
db.session.commit()
return back.redirect("show_type", protocoltype_id=protocoltype.id)
return render_template("default-top-edit.html", form=form, protocoltype=protocoltype, defaulttop=defaulttop)
return render_template(
"default-top-edit.html", form=form,
protocoltype=protocoltype, defaulttop=defaulttop)
@app.route("/type/tops/delete/<int:defaulttop_id>")
@login_required
......@@ -375,7 +439,9 @@ def edit_default_top(protocoltype, defaulttop):
def delete_default_top(defaulttop):
db.session.delete(defaulttop)
db.session.commit()
return back.redirect("show_type", protocoltype_id=defaulttop.protocoltype.id)
return back.redirect(
"show_type", protocoltype_id=defaulttop.protocoltype.id)
@app.route("/type/tops/move/<int:defaulttop_id>/<diff>/")
@login_required
......@@ -387,14 +453,14 @@ def move_default_top(defaulttop, diff):
db.session.commit()
except ValueError:
flash("Die angegebene Differenz ist keine Zahl.", "alert-error")
return back.redirect("show_type", protocoltype_id=defaulttop.protocoltype.id)
return back.redirect(
"show_type", protocoltype_id=defaulttop.protocoltype.id)
@app.route("/protocols/list")
@back.anchor
def list_protocols():
is_logged_in = check_login()
user = current_user()
protocoltype = None
protocoltype_id = None
try:
protocoltype_id = int(request.args.get("protocoltype_id"))
......@@ -406,11 +472,11 @@ def list_protocols():
except (ValueError, TypeError):
pass
search_term = request.args.get("search")
protocoltypes = ProtocolType.get_public_protocoltypes(user, check_networks=False)
protocoltypes = ProtocolType.get_public_protocoltypes(
user, check_networks=False)
search_form = ProtocolSearchForm(protocoltypes)
if protocoltype_id is not None:
search_form.protocoltype_id.data = protocoltype_id
protocoltype = ProtocolType.query.filter_by(id=protocoltype_id).first()
if state_open is not None:
search_form.state_open.data = state_open
if search_term is not None:
......@@ -427,14 +493,17 @@ def list_protocols():
))
protocols = [
protocol for protocol in protocol_query.all()
if protocol.protocoltype.has_public_view_right(user, check_networks=False)
if protocol.protocoltype.has_public_view_right(
user, check_networks=False)
]
def _matches_search(content):
content = content.lower()
for search_term in search_terms:
if search_term.lower() not in content:
return False
return True
def _matches_search_lazy(content):
content = content.lower()
for search_term in search_terms:
......@@ -462,7 +531,7 @@ def list_protocols():
and _matches_search(protocol.content_public))
]
for protocol in protocols:
content = protocol.content_private if protocol.protocoltype.has_private_view_right(user) else protocol.content_public
content = protocol.get_visible_content(user)
lines = content.splitlines()
matches = [line for line in lines if _matches_search_lazy(line)]
formatted_lines = []
......@@ -471,13 +540,18 @@ def list_protocols():
lower_line = line.lower()
last_index = 0
while last_index < len(line):
index_candidates = list(filter(lambda t: t[0] != -1,
[(lower_line.find(term, last_index), term) for term in search_terms]))
index_candidates = list(filter(
lambda t: t[0] != -1,
[
(lower_line.find(term, last_index), term)
for term in search_terms
]))
if len(index_candidates) == 0:
parts.append((line[last_index:], False))
break
else:
new_index, term = min(index_candidates, key=lambda t: t[0])
new_index, term = min(
index_candidates, key=lambda t: t[0])
new_end_index = new_index + len(term)
parts.append((line[last_index:new_index], False))
parts.append((line[new_index:new_end_index], True))
......@@ -487,7 +561,8 @@ def list_protocols():
for text, matched in parts
]))
search_results[protocol] = " …<br />\n".join(formatted_lines)
protocols = sorted(protocols, key=lambda protocol: protocol.date, reverse=True)
protocols = sorted(
protocols, key=lambda protocol: protocol.date, reverse=True)
page = _get_page()
page_length = _get_page_length()
page_count = int(math.ceil(len(protocols) / page_length))
......@@ -495,10 +570,17 @@ def list_protocols():
page = 0
begin_index = page * page_length
end_index = (page + 1) * page_length
max_page_length_exp = math.ceil(math.log10(len(protocols))) if len(protocols) > 0 else 1
max_page_length_exp = get_max_page_length_exp(protocols)
protocols = protocols[begin_index:end_index]
protocols_table = ProtocolsTable(protocols, search_results=search_results)
return render_template("protocols-list.html", protocols=protocols, protocols_table=protocols_table, search_form=search_form, page=page, page_count=page_count, page_diff=config.PAGE_DIFF, protocoltype_id=protocoltype_id, search_term=search_term, state_open=state_open, page_length=page_length, max_page_length_exp=max_page_length_exp)
return render_template(
"protocols-list.html", protocols=protocols,
protocols_table=protocols_table, search_form=search_form, page=page,
page_count=page_count, page_diff=config.PAGE_DIFF,
protocoltype_id=protocoltype_id, search_term=search_term,
state_open=state_open, page_length=page_length,
max_page_length_exp=max_page_length_exp)
@app.route("/protocol/new", methods=["GET", "POST"])
@login_required
......@@ -509,18 +591,23 @@ def new_protocol():
upload_form = NewProtocolSourceUploadForm(protocoltypes)
file_upload_form = NewProtocolFileUploadForm(protocoltypes)
if form.validate_on_submit():
protocoltype = ProtocolType.query.filter_by(id=form.protocoltype_id.data).first()
protocoltype = ProtocolType.query.filter_by(
id=form.protocoltype_id.data).first()
if protocoltype is None or not protocoltype.has_modify_right(user):
flash("Dir fehlen die nötigen Zugriffsrechte.", "alert-error")
return back.redirect()
protocol = Protocol.create_new_protocol(protocoltype,
form.date.data, form.start_time.data)
protocol = Protocol.create_new_protocol(
protocoltype, form.date.data, form.start_time.data)
return back.redirect("show_protocol", protocol_id=protocol.id)
type_id = request.args.get("protocoltype_id")
if type_id is not None:
form.protocoltype.data = type_id
upload_form.protocoltype.data = type_id
return render_template("protocol-new.html", form=form, upload_form=upload_form, file_upload_form=file_upload_form, protocoltypes=protocoltypes)
return render_template(
"protocol-new.html", form=form,
upload_form=upload_form, file_upload_form=file_upload_form,
protocoltypes=protocoltypes)
@app.route("/protocol/show/<int:protocol_id>")
@back.anchor
......@@ -528,32 +615,42 @@ def new_protocol():
def show_protocol(protocol):
user = current_user()
errors_table = ErrorsTable(protocol.errors)
if not protocol.protocoltype.has_public_view_right(user, check_networks=False):
if not protocol.protocoltype.has_public_view_right(
user, check_networks=False):
flash("Dir fehlen die nötigen Zugriffsrechte.", "alert-error")
if check_login():
return redirect(url_for("index"))