예제 #1
0
파일: api.py 프로젝트: itsibitzi/securedrop
    def seen() -> Tuple[flask.Response, int]:
        """
        Lists or marks the source conversation items that the journalist has seen.
        """
        user = _authenticate_user_from_auth_header(request)

        if request.method == "POST":
            if request.json is None or not isinstance(request.json,
                                                      collections.abc.Mapping):
                abort(400, "Please send requests in valid JSON.")

            if not any(map(request.json.get,
                           ["files", "messages", "replies"])):
                abort(400, "Please specify the resources to mark seen.")

            # gather everything to be marked seen. if any don't exist,
            # reject the request.
            targets = set()  # type: Set[Union[Submission, Reply]]
            for file_uuid in request.json.get("files", []):
                f = Submission.query.filter(
                    Submission.uuid == file_uuid).one_or_none()
                if f is None or not f.is_file:
                    abort(404, "file not found: {}".format(file_uuid))
                targets.add(f)

            for message_uuid in request.json.get("messages", []):
                m = Submission.query.filter(
                    Submission.uuid == message_uuid).one_or_none()
                if m is None or not m.is_message:
                    abort(404, "message not found: {}".format(message_uuid))
                targets.add(m)

            for reply_uuid in request.json.get("replies", []):
                r = Reply.query.filter(Reply.uuid == reply_uuid).one_or_none()
                if r is None:
                    abort(404, "reply not found: {}".format(reply_uuid))
                targets.add(r)

            # now mark everything seen.
            utils.mark_seen(list(targets), user)

            return jsonify({"message": "resources marked seen"}), 200

        abort(405)
예제 #2
0
파일: col.py 프로젝트: sheonhan/securedrop
    def download_single_file(filesystem_id, fn):
        """
        Marks the file being download (the file being downloaded is either a submission message,
        submission file attachement, or journalist reply) as seen by the current logged-in user and
        send the file to a client to be saved or opened.
        """
        if '..' in fn or fn.startswith('/'):
            abort(404)

        # mark as seen by the current user
        try:
            journalist = g.get("user")
            if fn.endswith("reply.gpg"):
                reply = Reply.query.filter(Reply.filename == fn).one()
                mark_seen([reply], journalist)
            elif fn.endswith("-doc.gz.gpg") or fn.endswith("doc.zip.gpg"):
                file = Submission.query.filter(Submission.filename == fn).one()
                mark_seen([file], journalist)
            else:
                message = Submission.query.filter(
                    Submission.filename == fn).one()
                mark_seen([message], journalist)
        except NoResultFound as e:
            current_app.logger.error("Could not mark {} as seen: {}".format(
                fn, e))

        return send_file(current_app.storage.path(filesystem_id, fn),
                         mimetype="application/pgp-encrypted")
예제 #3
0
def bulk_setup_for_seen_only(journo: Journalist,
                             storage: Storage) -> List[Dict]:
    """
    Create some sources with some seen submissions that are not marked as 'downloaded' in the
    database and some seen replies from journo.
    """

    setup_collection = []

    for i in range(random.randint(2, 4)):
        collection = {}

        source, _ = init_source(storage)

        submissions = submit(storage, source, random.randint(2, 4))
        half = math.ceil(len(submissions) / 2)
        messages = submissions[half:]
        files = submissions[:half]
        replies = reply(storage, journo, source, random.randint(1, 3))

        seen_files = random.sample(files, math.ceil(len(files) / 2))
        seen_messages = random.sample(messages, math.ceil(len(messages) / 2))
        seen_replies = random.sample(replies, math.ceil(len(replies) / 2))

        mark_seen(seen_files, journo)
        mark_seen(seen_messages, journo)
        mark_seen(seen_replies, journo)

        unseen_files = list(set(files).difference(set(seen_files)))
        unseen_messages = list(set(messages).difference(set(seen_messages)))
        unseen_replies = list(set(replies).difference(set(seen_replies)))
        not_downloaded = list(
            set(files + messages).difference(set(seen_files + seen_messages)))

        collection["source"] = source
        collection["seen_files"] = seen_files
        collection["seen_messages"] = seen_messages
        collection["seen_replies"] = seen_replies
        collection["unseen_files"] = unseen_files
        collection["unseen_messages"] = unseen_messages
        collection["unseen_replies"] = unseen_replies
        collection["not_downloaded"] = not_downloaded

        setup_collection.append(collection)

    return setup_collection
예제 #4
0
    def download_single_file(filesystem_id: str, fn: str) -> werkzeug.Response:
        """
        Marks the file being download (the file being downloaded is either a submission message,
        submission file attachement, or journalist reply) as seen by the current logged-in user and
        send the file to a client to be saved or opened.
        """
        if ".." in fn or fn.startswith("/"):
            abort(404)

        file = Storage.get_default().path(filesystem_id, fn)
        if not Path(file).is_file():
            flash(
                gettext(
                    "Your download failed because the file could not be found. An admin can find "
                    + "more information in the system and monitoring logs."),
                "error",
            )
            current_app.logger.error("File {} not found".format(file))
            return redirect(url_for("col.col", filesystem_id=filesystem_id))

        # mark as seen by the current user
        try:
            journalist = g.get("user")
            if fn.endswith("reply.gpg"):
                reply = Reply.query.filter(Reply.filename == fn).one()
                mark_seen([reply], journalist)
            elif fn.endswith("-doc.gz.gpg") or fn.endswith("doc.zip.gpg"):
                submitted_file = Submission.query.filter(
                    Submission.filename == fn).one()
                mark_seen([submitted_file], journalist)
            else:
                message = Submission.query.filter(
                    Submission.filename == fn).one()
                mark_seen([message], journalist)
        except NoResultFound as e:
            current_app.logger.error("Could not mark {} as seen: {}".format(
                fn, e))

        return send_file(Storage.get_default().path(filesystem_id, fn),
                         mimetype="application/pgp-encrypted")