Exemple #1
0
class TagsView(Resource):
    decorators = [cache_filler(), cache.cached()]

    def get(self, filename=None):
        """List all tags."""

        if not is_cache_filler():
            logger.info("Cache miss for {}".format(request.path))

        if request.args.get("include_theses_ids", False) or filename != None:
            results = (db.session.query(Tag).join(Tag.theses).group_by(
                Tag.title).order_by(Tag.title).all())

            rv = {
                "data":
                [tag.to_dict(include_theses_ids=True) for tag in results]
            }

        else:
            results = (db.session.query(Tag, func.count(Thesis.id)).join(
                Tag.theses).group_by(Tag.title).all())

            rv = {
                "data":
                [item[0].to_dict(thesis_count=item[1]) for item in results]
            }

        return json_response(rv, filename=filename)
Exemple #2
0
class TagView(Resource):
    decorators = [cache_filler(), cache.cached()]

    def get(self, slug: str):
        """Tag metadata, list of all related theses and their elections."""
        if not is_cache_filler():
            logger.info("Cache miss for {}".format(request.path))

        tag = db.session.query(Tag).filter(Tag.slug == slug.lower()).first()

        if tag is None:
            return json_response({"error": "Tag not found"}, status=404)

        rv = {
            "data": tag.to_dict(include_related_tags="full"),
            "theses": [thesis.to_dict() for thesis in tag.theses],
            "elections": {
                thesis.election_id: thesis.election.to_dict()
                for thesis in tag.theses
            },
        }

        return json_response(rv)

    def delete(self, slug: str):
        admin_key = request.get_json().get("admin_key", "")
        if admin_key != current_app.config.get("ADMIN_KEY"):
            logger.warning("Invalid admin password")
            return json_response({"error": "Invalid admin password"},
                                 status=401)

        tag = db.session.query(Tag).filter(Tag.slug == slug).first()

        if tag is None:
            return json_response({"error": "Tag not found"}, status=404)

        logger.warning("Removing {}".format(tag))
        db.session.delete(tag)
        db.session.commit()

        rv = {
            "data": tag.to_dict(include_related_tags="full"),
            "theses": [thesis.to_dict() for thesis in tag.theses],
            "elections": {
                thesis.election_id: thesis.election.to_dict()
                for thesis in tag.theses
            },
        }

        return json_response(rv)
Exemple #3
0
class ThesisView(Resource):
    decorators = [cache_filler(), cache.cached()]

    def get(self, thesis_id: str):
        """Return metadata for a specific thesis."""

        if not is_cache_filler():
            logger.info("Cache miss for {}".format(request.path))

        thesis = Thesis.query.get(thesis_id)

        if thesis is None:
            return json_response({"error": "Thesis not found"}, status=404)

        rv = {"data": thesis.to_dict(), "related": thesis.related()}

        return json_response(rv)
Exemple #4
0
class ElectionView(Resource):
    decorators = [cache_filler(), cache.cached()]

    def get(self, wom_id: int):
        """Election data and a list of its theses."""
        if not is_cache_filler():
            logger.info("Cache miss for {}".format(request.path))

        election = Election.query.get(wom_id)

        if election is None:
            return json_response({"error": "Election not found"}, status=404)

        rv = {
            "data": election.to_dict(),
            "theses": [thesis.to_dict() for thesis in election.theses],
        }

        return json_response(rv)
Exemple #5
0
class BaseView(Resource):
    decorators = [cache_filler(), cache.cached()]

    def get(self):
        """Return base data set required by the web client."""

        if not is_cache_filler():
            logger.info("Cache miss for {}".format(request.path))

        rv = {"data": dict()}

        # Elections

        try:
            elections = db.session.query(Election).all()
        except SQLAlchemyError as e:
            logger.error(e)
            return json_response({"error": "Server Error"})

        rv["data"]["elections"] = defaultdict(list)
        for election in elections:
            rv["data"]["elections"][election.territory].append(
                election.to_dict(thesis_data=False))

        # Tags

        tagItems = (db.session.query(Tag, func.count(Thesis.id)).join(
            Tag.theses).group_by(Tag.title).all())

        rv["data"]["tags"] = [
            item[0].to_dict(
                thesis_count=item[1],
                query_root_status=True,
                include_related_tags="simple",
            ) for item in tagItems
        ]

        return json_response(rv)
Exemple #6
0
class Elections(Resource):
    decorators = [cache_filler(), cache.cached()]

    def get(self):
        """A list of all elections."""

        if not is_cache_filler():
            logger.info("Cache miss for {}".format(request.path))

        try:
            elections = Election.query.all()
        except SQLAlchemyError as e:
            logger.error(e)
            return json_response({"error": "Server Error"})

        thesis_data = request.args.get("thesis_data", False)

        rv = {"data": defaultdict(list)}
        for election in elections:
            rv["data"][election.territory].append(
                election.to_dict(thesis_data=thesis_data))

        return json_response(rv)
Exemple #7
0
class Quiz(Resource):
    method_decorators = {"get": [cache.cached(timeout=(5 * 60))]}

    def get(self, election_num, thesis_num=None):
        """Return a tally of how many users guessed yes/no for each thesis"""
        rv = {}
        error = None

        election = Election.query.get(election_num)
        if election is None:
            return json_response({"error": "Election not found"}, status=404)

        for thesis in election.theses:
            thesis_num = int(thesis.id[-2:])
            rv[thesis_num] = thesis.quiz_tally()

        return json_response({"error": error, "data": rv})

    def post(self, election_num, thesis_num=None):
        """Record an answer given by a user in a quiz."""
        if thesis_num == None:
            return json_response(
                {"error": "Missing path parameter for thesis number"},
                status=422)

        log_request_info("Quiz answer post", request)
        rv = None
        error = None
        status = 200

        thesis_id = "WOM-{:03d}-{:02d}".format(election_num, thesis_num)

        data = request.get_json()
        if data is not None:
            uuid = data.get("uuid", None)
            answer = data.get("answer", None)

        if data is None or uuid is None or answer is None:
            logger.warning("Request missing data: {}".format(data))
            error = "The request is missing data"
            status = 422
        else:
            thesis = Thesis.query.get(thesis_id)

            if thesis is None:
                error = "Thesis not found"
                status = 404
            else:
                qa = QuizAnswer(uuid=uuid, answer=answer, thesis=thesis)

                try:
                    db.session.add(qa)
                    db.session.commit()
                except IntegrityError:
                    error = "Ignored duplicate quiz answer"
                    logger.info("Ignored duplicate quiz answer")
                else:
                    logger.info("Added {}".format(qa))

        if error is None:
            rv = qa.to_dict()

        return json_response({"error": error, "data": rv}, status=status)