added possibility to bulk import users/accounts from a CSV file
This commit is contained in:
parent
8db7bbb8e6
commit
225d803e96
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue