diff --git a/config.py.example b/config.py.example index 30d9180bff8d8894b151621273b2783cce837098..44109dfedce1dfb840521873b7cb647235a32e83 100644 --- a/config.py.example +++ b/config.py.example @@ -80,6 +80,7 @@ MAX_INDEX_DAYS = 14 # mail to contact in case of complex errors ADMIN_MAIL = "admin@example.com" +ADMIN_GROUP = "admin" # accept protocols even with some errors # useful for importing old protocols diff --git a/models/database.py b/models/database.py index 0788d1ec112b93cf6c3cd0651e9128713e478c8f..1399dadbac158d03918dccd87b5bf52e6fdc8240 100644 --- a/models/database.py +++ b/models/database.py @@ -107,6 +107,9 @@ class ProtocolType(db.Model): def has_modify_right(self, user): return (user is not None and self.modify_group != "" and self.modify_group in user.groups) + def has_admin_right(self, user): + return (user is not None and config.ADMIN_GROUP in user.groups) + @staticmethod def get_modifiable_protocoltypes(user): return [ diff --git a/server.py b/server.py index 2bc46061ac05035913242763e66a65de88aad90e..394a10c8c0ff2086a094e20fe192341684ce6520 100755 --- a/server.py +++ b/server.py @@ -177,7 +177,8 @@ def new_type(): form.private_mail.data, form.public_mail.data, form.use_wiki.data, form.wiki_category.data, form.wiki_only_public.data, form.printer.data, - form.calendar.data) + form.calendar.data, form.restrict_networks.data, + form.allowed_networks.data) db.session.add(protocoltype) db.session.commit() flash("Der Protokolltyp {} wurde angelegt.".format(protocoltype.name), "alert-success") @@ -224,6 +225,7 @@ def show_type(type_id): @app.route("/type/delete/<int:type_id>") @login_required +@group_required(config.ADMIN_GROUP) def delete_type(type_id): user = current_user() protocoltype = ProtocolType.query.filter_by(id=type_id).first() @@ -279,6 +281,7 @@ def edit_reminder(type_id, reminder_id): @app.route("/type/reminder/delete/<int:type_id>/<int:reminder_id>") @login_required +@group_required(config.ADMIN_GROUP) def delete_reminder(type_id, reminder_id): protocoltype = ProtocolType.query.filter_by(id=type_id).first() if protocoltype is None: @@ -521,6 +524,7 @@ def show_protocol(protocol_id): @app.route("/protocol/delete/<int:protocol_id>") @login_required +@group_required(config.ADMIN_GROUP) def delete_protocol(protocol_id): user = current_user() protocol = Protocol.query.filter_by(id=protocol_id).first() @@ -1016,6 +1020,7 @@ def upload_document(protocol_id): @app.route("/document/delete/<int:document_id>") @login_required +@group_required(config.ADMIN_GROUP) def delete_document(document_id): user = current_user() document = Document.query.filter_by(id=document_id).first() @@ -1177,6 +1182,7 @@ def edit_defaultmeta(meta_id): @app.route("/defaultmeta/delete/<int:meta_id>") @login_required +@group_required(config.ADMIN_GROUP) def delete_defaultmeta(meta_id): user = current_user() meta = DefaultMeta.query.filter_by(id=meta_id).first() @@ -1186,8 +1192,8 @@ def delete_defaultmeta(meta_id): name = meta.name type_id = meta.protocoltype.id db.session.delete(meta) - db.session.delete() - flash("Metadatenfeld '{}' gelöscht.", "alert-error") + db.session.commit() + flash("Metadatenfeld '{}' gelöscht.".format(name), "alert-error") return redirect(request.args.get("next") or url_for("show_type", type_id=type_id)) @app.route("/login", methods=["GET", "POST"]) diff --git a/shared.py b/shared.py index 3900c2da402ddd7b8929c9160c99bd25be29eb9b..f3807bf6b0dd4290126255342252c515c913b200 100644 --- a/shared.py +++ b/shared.py @@ -111,15 +111,17 @@ def login_required(function): return redirect(url_for("login", next=request.url)) return decorated_function -def group_required(function, group): - @wraps(function) - def decorated_function(*args, **kwargs): - if group in current_user.groups: - return function(*args, **kwargs) - else: - flash("You do not have the necessary permissions to view this page.") - return redirect(request.args.get("next") or url_for("index")) - return decorated_function +def group_required(group): + def decorator(function): + @wraps(function) + def decorated_function(*args, **kwargs): + if group in current_user().groups: + return function(*args, **kwargs) + else: + flash("You do not have the necessary permissions to view this page.") + return redirect(request.args.get("next") or url_for("index")) + return decorated_function + return decorator DATE_KEY = "Datum" START_TIME_KEY = "Beginn" diff --git a/templates/protocol-show.html b/templates/protocol-show.html index a78aa6d73d9e072523234091b6df191b7df22acb..3ea41a707c23eae6afb0b0760653ea3b265bf5e6 100644 --- a/templates/protocol-show.html +++ b/templates/protocol-show.html @@ -8,6 +8,7 @@ {% set has_public_view_right = protocol.has_public_view_right(user) %} {% set has_private_view_right = protocol.has_private_view_right(user) %} {% set has_modify_right = protocol.has_modify_right(user) %} +{% set has_admin_right = protocol.protocoltype.has_admin_right(user) %} {% block content %} <div class="container"> @@ -41,7 +42,9 @@ {% if protocol.has_compiled_document() %} <a class="btn btn-success" href="{{url_for("download_document", document_id=protocol.get_compiled_document().id)}}">Download</a> {% endif %} - <a class="btn btn-danger" href="{{url_for("delete_protocol", protocol_id=protocol.id)}}" onclick="return confirm('Bist du dir sicher, dass du das Protokoll {{protocol.get_identifier()}} löschen möchtest?');">Löschen</a> + {% if has_admin_right %} + <a class="btn btn-danger" href="{{url_for("delete_protocol", protocol_id=protocol.id)}}" onclick="return confirm('Bist du dir sicher, dass du das Protokoll {{protocol.get_identifier()}} löschen möchtest?');">Löschen</a> + {% endif %} {% endif %} </div> {% endif %} diff --git a/views/tables.py b/views/tables.py index 2922b03f0e051c7cf8b98559caa0753a90e5a97f..c64aa40a18ee12e3d4abb67aec85caf555dc2930 100644 --- a/views/tables.py +++ b/views/tables.py @@ -81,7 +81,8 @@ class ProtocolsTable(Table): if check_login(): if user is not None and protocol.protocoltype.has_private_view_right(user): result.append(Table.link(url_for("show_type", type_id=protocol.protocoltype.id), protocol.protocoltype.short_name)) - result.append(Table.link(url_for("delete_protocol", protocol_id=protocol.id), "Löschen", confirm="Bist du dir sicher, dass du das Protokoll {} löschen möchtest?".format(protocol.get_identifier()))) + if protocol.protocoltype.has_admin_right(user): + result.append(Table.link(url_for("delete_protocol", protocol_id=protocol.id), "Löschen", confirm="Bist du dir sicher, dass du das Protokoll {} löschen möchtest?".format(protocol.get_identifier()))) else: result.extend(["", ""]) return result @@ -131,6 +132,7 @@ class ProtocolTypeTable(SingleValueTable): + wiki_headers + calendar_headers + network_headers + action_headers) def row(self): + user = current_user() general_part = [ self.value.name, self.value.short_name, @@ -165,6 +167,8 @@ class ProtocolTypeTable(SingleValueTable): self.value.allowed_networks ] action_part = [Table.link(url_for("delete_type", type_id=self.value.id), "Löschen", confirm="Bist du dir sicher, dass du den Protokolltype {} löschen möchtest?".format(self.value.name))] + if not self.value.has_admin_right(user): + action_part = [""] return (general_part + mail_part + printing_part + wiki_part + calendar_part + network_part + action_part) @@ -197,15 +201,19 @@ class MeetingRemindersTable(Table): return ["Zeit", "Einladen", "Zusätzlicher Mailinhalt", ""] def row(self, reminder): - return [ + user = current_user() + general_part = [ "{} Tage".format(reminder.days_before), self.get_send_summary(reminder), - reminder.additional_text or "", - Table.concat([ - Table.link(url_for("edit_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Ändern"), - Table.link(url_for("delete_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Löschen", confirm="Bist du dir sicher, dass du die Einladungsmail {} Tage vor der Sitzung löschen willst?".format(reminder.days_before)) - ]) + reminder.additional_text or "" ] + action_links = [ + Table.link(url_for("edit_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Ändern"), + ] + if self.protocoltype.has_admin_right(user): + action_links.append(Table.link(url_for("delete_reminder", type_id=self.protocoltype.id, reminder_id=reminder.id), "Löschen", confirm="Bist du dir sicher, dass du die Einladungsmail {} Tage vor der Sitzung löschen willst?".format(reminder.days_before))) + action_part = [Table.concat(action_links)] + return general_part + action_part def get_send_summary(self, reminder): parts = [] @@ -333,15 +341,15 @@ class DocumentsTable(Table): def row(self, document): user = current_user() - links = [Table.link(url_for("delete_document", document_id=document.id), "Löschen", confirm="Bist du dir sicher, dass du das Dokument {} löschen willst?".format(document.name))] - if config.PRINTING_ACTIVE: + links = [] + if config.PRINTING_ACTIVE and document.protocol.has_modify_right(user): links.append(Table.link(url_for("print_document", document_id=document.id), "Drucken")) + if document.protocol.protocoltype.has_admin_right(user): + links.append(Table.link(url_for("delete_document", document_id=document.id), "Löschen", confirm="Bist du dir sicher, dass du das Dokument {} löschen willst?".format(document.name))) return [ document.id, Table.link(url_for("download_document", document_id=document.id), document.name), Table.concat(links) - if document.protocol.protocoltype.has_modify_right(user) - else "" ] class TodoMailsTable(Table): @@ -373,11 +381,16 @@ class DefaultMetasTable(Table): return ["Name", "Key", ""] def row(self, meta): - return [ + user = current_user() + general_part = [ meta.name, meta.key, - Table.concat([ - Table.link(url_for("edit_defaultmeta", meta_id=meta.id), "Ändern"), - Table.link(url_for("delete_defaultmeta", meta_id=meta.id, confirm="Bist du dir sicher, dass du das Metadatenfeld {} löschen willst?".format(meta.name)), "Löschen") - ]) ] + links = [ + Table.link(url_for("edit_defaultmeta", meta_id=meta.id), "Ändern") + ] + if meta.protocoltype.has_admin_right(user): + links.append(Table.link(url_for("delete_defaultmeta", meta_id=meta.id, confirm="Bist du dir sicher, dass du das Metadatenfeld {} löschen willst?".format(meta.name)), "Löschen")) + link_part = [Table.concat(links)] + return general_part + link_part +