def _do_import(self, users): success = list() failed = list() try: user_list = [] for _u in users: if 'surname' not in _u: _u['surname'] = _u['username'] if 'email' not in _u: _u['email'] = '' u = dict() u['_line'] = 0 u['_id'] = 0 u['type'] = TP_USER_TYPE_LDAP u['ldap_dn'] = _u['dn'] u['username'] = '******'.format(_u['username'], tp_cfg().sys.ldap.domain) u['surname'] = _u['surname'] u['email'] = _u['email'] u['mobile'] = '' u['qq'] = '' u['wechat'] = '' u['desc'] = '' u['password'] = '' # fix if len(u['surname']) == 0: u['surname'] = u['username'] u['username'] = u['username'].lower() user_list.append(u) print(user_list) user.create_users(self, user_list, success, failed) # 对于创建成功的用户,发送密码邮件函 sys_smtp_password = tp_cfg().sys_smtp_password if len(sys_smtp_password) > 0: web_url = '{}://{}'.format(self.request.protocol, self.request.host) for u in user_list: if u['_id'] == 0 or len(u['email']) == 0: continue u['email'] = '*****@*****.**' mail_body = '{surname} 您好!\n\n已为您创建teleport系统用户账号,现在可以使用以下信息登录teleport系统:\n\n' \ '登录用户名:{username}\n' \ '密码:您正在使用的域登录密码\n' \ '地址:{web_url}\n\n\n\n' \ '[本邮件由teleport系统自动发出,请勿回复]' \ '\n\n' \ ''.format(surname=u['surname'], username=u['username'], web_url=web_url) err, msg = yield mail.tp_send_mail(u['email'], mail_body, subject='用户密码函') if err != TPE_OK: failed.append({'line': u['_line'], 'error': '无法发送密码函到邮箱 {},错误:{}。'.format(u['email'], msg)}) # 统计结果 total_success = 0 total_failed = 0 for u in user_list: if u['_id'] == 0: total_failed += 1 else: total_success += 1 # 生成最终结果信息 if len(failed) == 0: # ret['code'] = TPE_OK # ret['message'] = '共导入 {} 个用户账号!'.format(total_success) return self.write_json(TPE_OK, message='共导入 {} 个用户账号!'.format(total_success)) else: # ret['code'] = TPE_FAILED msg = '' if total_success > 0: msg = '{} 个用户账号导入成功,'.format(total_success) if total_failed > 0: msg += '{} 个用户账号未能导入!'.format(total_failed) # ret['data'] = failed return self.write_json(TPE_FAILED, data=failed, message=msg) except: log.e('got exception when import LDAP user.\n') # ret['code'] = TPE_FAILED msg = '' if len(success) > 0: msg += '{} 个用户账号导入后发生异常!'.format(len(success)) else: msg = '发生异常!' # ret['data'] = failed return self.write_json(TPE_FAILED, data=failed, message=msg)
def post(self): """ csv导入规则: 每一行的数据格式: 用户账号,用户姓名,登录认证方式,email地址,Mobile,QQ,WeChat,所属组,描述 在导入时: 0. 以“#”作为行注释。 1. 用户账号是必须填写的,其他均为可选。 2. 一个用户属于多个组,可以用“|”将组分隔,如果某个组并不存在,则会创建这个组。 3. 空行跳过,数据格式不正确的跳过。 """ ret = dict() ret['code'] = TPE_OK ret['message'] = '' rv = self.check_privilege(TP_PRIVILEGE_USER_CREATE | TP_PRIVILEGE_USER_GROUP, need_process=False) if rv != TPE_OK: ret['code'] = rv ret['code'] = rv if rv == TPE_NEED_LOGIN: ret['message'] = '需要登录!' elif rv == TPE_PRIVILEGE: ret['message'] = '权限不足!' else: ret['message'] = '未知错误!' return self.write(json.dumps(ret).encode('utf8')) success = list() failed = list() group_failed = list() csv_filename = '' try: upload_path = os.path.join(tp_cfg().data_path, 'tmp') # 文件的暂存路径 if not os.path.exists(upload_path): os.mkdir(upload_path) file_metas = self.request.files[ 'csvfile'] # 提取表单中‘name’为‘file’的文件元数据 for meta in file_metas: now = time.localtime(time.time()) tmp_name = 'upload-{:04d}{:02d}{:02d}{:02d}{:02d}{:02d}.csv'.format( now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec) csv_filename = os.path.join(upload_path, tmp_name) with open(csv_filename, 'wb') as f: f.write(meta['body']) # file encode maybe utf8 or gbk... check it out. file_encode = None with open(csv_filename, encoding='gbk') as f: try: f.readlines() file_encode = 'gbk' except: pass if file_encode is None: log.v('file `{}` is not gbk, try utf8\n'.format(csv_filename)) with open(csv_filename, encoding='utf_8_sig') as f: try: f.readlines() file_encode = 'utf_8_sig' except: pass if file_encode is None: os.remove(csv_filename) log.e( 'file `{}` unknown encode, neither GBK nor UTF8.\n'.format( csv_filename)) ret['code'] = TPE_FAILED ret['message'] = '文件无法解码:不是GBK编码或者UTF8编码!' return self.write(json.dumps(ret).encode('utf8')) group_list = dict() user_list = list() # 解析csv文件 with open(csv_filename, encoding=file_encode) as f: username_list = [] # 用于检查是否有重复的用户被添加 csv_reader = csv.reader(f) line = 0 for csv_recorder in csv_reader: line += 1 # 跳过空行和注释 if len(csv_recorder) == 0 or csv_recorder[0].strip( ).startswith('#'): continue # 格式错误则记录在案,然后继续 if len(csv_recorder) != 8: failed.append({'line': line, 'error': '格式错误,字段数量不匹配。'}) continue # check _username = csv_recorder[self.IDX_USERNAME].strip() if len(_username) == 0: failed.append({ 'line': line, 'error': '格式错误,用户账号必须填写。' }) continue _email = csv_recorder[self.IDX_EMAIL].strip() _group = csv_recorder[self.IDX_GROUP].split('|') u = dict() u['_line'] = line u['_id'] = 0 u['username'] = _username u['surname'] = csv_recorder[self.IDX_SURNAME].strip() # u['auth'] = _auth u['email'] = _email u['mobile'] = csv_recorder[self.IDX_MOBILE].strip() u['qq'] = csv_recorder[self.IDX_QQ].strip() u['wechat'] = csv_recorder[self.IDX_WECHAT].strip() u['desc'] = csv_recorder[self.IDX_DESC].strip() u['password'] = tp_gen_password(8) # fix if len(u['surname']) == 0: u['surname'] = _username u['username'] = _username.lower() if u['username'] in username_list: failed.append({ 'line': line, 'error': '上传文件中用户 `{}` 重复。'.format(u['username']) }) continue else: username_list.append(u['username']) u['_group'] = list() for i in range(len(_group)): x = _group[i].strip() if len(x) > 0: u['_group'].append(x) # 更新一下组列表,以备后续为用户与所在组创建映射 for i in range(len(u['_group'])): if u['_group'][i] not in group_list: group_list[u['_group'][i]] = 0 user_list.append(u) if os.path.exists(csv_filename): os.remove(csv_filename) # 检查一下 if len(user_list) == 0: ret['code'] = TPE_FAILED ret['message'] = '上传的 csv 文件中没有可用于导入的用户!' ret['data'] = failed return self.write(json.dumps(ret).encode('utf8')) # 已经有了用户组列表,查询组数据库,有则更新用户组列表中组对应的id,无则创建组 if len(group_list) > 0: err = group.make_groups(self, TP_GROUP_USER, group_list, group_failed) if len(group_failed) > 0: ret['code'] = TPE_FAILED ret['message'] += '无法创建用户组 {}。'.format( ','.join(group_failed)) return self.write(json.dumps(ret).encode('utf8')) # 对用户列表中的每一项,创建用户 user.create_users(self, user_list, success, failed) # 对创建成功的用户,在用户组映射表中设定其对应关系 gm = list() for u in user_list: if u['_id'] == 0: continue for ug in u['_group']: for g in group_list: if group_list[g] == 0 or ug != g: continue gm.append({ 'type': TP_GROUP_USER, 'gid': group_list[g], 'mid': u['_id'] }) group.make_group_map(TP_GROUP_USER, gm) # 对于创建成功的用户,发送密码邮件函 sys_smtp_password = tp_cfg().sys_smtp_password if len(sys_smtp_password) > 0: web_url = '{}://{}'.format(self.request.protocol, self.request.host) for u in user_list: if u['_id'] == 0 or len(u['email']) == 0: continue err, msg = yield mail.tp_send_mail( u['email'], '{surname} 您好!\n\n已为您创建teleport系统用户账号,现在可以使用以下信息登录teleport系统:\n\n' '登录用户名:{username}\n' '密码:{password}\n' '地址:{web_url}\n\n\n\n' '[本邮件由teleport系统自动发出,请勿回复]' '\n\n' ''.format(surname=u['surname'], username=u['username'], password=u['password'], web_url=web_url), subject='用户密码函') if err != TPE_OK: failed.append({ 'line': u['_line'], 'error': '无法发送密码函到邮箱 {},错误:{}。'.format(u['email'], msg) }) # 统计结果 total_success = 0 total_failed = 0 for u in user_list: if u['_id'] == 0: total_failed += 1 else: total_success += 1 # 生成最终结果信息 if len(failed) == 0: ret['code'] = TPE_OK ret['message'] = '共导入 {} 个用户账号!'.format(total_success) return self.write(json.dumps(ret).encode('utf8')) else: ret['code'] = TPE_FAILED if total_success > 0: ret['message'] = '{} 个用户账号导入成功,'.format(total_success) if total_failed > 0: ret['message'] += '{} 个用户账号未能导入!'.format(total_failed) ret['data'] = failed return self.write(json.dumps(ret).encode('utf8')) except: log.e('got exception when import user.\n') ret['code'] = TPE_FAILED if len(success) > 0: ret['message'] += '{} 个用户账号导入后发生异常!'.format(len(success)) else: ret['message'] = '发生异常!' ret['data'] = failed return self.write(json.dumps(ret).encode('utf8'))
def post(self): """ csv导入规则: 每一行的数据格式: 用户账号,用户姓名,登录认证方式,email地址,Mobile,QQ,WeChat,所属组,描述 在导入时: 0. 以“#”作为行注释。 1. 用户账号是必须填写的,其他均为可选。 2. 一个用户属于多个组,可以用“|”将组分隔,如果某个组并不存在,则会创建这个组。 3. 空行跳过,数据格式不正确的跳过。 """ ret = dict() ret['code'] = TPE_OK ret['message'] = '' rv = self.check_privilege(TP_PRIVILEGE_USER_CREATE | TP_PRIVILEGE_USER_GROUP, need_process=False) if rv != TPE_OK: ret['code'] = rv ret['code'] = rv if rv == TPE_NEED_LOGIN: ret['message'] = '需要登录!' elif rv == TPE_PRIVILEGE: ret['message'] = '权限不足!' else: ret['message'] = '未知错误!' return self.write(json.dumps(ret).encode('utf8')) success = list() failed = list() group_failed = list() csv_filename = '' try: upload_path = os.path.join(tp_cfg().data_path, 'tmp') # 文件的暂存路径 if not os.path.exists(upload_path): os.mkdir(upload_path) file_metas = self.request.files['csvfile'] # 提取表单中‘name’为‘file’的文件元数据 for meta in file_metas: now = time.localtime(time.time()) tmp_name = 'upload-{:04d}{:02d}{:02d}{:02d}{:02d}{:02d}.csv'.format(now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec) csv_filename = os.path.join(upload_path, tmp_name) with open(csv_filename, 'wb') as f: f.write(meta['body']) # file encode maybe utf8 or gbk... check it out. file_encode = None with open(csv_filename, encoding='gbk') as f: try: f.readlines() file_encode = 'gbk' except: pass if file_encode is None: log.v('file `{}` is not gbk, try utf8\n'.format(csv_filename)) with open(csv_filename, encoding='utf_8_sig') as f: try: f.readlines() file_encode = 'utf_8_sig' except: pass if file_encode is None: os.remove(csv_filename) log.e('file `{}` unknown encode, neither GBK nor UTF8.\n'.format(csv_filename)) ret['code'] = TPE_FAILED ret['message'] = '文件无法解码:不是GBK编码或者UTF8编码!' return self.write(json.dumps(ret).encode('utf8')) group_list = dict() user_list = list() # 解析csv文件 with open(csv_filename, encoding=file_encode) as f: username_list = [] # 用于检查是否有重复的用户被添加 csv_reader = csv.reader(f) line = 0 for csv_recorder in csv_reader: line += 1 # 跳过空行和注释 if len(csv_recorder) == 0 or csv_recorder[0].strip().startswith('#'): continue # 格式错误则记录在案,然后继续 if len(csv_recorder) != 8: failed.append({'line': line, 'error': '格式错误,字段数量不匹配。'}) continue # check _username = csv_recorder[self.IDX_USERNAME].strip() if len(_username) == 0: failed.append({'line': line, 'error': '格式错误,用户账号必须填写。'}) continue _email = csv_recorder[self.IDX_EMAIL].strip() _group = csv_recorder[self.IDX_GROUP].split('|') u = dict() u['_line'] = line u['_id'] = 0 u['username'] = _username u['surname'] = csv_recorder[self.IDX_SURNAME].strip() # u['auth'] = _auth u['email'] = _email u['mobile'] = csv_recorder[self.IDX_MOBILE].strip() u['qq'] = csv_recorder[self.IDX_QQ].strip() u['wechat'] = csv_recorder[self.IDX_WECHAT].strip() u['desc'] = csv_recorder[self.IDX_DESC].strip() u['password'] = tp_gen_password(8) # fix if len(u['surname']) == 0: u['surname'] = _username u['username'] = _username.lower() if u['username'] in username_list: failed.append({'line': line, 'error': '上传文件中用户 `{}` 重复。'.format(u['username'])}) continue else: username_list.append(u['username']) u['_group'] = list() for i in range(len(_group)): x = _group[i].strip() if len(x) > 0: u['_group'].append(x) # 更新一下组列表,以备后续为用户与所在组创建映射 for i in range(len(u['_group'])): if u['_group'][i] not in group_list: group_list[u['_group'][i]] = 0 user_list.append(u) if os.path.exists(csv_filename): os.remove(csv_filename) # 检查一下 if len(user_list) == 0: ret['code'] = TPE_FAILED ret['message'] = '上传的 csv 文件中没有可用于导入的用户!' ret['data'] = failed return self.write(json.dumps(ret).encode('utf8')) # 已经有了用户组列表,查询组数据库,有则更新用户组列表中组对应的id,无则创建组 if len(group_list) > 0: err = group.make_groups(self, TP_GROUP_USER, group_list, group_failed) if len(group_failed) > 0: ret['code'] = TPE_FAILED ret['message'] += '无法创建用户组 {}。'.format(','.join(group_failed)) return self.write(json.dumps(ret).encode('utf8')) # 对用户列表中的每一项,创建用户 user.create_users(self, user_list, success, failed) # 对创建成功的用户,在用户组映射表中设定其对应关系 gm = list() for u in user_list: if u['_id'] == 0: continue for ug in u['_group']: for g in group_list: if group_list[g] == 0 or ug != g: continue gm.append({'type': TP_GROUP_USER, 'gid': group_list[g], 'mid': u['_id']}) group.make_group_map(TP_GROUP_USER, gm) # 对于创建成功的用户,发送密码邮件函 sys_smtp_password = tp_cfg().sys_smtp_password if len(sys_smtp_password) > 0: web_url = '{}://{}'.format(self.request.protocol, self.request.host) for u in user_list: if u['_id'] == 0 or len(u['email']) == 0: continue err, msg = yield mail.tp_send_mail( u['email'], '{surname} 您好!\n\n已为您创建teleport系统用户账号,现在可以使用以下信息登录teleport系统:\n\n' '登录用户名:{username}\n' '密码:{password}\n' '地址:{web_url}\n\n\n\n' '[本邮件由teleport系统自动发出,请勿回复]' '\n\n' ''.format(surname=u['surname'], username=u['username'], password=u['password'], web_url=web_url), subject='用户密码函' ) if err != TPE_OK: failed.append({'line': u['_line'], 'error': '无法发送密码函到邮箱 {},错误:{}。'.format(u['email'], msg)}) # 统计结果 total_success = 0 total_failed = 0 for u in user_list: if u['_id'] == 0: total_failed += 1 else: total_success += 1 # 生成最终结果信息 if len(failed) == 0: ret['code'] = TPE_OK ret['message'] = '共导入 {} 个用户账号!'.format(total_success) return self.write(json.dumps(ret).encode('utf8')) else: ret['code'] = TPE_FAILED if total_success > 0: ret['message'] = '{} 个用户账号导入成功,'.format(total_success) if total_failed > 0: ret['message'] += '{} 个用户账号未能导入!'.format(total_failed) ret['data'] = failed return self.write(json.dumps(ret).encode('utf8')) except: log.e('got exception when import user.\n') ret['code'] = TPE_FAILED if len(success) > 0: ret['message'] += '{} 个用户账号导入后发生异常!'.format(len(success)) else: ret['message'] = '发生异常!' ret['data'] = failed return self.write(json.dumps(ret).encode('utf8'))