def create_consumer(member): password = NeoProfile.generate_password() login_alias = normalize_username(member.username) wrapper = wrap_member(member, login_alias=login_alias, password=password) consumer_id, uri = api.create_consumer(wrapper.consumer) api.complete_registration(consumer_id) # activates the account # the NeoProfile needs to be saved elsewhere when member has been saved return NeoProfile(user=member, consumer_id=consumer_id, password=password, login_alias=login_alias)
def dataloadtool_export(output, credentials_output, members, password_callback=None, pretty_print=False): """ Export the given members as XML input for the CIDB Data Load Tool. :param output: File-like object to write to. :param members: Queryset of members to export. If this is a large queryset, consider using `iterator()` on it, to avoid excessive caching. :param password_callback: If supplied, use this function to set or generate new passwords as part of the export. This can be used, for example, to port member passwords from another source into CIDB. The function will be passed each `Member` in turn, and should return either a new (raw, unhashed) password, or `None`, to not include a password in the export. (To preserve what the default exported password would be, the function can explicitly return the member's `raw_password`, if it is set.) """ # XXX: We take advantage of the existing ConsumerWrapper logic to construct # a GeneratedsSuper instance, which we then convert to lxml for further # manipulation. Once ConsumerWrapper (or its replacement) can give us a # lxml tree directly, we can skip this step. def etree_from_gds(gds): sio = StringIO() gds.export(sio, 0, pretty_print=False) return etree.fromstring(sio.getvalue()) password_path = objectify.ObjectPath('Consumer.UserAccount.LoginCredentials.Password') output.write('<Consumers>\n') last_username = '' import time import csv credentials_csv = csv.DictWriter(credentials_output, ['username', 'login_alias', 'password']) # Important: The iterator() call prevents memory usage from growing out # of control, when exporting many members. Don't remove it accidentally. for (i, member) in enumerate(members.select_related('neoprofile').order_by('username').iterator()): # Resolve duplicate usernames, or use available login_alias try: wrapper = wrap_member(member, login_alias=member.neoprofile.login_alias, password=member.neoprofile.password) except (NeoProfile.DoesNotExist, AttributeError): password = NeoProfile.generate_password() if member.username.lower() == last_username: # append part of timestamp to username to make it unique timestamp = str(int(time.time() * 1000000))[-10:] login_alias = "%s%s" % (member.username, timestamp) else: login_alias = member.username login_alias = normalize_username(login_alias) wrapper = wrap_member(member, login_alias=login_alias, password=password) # write aliases and passwords to file credentials_csv.writerow({ 'username': member.username.encode('utf-8'), 'login_alias': login_alias.encode('utf-8'), 'password': password.encode('utf-8') }) last_username = member.username.lower() elem = etree_from_gds(wrapper.consumer) elem.attrib['recordNumber'] = str(i) if password_callback is not None: new_password = password_callback(member) if new_password is not None: # Set (or replace) the password. password_path.setattr(elem, new_password) objectify.deannotate(password_path(elem), cleanup_namespaces=True) elif password_path.hasattr(elem): # Clear the existing password element, if one exists. old_password = password_path(elem) old_password.getparent().remove(old_password) output.write(etree.tostring(elem, pretty_print=pretty_print)) output.write('\n') output.write('</Consumers>\n')
def test_username_normalization(self): # username should be lower case, [ +] replaced with '', and padded up to len = 4 self.assertEqual(normalize_username('+T '), 't000')