Ejemplo n.º 1
0
class EntryLockResource(Resource):
    @marshal_with(fields.entry_lock, envelope="lock")
    def get(self, entry_id, logbook_id=None):
        "Check for a lock"
        entry = Entry.get(Entry.id == entry_id)
        lock = entry.get_lock(request.environ["REMOTE_ADDR"])
        if lock:
            return lock
        raise EntryLock.DoesNotExist

    @use_args({"steal": Boolean(missing=False)})
    @marshal_with(fields.entry_lock, envelope="lock")
    def post(self, args, entry_id, logbook_id=None):
        "Acquire (optionally stealing) a lock"
        entry = Entry.get(Entry.id == entry_id)
        return entry.get_lock(ip=request.environ["REMOTE_ADDR"],
                              acquire=True,
                              steal=args["steal"])

    @use_args({"lock_id": Integer()})
    @marshal_with(fields.entry_lock, envelope="lock")
    def delete(self, args, entry_id=None, logbook_id=None):
        "Cancel a lock"
        if "lock_id" in args:
            lock = EntryLock.get(EntryLock.id == args["lock_id"])
        else:
            entry = Entry.get(Entry.id == entry_id)
            lock = entry.get_lock()
        lock.cancel(request.environ["REMOTE_ADDR"])
        return lock
Ejemplo n.º 2
0
class LogbooksResource(Resource):

    "Handle requests for logbooks"

    @use_args({"parent": Integer()})
    @marshal_with(fields.logbook, envelope="logbook")
    def get(self, args, logbook_id=None, revision_n=None):

        "Fetch a given logbook"

        if logbook_id:
            logbook = Logbook.get(Logbook.id == logbook_id)
            if revision_n is not None:
                return logbook.get_revision(revision_n)
            return logbook

        # Get either the direct children of a given parent, or else the
        # global list of top-level (no parent) logbooks
        parent_id = args.get("parent")
        if parent_id:
            return Logbook.get(Logbook.id == parent_id)
        children = (Logbook.select().where(Logbook.parent == None))
        return dict(children=children)

    @send_signal(new_logbook)
    @use_args(logbook_args)
    @marshal_with(fields.logbook, envelope="logbook")
    def post(self, args, logbook_id=None):

        "Create a new logbook"

        logbook = Logbook(name=args["name"],
                          parent=args.get("parent_id"),
                          description=args.get("description"),
                          template=args.get("template"),
                          attributes=args.get("attributes", []),
                          metadata=args.get("metadata", {}),
                          archived=args["archived"])
        if logbook_id:
            parent = Logbook.get(Logbook.id == logbook_id)
            logbook.parent = parent
        logbook.save()
        return logbook

    @send_signal(edit_logbook)
    @use_args(logbook_args)
    @marshal_with(fields.logbook, envelope="logbook")
    def put(self, args, logbook_id):

        "Update an existing logbook"

        logbook = Logbook.get(Logbook.id == logbook_id)
        logbook.make_change(**args).save()
        logbook.save()
        return logbook
Ejemplo n.º 3
0
        if not request.is_json:
            return make_resp(NO_JSON)
        try:
            project_schema.context["project_id"] = project.id
            project = project_schema.load(request.get_json(), instance=project)
            project.last_modified = datetime.datetime.utcnow()
            project_schema.context.pop("project_id")
        except ValidationError as errors:
            return errors.messages, 422
        db.session.commit()
        return jsonify(data=project_schema.dump(project)), 200
    elif request.method == "DELETE":
        if project.user != get_user():
            return make_resp(FORBIDDEN)
        db.session.delete(project)
        db.session.commit()
        return make_resp(({"msg": "success"}, 200))


@projects_bp.route("/uniquity-check/project-name/", methods=["GET"])
@use_args(
    {
        "name": String(required=True),
        "project_id": Integer(required=False)
    },
    locations=("querystring", ))
def project_name_check(args) -> Tuple[Any, int]:
    return jsonify(taken=Project.query.filter(
        Project.name == args.get("name", "").lower(),
        Project.id != args.get("project_id", 0)).first() is not None), 200
Ejemplo n.º 4
0
            user = user_schema.load(request.get_json(), instance=user)
            user_schema.context.pop("user_id")
        except ValidationError as errors:
            return errors.messages, 422
        db.session.commit()
        return jsonify(data=user_schema.dump(user)), 200
    elif request.method == "DELETE":
        if user != get_user():
            return make_resp(FORBIDDEN)
        db.session.delete(user)
        db.session.commit()
        return make_resp(({"msg": "success"}, 200))


@users_bp.route("/uniquity-check/username/", methods=["GET"])
@use_args({"username": String(required=True), "user_id": Integer(required=False)}, locations=("querystring",))
def username_check(args) -> Tuple[Any, int]:
    return jsonify(
        taken=User.query.filter(
            User.username == args.get("username", "").lower(),
            User.id != args.get("user_id", 0)
        ).first() is not None), 200


@users_bp.route("/uniquity-check/email/", methods=["GET"])
@use_args({"email": String(required=True), "user_id": Integer(required=False)}, locations=("querystring",))
def email_check(args) -> Tuple[Any, int]:
    return jsonify(
        taken=User.query.filter(
            User.email == args.get("email", "").lower(),
            User.id != args.get("user_id", 0)
Ejemplo n.º 5
0
from flask import request, send_file
from flask_restful import Resource, marshal, marshal_with, abort
from webargs.fields import (Integer, Str, Boolean, Dict, List, Nested, Email,
                            LocalDateTime)
from webargs.flaskparser import use_args

from ..db import Entry, Logbook, EntryLock
from ..attachments import handle_img_tags
from ..export import export_entries_as_pdf
from ..actions import new_entry, edit_entry
from . import fields, send_signal

entry_args = {
    "id":
    Integer(allow_none=True),
    "logbook_id":
    Integer(allow_none=True),
    "title":
    Str(allow_none=True),
    "content":
    Str(),
    "content_type":
    Str(missing="text/html"),
    "authors":
    List(Nested({
        "name": Str(),
        "login": Str(allow_none=True),
        "email": Email(allow_none=True)
    }),
         validate=lambda a: len(a) > 0),
Ejemplo n.º 6
0
class TextsRes(Resource):
    POST_MAX_N_TAGS = 16

    POST_ARGS = {
        'tags': DelimitedList(Str()),
        'content': Str(),
    }

    TAGS_BLACKLIST = {}

    GET_MAX_N_RESULTS = 1000

    GET_ARGS = {
        'any_tags': DelimitedList(Str()),
        'all_tags': DelimitedList(Str()),
        'no_tags': DelimitedList(Str()),
        'date_from': Date(),
        'date_to': Date(),
        'max_n_results': \
            Integer(validate=lambda n: n >= 0, missing=GET_MAX_N_RESULTS),
        'offset': \
            Integer(validate=lambda n: n >= 0, missing=0),
        'fields': DelimitedList(Str()),
    }

    @staticmethod
    def parse_post_args(req):
        args = parser.parse(TextsRes.POST_ARGS, req)
        if 'tags' in args:
            if len(args['tags']) > TextsRes.POST_MAX_N_TAGS:
                raise ValidationError('too many tags (limit={})'.format(
                    TextsRes.POST_MAX_N_TAGS))
            for tag in args['tags']:
                if tag in TextsRes.TAGS_BLACKLIST:
                    raise ValidationError('"{}" is blacklisted'.format(tag))
            args['tags'] = serialize_tags(get_tags(args['tags']))
        return args

    @staticmethod
    def filter_texts(args):
        #sorting in decreasing order by creation time
        query = Text.query.order_by(-Text.created_at)
        if 'date_to' in args:
            query = query.filter(func.DATE(Text.created_at) <= args['date_to'])
        if 'date_from' in args:
            query = query.filter(
                func.DATE(Text.created_at) >= args['date_from'])
        if 'all_tags' in args:
            tags = Tag.query.filter(Tag.content.in_(args['all_tags'])).all()
            if len(tags) < len(args['all_tags']):
                return [], None
            #dirty hack TODO: get a better solution
            for t in tags:
                query = query.filter(Text.tags.contains(t))
        elif 'any_tags' in args:
            query = query.join(Tag, Text.tags).join(
                Tag.query.join(Text, Tag.texts).filter(
                    Tag.content.in_(args['any_tags'])))
        if 'no_tags' in args:
            tags = Tag.query.filter(Tag.content.in_(args['no_tags'])).all()
            #new dirty hack TODO: get a better solution
            for t in tags:
                query = query.filter(~Text.tags.contains(t))

        query = query.offset(args['offset'])
        if query.count() <= args['max_n_results']:
            offset = None
        else:
            offset = args['offset'] + args['max_n_results']
        texts = query.limit(args['max_n_results']).all()

        return texts, offset

    @staticmethod
    def parse_get_args(req):
        args = parser.parse(TextsRes.GET_ARGS,
                            req,
                            locations=('querystring', ))
        return args

    @jwt_required
    def post(self):
        """
        Create new text resource.

        .. :quickref: Text creation; Create new text.

        **Example request**:

        .. sourcecode:: http

	    POST /texts HTTP/1.1
	    Host: example.com
	    Accept: application/json
	    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhb

        **Example response**:

        .. sourcecode:: http

	    HTTP/1.1 201 CREATED
	    Content-Type: application/json

            {
                "text": {
                    "content": "Bom dia!",
                    "text_id": 1,
                    "tags": [
                        "bomdia"
                    ],
                    "updated_at": null,
                    "created_at": "2018-09-15T22:53:26+00:00"
                },
            }


        :reqheader Authorization: access token of logged in user (required)
        :form content: the text contents (required)
        :form tags: comma-separated list of tags
        :resheader Content-Type: application/json
        :status 201: resource created
        :returns: :class:`memedata.models.Text`
        """
        try:
            args = TextsRes.parse_post_args(request)
            text = TextSchema().load(args)
        except ValidationError as e:
            return mk_errors(400, fmt_validation_error_messages(e.messages))
        db.session.add(text)
        db.session.commit()
        return TextSchema().dump(text), 201

    @jwt_required
    def get(self):
        """
        Return collection of texts.

        .. :quickref: Get Texts; Get collection of texts.

        **Example request**:

        .. sourcecode:: http

	    GET /texts HTTP/1.1
	    Host: example.com
	    Accept: application/json
	    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhb

        **Example response**:

        .. sourcecode:: http

	    HTTP/1.1 200 OK
	    Content-Type: application/json

            {
                "texts": [
                    {
                        "content": "Bom dia!",
                        "text_id": 1,
                        "tags": [
                            "bomdia"
                        ],
                        "updated_at": null,
                        "created_at": "2018-09-15T22:53:26+00:00"
                    },
                    {
                        "content": "Eu adoro as manhãs",
                        "text_id": 32,
                        "tags": [
                            "jesus",
                            "sexta"
                        ],
                        "updated_at": null,
                        "created_at": "2018-09-15T22:53:26+00:00"
                    },
                ],
                "offset": 2
            }


        :reqheader Authorization: access token of logged in user (required)
        :query string fields: comma-separated list of fields to get for each \
            text.
        :query string date_from: only texts created after specified date \
            (inclusive).
        :query string date_to: only texts created before specified date.
        :query string any_tags: texts with at least one tags in specified list.
        :query string all_tags: texts only containing all specified tags.
        :query string no_tags: texts only not containing any of specified tags.
        :query int offset: pagination offset to start getting results
        :query int max_n_results: maximum number of results to return.
        :resheader Content-Type: application/json
        :status 200: texts found
        :returns: :class:`memedata.models.Text`
        """
        try:
            args = TextsRes.parse_get_args(request)
        except ValidationError as e:
            return mk_errors(400, fmt_validation_error_messages(e.messages))
        texts, offset = TextsRes.filter_texts(args)
        objs = TextSchema(many=True).dump(texts)
        objs = filter_fields(objs, args.get('fields'))
        objs['offset'] = offset
        return objs
Ejemplo n.º 7
0
from flask_restful import Resource, marshal_with
from webargs.fields import Integer, Str, Boolean, Dict, List, Nested
from webargs.flaskparser import use_args

from ..db import Logbook
from ..actions import new_logbook, edit_logbook
from . import fields, send_signal


logbook_args = {
    "parent_id": Integer(allow_none=True),
    "name": Str(),
    "description": Str(allow_none=True),
    "template": Str(allow_none=True),
    "attributes": List(Nested({
        "name": Str(),
        "type": Str(
            validate=lambda t: t in ["text",
                                     "number",
                                     "boolean",
                                     "option",
                                     "multioption"]),
        "required": Boolean(),
        "options": List(Str(), missing=None)
    })),
    "metadata": Dict(),
    "archived": Boolean(missing=False)
}


class LogbooksResource(Resource):
Ejemplo n.º 8
0
from flask import request, send_file
from flask_restful import Resource, marshal, marshal_with, abort
from webargs.fields import (Integer, Str, Boolean, Dict, List,
                            Nested, Email, LocalDateTime)
from webargs.flaskparser import use_args

from ..db import Entry, Logbook, EntryLock
from ..attachments import handle_img_tags
from ..export import export_entries_as_pdf
from ..actions import new_entry, edit_entry
from . import fields, send_signal


entry_args = {
    "id": Integer(allow_none=True),
    "logbook_id": Integer(allow_none=True),
    "title": Str(allow_none=True),
    "content": Str(),
    "content_type": Str(missing="text/html"),
    "authors": List(Nested({
        "name": Str(),
        "login": Str(allow_none=True),
        "email": Email(allow_none=True)
    }), validate=lambda a: len(a) > 0),
    "created_at": LocalDateTime(),
    "last_changed_at": LocalDateTime(allow_none=True),
    "follows_id": Integer(allow_none=True),
    "attributes": Dict(),
    "archived": Boolean(),
    "metadata": Dict(),
Ejemplo n.º 9
0
from flask_restful import Resource, marshal_with
from webargs.fields import Integer, Str, Boolean, Dict, List, Nested
from webargs.flaskparser import use_args

from ..db import Logbook
from ..actions import new_logbook, edit_logbook
from . import fields, send_signal

logbook_args = {
    "parent_id":
    Integer(allow_none=True),
    "name":
    Str(),
    "description":
    Str(allow_none=True),
    "template":
    Str(allow_none=True),
    "attributes":
    List(
        Nested({
            "name":
            Str(),
            "type":
            Str(validate=lambda t: t in
                ["text", "number", "boolean", "option", "multioption"]),
            "required":
            Boolean(),
            "options":
            List(Str())
        })),
    "metadata":