added possibility to bulk import users/accounts from a CSV file

This commit is contained in:
Frédéric Péters 2009-03-25 10:54:47 +00:00
parent 8db7bbb8e6
commit 225d803e96
1 changed files with 118 additions and 1 deletions

View File

@ -1,6 +1,7 @@
import random
import string
import time
import csv
from base import AuthMethod
@ -530,18 +531,23 @@ class MethodAdminDirectory(Directory):
title = ADMIN_TITLE
label = N_('Configure username/password identification method')
_q_exports = ['', 'passwords', 'identities']
_q_exports = ['', 'passwords', 'identities', ('import', 'p_import')]
def _q_index [html] (self):
admin_html_top('settings', title = _(ADMIN_TITLE))
get_response().breadcrumb.append( ('password/', _(self.title)))
'<h2>%s</h2>' % _(ADMIN_TITLE)
get_session().display_message()
'<dl>'
'<dt><a href="identities">%s</a></dt> <dd>%s</dd>' % (
_('Identities'), _('Configure identities creation'))
'<dt><a href="passwords">%s</a></dt> <dd>%s</dd>' % (
_('Passwords'), _('Configure all password things'))
'<dt><a href="import">%s</a></dt> <dd>%s</dd>' % (
_('Bulk Import'), _('Import accounts from a CVSV file'))
'</dl>'
def passwords [html] (self):
@ -635,6 +641,117 @@ class MethodAdminDirectory(Directory):
('creation', 'email-as-username', 'notify-on-register', 'email-confirmation',
'warn_about_unused_account_delay', 'remove_unused_account_delay'))
def p_import [html] (self):
form = Form(enctype='multipart/form-data')
form.add(FileWidget, 'file', title = _('File'), required = True)
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
if form.get_submit() == 'cancel':
return redirect('.')
if form.is_submitted() and not form.has_errors():
self.import_submit(form)
if not form.has_errors():
return redirect('.')
admin_html_top('settings', title = _('Bulk Import'))
identities_cfg = get_cfg('identities', {})
users_cfg = get_cfg('users', {})
'<h2>%s</h2>' % _('Bulk Import')
'<p>'
_('The CSV file must strictly adhere to the following structure:')
'</p>'
'<ul>'
'<li>%s</li>' % _('Charset: %s') % get_publisher().site_charset
'<li>%s</li>' % _('Column Separator: ;')
'<li>%s' % ('Columns:')
'<ul>'
if not identities_cfg.get('email-as-username', False):
'<li>%s</li>' % _('Username')
formdef = get_publisher().user_class.get_formdef()
if not formdef or not users_cfg.get('field_name'):
'<li>%s</li>' % _('Name')
if not formdef or not users_cfg.get('field_email'):
'<li>%s</li>' % _('Email')
if formdef:
for field in formdef.fields:
'<li>%s</li>' % field.label
'</ul>'
'</li>'
'</li>'
'</ul>'
'<p>'
_('Passwords will be automatically generated.')
'</p>'
form.render()
def import_submit(self, form):
identities_cfg = get_cfg('identities', {})
users_cfg = get_cfg('users', {})
required_nb_columns = 0
if not identities_cfg.get('email-as-username', False):
required_nb_columns += 1
username_field_number = 0
formdef = get_publisher().user_class.get_formdef()
if not formdef or not users_cfg.get('field_name'):
name_field = required_nb_columns
required_nb_columns += 1
if not formdef or not users_cfg.get('field_email'):
email_field = required_nb_columns
if identities_cfg.get('email-as-username', False):
username_field_number = required_nb_columns
required_nb_columns += 1
if formdef:
base_formdef_field_no = required_nb_columns
required_nb_columns += len(formdef.fields)
objects = []
reader = csv.reader(form.get_widget('file').parse().fp, delimiter=';')
for i, csv_line in enumerate(reader):
if len(csv_line) != required_nb_columns:
form.set_error('file', _('Incorrect number of columns (line: %s)') % (i+1))
return
u = get_publisher().user_class()
if formdef:
if not users_cfg.get('field_name'):
u.name = csv_line[name_field]
if not users_cfg.get('field_email'):
u.email = csv_line[email_field]
data = {}
for j, field in enumerate(formdef.fields):
if users_cfg.get('field_email') == field.id:
username_field_number = base_formdef_field_no+j
data[field.id] = csv_line[base_formdef_field_no+j]
u.set_attributes_from_formdata(data)
u.form_data = data
else:
u.name = csv_line[name_field]
u.email = csv_line[email_field]
username = csv_line[username_field_number]
if PasswordAccount.has_key(username):
form.set_error('file', _('Duplicate username (line: %s)') % (i+1))
return
if [x for x in objects if x[1].id == username]:
form.set_error('file', _('Duplicate username (line: %s)') % (i+1))
return
p = PasswordAccount(id=username)
objects.append((u, p))
for u, p in objects:
u.store()
p.user_id = u.id
p.store()
get_session().message = ('info', _('Number of accounts created: %s') % (i+1))
class UsernamePasswordWidget(CompositeWidget):