def get_tasks_summary(tasks, endpoint, complete=False, **kwargs): """Returns a dict that represents a summary of a tasks response :param tasks: items to be included in the response :param endpoint: endpoint from the request :param complete: whether to include the full representation of the tasks :param kwargs: additional (hashable) params to be included in the message :return: dict with the summary and the list of task representations """ tasks = tasks or [] if not isinstance(tasks, (list, tuple)): tasks = [tasks] # Get the information dict of each task tasks = filter(None, tasks) tasks = map(lambda t: get_task_info(t, complete=complete), tasks) zeo = get_post_zeo() complete_info = complete and " (complete)" or "" logger.info("::{}: {} tasks{} [{}]".format(endpoint, len(tasks), complete_info, zeo)) info = kwargs or {} info.update({ "count": len(tasks), "items": tasks, "url": japi.url_for("senaite.queue.{}".format(endpoint)), "zeo": zeo, }) return info
def get(context, request, catalog_id=None): """Returns all registered catalogs if key is None, otherwise try to fetch the information about the catalog name passed in """ archetype_tool = api.get_tool("archetype_tool") def get_data(catalog): portal_types = catalog.getPortalTypes() # Bail out portal types not present in this catalog pt_catalogs = map(archetype_tool.getCatalogsByType, portal_types) pt_catalogs = map(lambda pts: catalog in pts, pt_catalogs) pt_catalogs = zip(pt_catalogs, portal_types) portal_types = filter(lambda it: it[0], pt_catalogs) return { "id": catalog.id, "indexes": sorted(catalog.indexes()), "schema": sorted(catalog.schema()), "portal_types": sorted(map(lambda it: it[1], portal_types)), } if catalog_id: # Return the catalog directly catalog = api.get_tool(catalog_id) # If a catalog name was passed in, return the catalog info directly return get_data(catalog) # Look for all catalogs if not archetype_tool: # Default catalog catalogs = [api.get_tool("portal_catalog")], else: catalogs = archetype_tool.getCatalogsInSite() catalogs = map(api.get_tool, catalogs) # Exclude some catalogs skip = ["reference_catalog", "uid_catalog"] catalogs = filter(lambda cat: cat.id not in skip, catalogs) # Generate the metadata info for catalogs records = map(get_data, catalogs) # Prepare batch size = req.get_batch_size() start = req.get_batch_start() batch = api.make_batch(records, size, start) return { "pagesize": batch.get_pagesize(), "next": batch.make_next_url(), "previous": batch.make_prev_url(), "page": batch.get_pagenumber(), "pages": batch.get_numpages(), "count": batch.get_sequence_length(), "items": records, "url": api.url_for("senaite.jsonapi.v1.catalogs", key=catalog_id), }
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}
def get_user_info(user): """Get the user information """ user = api.get_user(user) current = api.get_current_user() if api.is_anonymous(): return { "username": current.getUserName(), "authenticated": False, "roles": current.getRoles(), "api_url": api.url_for("senaite.jsonapi.v1.users", username="******"), } # nothing to do if user is None: logger.warn("No user found for {}".format(user)) return None # plone user pu = user.getUser() info = { "username": user.getUserName(), "roles": user.getRoles(), "groups": pu.getGroups(), "authenticated": current == user, "api_url": api.url_for("senaite.jsonapi.v1.users", username=user.getId()), } for k, v in api.get_user_properties(user).items(): if api.is_date(v): v = api.to_iso_date(v) if not api.is_json_serializable(v): logger.warn( "User property '{}' is not JSON serializable".format(k)) continue info[k] = v return info
def get_message_summary(message, endpoint, **kwargs): """Returns a dict that represents a summary of a message response :param message: message to be included in the response :param endpoint: endpoint from the request :param kwargs: additional (hashable) params to be included in the message :return: dict with the summary of the response """ zeo = get_post_zeo() logger.info("::{}: {} [{}]".format(endpoint, message, zeo)) info = kwargs or {} info.update({ "message": message, "url": japi.url_for("senaite.queue.{}".format(endpoint)), "zeo": zeo, }) return info
def get(context, request, key=None): """Return settings by keyword. If key is None, return all settings. """ settings = api.get_settings_by_keyword(key) # Prepare batch size = req.get_batch_size() start = req.get_batch_start() batch = api.make_batch(settings, size, start) return { "pagesize": batch.get_pagesize(), "next": batch.make_next_url(), "previous": batch.make_prev_url(), "page": batch.get_pagenumber(), "pages": batch.get_numpages(), "count": batch.get_sequence_length(), "items": settings, "url": api.url_for("senaite.jsonapi.v1.settings", key=key), }
def get(context, request, key=None): """Return all registry items if key is None, otherwise try to fetch the registry key """ registry_records = api.get_registry_records_by_keyword(key) # Prepare batch size = req.get_batch_size() start = req.get_batch_start() batch = api.make_batch(registry_records, size, start) return { "pagesize": batch.get_pagesize(), "next": batch.make_next_url(), "previous": batch.make_prev_url(), "page": batch.get_pagenumber(), "pages": batch.get_numpages(), "count": batch.get_sequence_length(), "items": [registry_records], "url": api.url_for("senaite.jsonapi.v1.registry", key=key), }
def action(context, request, action=None, resource=None, uid=None): """Various HTTP POST actions Case 1: /<uid> -> Return the full object immediately in the root of the JSON API response <Senaite-Site>/@@API/senaite/v1/<uid> Case 2: /<action>/<uid> -> The actions (update, delete) will performed on the object identified by <uid> -> The actions (create) will use the <uid> as the parent folder <Senaite-Site>/@@API/senaite/v1/<action>/<uid> Case 3: <resource>/<action> -> The "target" object will be located by a location given in the request body (uid, path, parent_path + id) -> The actions (cut, copy, update, delete) will performed on the target object -> The actions (create) will use the target object as the container <Senaite-Site>/@@API/senaite/v1/<resource>/<action> Case 4: <resource>/<action>/<uid> -> The actions (cut, copy, update, delete) will performed on the object identified by <uid> -> The actions (create) will use the <uid> as the parent folder <Senaite-Site>/@@API/senaite/v1/<resource>/<action> """ # Fetch and call the action function of the API func_name = "{}_items".format(action) action_func = getattr(api, func_name, None) if action_func is None: api.fail(500, "API has no member named '{}'".format(func_name)) portal_type = api.resource_to_portal_type(resource) items = action_func(portal_type=portal_type, uid=uid) return { "count": len(items), "items": items, "url": api.url_for("senaite.jsonapi.v1.action", action=action), }
def action(context, request, action=None, resource=None, uid=None): """Various HTTP POST actions """ # allow to set the method via the header if action is None: action = request.get_header("HTTP_X_HTTP_METHOD_OVERRIDE", "CREATE").lower() # Fetch and call the action function of the API func_name = "{}_items".format(action) action_func = getattr(api, func_name, None) if action_func is None: api.fail(500, "API has no member named '{}'".format(func_name)) portal_type = api.resource_to_portal_type(resource) items = action_func(portal_type=portal_type, uid=uid) return { "count": len(items), "items": items, "url": api.url_for("senaite.jsonapi.v1.action", action=action), }
def get_list_summary(items, endpoint, **kwargs): """Returns a dict that represents a summary of a list response :param items: items to be included in the response :param endpoint: endpoint from the request :param kwargs: additional (hashable) params to be included in the message :return: dict with the summary and the list of items """ items = items or [] if not isinstance(items, (list, tuple)): items = [items] # Remove empties items = filter(None, items) zeo = get_post_zeo() logger.info("::{}: {} items [{}]".format(endpoint, len(items), zeo)) info = kwargs or {} info.update({ "count": len(items), "items": items, "url": japi.url_for("senaite.queue.{}".format(endpoint)), "zeo": zeo, }) return info