comparison src/plugins/plugin_misc_groupblog.py @ 1662:9aa2a703e460

plugin group blog: group permissions are used if "group*" keys are found in mbdata (in data2entry and comments trigger)
author Goffi <goffi@goffi.org>
date Tue, 24 Nov 2015 16:21:18 +0100
parents e0bde0d0b321
children 5d0ff155be1a
comparison
equal deleted inserted replaced
1661:96ee986dab3c 1662:9aa2a703e460
26 from twisted.words.xish.domish import generateElementsNamed 26 from twisted.words.xish.domish import generateElementsNamed
27 from sat.core import exceptions 27 from sat.core import exceptions
28 from wokkel import disco, data_form, iwokkel 28 from wokkel import disco, data_form, iwokkel
29 from wokkel import rsm 29 from wokkel import rsm
30 from zope.interface import implements 30 from zope.interface import implements
31 from tools import common
31 # import uuid 32 # import uuid
32 33
33 try: 34 try:
34 from twisted.words.protocols.xmlstream import XMPPHandler 35 from twisted.words.protocols.xmlstream import XMPPHandler
35 except ImportError: 36 except ImportError:
46 NS_PUBSUB_ITEM_CONFIG = NS_PUBSUB_EXP + "#item-config" 47 NS_PUBSUB_ITEM_CONFIG = NS_PUBSUB_EXP + "#item-config"
47 NS_PUBSUB_AUTO_CREATE = NS_PUBSUB + "#auto-create" 48 NS_PUBSUB_AUTO_CREATE = NS_PUBSUB + "#auto-create"
48 ACCESS_TYPE_MAP = { 'PUBLIC': 'open', 49 ACCESS_TYPE_MAP = { 'PUBLIC': 'open',
49 'GROUP': 'roster', 50 'GROUP': 'roster',
50 'JID': None, #JID is not yet managed 51 'JID': None, #JID is not yet managed
51 } 52 }
52 53
53 MAX_ITEMS = 5 54 MAX_ITEMS = 5
54 MAX_COMMENTS = 5 55 MAX_COMMENTS = 5
55 DO_NOT_COUNT_COMMENTS = -1 # must be lower than 0 56 DO_NOT_COUNT_COMMENTS = -1 # must be lower than 0
56 57
58 "name": "Group blogging throught collections", 59 "name": "Group blogging throught collections",
59 "import_name": "GROUPBLOG", 60 "import_name": "GROUPBLOG",
60 "type": "MISC", 61 "type": "MISC",
61 "protocols": [], 62 "protocols": [],
62 "dependencies": ["XEP-0277"], 63 "dependencies": ["XEP-0277"],
63 "recommendations": ["XEP-0059"],
64 "main": "GroupBlog", 64 "main": "GroupBlog",
65 "handler": "yes", 65 "handler": "yes",
66 "description": _("""Implementation of microblogging with roster access""") 66 "description": _("""Implementation of microblogging fine permissions""")
67 } 67 }
68 68
69 69
70 class NoCompatiblePubSubServerFound(Exception): 70 class NoCompatiblePubSubServerFound(Exception):
71 pass 71 pass
86 """This class use a SàT PubSub Service to manage access on microblog""" 86 """This class use a SàT PubSub Service to manage access on microblog"""
87 87
88 def __init__(self, host): 88 def __init__(self, host):
89 log.info(_("Group blog plugin initialization")) 89 log.info(_("Group blog plugin initialization"))
90 self.host = host 90 self.host = host
91 91 self._p = self.host.plugins["XEP-0060"]
92 host.bridge.addMethod("sendGroupBlog", ".plugin", in_sign='sassa{ss}s', out_sign='', 92
93 method=self.sendGroupBlog, 93 # host.bridge.addMethod("sendGroupBlog", ".plugin", in_sign='sassa{ss}s', out_sign='',
94 async=True) 94 # method=self.sendGroupBlog,
95 95 # async=True)
96 host.bridge.addMethod("deleteGroupBlog", ".plugin", in_sign='(sss)ss', out_sign='', 96
97 method=self.deleteGroupBlog, 97 # host.bridge.addMethod("deleteGroupBlog", ".plugin", in_sign='(sss)ss', out_sign='',
98 async=True) 98 # method=self.deleteGroupBlog,
99 99 # async=True)
100 host.bridge.addMethod("updateGroupBlog", ".plugin", in_sign='(sss)ssa{ss}s', out_sign='', 100
101 method=self.updateGroupBlog, 101 # host.bridge.addMethod("updateGroupBlog", ".plugin", in_sign='(sss)ssa{ss}s', out_sign='',
102 async=True) 102 # method=self.updateGroupBlog,
103 103 # async=True)
104 host.bridge.addMethod("sendGroupBlogComment", ".plugin", in_sign='ssa{ss}s', out_sign='', 104
105 method=self.sendGroupBlogComment, 105 # host.bridge.addMethod("sendGroupBlogComment", ".plugin", in_sign='ssa{ss}s', out_sign='',
106 async=True) 106 # method=self.sendGroupBlogComment,
107 # async=True)
107 108
108 # host.bridge.addMethod("getGroupBlogs", ".plugin", 109 # host.bridge.addMethod("getGroupBlogs", ".plugin",
109 # in_sign='sasa{ss}bs', out_sign='(aa{ss}a{ss})', 110 # in_sign='sasa{ss}bs', out_sign='(aa{ss}a{ss})',
110 # method=self.getGroupBlogs, 111 # method=self.getGroupBlogs,
111 # async=True) 112 # async=True)
112 113
113 host.bridge.addMethod("getGroupBlogsWithComments", ".plugin", 114 # host.bridge.addMethod("getGroupBlogsWithComments", ".plugin",
114 in_sign='sasa{ss}is', out_sign='(a(a{ss}(aa{ss}a{ss}))a{ss})', 115 # in_sign='sasa{ss}is', out_sign='(a(a{ss}(aa{ss}a{ss}))a{ss})',
115 method=self.getGroupBlogsWithComments, 116 # method=self.getGroupBlogsWithComments,
116 async=True) 117 # async=True)
117 118
118 # host.bridge.addMethod("getMassiveGroupBlogs", ".plugin", 119 # host.bridge.addMethod("getMassiveGroupBlogs", ".plugin",
119 # in_sign='sasa{ss}s', out_sign='a{s(aa{ss}a{ss})}', 120 # in_sign='sasa{ss}s', out_sign='a{s(aa{ss}a{ss})}',
120 # method=self._getMassiveGroupBlogs, 121 # method=self._getMassiveGroupBlogs,
121 # async=True) 122 # async=True)
128 # host.bridge.addMethod("subscribeGroupBlog", ".plugin", in_sign='ss', out_sign='', 129 # host.bridge.addMethod("subscribeGroupBlog", ".plugin", in_sign='ss', out_sign='',
129 # method=self.subscribeGroupBlog, 130 # method=self.subscribeGroupBlog,
130 # async=True) 131 # async=True)
131 132
132 # host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger) 133 # host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger)
134 host.trigger.add("XEP-0277_data2entry", self._data2entryTrigger)
135 host.trigger.add("XEP-0277_comments", self._commentsTrigger)
133 136
134 ## plugin management methods ## 137 ## plugin management methods ##
135 138
136 def getHandler(self, profile): 139 def getHandler(self, profile):
137 return GroupBlog_handler() 140 return GroupBlog_handler()
138 141
139 @defer.inlineCallbacks 142 @defer.inlineCallbacks
140 def profileConnected(self, profile): 143 def profileConnected(self, profile):
141 client = self.host.getClient(profile) 144 client = self.host.getClient(profile)
142 try: 145 try:
143 yield self.host.checkFeatures((NS_PUBSUB_GROUPBLOG, NS_PUBSUB_AUTO_CREATE), profile=profile) 146 yield self.host.checkFeatures((NS_PUBSUB_GROUPBLOG,), profile=profile)
144 except exceptions.FeatureNotFound: 147 except exceptions.FeatureNotFound:
145 client.server_groupblog_available = False 148 client.server_groupblog_available = False
146 log.warning(_(u"Server is not able to manage item-access pubsub, we can't use group blog")) 149 log.warning(_(u"Server is not able to manage item-access pubsub, we can't use group blog"))
147 else: 150 else:
148 client.server_groupblog_available = True 151 client.server_groupblog_available = True
160 log.debug("Profile is not connected, service is not checked yet") 163 log.debug("Profile is not connected, service is not checked yet")
161 else: 164 else:
162 log.error("Service should be available !") 165 log.error("Service should be available !")
163 return {} 166 return {}
164 167
168 def _data2entryTrigger(self, client, mb_data, entry_elt, item_elt):
169 """Build fine access permission if needed
170
171 This trigger check if "group*" key are present,
172 and create a fine item config to restrict view to these groups
173 """
174 groups = list(common.dict2iter('group', mb_data))
175 if not groups:
176 return
177 if not client.server_groupblog_available:
178 raise exceptions.CancelError(u"GroupBlog is not available")
179 log.debug(u"This entry use group blog")
180 form = data_form.Form('submit', formNamespace=NS_PUBSUB_ITEM_CONFIG)
181 # FIXME: ACCESS_ROSTER need to be changed to a new ACCESS_PUBLISHER_ROSTER when available
182 access = data_form.Field(None, self._p.OPT_ACCESS_MODEL, value=self._p.ACCESS_ROSTER)
183 allowed = data_form.Field(None, self._p.OPT_ROSTER_GROUPS_ALLOWED, values=groups)
184 form.addField(access)
185 form.addField(allowed)
186 item_elt.addChild(form.toElement())
187
188 def _commentsTrigger(self, client, mb_data, options):
189 """This method is called when a comments node is about to be created
190
191 It changes the access mode to roster if needed, and give the authorized groups
192 """
193 if "group" in mb_data:
194 # FIXME: ACCESS_ROSTER need to be changed to a new ACCESS_PUBLISHER_ROSTER when available
195 options[self._p.OPT_ACCESS_MODEL] = self._p.ACCESS_ROSTER
196 options[self._p.OPT_ROSTER_GROUPS_ALLOWED] = list(common.dict2iter('group', mb_data))
165 197
166 @defer.inlineCallbacks 198 @defer.inlineCallbacks
167 def _initialise(self, profile_key): 199 def _initialise(self, profile_key):
168 """Check that the data for this profile are initialised, and do it else 200 """Check that the data for this profile are initialised, and do it else
169 @param profile_key: %(doc_profile)s""" 201 @param profile_key: %(doc_profile)s"""