Switch to unified view

a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
1
'''
1
'''
2
Allura plugins for authentication and project registration
2
Allura plugins for authentication and project registration
3
'''
3
'''
4
import re
5
import os
4
import logging
6
import logging
5
import re
7
import subprocess
6
8
7
from random import randint
9
from random import randint
8
from hashlib import sha256
10
from hashlib import sha256
9
from base64 import b64encode
11
from base64 import b64encode
10
from datetime import datetime
12
from datetime import datetime
11
13
12
import ldap
14
import ldap
15
from ldap import modlist
13
import pkg_resources
16
import pkg_resources
14
from tg import config
17
from tg import config
15
from pylons import g, c
18
from pylons import g, c
16
from webob import exc
19
from webob import exc
17
20
...
...
78
        raise NotImplementedError, 'by_username'
81
        raise NotImplementedError, 'by_username'
79
82
80
    def set_password(self, user, old_password, new_password):
83
    def set_password(self, user, old_password, new_password):
81
        raise NotImplementedError, 'set_password'
84
        raise NotImplementedError, 'set_password'
82
85
86
    def upload_sshkey(self, username, pubkey):
87
        raise NotImplemented, 'upload_sshkey'
88
83
class LocalAuthenticationProvider(AuthenticationProvider):
89
class LocalAuthenticationProvider(AuthenticationProvider):
84
90
85
    def register_user(self, user_doc):
91
    def register_user(self, user_doc):
86
        from allura import model as M
92
        from allura import model as M
87
        return M.User(**user_doc)
93
        return M.User(**user_doc)
...
...
121
127
122
class LdapAuthenticationProvider(AuthenticationProvider):
128
class LdapAuthenticationProvider(AuthenticationProvider):
123
129
124
    def register_user(self, user_doc):
130
    def register_user(self, user_doc):
125
        from allura import model as M
131
        from allura import model as M
126
        password = user_doc.pop('password', None)
132
        password = user_doc['password'].encode('utf-8')
127
        result = M.User(**user_doc)
133
        result = M.User(**user_doc)
128
        dn = 'uid=%s,%s' % (user_doc['username'], config['auth.ldap.suffix'])
134
        dn_u = 'uid=%s,%s' % (user_doc['username'], config['auth.ldap.suffix'])
135
        uid = str(M.AuthGlobals.get_next_uid())
129
        try:
136
        try:
130
            con = ldap.initialize(config['auth.ldap.server'])
137
            con = ldap.initialize(config['auth.ldap.server'])
131
            con.bind_s(config['auth.ldap.admin_dn'],
138
            con.bind_s(config['auth.ldap.admin_dn'],
132
                       config['auth.ldap.admin_password'])
139
                       config['auth.ldap.admin_password'])
133
            ldap_info = dict(
140
            uname = user_doc['username'].encode('utf-8')
134
                uid=user_doc['username'],
135
                displayName=user_doc['display_name'],
141
            display_name = user_doc['display_name'].encode('utf-8')
136
                cn=user_doc['display_name'],
142
            ldif_u = modlist.addModlist(dict(
143
                uid=uname,
137
                userPassword=password,
144
                userPassword=password,
138
                objectClass=['inetOrgPerson'],
145
                objectClass=['account', 'posixAccount' ],
139
                givenName=user_doc['display_name'].split()[0],
146
                cn=display_name,
140
                sn=user_doc['display_name'].split()[-1])
147
                uidNumber=uid,
141
            ldap_info = dict((k,v) for k,v in ldap_info.iteritems()
148
                gidNumber='10001',
142
                             if v is not None)
149
                homeDirectory='/home/' + uname,
150
                loginShell='/bin/bash',
151
                gecos=uname,
152
                description='SCM user account'))
143
            try:
153
            try:
144
                con.add_s(dn, ldap_info.items())
154
                con.add_s(dn_u, ldif_u)
145
            except ldap.ALREADY_EXISTS:
155
            except ldap.ALREADY_EXISTS:
146
                con.modify_s(dn, [(ldap.MOD_REPLACE, k, v)
156
                log.exception('Trying to create existing user %s', uname)
147
                                  for k,v in ldap_info.iteritems()])
157
                raise
148
            con.unbind_s()
158
            con.unbind_s()
159
            argv = ('schroot -d / -c %s -u root /ldap-userconfig.py init %s' % (
160
                config['auth.ldap.schroot_name'], user_doc['username'])).split()
161
            p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
162
            rc = p.wait()
163
            if rc != 0:
164
                log.error('Error creating home directory for %s',
165
                          user_doc['username'])
149
        except:
166
        except:
150
            raise
167
            raise
151
        return result
168
        return result
152
169
170
    def upload_sshkey(self, username, pubkey):
171
            argv = ('schroot -d / -c %s -u root /ldap-userconfig.py upload %s' % (
172
                config['auth.ldap.schroot_name'], username)).split() + [ pubkey ]
173
            p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
174
            rc = p.wait()
175
            if rc != 0:
176
                errmsg = p.stdout.read()
177
                log.exception('Error uploading public SSH key for %s: %s',
178
                              username, errmsg)
179
                assert False, errmsg
180
153
    def by_username(self, username):
181
    def by_username(self, username):
154
        from allura import model as M
182
        from allura import model as M
155
        return M.User.query.get(username=username)
183
        return M.User.query.get(username=username)
156
184
157
    def set_password(self, user, old_password, new_password):
185
    def set_password(self, user, old_password, new_password):
158
        try:
186
        try:
187
            import pdb; pdb.set_trace()
159
            dn = 'uid=%s,%s' % (self.username, config['auth.ldap.suffix'])
188
            dn = 'uid=%s,%s' % (user.username, config['auth.ldap.suffix'])
160
            con = ldap.initialize(config['auth.ldap.server'])
189
            con = ldap.initialize(config['auth.ldap.server'])
161
            con.bind_s(dn, old_password)
190
            con.bind_s(dn, old_password.encode('utf-8'))
162
            con.modify_s(dn, [(ldap.MOD_REPLACE, 'userPassword', new_password)])
191
            con.modify_s(dn, [(ldap.MOD_REPLACE, 'userPassword', new_password.encode('utf-8'))])
163
            con.unbind_s()
192
            con.unbind_s()
164
        except ldap.INVALID_CREDENTIALS:
193
        except ldap.INVALID_CREDENTIALS:
165
            raise exc.HTTPUnauthorized()
194
            raise exc.HTTPUnauthorized()
166
195
167
    def _login(self):
196
    def _login(self):
...
...
299
            32: 'images/ext_32.png',
328
            32: 'images/ext_32.png',
300
            48: 'images/ext_48.png'
329
            48: 'images/ext_48.png'
301
        }
330
        }
302
    }
331
    }
303
332
333
    @LazyProperty
334
    def password_change_form(self):
335
        from allura.lib.widgets.forms import PasswordChangeForm
336
        return PasswordChangeForm(action='/auth/prefs/change_password')
337
338
    @LazyProperty
339
    def upload_key_form(self):
340
        from allura.lib.widgets.forms import UploadKeyForm
341
        return UploadKeyForm(action='/auth/prefs/upload_sshkey')
342
304
    @property
343
    @property
305
    def master(self):
344
    def master(self):
306
        return self.master_template
345
        return self.master_template
307
346
308
    @classmethod
347
    @classmethod
...
...
326
                    app_class = ep.load()
365
                    app_class = ep.load()
327
                    return app_class.icon_url(size)
366
                    return app_class.icon_url(size)
328
        else:
367
        else:
329
            return app.icon_url(size)
368
            return app.icon_url(size)
330
369
331
332
class LocalProjectRegistrationProvider(ProjectRegistrationProvider):
370
class LocalProjectRegistrationProvider(ProjectRegistrationProvider):
333
    pass
371
    pass