Esempio n. 1
0
def login(context, request):
    """ Login Route

    Login route to authenticate a user against Plone.
    """
    # extract the data
    __ac_name = request.get("__ac_name", None)
    __ac_password = request.get("__ac_password", None)

    logger.info("*** LOGIN %s ***" % __ac_name)

    if __ac_name is None:
        api.fail(400, "__ac_name is missing")
    if __ac_password is None:
        api.fail(400, "__ac_password is missing")

    acl_users = api.get_tool("acl_users")

    # XXX hard coded
    acl_users.credentials_cookie_auth.login()

    # XXX amin user won't be logged in if I use this approach
    # acl_users.login()
    # response = request.response
    # acl_users.updateCredentials(request, response, __ac_name, __ac_password)

    if api.is_anonymous():
        api.fail(401, "Invalid Credentials")

    # return the JSON in the same format like the user route
    return get(context, request, username=__ac_name)
Esempio n. 2
0
def get_search_results(portal_type=None, uid=None, **kw):
    """Search the catalog and return the results

    :returns: Catalog search results
    :rtype: iterable
    """

    # If we have an UID, return the object immediately
    if uid is not None:
        logger.info("UID '%s' found, returning the object immediately" % uid)
        return u.to_list(get_object_by_uid(uid))

    # allow to search search for the Plone Site with portal_type
    include_portal = False
    if u.to_string(portal_type) == "Plone Site":
        include_portal = True

    # The request may contain a list of portal_types, e.g.
    # `?portal_type=Document&portal_type=Plone Site`
    if "Plone Site" in u.to_list(req.get("portal_type")):
        include_portal = True

    # Build and execute a catalog query
    results = search(portal_type=portal_type, uid=uid, **kw)

    if include_portal:
        results = list(results) + u.to_list(get_portal())

    return results
Esempio n. 3
0
def logout(context, request):
    """ Logout Route
    """
    logger.info("*** LOGOUT ***")

    acl_users = api.get_tool("acl_users")
    acl_users.logout(request)

    return {"url": api.url_for("senaite.jsonapi.v1.users"), "success": True}
Esempio n. 4
0
 def search(self, query):
     """search the catalog
     """
     logger.info("Catalog query={}".format(query))
     # Support to set the catalog as a request parameter
     catalogs = _.to_list(req.get("catalog", None))
     if catalogs:
         return senaiteapi.search(query, catalog=catalogs)
     # Delegate to the search API of Bika LIMS
     return senaiteapi.search(query)
Esempio n. 5
0
def auth(context, request):
    """ Basic Authentication
    """

    if ploneapi.user.is_anonymous():
        request.response.setStatus(401)
        request.response.setHeader('WWW-Authenticate',
                                   'basic realm="JSONAPI AUTH"', 1)

    logger.info("*** BASIC AUTHENTICATE ***")
    return {}
Esempio n. 6
0
def update_object_with_data(content, record):
    """Update the content with the record data

    :param content: A single folderish catalog brain or content object
    :type content: ATContentType/DexterityContentType/CatalogBrain
    :param record: The data to update
    :type record: dict
    :returns: The updated content object
    :rtype: object
    :raises:
        APIError,
        :class:`~plone.jsonapi.routes.exceptions.APIError`
    """

    # ensure we have a full content object
    content = get_object(content)

    # Look for an update-specific adapter for this object
    adapter = queryAdapter(content, IUpdate)
    if adapter:
        # Use the adapter to update the object
        logger.info("Delegating 'update' operation of '{}'".format(
            api.get_path(content)))
        adapter.update_object(**record)

    else:
        # Fall-back to default update machinery
        # get the proper data manager
        dm = IDataManager(content)

        if dm is None:
            fail(400, "Update for this object is not allowed")

        # Bail-out non-update-able fields
        purged_records = copy.deepcopy(record)
        map(lambda key: purged_records.pop(key, None), SKIP_UPDATE_FIELDS)

        # Iterate through record items
        for k, v in purged_records.items():
            try:
                success = dm.set(k, v, **record)
            except Unauthorized:
                fail(401, "Not allowed to set the field '%s'" % k)
            except ValueError, exc:
                fail(400, str(exc))

            if not success:
                logger.warn("update_object_with_data::skipping key=%r", k)
                continue

            logger.debug("update_object_with_data::field %r updated", k)
Esempio n. 7
0
def create_object(container, portal_type, **data):
    """Creates an object slug

    :returns: The new created content object
    :rtype: object
    """

    if "id" in data:
        # always omit the id as senaite LIMS generates a proper one
        id = data.pop("id")
        logger.warn("Passed in ID '{}' omitted! Senaite LIMS "
                    "generates a proper ID for you".format(id))

    try:
        # Is there any adapter registered to handle the creation of this type?
        adapter = queryAdapter(container, ICreate, name=portal_type)
        if adapter and adapter.is_creation_delegated():
            logger.info("Delegating 'create' operation of '{}' in '{}'".format(
                portal_type, api.get_path(container)))
            return adapter.create_object(**data)

        # Special case for ARs
        # => return immediately w/o update
        if portal_type == "AnalysisRequest":
            obj = create_analysisrequest(container, **data)
            # Omit values which are already set through the helper
            data = u.omit(data, "SampleType", "Analyses")
            # Set the container as the client, as the AR lives in it
            data["Client"] = container
            return obj
        # Standard content creation
        else:
            # we want just a minimun viable object and set the data later
            obj = api.create(container, portal_type)
            # obj = api.create(container, portal_type, **data)
    except Unauthorized:
        fail(401, "You are not allowed to create this content")

    # Update the object with the given data, but omit the id
    try:
        update_object_with_data(obj, data)
    except APIError:
        # Failure in creation process, delete the invalid object
        # NOTE: We bypass the permission checks
        container._delObject(obj.id)
        # reraise the error
        raise

    return obj
Esempio n. 8
0
    def make_query(self, **kw):
        """create a query suitable for the catalog
        """
        query = kw.pop("query", {})

        query.update(self.get_request_query())
        query.update(self.get_custom_query())
        query.update(self.get_keyword_query(**kw))

        sort_on, sort_order = self.get_sort_spec()
        if sort_on and "sort_on" not in query:
            query.update({"sort_on": sort_on})
        if sort_order and "sort_order" not in query:
            query.update({"sort_order": sort_order})

        logger.info("make_query:: query={} | catalog={}".format(
            query, self.catalog))

        return query
Esempio n. 9
0
# -*- coding: utf-8 -*-

import pkgutil

from senaite.jsonapi import logger
from senaite.jsonapi.v1 import routes
from senaite.jsonapi import add_route as add_senaite_route

__version__ = 1
__date__ = "2017-10-01"

BASE_URL = "/senaite/v1"


def add_route(route, endpoint=None, **kw):
    """Add a new JSON API route
    """

    # ensure correct amout of slashes
    def apiurl(route):
        return '/'.join(s.strip('/') for s in ["", BASE_URL, route])

    return add_senaite_route(apiurl(route), endpoint, **kw)


prefix = routes.__name__ + "."
for importer, modname, ispkg in pkgutil.iter_modules(routes.__path__, prefix):
    module = __import__(modname, fromlist="dummy")
    logger.info("INITIALIZED SENAITE JSONAPI V1 ROUTE ---> %s" %
                module.__name__)