예제 #1
0
def parseQuery(context, request):
    """parse query"""
    reg = getUtility(IRegistry)
    conditions = []
    form = request.form or {}
    body_form = json_body(request).get("form") or {}
    data_query = json_body(request).get("data_query") or []
    # Update form with body form
    form.update(body_form)
    # Compute data_query from form
    form_data_query = getDataQuery(form)
    # Merge queries
    _data_query = mergeLists(data_query, form_data_query)
    # Parse sql query
    db_version = form.get("db_version") or "latest"
    sql_parsed = getParsedSQLQuery(context, db_version)
    # Get context properties
    parameters = getParameters(context.parameters)
    required_parameters = context.required_parameters
    collate = context.collate
    # Get indexes
    __data_query = []
    __indexes = []

    for row in _data_query:
        _index = row.get("i")
        if not parameters:
            break
        if _index not in parameters:
            continue
        __data_query.append(row)
        __indexes.append(_index)

    # Check if required parameters exists in data_query
    if not hasRequiredParameters(required_parameters, __indexes):
        return None

    for row in __data_query:
        operator = row.get("o", None)
        index = row.get("i", None)
        value = row.get("v", None)
        table = parameters.get(index) if parameters else None
        function_path = operator
        if "eea.api.dataconnector.queryparser" not in operator:
            function_path = reg["%s.operation" % operator].replace(
                "plone.app.querystring", "eea.api.dataconnector")
        row = Row(index=index, values=value, table=table, collate=collate)
        parser = resolve(function_path)
        condition = parser(row)
        if condition:
            if isinstance(condition, list):
                condition = {"and": condition}
            conditions.append(condition)

    return {
        "query": sql_parsed,
        "conditions": conditions,
        "form": form,
        "data_query": _data_query,
    }
예제 #2
0
    def __init__(self, request, results):
        self.request = request

        self.b_start = int(json_body(self.request).get(
            "b_start", False)) or int(self.request.form.get("b_start", 0))
        self.b_size = int(json_body(self.request).get("b_size", False)) or int(
            self.request.form.get("b_size", DEFAULT_BATCH_SIZE))

        self.batch = Batch(results, self.b_size, self.b_start)
예제 #3
0
    def __init__(self, request, results):
        self.request = request

        self.b_start = int(
            json_body(self.request).get("b_start", False)
        ) or int(self.request.form.get("b_start", 0))
        self.b_size = int(json_body(self.request).get("b_size", False)) or int(
            self.request.form.get("b_size", DEFAULT_BATCH_SIZE)
        )

        self.hits = getattr(results, "hits", 0)
예제 #4
0
def computeDataQuery(request):
    """compute data_query"""
    form = request.form or {}
    body_form = json_body(request).get("form") or {}
    data_query = json_body(request).get("data_query") or []
    # Update form with body form
    form.update(body_form)
    # Compute data_query from form
    form_data_query = getDataQuery(form)
    # Merge queries
    _data_query = mergeLists(data_query, form_data_query)
    return _data_query
예제 #5
0
    def reply(self):
        if self.transition is None:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='BadRequest',
                message='Missing transition'))

        data = json_body(self.request)
        if data.keys() not in [[], ['comment']]:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='BadRequest',
                message='Invalid body'))

        wftool = getToolByName(self.context, 'portal_workflow')

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        try:
            wftool.doActionFor(self.context, self.transition, **data)
        except WorkflowException as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='WorkflowException',
                message=translate(e.message, context=self.request)))

        history = wftool.getInfoFor(self.context, "review_history")
        return json_compatible(history[-1])
예제 #6
0
    def reply(self):
        data = json_body(self.request)
        category = data.get('category', DEFAULT_COMMENT_CATEGORY)
        comment = data.get('comment')

        if not comment:
            raise BadRequest("The request body requires the 'comment' attribute")

        if not self._validate_category(category):
            raise BadRequest("The provided 'category' does not exists.")

        documents, invalid_urls = self._lookup_documents(
            data.get('related_documents', []))

        if invalid_urls:
            raise BadRequest(
                "Could not lookup the following documents: {}".format(
                    ', '.join(invalid_urls)))

        contacts = []
        users = []

        entry = ManualJournalEntry(self.context,
                                   category,
                                   comment,
                                   contacts,
                                   users,
                                   documents)
        entry.save()

        self.request.response.setStatus(204)
        return super(JournalPost, self).reply()
예제 #7
0
 def reply(self):
     data = json_body(self.request)
     result = []
     for element in data["data"]:
         self.request.set("BODY", json.dumps(element))
         result.extend(super(ImportPost, self).reply())
     return {"data": result}
예제 #8
0
    def reply(self):
        data = json_body(self.request)
        option_type = data.get('option_type')

        if not option_type:
            raise BadRequest(error_msgs.get('missing_option_type'))

        reminder_option = TASK_REMINDER_OPTIONS.get(option_type)

        if not reminder_option:
            raise BadRequest(error_msgs.get('non_existing_option_type'))

        # Disable CSRF protection
        alsoProvides(self.request, IDisableCSRFProtection)

        task_reminder = TaskReminder()

        if task_reminder.get_reminder(self.context):
            self.request.response.setStatus(409)
            return super(TaskReminderPost, self).reply()

        task_reminder.set_reminder(self.context, reminder_option)
        self.context.sync()

        self.request.response.setStatus(204)
        return super(TaskReminderPost, self).reply()
예제 #9
0
    def __call__(self):
        data = json_body(self.request)
        sharing_view = getMultiAdapter((self.context, self.request),
                                       name="sharing")

        # inherit roles
        inherit_reindex = False
        # block can be None, so we might get False or None, so we test
        # for a marker.
        inherit = data.get("inherit", marker)
        if inherit is not marker:
            inherit_reindex = sharing_view.update_inherit(status=inherit,
                                                          reindex=False)
        # roles
        roles_reindex = False
        new_roles = data.get("entries", None)
        if new_roles is not None:
            # the roles are converted into a FrozenSet so we have to filter
            # the data structure we get.
            for user in new_roles:
                roles_list = [
                    key for key in user["roles"] if user["roles"][key]
                ]
                user["roles"] = roles_list
            roles_reindex = sharing_view.update_role_settings(new_roles,
                                                              reindex=False)

        # reindex object security
        can_reindex = ICatalogAware(
            self.context, None) or IPloneSiteRoot.providedBy(self.context)
        if can_reindex and (inherit_reindex or roles_reindex):
            self.context.reindexObjectSecurity()
            if LOCALROLES_MODIFIED_EVENT_AVAILABLE:
                notify(LocalrolesModifiedEvent(self.context, self.request))
예제 #10
0
    def reply(self):
        data = json_body(self.request)

        sender_from_address = data.get('from', None)
        message = data.get('message', None)
        sender_fullname = data.get('name', '')
        subject = data.get('subject', '')

        if not sender_from_address or not message:
            raise BadRequest('Missing from or message parameters')

        overview_controlpanel = getMultiAdapter((self.context, self.request),
                                                name='overview-controlpanel')
        if overview_controlpanel.mailhost_warning():
            raise BadRequest('MailHost is not configured.')

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        contact_info_view = getMultiAdapter((self.context, self.request),
                                            name='contact-info')

        contact_info_view.send_message(
            dict(message=message,
                 subject=subject,
                 sender_from_address=sender_from_address,
                 sender_fullname=sender_fullname))

        self.request.response.setStatus(204)
        return
예제 #11
0
파일: pam.py 프로젝트: eea/plone.restapi
    def reply(self):
        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        data = json_body(self.request)
        id_ = data.get("id", None)
        if id_ is None:
            self.request.response.setStatus(400)
            return dict(error=dict(type="BadRequest",
                                   message="Missing content id to link to"))

        target = self.get_object(id_)
        if target is None:
            self.request.response.setStatus(400)
            return dict(error=dict(type="BadRequest",
                                   message="Content does not exist"))

        target_language = ILanguage(target).get_language()
        manager = ITranslationManager(self.context)
        current_translation = manager.get_translation(target_language)
        if current_translation is not None:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type="BadRequest",
                message="Already translated into language {}".format(
                    target_language),
            ))

        manager.register_translation(target_language, target)
        self.request.response.setStatus(201)
        self.request.response.setHeader("Location",
                                        self.context.absolute_url())
        return {}
예제 #12
0
    def reply(self):
        alsoProvides(self.request, IDisableCSRFProtection)
        form_data = json_body(self.request)
        self.validate_form(form_data=form_data)

        tool = getUtility(self.store)
        try:
            res = tool.add(form_data)
        except ValueError as e:
            self.request.response.setStatus(500)
            return dict(
                error=dict(
                    type="InternalServerError",
                    message=getattr(e, "message", e.__str__()),
                )
            )

        if res:
            return self.reply_no_content()

        self.request.response.setStatus(500)
        return dict(
            error=dict(
                type="InternalServerError",
                message="Unable to add. Contact site manager.",
            )
        )
예제 #13
0
    def reply(self):
        data = json_body(self.request)
        group = self._get_group(self._get_group_id)

        if not group:
            raise BadRequest('Trying to update a non-existing group.')

        title = data.get('title', None)
        description = data.get('description', None)
        roles = data.get('roles', None)
        groups = data.get('groups', None)

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        portal_groups = getToolByName(self.context, 'portal_groups')

        portal_groups.editGroup(self._get_group_id,
                                roles=roles,
                                groups=groups,
                                title=title,
                                description=description)

        properties = {}
        for id, property in group.propertyItems():
            if data.get(id, False):
                properties[id] = data[id]

        group.setGroupProperties(properties)

        self.request.response.setStatus(204)
        return None
예제 #14
0
    def reply(self):
        if self.transition is None:
            self.request.response.setStatus(400)
            return dict(
                error=dict(type='BadRequest', message='Missing transition'))

        data = json_body(self.request)
        if data.keys() not in [[], ['comment']]:
            self.request.response.setStatus(400)
            return dict(error=dict(type='BadRequest', message='Invalid body'))

        wftool = getToolByName(self.context, 'portal_workflow')

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        try:
            wftool.doActionFor(self.context, self.transition, **data)
        except WorkflowException as e:
            self.request.response.setStatus(400)
            return dict(
                error=dict(type='WorkflowException',
                           message=translate(e.message, context=self.request)))

        history = wftool.getInfoFor(self.context, "review_history")
        action = history[-1]
        action['title'] = self.context.translate(
            wftool.getTitleForStateOnType(action['review_state'],
                                          self.context.portal_type))

        return json_compatible(action)
예제 #15
0
 def parse_query(self):
     data = json_body(self.request)
     if "file" not in data:
         raise BadRequest(
             _("missing_file",
               default=u"You need to pass a file at least."))
     return data
예제 #16
0
    def reply(self):
        data = json_body(self.request)
        option_type = data.get('option_type')
        params = data.get('params')

        if not option_type:
            raise BadRequest(error_msgs.get('missing_option_type'))

        if option_type not in REMINDER_TYPE_REGISTRY:
            raise BadRequest(error_msgs.get('non_existing_option_type'))

        reminder_data = {'option_type': option_type, 'params': params}

        try:
            reminder = Reminder.deserialize(reminder_data)
        except (ValidationError, ValueError) as exc:
            raise BadRequest(repr(exc))

        # Disable CSRF protection
        alsoProvides(self.request, IDisableCSRFProtection)

        if self.context.get_reminder():
            self.request.response.setStatus(409)
            return _no_content_marker

        self.context.set_reminder(reminder)
        self.context.sync()

        self.request.response.setStatus(204)
        return _no_content_marker
예제 #17
0
    def reply(self):
        data = json_body(self.request)

        option_type = data.get('option_type')
        params = data.get('params')

        if option_type and option_type not in REMINDER_TYPE_REGISTRY:
            raise BadRequest(error_msgs.get('non_existing_option_type'))

        # Disable CSRF protection
        alsoProvides(self.request, IDisableCSRFProtection)

        if option_type or params:
            existing_reminder = self.context.get_reminder()
            if not existing_reminder:
                raise NotFound

            # Pick existing settings if not given (PATCH semantics)
            option_type = option_type or existing_reminder.option_type
            params = params if 'params' in data else existing_reminder.params

            reminder_data = {'option_type': option_type, 'params': params}
            try:
                reminder = Reminder.deserialize(reminder_data)
            except (ValidationError, ValueError) as exc:
                raise BadRequest(repr(exc))

            self.context.set_reminder(reminder)
            self.context.sync()

        self.request.response.setStatus(204)
        return _no_content_marker
예제 #18
0
    def update(self, action):
        action_delta = json_body(self.request)

        # Reject any fields that aren't user-controlled or unknown
        errors = get_unknown_fields(action_delta, IWebActionSchema)
        if errors:
            raise BadRequest(errors)

        scrub_json_payload(action_delta)

        # Validate on a copy
        action_copy = action.copy()
        action_copy.update(action_delta)
        errors = get_validation_errors(action_copy, IPersistedWebActionSchema)
        if errors:
            raise BadRequest(errors)

        # If validation succeeded, update actual action
        storage = get_storage()

        try:
            storage.update(action['action_id'], action_delta)
        except ActionAlreadyExists as exc:
            raise BadRequest([('unique_name', exc)])

        self.request.response.setStatus(204)
        return _no_content_marker
예제 #19
0
파일: post.py 프로젝트: plone/plone.restapi
    def reply(self):
        data = json_body(self.request)

        sender_from_address = data.get("from", None)
        message = data.get("message", None)
        sender_fullname = data.get("name", "")
        subject = data.get("subject", "")

        if not sender_from_address or not message:
            raise BadRequest("Missing from or message parameters")

        overview_controlpanel = getMultiAdapter((self.context, self.request),
                                                name="overview-controlpanel")
        if overview_controlpanel.mailhost_warning():
            raise BadRequest("MailHost is not configured.")

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        contact_info_view = getMultiAdapter((self.context, self.request),
                                            name="contact-info")

        contact_info_view.send_message(
            dict(
                message=message,
                subject=subject,
                sender_from_address=sender_from_address,
                sender_fullname=sender_fullname,
            ))

        return self.reply_no_content()
예제 #20
0
 def show_all_metadata_fields(self):
     query = self.request.form
     if not query:
         # maybe its a POST request
         query = json_body(self.request)
     metadata_fields = query.get("metadata_fields", [])
     return "_all" in metadata_fields or self.force_all_metadata
예제 #21
0
    def reply(self):
        data = json_body(self.request)
        category = data.get('category', DEFAULT_COMMENT_CATEGORY)
        comment = data.get('comment')

        if not comment:
            raise BadRequest(
                "The request body requires the 'comment' attribute")

        if not self._validate_category(category):
            raise BadRequest("The provided 'category' does not exists.")

        documents, invalid_urls = self._lookup_documents(
            data.get('related_documents', []))

        if invalid_urls:
            raise BadRequest(
                "Could not lookup the following documents: {}".format(
                    ', '.join(invalid_urls)))

        contacts = []
        users = []

        entry = ManualJournalEntry(self.context, category, comment, contacts,
                                   users, documents)
        entry.save()

        self.request.response.setStatus(204)
        return super(JournalPost, self).reply()
예제 #22
0
    def reply(self):
        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        data = json_body(self.request)
        manager = ITranslationManager(self.context)
        language = data.get('language', None)
        if language is None:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='BadRequest',
                message='You need to provide the language to unlink'))

        if language not in manager.get_translations().keys():
            self.request.response.setStatus(400)
            return dict(
                error=dict(type='BadRequest',
                           message='This objects is not translated into {}'.
                           format(language)))

        manager.remove_translation(language)
        self.request.response.setStatus(204)
        return {}
예제 #23
0
 def reply(self):
     data = json_body(self.request)
     result = []
     for element in data["data"]:
         self.request.set("BODY", json.dumps(element))
         result.extend(super(BulkFolderPost, self).create_content())
     return {"data": result}
예제 #24
0
    def __call__(self, validate_all=False, data=None, create=False):
        if data is None:
            data = json_body(self.request)

        context = super(DeserializeMailFromJson,
                        self).__call__(validate_all=validate_all,
                                       data=data,
                                       create=create)

        if context.message and context.message.filename.lower().endswith(
                '.msg'):
            self.context.original_message = context.message
            transform = Msg2MimeTransform()
            eml = transform.transform(context.message.data)
            file_ = NamedBlobFile(data=eml,
                                  filename=context.message.filename[:-3] +
                                  'eml',
                                  contentType='message/rfc822')
            context.message = file_

        if create and 'message' in data:
            if not data.get('title'):
                context._update_title_from_message_subject()
                initalize_title(context, None)

            initialize_metadata(context, None)

        return context
예제 #25
0
파일: pam.py 프로젝트: eea/plone.restapi
    def reply(self):
        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        data = json_body(self.request)
        manager = ITranslationManager(self.context)
        language = data.get("language", None)
        if language is None:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type="BadRequest",
                message="You need to provide the language to unlink",
            ))

        if language not in list(manager.get_translations()):
            self.request.response.setStatus(400)
            return dict(error=dict(
                type="BadRequest",
                message="This objects is not translated into {}".format(
                    language),
            ))

        manager.remove_translation(language)
        return self.reply_no_content()
예제 #26
0
 def generate_query_for_events(self):
     data = json_body(self.request)
     parsed_query = queryparser.parseFormquery(context=self.context,
                                               formquery=data["query"])
     fullobjects = data.get("fullobjects", False)
     b_size = data.get("b_size", None)
     b_start = data.get("b_start", 0)
     query = {
         k: v
         for k, v in parsed_query.items() if k not in ["start", "end"]
     }
     limit = int(data.get("limit", 1000))
     sort = "start"
     sort_reverse = False
     start, end = self.parse_event_dates(parsed_query)
     if data.get("sort_on", ""):
         sort = data["sort_on"]
     if data.get("sort_order", ""):
         sort_reverse = data["sort_order"] == "descending" and True or False
     return (
         start,
         end,
         fullobjects,
         b_size,
         b_start,
         query,
         sort_reverse,
         sort,
         limit,
     )
예제 #27
0
    def reply(self):
        if not self.comment_id:
            raise BadRequest("Comment id is a required part of the url")

        conversation = IConversation(self.context)
        if self.comment_id not in list(conversation):
            self.request.response.setStatus(404)
            return
        comment = conversation[self.comment_id]

        # Permission checks
        if not (edit_comment_allowed() and can_edit(comment)):
            raise Unauthorized()

        # Fake request data
        body = json_body(self.request)
        for key, value in body.items():
            self.request.form["form.widgets." + key] = value

        form = EditCommentForm(comment, self.request)
        form.__parent__ = form.context.__parent__.__parent__
        form.update()

        action = form.actions["comment"]
        data, errors = form.extractData()
        if errors:
            raise BadRequest({"errors": [err.error for err in errors]})

        comment.modification_date = datetime.utcnow()
        form.handleComment(form=form, action=action)

        fix_location_header(self.context, self.request)
        return self.reply_no_content()
예제 #28
0
    def reply(self):
        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        conversation = IConversation(self.context)
        if self.comment_id and self.comment_id not in list(conversation):
            self.request.response.setStatus(404)
            return

        # Fake request data
        body = json_body(self.request)
        for key, value in body.items():
            self.request.form["form.widgets." + key] = value

        form = CommentForm(self.context, self.request)
        form.update()

        action = form.actions["comment"]
        data, errors = form.extractData()
        if errors:
            raise BadRequest({"errors": [err.error for err in errors]})

        form.handleComment(form=form, action=action)

        fix_location_header(self.context, self.request)
        return self.reply_no_content()
예제 #29
0
    def reply(self):
        portal = getSite()
        data = json_body(self.request)

        groupname = data.get("groupname", None)

        if not groupname:
            raise BadRequest("Property 'groupname' is required")

        email = data.get("email", None)
        title = data.get("title", None)
        description = data.get("description", None)
        roles = data.get("roles", None)
        groups = data.get("groups", None)
        users = data.get("users", [])

        properties = {
            "title": title,
            "description": description,
            "email": email
        }

        gtool = getToolByName(self.context, "portal_groups")
        regtool = getToolByName(self.context, "portal_registration")

        if not regtool.isMemberIdAllowed(groupname):
            raise BadRequest("The group name you entered is not valid.")

        already_exists = gtool.getGroupById(groupname)
        if already_exists:
            raise BadRequest("The group name you entered already exists.")

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        success = gtool.addGroup(
            groupname,
            roles,
            groups,
            properties=properties,
            title=title,
            description=description,
        )
        if not success:
            raise BadRequest(
                f"Error occurred, could not add group {groupname}.")

        # Add members
        group = gtool.getGroupById(groupname)
        for userid in users:
            group.addMember(userid)

        self.request.response.setStatus(201)
        self.request.response.setHeader(
            "Location",
            portal.absolute_url() + "/@groups/" + groupname)
        serializer = queryMultiAdapter((group, self.request), ISerializeToJson)
        return serializer()
예제 #30
0
    def render(self):
        data = json_body(self.request)

        type_ = data.get('@type', None)
        id_ = data.get('id', None)
        title = data.get('title', None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        # Generate a temporary id if the id is not given
        if not id_:
            now = DateTime()
            new_id = '{}.{}.{}{:04d}'.format(type_.lower().replace(' ', '_'),
                                             now.strftime('%Y-%m-%d'),
                                             str(now.millis())[7:],
                                             randint(0, 9999))
        else:
            new_id = id_

        # Create object
        try:
            new_id = self.context.invokeFactory(type_, new_id, title=title)
        except BadRequest as e:
            self.request.response.setStatus(400)
            return dict(error=dict(type='DeserializationError',
                                   message=str(e.message)))
        except ValueError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(type='DeserializationError',
                                   message=str(e.message)))

        # Update fields
        obj = self.context[new_id]
        deserializer = queryMultiAdapter((obj, self.request),
                                         IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(error=dict(
                message='Cannot deserialize type {}'.format(obj.portal_type)))

        try:
            deserializer(validate_all=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(
                error=dict(type='DeserializationError', message=str(e)))

        # Rename if generated id
        if not id_:
            self.rename_object(obj)

        self.request.response.setStatus(201)
        self.request.response.setHeader('Location', obj.absolute_url())
        return None
예제 #31
0
파일: add.py 프로젝트: eea/plone.restapi
    def reply(self):
        if not self.params:
            raise BadRequest("Missing parameter typename")

        data = json_body(self.request)

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        # Make sure we get the right dexterity-types adapter
        if IPloneRestapiLayer.providedBy(self.request):
            noLongerProvides(self.request, IPloneRestapiLayer)

        name = self.params.pop()
        context = queryMultiAdapter((self.context, self.request),
                                    name="dexterity-types")
        context = context.publishTraverse(self.request, name)

        factory = data.get("factory", None)
        if not factory:
            raise BadRequest("Missing parameter: 'factory'")

        if factory == "fieldset":
            res = add_fieldset(context, self.request, data)
        else:
            res = add_field(context, self.request, data)

        self.request.response.setStatus(201)
        return res
예제 #32
0
    def update(self, action):
        action_delta = json_body(self.request)

        # Reject any fields that aren't user-controlled or unknown
        errors = get_unknown_fields(action_delta, IWebActionSchema)
        if errors:
            raise BadRequest(errors)

        scrub_json_payload(action_delta)

        # Validate on a copy
        action_copy = action.copy()
        action_copy.update(action_delta)
        errors = get_validation_errors(action_copy, IPersistedWebActionSchema)
        if errors:
            raise BadRequest(errors)

        # If validation succeeded, update actual action
        storage = get_storage()

        try:
            storage.update(action['action_id'], action_delta)
        except ActionAlreadyExists as exc:
            raise BadRequest([('unique_name', exc)])

        self.request.response.setStatus(204)
        return _no_content_marker
예제 #33
0
    def __call__(self, validate_all=False, data=None):
        if data is None:
            data = json_body(self.request)

        if 'message' in data:
            field = IMail['message']
            deserializer = queryMultiAdapter(
                (field, self.context, self.request), IFieldDeserializer)
            message = deserializer(data['message'])

            if message and message.filename.lower().endswith('.msg'):
                self.context.original_message = message
                transform = Msg2MimeTransform()
                eml = transform.transform(message.data)
                data['message'] = {
                    'data': eml,
                    'content-type': 'message/rfc822',
                    'filename': message.filename[:-3] + 'eml',
                }

        context = super(DeserializeMailFromJson, self).__call__(
            validate_all=validate_all, data=data)

        context._update_title_from_message_subject()
        initialize_metadata(context, None)
        initalize_title(context, None)
        return context
예제 #34
0
    def reply(self):
        data = json_body(self.request)
        query = data.get("query", None)
        b_start = int(data.get("b_start", 0))
        b_size = int(data.get("b_size", 25))
        sort_on = data.get("sort_on", None)
        sort_order = data.get("sort_order", None)
        limit = int(data.get("limit", 1000))
        fullobjects = data.get("fullobjects", False)

        if query is None:
            raise Exception("No query supplied")

        if sort_order:
            sort_order = "descending" if sort_order else "ascending"

        querybuilder = getMultiAdapter(
            (self.context, self.request), name="querybuilderresults"
        )
        results = querybuilder(
            query=query,
            brains=True,
            b_start=b_start,
            b_size=b_size,
            sort_on=sort_on,
            sort_order=sort_order,
            limit=limit,
        )

        results = getMultiAdapter((results, self.request), ISerializeToJson)(
            fullobjects=fullobjects
        )
        return results
예제 #35
0
    def reactivate_dossier(self, objs, comment, publication_dates,
                           include_children=False):
        # Reject explicit attempts to non-recursively reactivate a dossier
        if not json_body(self.request).get('include_children', True):
            raise BadRequest('Reactivating dossier must always be recursive')

        reactivator = Reactivator(self.context)
        reactivator.reactivate()
예제 #36
0
    def reply(self):
        # return 401/403 Forbidden if the user has no permission
        if not checkPermission('cmf.AddPortalContent', self.context):
            pm = getToolByName(self.context, 'portal_membership')
            if bool(pm.isAnonymousUser()):
                self.request.response.setStatus(401)
            else:
                self.request.response.setStatus(403)
            return

        data = json_body(self.request)

        source = data.get('source', None)

        if not source:
            raise BadRequest("Property 'source' is required")

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        if not isinstance(source, list):
            source = [source]

        parents_ids = {}
        for item in source:
            obj = self.get_object(item)
            if obj is not None:
                # -- Commented out the following block to disable checking for
                # -- delete permission, as in GEVER the user is not allowed to
                # -- delete content.
                # if self.is_moving:
                #     # To be able to safely move the object, the user requires
                #     # permissions on the parent
                #     if not checkPermission('zope2.DeleteObjects', obj) and \
                #        not checkPermission(
                #             'zope2.DeleteObjects', aq_parent(obj)):
                #         self.request.response.setStatus(403)
                #         return
                parent = aq_parent(obj)
                if parent in parents_ids:
                    parents_ids[parent].append(obj.getId())
                else:
                    parents_ids[parent] = [obj.getId()]

        results = []
        for parent, ids in parents_ids.items():
            result = self.context.manage_pasteObjects(
                cb_copy_data=self.clipboard(parent, ids))
            for res in result:
                results.append({
                    'source': '{}/{}'.format(
                        parent.absolute_url(), res['id']),
                    'target': '{}/{}'.format(
                        self.context.absolute_url(), res['new_id']),
                })
        return results
예제 #37
0
        def __call__(self, validate_all=False, data=None, create=False):
            if data is None:
                data = json_body(self.request)

            # set default values
            if create:
                container = aq_parent(aq_inner(self.context))
                set_default_values(self.context, container, data)

            # super call
            return original___call__(self, validate_all, data, create)
예제 #38
0
    def reply(self):
        userid, notification_id = self.read_params()

        mark_as_read = json_body(self.request).get('read', False)

        if userid != api.user.get_current().getId():
            raise Unauthorized(
                "It's not allowed to access notifications of other users.")

        notification = self.get_notification(userid, notification_id)
        if mark_as_read:
            self.center.mark_notification_as_read(notification.notification_id)

        self.request.response.setStatus(204)
예제 #39
0
    def reply(self):

        # Only allow updating a documents file if the document is checked-out
        # by the current user.
        manager = getMultiAdapter((self.context, self.request),
                                  ICheckinCheckoutManager)
        if not manager.is_checked_out_by_current_user():
            data = json_body(self.request)
            if 'file' in data:
                self.request.response.setStatus(403)
                return dict(error=dict(
                    type='Forbidden',
                    message='Document not checked-out by current user.'))

        return super(DocumentPatch, self).reply()
예제 #40
0
    def reply(self):
        plugin = None
        acl_users = getToolByName(self, "acl_users")
        plugins = acl_users._getOb('plugins')
        authenticators = plugins.listPlugins(IAuthenticationPlugin)
        for id_, authenticator in authenticators:
            if authenticator.meta_type == "JWT Authentication Plugin":
                plugin = authenticator
                break

        if plugin is None:
            self.request.response.setStatus(501)
            return dict(error=dict(
                type='Login failed',
                message='JWT authentication plugin not installed.'))

        data = json_body(self.request)
        if 'login' not in data or 'password' not in data:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='Missing credentials',
                message='Login and password must be provided in body.'))

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        userid = data['login'].encode('utf8')
        password = data['password'].encode('utf8')
        uf = self._find_userfolder(userid)
        if uf is not None:
            user = uf.authenticate(
                userid, password, self.request)
        else:
            user = None

        if not user:
            self.request.response.setStatus(401)
            return dict(error=dict(
                type='Invalid credentials',
                message='Wrong login and/or password.'))

        payload = {}
        payload['fullname'] = user.getProperty('fullname')
        return {
            'token': plugin.create_token(user.getId(), data=payload)
        }
예제 #41
0
    def reply(self):
        userid = self.validate_user(self.get_userid())
        data = self.validate_data(json_body(self.request))
        obj = self.lookup_object(data)

        favorite = FavoriteManager().get_favorite(obj, api.user.get_current())
        if favorite:
            # favorite already exists
            self.request.response.setStatus(409)
            return favorite.serialize(api.portal.get().absolute_url())

        favorite = FavoriteManager().add(userid, obj)
        self.request.response.setStatus(201)
        url = favorite.api_url(api.portal.get().absolute_url())
        self.request.response.setHeader('Location', url)

        return favorite.serialize(api.portal.get().absolute_url())
예제 #42
0
    def resolve_dossier(self, objs, comment, publication_dates,
                        include_children=False):
        if self.is_already_resolved():
            # XXX: This should be prevented by the workflow tool.
            # For some reason it currently doesn't.
            raise BadRequest('Dossier has already been resolved.')

        # Reject explicit attempts to non-recursively resolve a dossier
        if not json_body(self.request).get('include_children', True):
            raise BadRequest('Resolving dossier must always be recursive')

        resolve_manager = LockingResolveManager(self.context)

        if resolve_manager.is_archive_form_needed():
            raise BadRequest(
                "Can't resolve dossiers via REST API if filing number "
                "feature is activated")

        resolve_manager.resolve()
예제 #43
0
    def __call__(self, validate_all=False):
        data = json_body(self.request)

        obj = self.context
        modified = False

        for field in obj.Schema().fields():
            if not field.writeable(obj):
                continue

            name = field.getName()

            if name in data:
                deserializer = queryMultiAdapter((field, obj, self.request),
                                                 IFieldDeserializer)
                if deserializer is None:
                    continue
                value, kwargs = deserializer(data[name])
                mutator = field.getMutator(obj, **kwargs)
                mutator(value)
                modified = True

        if modified:
            errors = obj.validate(data=True, metadata=True)
            if not validate_all:
                errors = {f: e for f, e in errors.items() if f in data}
            if errors:
                errors = [{
                    'message': e,
                    'field': f,
                    'error': 'ValidationError'} for f, e in errors.items()]
                raise BadRequest(errors)

            if obj.checkCreationFlag():
                obj.unmarkCreationFlag()
                notify(ObjectInitializedEvent(obj))
                obj.at_post_create_script()
            else:
                notify(ObjectEditedEvent(obj))
                obj.at_post_edit_script()

        return obj
예제 #44
0
    def reply(self):
        manager = getMultiAdapter((self.context, self.request),
                                  ICheckinCheckoutManager)

        if not manager.is_checkin_allowed():
            self.request.response.setStatus(403)
            return {'error': {
                'type': 'Forbidden',
                'message': 'Checkin is not allowed.',
            }}

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        data = json_body(self.request)
        comment = data.get('comment', '')

        manager.checkin(comment=comment)
        self.request.response.setStatus(204)
        return super(Checkin, self).reply()
예제 #45
0
    def reply(self):

        # Disable CSRF protection
        alsoProvides(self.request, IDisableCSRFProtection)

        action_data = json_body(self.request)
        scrub_json_payload(action_data)

        errors = get_validation_errors(action_data, IWebActionSchema)
        if errors:
            raise BadRequest(errors)

        storage = get_storage()
        try:
            action_id = storage.add(action_data)
        except ActionAlreadyExists as exc:
            raise BadRequest([('unique_name', exc)])

        serialized_action = serialize_webaction(storage.get(action_id))

        self.request.response.setStatus(201)
        self.request.response.setHeader('Location', serialized_action['@id'])
        return serialized_action
예제 #46
0
    def reply(self):
        userid, fav_id = self.read_params()

        if userid != api.user.get_current().getId():
            raise Unauthorized(
                "It's not allowed to update favorites of other users.")

        data = json_body(self.request)
        if data.get('title') is None and data.get('position') is None:
            raise BadRequest('Missing parameter title or position')

        FavoriteManager().update(
            userid, fav_id, title=data.get('title'),
            position=data.get('position'))

        prefer = self.request.getHeader('Prefer')
        if prefer == 'return=representation':
            self.request.response.setStatus(200)
            favorite = Favorite.query.get(fav_id)
            return favorite.serialize(api.portal.get().absolute_url())

        self.request.response.setStatus(204)
        return None
예제 #47
0
    def recurse_transition(self, objs, comment, publication_dates,
                           include_children=False):

        data = json_body(self.request)

        for obj in objs:
            if publication_dates:
                deserializer = queryMultiAdapter((obj, self.request),
                                                 IDeserializeFromJson)
                deserializer(data=publication_dates)

            adapter = queryMultiAdapter(
                (obj, getRequest()), ITransitionExtender, name=self.transition)
            if adapter:
                errors = adapter.validate_schema(data)
                if errors:
                    raise BadRequest(errors)

            self.wftool.doActionFor(obj, self.transition,
                                    comment=comment, transition_params=data)
            if include_children and IFolderish.providedBy(obj):
                self.recurse_transition(
                    obj.objectValues(), comment, publication_dates,
                    include_children)
예제 #48
0
    def perform_custom_transition(self):
        data = json_body(self.request)
        self.disable_csrf_protection()

        # TODO: Do we need to handle comments and publication dates
        # etc. for dossier transitions like the original implementation does?
        # For now we also extract these, but we don't do anything with them
        # in the case of resolving a dossier.
        comment = data.get('comment', '')
        include_children = data.get('include_children', False)
        publication_dates = self.parse_publication_dates(data)

        args = [self.context], comment, publication_dates, include_children

        if self.transition == 'dossier-transition-resolve':
            self.resolve_dossier(*args)
        elif self.transition == 'dossier-transition-activate':
            self.activate_dossier(*args)
        elif self.transition == 'dossier-transition-deactivate':
            self.deactivate_dossier(*args)
        elif self.transition == 'dossier-transition-reactivate':
            self.reactivate_dossier(*args)
        else:
            raise BadRequest('Unexpected custom transition %r' % self.transition)
예제 #49
0
    def __call__(self, validate_all=False):
        data = json_body(self.request)

        modified = False
        schema_data = {}
        errors = []

        for schema in iterSchemata(self.context):
            write_permissions = mergedTaggedValueDict(
                schema, WRITE_PERMISSIONS_KEY)

            for name, field in getFields(schema).items():

                field_data = schema_data.setdefault(schema, {})

                if field.readonly:
                    continue

                if name in data:
                    dm = queryMultiAdapter((self.context, field), IDataManager)
                    if not dm.canWrite():
                        continue

                    if not self.check_permission(write_permissions.get(name)):
                        continue

                    # Deserialize to field value
                    deserializer = queryMultiAdapter(
                        (field, self.context, self.request),
                        IFieldDeserializer)
                    if deserializer is None:
                        continue

                    try:
                        value = deserializer(data[name])
                    except ValueError as e:
                        errors.append({
                            'message': e.message, 'field': name, 'error': e})
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(), 'field': name, 'error': e})
                    else:
                        field_data[name] = value
                        if value != dm.get():
                            dm.set(value)
                            modified = True

                elif validate_all:
                    # Never validate the changeNote of p.a.versioningbehavior
                    # The Versionable adapter always returns an empty string
                    # which is the wrong type. Should be unicode and should be
                    # fixed in p.a.versioningbehavior
                    if name == 'changeNote':
                        continue
                    dm = queryMultiAdapter((self.context, field), IDataManager)
                    bound = field.bind(self.context)
                    try:
                        bound.validate(dm.get())
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(), 'field': name, 'error': e})

        # Validate schemata
        for schema, field_data in schema_data.items():
            validator = queryMultiAdapter(
                (self.context, self.request, None, schema, None),
                IManagerValidator)
            for error in validator.validate(field_data):
                errors.append({'error': error, 'message': error.message})

        if errors:
            raise BadRequest(errors)

        if modified:
            notify(ObjectModifiedEvent(self.context))

        return self.context
예제 #50
0
    def render(self):
        data = json_body(self.request)

        type_ = data.get('@type', None)
        id_ = data.get('id', None)
        title = data.get('title', None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        # Generate a temporary id if the id is not given
        if not id_:
            now = DateTime()
            new_id = '{}.{}.{}{:04d}'.format(
                type_.lower().replace(' ', '_'),
                now.strftime('%Y-%m-%d'),
                str(now.millis())[7:],
                randint(0, 9999))
        else:
            new_id = id_

        # Create object
        try:
            new_id = self.context.invokeFactory(type_, new_id, title=title)
        except BadRequest as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='DeserializationError',
                message=str(e.message)))
        except ValueError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='DeserializationError',
                message=str(e.message)))

        # Update fields
        obj = self.context[new_id]
        deserializer = queryMultiAdapter((obj, self.request),
                                         IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(error=dict(
                message='Cannot deserialize type {}'.format(obj.portal_type)))

        try:
            deserializer(validate_all=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='DeserializationError',
                message=str(e)))

        # Rename if generated id
        if not id_:
            self.rename_object(obj)

        self.request.response.setStatus(201)
        self.request.response.setHeader('Location', obj.absolute_url())
        return None
예제 #51
0
파일: add.py 프로젝트: plone/plone.restapi
    def reply(self):
        portal = getSite()
        data = json_body(self.request)

        username = data.get('username', None)
        email = data.get('email', None)
        password = data.get('password', None)
        roles = data.get('roles', [])
        properties = data.get('properties', {})

        security_settings = getAdapter(self.context, ISecuritySchema)
        use_email_as_login = security_settings.use_email_as_login

        if not username and not use_email_as_login:
            raise BadRequest("Property 'username' is required")

        if not email and use_email_as_login:
            raise BadRequest("Property 'email' is required")

        if not password:
            raise BadRequest("Property 'password' is required")

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        # set username based on the login settings (username or email)
        if use_email_as_login:
            username = email
            properties['username'] = email
        else:
            properties['username'] = username

        # set email property
        if email:
            properties['email'] = email

        # Create user
        try:
            registration = getToolByName(portal, 'portal_registration')
            user = registration.addMember(
                username,
                password,
                roles,
                properties=properties
            )
        except ValueError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='MissingParameterError',
                message=str(e.message)))

        if not username and use_email_as_login:
            username = email

        self.request.response.setStatus(201)
        self.request.response.setHeader(
            'Location', portal.absolute_url() + '/@users/' + username
        )
        serializer = queryMultiAdapter(
            (user, self.request),
            ISerializeToJson
        )
        return serializer()
예제 #52
0
파일: add.py 프로젝트: casdr/plone.restapi
    def render(self):
        sm = getSecurityManager()
        if not sm.checkPermission('Add portal content', self.context):
            raise Unauthorized

        data = json_body(self.request)

        type_ = data.get('@type', None)
        id_ = data.get('id', None)
        title = data.get('title', None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        # Generate a temporary id if the id is not given
        if not id_:
            now = DateTime()
            new_id = '%s.%s' % (now.millis(), randint(0, 99999999))
        else:
            new_id = id_

        # Create object
        try:
            new_id = self.context.invokeFactory(type_, new_id, title=title)
        except BadRequest as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='DeserializationError',
                message=str(e.message)))
        except ValueError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='DeserializationError',
                message=str(e.message)))

        # Update fields
        obj = self.context[new_id]
        deserializer = queryMultiAdapter((obj, self.request),
                                         IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(error=dict(
                message='Cannot deserialize type {}'.format(obj.portal_type)))

        try:
            deserializer(validate_all=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(
                type='DeserializationError',
                message=str(e)))

        # Rename if generated id
        if not id_:
            chooser = INameChooser(self.context)
            # INameFromTitle adaptable objects should not get a name
            # suggestion. NameChooser would prefer the given name instead of
            # the one provided by the INameFromTitle adapter.
            name_from_title = INameFromTitle(obj, None)
            if name_from_title is None:
                name = chooser.chooseName(title, obj)
            else:
                name = chooser.chooseName(None, obj)
            transaction.savepoint(optimistic=True)
            self.context.manage_renameObject(new_id, name)

        self.request.response.setStatus(201)
        self.request.response.setHeader('Location', obj.absolute_url())
        return None