Example #1
0
    def reply() -> werkzeug.Response:
        """Attempt to send a Reply from a Journalist to a Source. Empty
        messages are rejected, and an informative error message is flashed
        on the client. In the case of unexpected errors involving database
        transactions (potentially caused by racing request threads that
        modify the same the database object) logging is done in such a way
        so as not to write potentially sensitive information to disk, and a
        generic error message is flashed on the client.

        Returns:
           flask.Response: The user is redirected to the same Source
               collection view, regardless if the Reply is created
               successfully.
        """
        form = ReplyForm()
        if not form.validate_on_submit():
            for error in form.message.errors:
                flash(error, "error")
            return redirect(url_for('col.col', filesystem_id=g.filesystem_id))

        g.source.interaction_count += 1
        filename = "{0}-{1}-reply.gpg".format(g.source.interaction_count,
                                              g.source.journalist_filename)
        current_app.crypto_util.encrypt(
            form.message.data,
            [
                current_app.crypto_util.get_fingerprint(g.filesystem_id),
                config.JOURNALIST_KEY
            ],
            output=current_app.storage.path(g.filesystem_id, filename),
        )

        try:
            reply = Reply(g.user, g.source, filename)
            db.session.add(reply)
            db.session.flush()
            seen_reply = SeenReply(reply_id=reply.id, journalist_id=g.user.id)
            db.session.add(seen_reply)
            db.session.commit()
            store.async_add_checksum_for_file(reply)
        except Exception as exc:
            flash(
                gettext("An unexpected error occurred! Please "
                        "inform your admin."), "error")
            # We take a cautious approach to logging here because we're dealing
            # with responses to sources. It's possible the exception message
            # could contain information we don't want to write to disk.
            current_app.logger.error(
                "Reply from '{}' (ID {}) failed: {}!".format(
                    g.user.username, g.user.id, exc.__class__))
        else:

            flash(
                Markup("<b>{}</b> {}".format(
                    # Translators: Precedes a message confirming the success of an operation.
                    escape(gettext("Success!")),
                    escape(gettext("Your reply has been stored.")))),
                'success')
        finally:
            return redirect(url_for('col.col', filesystem_id=g.filesystem_id))
Example #2
0
    def reply():
        """Attempt to send a Reply from a Journalist to a Source. Empty
        messages are rejected, and an informative error message is flashed
        on the client. In the case of unexpected errors involving database
        transactions (potentially caused by racing request threads that
        modify the same the database object) logging is done in such a way
        so as not to write potentially sensitive information to disk, and a
        generic error message is flashed on the client.

        Returns:
           flask.Response: The user is redirected to the same Source
               collection view, regardless if the Reply is created
               successfully.
        """
        form = ReplyForm()
        if not form.validate_on_submit():
            for error in form.message.errors:
                flash(error, "error")
            return redirect(url_for('col.col', filesystem_id=g.filesystem_id))

        g.source.interaction_count += 1
        filename = "{0}-{1}-reply.gpg".format(g.source.interaction_count,
                                              g.source.journalist_filename)
        crypto_util.encrypt(form.message.data,
                            [crypto_util.getkey(g.filesystem_id),
                             config.JOURNALIST_KEY],
                            output=store.path(g.filesystem_id, filename))
        reply = Reply(g.user, g.source, filename)

        try:
            db_session.add(reply)
            db_session.commit()
        except Exception as exc:
            flash(gettext(
                "An unexpected error occurred! Please "
                "inform your administrator."), "error")
            # We take a cautious approach to logging here because we're dealing
            # with responses to sources. It's possible the exception message
            # could contain information we don't want to write to disk.
            current_app.logger.error(
                "Reply from '{}' (ID {}) failed: {}!".format(g.user.username,
                                                             g.user.id,
                                                             exc.__class__))
        else:
            flash(gettext("Thanks. Your reply has been stored."),
                  "notification")
        finally:
            return redirect(url_for('col.col', filesystem_id=g.filesystem_id))
Example #3
0
    def reply():
        """Attempt to send a Reply from a Journalist to a Source. Empty
        messages are rejected, and an informative error message is flashed
        on the client. In the case of unexpected errors involving database
        transactions (potentially caused by racing request threads that
        modify the same the database object) logging is done in such a way
        so as not to write potentially sensitive information to disk, and a
        generic error message is flashed on the client.

        Returns:
           flask.Response: The user is redirected to the same Source
               collection view, regardless if the Reply is created
               successfully.
        """
        form = ReplyForm()
        if not form.validate_on_submit():
            for error in form.message.errors:
                flash(error, "error")
            return redirect(url_for('col.col', filesystem_id=g.filesystem_id))

        g.source.interaction_count += 1
        filename = "{0}-{1}-reply.gpg".format(g.source.interaction_count,
                                              g.source.journalist_filename)
        crypto_util.encrypt(
            form.message.data,
            [crypto_util.getkey(g.filesystem_id), config.JOURNALIST_KEY],
            output=store.path(g.filesystem_id, filename))
        reply = Reply(g.user, g.source, filename)

        try:
            db_session.add(reply)
            db_session.commit()
        except Exception as exc:
            flash(
                gettext("An unexpected error occurred! Please "
                        "inform your administrator."), "error")
            # We take a cautious approach to logging here because we're dealing
            # with responses to sources. It's possible the exception message
            # could contain information we don't want to write to disk.
            current_app.logger.error(
                "Reply from '{}' (ID {}) failed: {}!".format(
                    g.user.username, g.user.id, exc.__class__))
        else:
            flash(gettext("Thanks. Your reply has been stored."),
                  "notification")
        finally:
            return redirect(url_for('col.col', filesystem_id=g.filesystem_id))
Example #4
0
 def col(filesystem_id):
     form = ReplyForm()
     source = get_source(filesystem_id)
     source.has_key = crypto_util.getkey(filesystem_id)
     return render_template("col.html",
                            filesystem_id=filesystem_id,
                            source=source,
                            form=form)
Example #5
0
 def col(filesystem_id: str) -> str:
     form = ReplyForm()
     source = get_source(filesystem_id)
     source.has_key = current_app.crypto_util.get_fingerprint(filesystem_id)
     return render_template("col.html",
                            filesystem_id=filesystem_id,
                            source=source,
                            form=form)
Example #6
0
    def col(filesystem_id: str) -> str:
        form = ReplyForm()
        source = get_source(filesystem_id)
        try:
            EncryptionManager.get_default().get_source_public_key(
                filesystem_id)
            source.has_key = True
        except GpgKeyNotFoundError:
            source.has_key = False

        return render_template("col.html",
                               filesystem_id=filesystem_id,
                               source=source,
                               form=form)