comparison src/plugins/plugin_xep_0277.py @ 2227:79d279d1ee88

plugin XEP-0277: comments node access model changes: comments node access model is now copied from parent item by default. If whitelist access is used, parent item affiliations are copied too. publish model is now open by default instead of subscribers
author Goffi <goffi@goffi.org>
date Mon, 17 Apr 2017 20:33:32 +0200
parents 6a2fa651d7fa
children 5e12fc5ae52a
comparison
equal deleted inserted replaced
2226:6856b7225c5b 2227:79d279d1ee88
464 @param return(jid.JID, None): PubSub service to use 464 @param return(jid.JID, None): PubSub service to use
465 """ 465 """
466 return client.pubsub_service if client.pubsub_service is not None else parent_service 466 return client.pubsub_service if client.pubsub_service is not None else parent_service
467 467
468 @defer.inlineCallbacks 468 @defer.inlineCallbacks
469 def _manageComments(self, access, mb_data, service, node, item_id, profile): 469 def _manageComments(self, client, mb_data, service, node, item_id, access=None):
470 """Check comments keys in mb_data and create comments node if necessary 470 """Check comments keys in mb_data and create comments node if necessary
471 471
472 if mb_data['comments'] exists, it is used (or mb_data['comments_service'] and/or mb_data['comments_node']), 472 if mb_data['comments'] exists, it is used (or mb_data['comments_service'] and/or mb_data['comments_node']),
473 else it is generated (if allow_comments is True). 473 else it is generated (if allow_comments is True).
474 @param access(unicode): access model
475 @param mb_data(dict): microblog mb_data 474 @param mb_data(dict): microblog mb_data
476 @param service(jid.JID, None): PubSub service of the parent item 475 @param service(jid.JID, None): PubSub service of the parent item
477 @param node(unicode): node of the parent item 476 @param node(unicode): node of the parent item
478 @param item_id(unicoe): id of the parent item 477 @param item_id(unicode): id of the parent item
478 @param access(unicode, None): access model
479 None to use same access model as parent item
479 """ 480 """
480 # FIXME: if 'comments' already exists in mb_data, it is not used to create the Node 481 # FIXME: if 'comments' already exists in mb_data, it is not used to create the Node
481 allow_comments = C.bool(mb_data.pop("allow_comments", "false")) 482 allow_comments = C.bool(mb_data.pop("allow_comments", "false"))
482 if not allow_comments: 483 if not allow_comments:
483 if 'comments' in mb_data: 484 if 'comments' in mb_data:
484 log.warning(u"comments are not allowed but there is already a comments node, it may be lost: {uri}".format(uri=mb_data['comments'])) 485 log.warning(u"comments are not allowed but there is already a comments node, it may be lost: {uri}".format(uri=mb_data['comments']))
485 del mb_data['comments'] 486 del mb_data['comments']
486 return 487 return
487 488
488 client = self.host.getClient(profile) 489 if access is None:
490 # TODO: cache access models per service/node
491 parent_node_config = yield self._p.getConfiguration(client, service, node)
492 access = parent_node_config.get(self._p.OPT_ACCESS_MODEL, self._p.ACCESS_OPEN)
489 493
490 options = {self._p.OPT_ACCESS_MODEL: access, 494 options = {self._p.OPT_ACCESS_MODEL: access,
491 self._p.OPT_PERSIST_ITEMS: 1, 495 self._p.OPT_PERSIST_ITEMS: 1,
492 self._p.OPT_MAX_ITEMS: -1, 496 self._p.OPT_MAX_ITEMS: -1,
493 self._p.OPT_DELIVER_PAYLOADS: 1, 497 self._p.OPT_DELIVER_PAYLOADS: 1,
494 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1, 498 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1,
495 self._p.OPT_PUBLISH_MODEL: "subscribers", # TODO: should be open if *both* node and item access_model are open (public node and item) 499 # FIXME: would it make sense to restrict publish model to subscribers?
500 self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN,
496 } 501 }
497 502
498 # if other plugins need to change the options 503 # if other plugins need to change the options
499 yield self.host.trigger.point("XEP-0277_comments", client, mb_data, options) 504 yield self.host.trigger.point("XEP-0277_comments", client, mb_data, options)
500 505
516 except error.StanzaError as e: 521 except error.StanzaError as e:
517 if e.condition == 'conflict': 522 if e.condition == 'conflict':
518 log.info(u"node {} already exists on service {}".format(comments_node, comments_service)) 523 log.info(u"node {} already exists on service {}".format(comments_node, comments_service))
519 else: 524 else:
520 raise e 525 raise e
526 else:
527 if access == self._p.ACCESS_WHITELIST:
528 # for whitelist access we need to copy affiliations from parent item
529 parent_affiliations = yield self._p.getNodeAffiliations(client, service, node)
530 yield self._p.setNodeAffiliations(client, comments_service, comments_node, parent_affiliations)
521 531
522 if comments_service is None: 532 if comments_service is None:
523 comments_service = client.jid.userhostJID() 533 comments_service = client.jid.userhostJID()
524 534
525 if 'comments' in mb_data: 535 if 'comments' in mb_data:
531 mb_data['comments'] = self._p.getNodeURI(comments_service, comments_node) 541 mb_data['comments'] = self._p.getNodeURI(comments_service, comments_node)
532 542
533 def _mbSend(self, service, node, data, profile_key): 543 def _mbSend(self, service, node, data, profile_key):
534 service = jid.JID(service) if service else None 544 service = jid.JID(service) if service else None
535 node = node if node else NS_MICROBLOG 545 node = node if node else NS_MICROBLOG
536 profile = self.host.memory.getProfileName(profile_key) 546 client = self.host.getClient(profile_key)
537 return self.send(data, service, node, profile) 547 return self.send(client, data, service, node)
538 548
539 @defer.inlineCallbacks 549 @defer.inlineCallbacks
540 def send(self, data, service=None, node=NS_MICROBLOG, profile=None): 550 def send(self, client, data, service=None, node=NS_MICROBLOG):
541 """Send XEP-0277's microblog data 551 """Send XEP-0277's microblog data
542 552
543 @param data(dict): microblog data (must include at least a "content" or a "title" key). 553 @param data(dict): microblog data (must include at least a "content" or a "title" key).
544 see http://wiki.goffi.org/wiki/Bridge_API_-_Microblogging/en for details 554 see http://wiki.goffi.org/wiki/Bridge_API_-_Microblogging/en for details
545 @param service(jid.JID, None): PubSub service where the microblog must be published 555 @param service(jid.JID, None): PubSub service where the microblog must be published
546 None to publish on profile's PEP 556 None to publish on profile's PEP
547 @param node(unicode, None): PubSub node to use (defaut to microblog NS) 557 @param node(unicode, None): PubSub node to use (defaut to microblog NS)
548 None is equivalend as using default value 558 None is equivalend as using default value
549 @param profile: %(doc_profile)s
550 """ 559 """
551 # TODO: check that all data keys are used, this would avoid sending publicly a private message 560 # TODO: check that all data keys are used, this would avoid sending publicly a private message
552 # by accident (e.g. if group pluging is not loaded, and "grou*" key are not used) 561 # by accident (e.g. if group pluging is not loaded, and "grou*" key are not used)
553 assert profile is not None
554 if node is None: 562 if node is None:
555 node = NS_MICROBLOG 563 node = NS_MICROBLOG
556 564
557 item_id = data.get('id') or unicode(uuid.uuid4()) 565 item_id = data.get('id') or unicode(uuid.uuid4())
558 try: 566
559 yield self._manageComments(self._p.ACCESS_OPEN, data, service, node, item_id, profile) 567 try:
568 yield self._manageComments(client, data, service, node, item_id, access=None)
560 except error.StanzaError: 569 except error.StanzaError:
561 log.warning(u"Can't create comments node for item {}".format(item_id)) 570 log.warning(u"Can't create comments node for item {}".format(item_id))
562 item = yield self.data2entry(data, item_id, profile) 571 item = yield self.data2entry(data, item_id, client.profile)
563 ret = yield self._p.publish(service, node, [item], profile_key=profile) 572 ret = yield self._p.publish(service, node, [item], profile_key=client.profile)
564 defer.returnValue(ret) 573 defer.returnValue(ret)
565 574
566 ## retract ## 575 ## retract ##
567 576
568 def _mbRetract(self, service_jid_s, nodeIdentifier, itemIdentifier, profile_key): 577 def _mbRetract(self, service_jid_s, nodeIdentifier, itemIdentifier, profile_key):