comparison src/plugins/plugin_misc_account.py @ 569:06faf5bffbc0

plugin account: first draft of automatic SàT/Prosody account creation (basis coming from Libervia)
author Goffi <goffi@goffi.org>
date Mon, 07 Jan 2013 01:03:49 +0100
parents
children 1cb24325485c
comparison
equal deleted inserted replaced
568:239abc5484c9 569:06faf5bffbc0
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 """
5 SAT plugin for parrot mode (experimental)
6 Copyright (C) 2009, 2010, 2011, 2012 Jérôme Poisson (goffi@goffi.org)
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """
21
22 from logging import debug, info, warning, error
23 from sat.core import exceptions
24 from twisted.internet import reactor, defer, protocol
25 from os.path import join, dirname
26 from twisted.python.procutils import which
27
28 PLUGIN_INFO = {
29 "name": "Account Plugin",
30 "import_name": "MISC-ACCOUNT",
31 "type": "MISC",
32 "protocols": [],
33 "dependencies": [],
34 "main": "MiscAccount",
35 "handler": "no",
36 "description": _(u"""SàT account creation""")
37 }
38
39 #You need do adapt the following consts to your server
40 _REG_EMAIL_FROM = "NOREPLY@libervia.org"
41 _REG_EMAIL_SERVER = "localhost"
42 _REG_ADMIN_EMAIL = "goffi@goffi.org"
43 _NEW_ACCOUNT_SERVER = "localhost"
44 _NEW_ACCOUNT_DOMAIN = "necton3.int"
45 _NEW_ACCOUNT_RESOURCE = "libervia"
46 _PROSODY_PATH = None #prosody path (where prosodyctl will be executed from), or None to automaticaly find it
47 _PROSODYCTL = "prosodyctl"
48
49 RESERVED = ['libervia']
50
51 class ProsodyRegisterProtocol(protocol.ProcessProtocol):
52 """ Try to register an account with prosody """
53
54 def __init__(self, password, deferred = None):
55 self.password = password
56 self.deferred = deferred
57 self.data = ''
58
59 def connectionMade(self):
60 self.transport.write("%s\n%s" % ((self.password.encode('utf-8'),)*2))
61 self.transport.closeStdin()
62
63
64 def outReceived(self, data):
65 self.data += data
66
67 def errReceived(self, data):
68 self.err += data
69
70 def processEnded(self, reason):
71 if (reason.value.exitCode == 0):
72 info(_('Prosody registration success'))
73 self.deferred.callback(None)
74 else:
75 error(_(u"Can't register Prosody account (error code: %(code)d): %(message)s") % {'code': reason.value.exitCode, 'message': self.data})
76 self.deferred.errback("INTERNAL")
77
78
79 class MiscAccount():
80 """Account plugin: create a SàT + Prosody account, used by Libervia"""
81 #XXX: This plugin is a Q&D one used for the demo. Something more generic (and not
82 # only focused on Prosody) is planed
83 _prosody_path = _PROSODY_PATH or ''
84
85 def __init__(self, host):
86 info(_(u"Plugin Account initialization"))
87 self.host = host
88 host.bridge.addMethod("registerSatAccount", ".plugin", in_sign='sss', out_sign='', method=self._registerAccount, async = True)
89 if not self._prosody_path:
90 paths = which(_PROSODYCTL)
91 if not paths:
92 error(_("Can't find %s") % (_PROSODYCTL,))
93 else:
94 self._prosody_path = dirname(paths[0])
95 info(_('Prosody path found: %s') % (self._prosody_path,))
96
97 def _registerAccount(self, email, password, profile):
98
99 """
100 #Password Generation
101 #_charset = [chr(i) for i in range(0x21,0x7F)] #XXX: this charset seems to have some issues with openfire
102 _charset = [chr(i) for i in range(0x30,0x3A) + range(0x41,0x5B) + range (0x61,0x7B)]
103 import random
104 random.seed()
105 password = ''.join([random.choice(_charset) for i in range(15)])
106 """
107 if not email or not password or not profile:
108 raise exceptions.DataError
109
110 if profile.lower() in RESERVED:
111 return defer.fail('CONFLICT')
112
113 d = self.host.memory.asyncCreateProfile(profile)
114 d.addCallback(self._profileRegistered, email, password, profile)
115 return d
116
117 def _profileRegistered(self, result, email, password, profile):
118
119 #FIXME: values must be in a config file instead of hardcoded
120 self.host.memory.setParam("JabberID", "%s@%s/%s" % (profile, _NEW_ACCOUNT_DOMAIN, _NEW_ACCOUNT_RESOURCE), "Connection", profile)
121 self.host.memory.setParam("Server", _NEW_ACCOUNT_SERVER, "Connection", profile)
122 self.host.memory.setParam("Password", password, "Connection", profile)
123 #and the account
124
125 #XXX: we use "prosodyctl adduser" because "register" doesn't check conflict
126 # and just change the password if the account already exists
127 d = defer.Deferred()
128 prosody_reg = ProsodyRegisterProtocol(password, d)
129 prosody_exe = join (self._prosody_path, _PROSODYCTL)
130 reactor.spawnProcess(prosody_reg, prosody_exe, [prosody_exe, 'adduser', "%s@%s" % (profile, _NEW_ACCOUNT_DOMAIN)], path=self._prosody_path)
131
132 d.addCallback(self._accountCreated)
133 return d
134
135 def _accountCreated(self, result):
136 print "_accountCreated"
137
138 #action_id = self.sat_host.bridge.registerNewAccount(login, password, email, _NEW_ACCOUNT_DOMAIN, 5222)
139 #self.sat_host.action_handler.waitForId(self._postAccountCreation, action_id, profile)
140
141 ##time to send the email
142
143 #_email_host = _REG_EMAIL_SERVER
144 #_email_from = _REG_EMAIL_FROM
145
146 #def email_ok(ignore):
147 # print ("Account creation email sent to %s" % email)
148
149 #def email_ko(ignore):
150 # #TODO: return error code to user
151 # error ("Failed to send email to %s" % email)
152 #
153 #body = (u"""Welcome to Libervia, a Salut à Toi project part
154 #
155 #/!\\ WARNING, THIS IS ONLY A TECHNICAL DEMO, DON'T USE THIS ACCOUNT FOR ANY SERIOUS PURPOSE /!\\
156 #
157 #Here are your connection informations:
158 #login: %(login)s
159 #password: %(password)s
160 #
161 #Your Jabber ID (JID) is: %(jid)s
162 #
163 #Any feedback welcome
164 #
165 #Cheers
166 #Goffi""" % { 'login': login, 'password': password, 'jid':"%s@%s" % (login, _NEW_ACCOUNT_DOMAIN) }).encode('utf-8')
167 #msg = MIMEText(body, 'plain', 'UTF-8')
168 #msg['Subject'] = 'Libervia account created'
169 #msg['From'] = _email_from
170 #msg['To'] = email
171
172 #d = sendmail(_email_host, _email_from, email, msg.as_string())
173 #d.addCallbacks(email_ok, email_ko)
174
175 ##email to the administrator
176
177 #body = (u"""New account created: %(login)s [%(email)s]""" % { 'login': login, 'email': email }).encode('utf-8')
178 #msg = MIMEText(body, 'plain', 'UTF-8')
179 #msg['Subject'] = 'Libervia new account created'
180 #msg['From'] = _email_from
181 #msg['To'] = _REG_ADMIN_EMAIL
182
183 #d = sendmail(_email_host, _email_from, _REG_ADMIN_EMAIL, msg.as_string())
184 #d.addCallbacks(email_ok, email_ko)
185 #return "REGISTRATION"