Mercurial > libervia-pubsub
comparison sat_pubsub/backend.py @ 318:d13526c0eb32
RSM improvments/refactoring:
- a warning message is displayed if maxItems == 0 in getItems, and an empty list is returned in this case
- use the new container.ItemData instead of doing tuple (un)packing
- the list of ItemData => list of domish.Element conversion is done at the end of the workflow
- rsm request is checked in self._items_rsm directly
- better handling of Response.index in _items_rsm
- itemsIdentifiers can't be used with RSM (the later will be ignored if this happen)
- don't do approximative unpacking anymore in _items_rsm
- countItems and getIndex have been refactored and renamed getItemsCount and getItemsIndex, don't use query duplications anymore
- cleaned query handling in getItems
- /!\ mam module is temporarly broken
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 03 Jan 2016 18:33:22 +0100 |
parents | 34adc4a8aa64 |
children | 29c2553ef863 |
comparison
equal
deleted
inserted
replaced
317:34adc4a8aa64 | 318:d13526c0eb32 |
---|---|
595 return {} | 595 return {} |
596 | 596 |
597 def _doGetItems(self, result, requestor, maxItems, itemIdentifiers, | 597 def _doGetItems(self, result, requestor, maxItems, itemIdentifiers, |
598 ext_data): | 598 ext_data): |
599 node, affiliation = result | 599 node, affiliation = result |
600 if maxItems == 0: | |
601 log.msg("WARNING: maxItems=0 on items retrieval") | |
602 return [] | |
600 | 603 |
601 def append_item_config(items_data): | 604 def append_item_config(items_data): |
602 ret = [] | 605 """Add item config data form to items with roster access model""" |
603 for item_data in items_data: | 606 for item_data in items_data: |
604 item, access_model, access_list = item_data.item, item_data.access_model, item_data.config | 607 if item_data.access_model == const.VAL_AMODEL_OPEN: |
605 if access_model == const.VAL_AMODEL_OPEN: | |
606 pass | 608 pass |
607 elif access_model == const.VAL_AMODEL_ROSTER: | 609 elif item_data.access_model == const.VAL_AMODEL_ROSTER: |
608 form = data_form.Form('submit', formNamespace=const.NS_ITEM_CONFIG) | 610 form = data_form.Form('submit', formNamespace=const.NS_ITEM_CONFIG) |
609 access = data_form.Field(None, const.OPT_ACCESS_MODEL, value=const.VAL_AMODEL_ROSTER) | 611 access = data_form.Field(None, const.OPT_ACCESS_MODEL, value=const.VAL_AMODEL_ROSTER) |
610 allowed = data_form.Field(None, const.OPT_ROSTER_GROUPS_ALLOWED, values=access_list[const.OPT_ROSTER_GROUPS_ALLOWED]) | 612 allowed = data_form.Field(None, const.OPT_ROSTER_GROUPS_ALLOWED, values=item_data.config[const.OPT_ROSTER_GROUPS_ALLOWED]) |
611 form.addField(access) | 613 form.addField(access) |
612 form.addField(allowed) | 614 form.addField(allowed) |
613 item.addChild(form.toElement()) | 615 item_data.item.addChild(form.toElement()) |
614 elif access_model == const.VAL_AMODEL_JID: | 616 elif access_model == const.VAL_AMODEL_JID: |
615 #FIXME: manage jid | 617 #FIXME: manage jid |
616 raise NotImplementedError | 618 raise NotImplementedError |
617 else: | 619 else: |
618 raise error.BadAccessTypeError(access_model) | 620 raise error.BadAccessTypeError(access_model) |
619 | 621 return items_data |
620 ret.append(item) | |
621 return ret | |
622 | 622 |
623 def access_checked(access_data): | 623 def access_checked(access_data): |
624 authorized, roster = access_data | 624 authorized, roster = access_data |
625 if not authorized: | 625 if not authorized: |
626 raise error.NotAuthorized() | 626 raise error.NotAuthorized() |
627 | 627 |
628 roster_item = roster.get(requestor.userhostJID()) | 628 roster_item = roster.get(requestor.userhostJID()) |
629 authorized_groups = tuple(roster_item.groups) if roster_item else tuple() | 629 authorized_groups = tuple(roster_item.groups) if roster_item else tuple() |
630 unrestricted = affiliation == 'owner' | 630 owner = affiliation == 'owner' |
631 | 631 |
632 if itemIdentifiers: | 632 if itemIdentifiers: |
633 d = node.getItemsById(authorized_groups, unrestricted, itemIdentifiers) | 633 d = node.getItemsById(authorized_groups, owner, itemIdentifiers) |
634 else: | 634 else: |
635 d = node.getItems(authorized_groups, unrestricted, maxItems, ext_data) | 635 d = node.getItems(authorized_groups, owner, maxItems, ext_data) |
636 if unrestricted: | 636 if owner: |
637 d.addCallback(append_item_config) | 637 d.addCallback(append_item_config) |
638 | 638 |
639 try: | 639 d.addCallback(self._items_rsm, node, authorized_groups, |
640 rsm_data = ext_data['rsm'] | 640 owner, itemIdentifiers, |
641 except KeyError: | 641 ext_data) |
642 pass | |
643 else: | |
644 if rsm_data is not None: | |
645 d.addCallback(self._items_rsm, node, authorized_groups, | |
646 unrestricted, maxItems, itemIdentifiers, | |
647 rsm_data) | |
648 return d | 642 return d |
649 | 643 |
650 if not iidavoll.ILeafNode.providedBy(node): | 644 if not iidavoll.ILeafNode.providedBy(node): |
651 return [] | 645 return [] |
652 | 646 |
669 elif access_model == const.VAL_AMODEL_ROSTER: | 663 elif access_model == const.VAL_AMODEL_ROSTER: |
670 d.addCallback(self._getNodeGroups, node.nodeIdentifier, ext_data.get('pep', False)) | 664 d.addCallback(self._getNodeGroups, node.nodeIdentifier, ext_data.get('pep', False)) |
671 d.addCallback(self.checkGroup, requestor) | 665 d.addCallback(self.checkGroup, requestor) |
672 d.addCallback(access_checked) | 666 d.addCallback(access_checked) |
673 | 667 |
668 d.addCallback(lambda items_data: [item_data.item for item_data in items_data]) | |
669 | |
674 return d | 670 return d |
675 | 671 |
676 def _setCount(self, value, response): | 672 def _setCount(self, value, response): |
677 response.count = value | 673 response.count = value |
678 | 674 |
679 def _setIndex(self, value, response): | 675 def _setIndex(self, value, response, adjust): |
680 response.index = value | 676 """Set index in RSM response |
681 | 677 |
682 def _items_rsm(self, elts, node, authorized_groups, unrestricted, maxItems, | 678 @param value(int): value of the reference index (i.e. before or after item) |
683 itemIdentifiers, request): | 679 @param response(RSMResponse): response instance to fill |
684 # FIXME: move this to a separate module ? | 680 @param adjust(int): adjustement term (i.e. difference between reference index and first item of the result) |
681 """ | |
682 response.index = value + adjust | |
683 | |
684 def _items_rsm(self, items_data, node, authorized_groups, owner, | |
685 itemIdentifiers, ext_data): | |
686 # FIXME: move this to a separate module | |
687 # TODO: Index can be optimized by keeping a cache of the last RSM request | |
688 # An other optimisation would be to look for index first and use it as offset | |
689 try: | |
690 rsm_request = ext_data['rsm'] | |
691 except KeyError: | |
692 # No RSM in this request, nothing to do | |
693 return items_data | |
694 | |
695 if itemIdentifiers: | |
696 log.msg("WARNING, itemIdentifiers used with RSM, ignoring the RSM part") | |
697 return items_data | |
698 | |
685 response = rsm.RSMResponse() | 699 response = rsm.RSMResponse() |
686 | 700 |
687 d_count = node.countItems(authorized_groups, unrestricted) | 701 d_count = node.getItemsCount(authorized_groups, owner, ext_data) |
688 d_count.addCallback(self._setCount, response) | 702 d_count.addCallback(self._setCount, response) |
689 d_list = [d_count] | 703 d_list = [d_count] |
690 | 704 |
691 if request.index is not None: | 705 if items_data: |
692 response.index = request.index | 706 response.first = items_data[0].item['id'] |
693 elif request.before is not None: | 707 response.last = items_data[-1].item['id'] |
694 if request.before != '': | 708 |
695 # XXX: getIndex starts with index 1, RSM starts with 0 | 709 # index handling |
696 d_index = node.getIndex(authorized_groups, unrestricted, request.before) | 710 if rsm_request.index is not None: |
697 d_index.addCallback(lambda index: max(index - request.max - 1, 0)) | 711 response.index = rsm_request.index |
698 d_index.addCallback(self._setIndex, response) | 712 elif rsm_request.before: |
713 # The last page case (before == '') is managed in render method | |
714 d_index = node.getItemsIndex(rsm_request.before, authorized_groups, owner, ext_data) | |
715 d_index.addCallback(self._setIndex, response, -len(items_data)) | |
699 d_list.append(d_index) | 716 d_list.append(d_index) |
700 elif request.after is not None: | 717 elif rsm_request.after is not None: |
701 d_index = node.getIndex(authorized_groups, unrestricted, request.after) | 718 d_index = node.getItemsIndex(rsm_request.after, authorized_groups, owner, ext_data) |
702 d_index.addCallback(self._setIndex, response) | 719 d_index.addCallback(self._setIndex, response, 1) |
703 d_list.append(d_index) | 720 d_list.append(d_index) |
704 elif itemIdentifiers: | 721 else: |
705 d_index = node.getIndex(authorized_groups, unrestricted, itemIdentifiers[0]) | 722 # the first page was requested |
706 d_index.addCallback(lambda index: index - 1) | 723 response.index = 0 |
707 d_index.addCallback(self._setIndex, response) | |
708 d_list.append(d_index) | |
709 | |
710 | 724 |
711 def render(result): | 725 def render(result): |
712 try: | 726 if rsm_request.before == '': |
713 items = [elt for elt in elts if elt.name == 'item'] | 727 # the last page was requested |
714 except AttributeError: | 728 response.index = response.count - len(items_data) |
715 # XXX: see sat_pubsub.pgsql_storage.LeafNode.getItemsById return value | 729 items_data.append(container.ItemData(response.toElement())) |
716 items = [elt[0] for elt in elts if elt[0].name == 'item'] | 730 return items_data |
717 if len(items) > 0: | |
718 if response.index is None: | |
719 if request.before == '': # last page | |
720 response.index = response.count - request.max | |
721 else: # first page | |
722 response.index = 0 | |
723 response.first = items[0]['id'] | |
724 response.last = items[len(items) - 1]['id'] | |
725 if request.before is not None: | |
726 response.first, response.last = response.last, response.first | |
727 else: | |
728 response.index = None | |
729 elts.append(response.toElement()) | |
730 return elts | |
731 | 731 |
732 return defer.DeferredList(d_list).addCallback(render) | 732 return defer.DeferredList(d_list).addCallback(render) |
733 | 733 |
734 def retractItem(self, nodeIdentifier, itemIdentifiers, requestor, notify, pep, recipient): | 734 def retractItem(self, nodeIdentifier, itemIdentifiers, requestor, notify, pep, recipient): |
735 d = self.storage.getNode(nodeIdentifier, pep, recipient) | 735 d = self.storage.getNode(nodeIdentifier, pep, recipient) |