Mercurial > libervia-backend
comparison src/plugins/plugin_misc_invitations.py @ 2219:77a3d0a28642
plugin invitations: added modify method (+ bridge) and fixed email setting in extra
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 03 Apr 2017 00:23:01 +0200 |
parents | eaf2467d19ce |
children | c6c9a97ffebf |
comparison
equal
deleted
inserted
replaced
2218:6a2fa651d7fa | 2219:77a3d0a28642 |
---|---|
46 INVITEE_PROFILE_TPL = u"guest@@{uuid}" | 46 INVITEE_PROFILE_TPL = u"guest@@{uuid}" |
47 KEY_ID = u'id' | 47 KEY_ID = u'id' |
48 KEY_JID = u'jid' | 48 KEY_JID = u'jid' |
49 KEY_CREATED = u'created' | 49 KEY_CREATED = u'created' |
50 KEY_LAST_CONNECTION = u'last_connection' | 50 KEY_LAST_CONNECTION = u'last_connection' |
51 EXTRA_RESERVED = {KEY_ID, KEY_JID, KEY_CREATED, u'jid_', u'jid', KEY_LAST_CONNECTION} | 51 KEY_GUEST_PROFILE = u'guest_profile' |
52 KEY_PASSWORD = u'password' | |
53 EXTRA_RESERVED = {KEY_ID, KEY_JID, KEY_CREATED, u'jid_', u'jid', KEY_LAST_CONNECTION, KEY_GUEST_PROFILE, KEY_PASSWORD} | |
52 DEFAULT_SUBJECT = D_(u"You have been invited by {host_name} to {app_name}") | 54 DEFAULT_SUBJECT = D_(u"You have been invited by {host_name} to {app_name}") |
53 DEFAULT_BODY = D_(u"""Hello {name}! | 55 DEFAULT_BODY = D_(u"""Hello {name}! |
54 | 56 |
55 You have received an invitation from {host_name} to participate to "{app_name}". | 57 You have received an invitation from {host_name} to participate to "{app_name}". |
56 To join, you just have to click on the following URL: | 58 To join, you just have to click on the following URL: |
68 def __init__(self, host): | 70 def __init__(self, host): |
69 log.info(_(u"plugin Invitations initialization")) | 71 log.info(_(u"plugin Invitations initialization")) |
70 self.host = host | 72 self.host = host |
71 self.invitations = persistent.LazyPersistentBinaryDict(u'invitations') | 73 self.invitations = persistent.LazyPersistentBinaryDict(u'invitations') |
72 host.bridge.addMethod("invitationCreate", ".plugin", in_sign='sssssssssa{ss}s', out_sign='a{ss}', | 74 host.bridge.addMethod("invitationCreate", ".plugin", in_sign='sssssssssa{ss}s', out_sign='a{ss}', |
73 method=self._createInvitation, | 75 method=self._create, |
74 async=True) | 76 async=True) |
75 host.bridge.addMethod("invitationGet", ".plugin", in_sign='s', out_sign='a{ss}', | 77 host.bridge.addMethod("invitationGet", ".plugin", in_sign='s', out_sign='a{ss}', |
76 method=self.getInvitation, | 78 method=self.get, |
77 async=True) | 79 async=True) |
78 | 80 host.bridge.addMethod("invitationModify", ".plugin", in_sign='sa{ss}b', out_sign='', |
79 def _createInvitation(self, jid_=u'', password=u'', name=u'', host_name=u'', email=u'', language=u'', url_template=u'', message_subject=u'', message_body=u'', extra=None, profile=u''): | 81 method=self._modify, |
82 async=True) | |
83 | |
84 def checkExtra(self, extra): | |
85 if EXTRA_RESERVED.intersection(extra): | |
86 raise ValueError(_(u"You can't use following key(s) in extra, they are reserved: {}").format( | |
87 u', '.join(EXTRA_RESERVED.intersection(extra)))) | |
88 | |
89 def _create(self, jid_=u'', password=u'', name=u'', host_name=u'', email=u'', language=u'', url_template=u'', message_subject=u'', message_body=u'', extra=None, profile=u''): | |
80 # XXX: we don't use **kwargs here to keep arguments name for introspection with D-Bus bridge | 90 # XXX: we don't use **kwargs here to keep arguments name for introspection with D-Bus bridge |
81 | 91 |
82 if extra is None: | 92 if extra is None: |
83 extra = {} | 93 extra = {} |
84 else: | 94 else: |
88 kwargs = {"extra": extra} | 98 kwargs = {"extra": extra} |
89 for key in ("jid_", "password", "name", "host_name", "email", "language", "url_template", "message_subject", "message_body", "profile"): | 99 for key in ("jid_", "password", "name", "host_name", "email", "language", "url_template", "message_subject", "message_body", "profile"): |
90 value = locals()[key] | 100 value = locals()[key] |
91 if value: | 101 if value: |
92 kwargs[key] = unicode(value) | 102 kwargs[key] = unicode(value) |
93 d = self.createInvitation(**kwargs) | 103 d = self.create(**kwargs) |
94 def serialize(data): | 104 def serialize(data): |
95 data[KEY_JID] = data[KEY_JID].full() | 105 data[KEY_JID] = data[KEY_JID].full() |
96 d.addCallback(serialize) | 106 d.addCallback(serialize) |
97 return d | 107 return d |
98 | 108 |
99 @defer.inlineCallbacks | 109 @defer.inlineCallbacks |
100 def createInvitation(self, **kwargs): | 110 def create(self, **kwargs): |
101 ur"""create an invitation | 111 ur"""create an invitation |
102 | 112 |
103 this will create an XMPP account and a profile, and use a UUID to retrieve them. | 113 this will create an XMPP account and a profile, and use a UUID to retrieve them. |
104 the profile is automatically generated in the form guest@@[UUID], this way they can be retrieved easily | 114 the profile is automatically generated in the form guest@@[UUID], this way they can be retrieved easily |
105 **kwargs: keywords arguments which can have the following keys, unset values are equivalent to None: | 115 **kwargs: keywords arguments which can have the following keys, unset values are equivalent to None: |
144 - filled extra dictionary, as saved in the databae | 154 - filled extra dictionary, as saved in the databae |
145 """ | 155 """ |
146 ## initial checks | 156 ## initial checks |
147 extra = kwargs.pop('extra', {}) | 157 extra = kwargs.pop('extra', {}) |
148 if set(kwargs).intersection(extra): | 158 if set(kwargs).intersection(extra): |
149 raise exceptions.ValueError(_(u"You can't use following key(s) in both args and extra: {}").format( | 159 raise ValueError(_(u"You can't use following key(s) in both args and extra: {}").format( |
150 u', '.join(set(kwargs).intersection(extra)))) | 160 u', '.join(set(kwargs).intersection(extra)))) |
151 | 161 |
152 if EXTRA_RESERVED.intersection(extra): | 162 self.checkExtra(extra) |
153 raise exceptions.ValueError(_(u"You can't use following key(s) in extra, they are reserved: {}").format( | |
154 u', '.join(EXTRA_RESERVED.intersection(extra)))) | |
155 | 163 |
156 if not 'url_template' in extra and not 'message_body' in extra: | 164 if not 'url_template' in extra and not 'message_body' in extra: |
157 raise ValueError(_(u"You need to provide url_template if you use default message body")) | 165 raise ValueError(_(u"You need to provide url_template if you use default message body")) |
158 | 166 |
159 | 167 |
170 # it is needed for invitation as the same password is used for profile | 178 # it is needed for invitation as the same password is used for profile |
171 # and SàT need to be able to automatically open the profile with the uuid | 179 # and SàT need to be able to automatically open the profile with the uuid |
172 # FIXME: we could add an extra encryption key which would be used with the uuid | 180 # FIXME: we could add an extra encryption key which would be used with the uuid |
173 # when the invitee is connecting (e.g. with URL). This key would not be saved | 181 # when the invitee is connecting (e.g. with URL). This key would not be saved |
174 # and could be used to encrypt profile password. | 182 # and could be used to encrypt profile password. |
175 extra[u'password'] = password | 183 extra[KEY_PASSWORD] = password |
176 | 184 |
177 jid_ = kwargs.pop(u'jid_', None) | 185 jid_ = kwargs.pop(u'jid_', None) |
178 if not jid_: | 186 if not jid_: |
179 domain = self.host.memory.getConfig(None, 'xmpp_domain') | 187 domain = self.host.memory.getConfig(None, 'xmpp_domain') |
180 if not domain: | 188 if not domain: |
204 raise e | 212 raise e |
205 | 213 |
206 log.info(_(u"account {jid_} created").format(jid_=jid_.full())) | 214 log.info(_(u"account {jid_} created").format(jid_=jid_.full())) |
207 | 215 |
208 ## profile creation | 216 ## profile creation |
209 extra['guest_profile'] = guest_profile = INVITEE_PROFILE_TPL.format(uuid=id_) | 217 extra[KEY_GUEST_PROFILE] = guest_profile = INVITEE_PROFILE_TPL.format(uuid=id_) |
210 # profile creation should not fail as we generate unique name ourselves | 218 # profile creation should not fail as we generate unique name ourselves |
211 yield self.host.memory.createProfile(guest_profile, password) | 219 yield self.host.memory.createProfile(guest_profile, password) |
212 yield self.host.memory.startSession(password, guest_profile) | 220 yield self.host.memory.startSession(password, guest_profile) |
213 yield self.host.memory.setParam("JabberID", jid_.full(), "Connection", profile_key=guest_profile) | 221 yield self.host.memory.setParam("JabberID", jid_.full(), "Connection", profile_key=guest_profile) |
214 yield self.host.memory.setParam("Password", password, "Connection", profile_key=guest_profile) | 222 yield self.host.memory.setParam("Password", password, "Connection", profile_key=guest_profile) |
218 if language is not None: | 226 if language is not None: |
219 extra[u'language'] = language | 227 extra[u'language'] = language |
220 email = kwargs.pop(u'email', None) | 228 email = kwargs.pop(u'email', None) |
221 | 229 |
222 if email is not None: | 230 if email is not None: |
231 extra[u'email'] = email | |
223 url_template = kwargs.pop(u'url_template', '') | 232 url_template = kwargs.pop(u'url_template', '') |
224 format_args = { | 233 format_args = { |
225 u'uuid': id_, | 234 u'uuid': id_, |
226 u'app_name': C.APP_NAME, | 235 u'app_name': C.APP_NAME, |
227 u'app_url': C.APP_URL} | 236 u'app_url': C.APP_URL} |
262 | 271 |
263 extra[KEY_ID] = id_ | 272 extra[KEY_ID] = id_ |
264 extra[KEY_JID] = jid | 273 extra[KEY_JID] = jid |
265 defer.returnValue(extra) | 274 defer.returnValue(extra) |
266 | 275 |
267 def getInvitation(self, id_): | 276 def get(self, id_): |
268 """Retrieve invitation linked to uuid if it exists | 277 """Retrieve invitation linked to uuid if it exists |
269 | 278 |
270 @param id_(unicode): UUID linked to an invitation | 279 @param id_(unicode): UUID linked to an invitation |
271 @return dict(unicode, unicode): data associated to the invitation | 280 @return (dict[unicode, unicode]): data associated to the invitation |
272 @raise KeyError: there is not invitation with this id_ | 281 @raise KeyError: there is not invitation with this id_ |
273 """ | 282 """ |
274 return self.invitations[id_] | 283 return self.invitations[id_] |
284 | |
285 def _modify(self, id_, new_extra, replace): | |
286 return self.modify(id_, {unicode(k): unicode(v) for k,v in new_extra.iteritems()}, replace) | |
287 | |
288 def modify(self, id_, new_extra, replace=False): | |
289 """Modify invitation data | |
290 | |
291 @param id_(unicode): UUID linked to an invitation | |
292 @param new_extra(dict[unicode, unicode]): data to update | |
293 @param replace(bool): if True replace the data | |
294 else update them | |
295 @raise KeyError: there is not invitation with this id_ | |
296 """ | |
297 self.checkExtra(new_extra) | |
298 def gotCurrentData(current_data): | |
299 if replace: | |
300 new_data = new_extra | |
301 for k in EXTRA_RESERVED: | |
302 try: | |
303 new_data[k] = current_data[k] | |
304 except KeyError: | |
305 continue | |
306 else: | |
307 new_data = current_data | |
308 for k,v in new_extra.iteritems(): | |
309 new_data[k] = v | |
310 | |
311 self.invitations[id_] = new_data | |
312 | |
313 d = self.invitations[id_] | |
314 d.addCallback(gotCurrentData) | |
315 return d |