diff --git a/migrations/versions/a1f23743bddb_.py b/migrations/versions/a1f23743bddb_.py new file mode 100644 index 0000000000000000000000000000000000000000..85bed956e41332c1318c411799abf4df725fe05e --- /dev/null +++ b/migrations/versions/a1f23743bddb_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: a1f23743bddb +Revises: 0555db125011 +Create Date: 2017-02-28 13:38:25.900461 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'a1f23743bddb' +down_revision = '0555db125011' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('protocols', sa.Column('public', sa.Boolean(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('protocols', 'public') + # ### end Alembic commands ### diff --git a/models/database.py b/models/database.py index 2a6d373df10438c247d046deaca2215654762edd..029b8339c322c6e074c7234954038842a1e34b91 100644 --- a/models/database.py +++ b/models/database.py @@ -125,13 +125,14 @@ class Protocol(db.Model): participants = db.Column(db.String) location = db.Column(db.String) done = db.Column(db.Boolean) + public = db.Column(db.Boolean) tops = relationship("TOP", backref=backref("protocol"), cascade="all, delete-orphan", order_by="TOP.number") decisions = relationship("Decision", backref=backref("protocol"), cascade="all, delete-orphan", order_by="Decision.id") documents = relationship("Document", backref=backref("protocol"), cascade="all, delete-orphan", order_by="Document.is_compiled") errors = relationship("Error", backref=backref("protocol"), cascade="all, delete-orphan", order_by="Error.id") - def __init__(self, protocoltype_id, date, source=None, content_public=None, content_private=None, start_time=None, end_time=None, author=None, participants=None, location=None, done=False): + def __init__(self, protocoltype_id, date, source=None, content_public=None, content_private=None, start_time=None, end_time=None, author=None, participants=None, location=None, done=False, public=False): self.protocoltype_id = protocoltype_id self.date = date self.source = source @@ -143,6 +144,7 @@ class Protocol(db.Model): self.participants = participants self.location = location self.done = done + self.public = public def __repr__(self): return "<Protocol(id={}, protocoltype_id={})>".format( @@ -190,6 +192,18 @@ class Protocol(db.Model): if LOCATION_KEY in remarks: self.location = remarks[LOCATION_KEY].value.strip() + def has_public_view_right(self, user): + return ( + (self.public and self.protocoltype.has_public_view_right(user)) + or self.protocoltype.has_private_view_right(user) + ) + + def has_private_view_right(self, user): + return self.protocoltype.has_private_view_right(user) + + def has_modify_right(self, user): + return self.protocoltype.has_modify_right(user) + def is_done(self): return self.done diff --git a/server.py b/server.py index 8036f3b958449caf2866ed45ca4f2d7092234194..ce68e5e7edf2ef47107db00edf898a7d3c347781 100755 --- a/server.py +++ b/server.py @@ -104,7 +104,12 @@ def index(): key=_sort_key ) finished_protocols = sorted( - [protocol for protocol in protocols if protocol.done], + [ + protocol for protocol in protocols + if protocol.done + and (protocol.has_public_view_right(user) + or protocol.has_private_view_right(user)) + ], key=_sort_key ) protocol = finished_protocols[0] if len(finished_protocols) > 0 else None @@ -112,7 +117,7 @@ def index(): if check_login(): todos = [ todo for todo in Todo.query.all() - if todo.protocoltype.has_public_view_right(user) + if todo.protocoltype.has_private_view_right(user) and not todo.is_done() ] todos_table = TodosTable(todos) if todos is not None else None @@ -395,7 +400,7 @@ def list_protocols(): protocol for protocol in protocols if (protocol.protocoltype.has_private_view_right(user) and _matches_search(protocol.content_private)) - or (protocol.protocoltype.has_public_view_right(user) + or (protocol.has_public_view_right(user) and _matches_search(protocol.content_public)) ] for protocol in protocols: @@ -464,12 +469,12 @@ def show_protocol(protocol_id): user = current_user() protocol = Protocol.query.filter_by(id=protocol_id).first() if protocol is None or not protocol.protocoltype.has_public_view_right(user): - flash("Invalides Protokoll.", "alert-error") + flash("Invalides Protokoll oder fehlende Zugriffsrechte.", "alert-error") return redirect(request.args.get("next") or url_for("index")) errors_table = ErrorsTable(protocol.errors) visible_documents = [ document for document in protocol.documents - if (not document.is_private and document.protocol.protocoltype.has_public_view_right(user)) + if (not document.is_private and document.protocol.has_public_view_right(user)) or (document.is_private and document.protocol.protocoltype.has_private_view_right(user)) ] documents_table = DocumentsTable(visible_documents) @@ -650,6 +655,19 @@ def update_protocol(protocol_id): return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id)) return render_template("protocol-update.html", upload_form=upload_form, edit_form=edit_form, protocol=protocol) +@app.route("/protocol/publish/<int:protocol_id>") +@login_required +def publish_protocol(protocol_id): + user = current_user() + protocol = Protocol.query.filter_by(id=protocol_id).first() + if protocol is None or not protocol.protocoltype.has_modify_right(user): + flash("Invalides Protokoll oder keine Berechtigung.", "alert-error") + return redirect(request.args.get("next") or url_for("index")) + protocol.public = True + db.session.commit() + return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id)) + + @app.route("/prococol/send/<int:protocol_id>") @login_required def send_protocol(protocol_id): @@ -891,7 +909,7 @@ def list_decisions(): search_form.search.data = search_term decisions = [ decision for decision in Decision.query.all() - if decision.protocol.protocoltype.has_public_view_right(user) + if decision.protocol.has_public_view_right(user) ] if protocoltype_id is not None and protocoltype_id != -1: decisions = [ @@ -926,7 +944,7 @@ def download_document(document_id): if ((document.is_private and not document.protocol.protocoltype.has_private_view_right(user)) or (not document.is_private - and not document.protocol.protocoltype.has_public_view_right(user))): + and not document.protocol.has_public_view_right(user))): flash("Keine Berechtigung.", "alert-error") return redirect(request.args.get("next") or url_for("index")) return send_file(document.as_file_like(), cache_timeout=1, as_attachment=True, attachment_filename=document.name) diff --git a/templates/protocol-show.html b/templates/protocol-show.html index 8ff11867f3a0ad3db1f1732ffc72fd8ec2002a03..2a11a9ca2155bcc8f87bb6c097a09d0106ef4e57 100644 --- a/templates/protocol-show.html +++ b/templates/protocol-show.html @@ -4,41 +4,47 @@ {% set logged_in = check_login() %} {% set user = current_user() %} -{% set has_public_view_right = protocol.protocoltype.has_public_view_right(user) %} -{% set has_private_view_right = protocol.protocoltype.has_private_view_right(user) %} -{% set has_modify_right = protocol.protocoltype.has_modify_right(user) %} +{% set has_public_type_view_right = protocol.protocoltype.has_public_view_right(user) %} +{% 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) %} {% block content %} <div class="container"> - <div class="btn-group"> - {% if has_modify_right %} - {% if config.ETHERPAD_ACTIVE %} - <a class="btn {% if protocol.source is none %}btn-primary{% else %}btn-default{% endif %}" href="{{url_for("etherpull_protocol", protocol_id=protocol.id)}}">Aus Etherpad</a> - {% endif %} - {% if protocol.source is not none %} - <a class="btn btn-primary" href="{{url_for("get_protocol_source", protocol_id=protocol.id)}}">Quelltext</a> - {% endif %} - <a class="btn {% if protocol.is_done() %}btn-success{% else %}btn-default{% endif %}" href="{{url_for("update_protocol", protocol_id=protocol.id)}}">Editieren</a> - {% if not protocol.is_done() %} - <a class="btn btn-default" href="{{url_for("get_protocol_template", protocol_id=protocol.id)}}">Vorlage</a> + {% if has_modify_right %} + <div class="btn-group"> + {% if has_modify_right %} {% if config.ETHERPAD_ACTIVE %} - <a class="btn btn-primary" href="{{url_for("etherpush_protocol", protocol_id=protocol.id)}}">In Etherpad</a> + <a class="btn {% if protocol.source is none %}btn-primary{% else %}btn-default{% endif %}" href="{{url_for("etherpull_protocol", protocol_id=protocol.id)}}">Aus Etherpad</a> {% endif %} - {% else %} - {% if config.MAIL_ACTIVE %} - <a class="btn btn-default" href="{{url_for("send_protocol", protocol_id=protocol.id)}}">Mail versenden</a> + {% if protocol.source is not none %} + <a class="btn btn-primary" href="{{url_for("get_protocol_source", protocol_id=protocol.id)}}">Quelltext</a> + {% endif %} + <a class="btn {% if protocol.is_done() %}btn-success{% else %}btn-default{% endif %}" href="{{url_for("update_protocol", protocol_id=protocol.id)}}">Editieren</a> + {% if not protocol.is_done() %} + <a class="btn btn-default" href="{{url_for("get_protocol_template", protocol_id=protocol.id)}}">Vorlage</a> + {% if config.ETHERPAD_ACTIVE %} + <a class="btn btn-primary" href="{{url_for("etherpush_protocol", protocol_id=protocol.id)}}">In Etherpad</a> + {% endif %} + {% else %} + {% if config.MAIL_ACTIVE %} + <a class="btn btn-default" href="{{url_for("send_protocol", protocol_id=protocol.id)}}">Mail versenden</a> + {% endif %} + {% if not protocol.public %} + <a class="btn btn-default" href="{{url_for("publish_protocol", protocol_id=protocol.id)}}">Veröffentlichen</a> + {% endif %} {% endif %} + {% if config.ETHERPAD_ACTIVE %} + <a class="btn btn-default" href="{{protocol.get_etherpad_link()}}" target="_blank">Etherpad</a> + {% endif %} + <a class="btn btn-default" href="{{url_for("show_type", type_id=protocol.protocoltype.id)}}">Typ</a> + {% 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> {% endif %} - {% if config.ETHERPAD_ACTIVE %} - <a class="btn btn-default" href="{{protocol.get_etherpad_link()}}" target="_blank">Etherpad</a> - {% endif %} - <a class="btn btn-default" href="{{url_for("show_type", type_id=protocol.protocoltype.id)}}">Typ</a> - {% 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> - {% endif %} - </div> + </div> + {% endif %} <div class="row"> <div id="left-column" class="col-lg-6"> {% if protocol.is_done() %} @@ -69,7 +75,7 @@ <h3>Tagesordnung{% if has_modify_right and not protocol.has_nonplanned_tops() %} <a href="{{url_for("new_top", protocol_id=protocol.id)}}">Top hinzufügen</a>{% endif %}</h3> {% include "protocol-tops-include.html" %} - {% if protocol.is_done() %} + {% if protocol.is_done() and has_public_view_right %} <h3>Beschlüsse</h3> <ul> {% if protocol.decisions|length > 0 %} @@ -105,7 +111,7 @@ {{render_table(errors_table)}} {% endif %} {% endif %} - {% if protocol.documents|length > 0 %} + {% if protocol.documents|length > 0 and has_public_view_right %} {{render_table(documents_table)}} {% else %} {% if has_modify_right %} diff --git a/templates/protocol-tops-include.html b/templates/protocol-tops-include.html index c7302ed1d7e5b88b39568d8c662014c17e266c32..ca7dc22d943a61870667af2fde26e1879da06ba2 100644 --- a/templates/protocol-tops-include.html +++ b/templates/protocol-tops-include.html @@ -9,7 +9,7 @@ {% for top in protocol.tops %} <li> {{top.name}} - {% if not protocol.is_done() and has_private_view_right %} + {% if not protocol.is_done() and has_public_type_view_right %} ({{top.number}}) {% endif %} {% if not protocol.is_done() and has_modify_right %} diff --git a/templates/top-new.html b/templates/top-new.html index 3b604d0fb68d5b041a6aed4b5a911acb4fa820bd..b06524649de2031a10dd6938efc803131b536c1a 100644 --- a/templates/top-new.html +++ b/templates/top-new.html @@ -4,9 +4,10 @@ {% set loggedin = check_login() %} {% set user = current_user() %} -{% set has_public_view_right = protocol.protocoltype.has_public_view_right(user) %} -{% set has_private_view_right = protocol.protocoltype.has_private_view_right(user) %} -{% set has_modify_right = protocol.protocoltype.has_modify_right(user) %} +{% set has_public_type_view_right = protocol.has_public_type_view_right(user) %} +{% 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) %} {% block content %} <div class="container"> diff --git a/views/forms.py b/views/forms.py index 91d108f05102181380cc95c9a7d90a66af92f776..0f8bb8791a8b9c137879f2a47a4a298b02961931 100644 --- a/views/forms.py +++ b/views/forms.py @@ -106,6 +106,7 @@ class ProtocolForm(FlaskForm): author = StringField("Protokollant") participants = StringField("Anwesende") done = BooleanField("Fertig") + public = BooleanField("Veröffentlicht") class TopForm(FlaskForm): name = StringField("TOP", validators=[InputRequired("Du musst den Namen des TOPs angeben.")])