예제 #1
0
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            _server = args['server']
            _port = int(args['port'])
            _ssl = args['ssl']
            _sender = args['sender']
            _password = args['password']
            _recipient = args['recipient']
        except:
            return self.write_json(TPE_PARAM)

        code, msg = yield mail.tp_send_mail(
            _recipient,
            '您好!\n\n这是一封测试邮件,仅用于验证系统的邮件发送模块工作是否正常。\n\n请忽略本邮件。',
            subject='测试邮件',
            sender='Teleport Server <{}>'.format(_sender),
            server=_server,
            port=_port,
            use_ssl=_ssl,
            username=_sender,
            password=_password)

        self.write_json(code, message=msg)
예제 #2
0
파일: system.py 프로젝트: eomsoft/teleport
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            _server = args['server']
            _port = int(args['port'])
            _ssl = args['ssl']
            _sender = args['sender']
            _password = args['password']
            _recipient = args['recipient']
        except:
            return self.write_json(TPE_PARAM)

        code, msg = yield mail.tp_send_mail(
            _recipient,
            '您好!\n\n这是一封测试邮件,仅用于验证系统的邮件发送模块工作是否正常。\n\n请忽略本邮件。',
            subject='测试邮件',
            sender='Teleport Server <{}>'.format(_sender),
            server=_server,
            port=_port,
            use_ssl=_ssl,
            username=_sender,
            password=_password
        )

        self.write_json(code, message=msg)
예제 #3
0
    def post(self):

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            mode = int(args['mode'])
        except:
            return self.write_json(TPE_PARAM)

        password = ''

        if mode == 1:
            # 管理员直接在后台给用户发送密码重置邮件
            err = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
            if err != TPE_OK:
                return self.write_json(err)

            try:
                user_id = int(args['id'])
            except:
                return self.write_json(TPE_PARAM)

        elif mode == 2:
            # 管理员直接在后台为用户重置密码
            err = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
            if err != TPE_OK:
                return self.write_json(err)

            try:
                user_id = int(args['id'])
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

        elif mode == 3:
            # 用户自行找回密码,需要填写用户名、邮箱、验证码
            try:
                username = args['username']
                email = args['email']
                captcha = args['captcha']
            except:
                return self.write_json(TPE_PARAM)

            code = self.get_session('captcha')
            if code is None:
                return self.write_json(TPE_CAPTCHA_EXPIRED, '验证码已失效')
            if code.lower() != captcha.lower():
                return self.write_json(TPE_CAPTCHA_MISMATCH, '验证码错误')

            self.del_session('captcha')
            err, user_info = user.get_by_username(username)
            if err != TPE_OK:
                return self.write_json(err)
            if user_info.email != email:
                return self.write_json(TPE_NOT_EXISTS)

            user_id = user_info.id

        elif mode == 4:
            # 用户通过密码重置邮件中的链接(有token验证),在页面上设置新密码,需要提供token、新密码
            try:
                token = args['token']
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

            err, user_id = user.check_reset_token(token)
            if err != TPE_OK:
                return self.write_json(err)

        elif mode == 5:
            # 用户输入当前密码和新密码进行设置
            try:
                current_password = args['current_password']
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

            err, user_info = user.get_by_username(
                self.get_current_user()['username'])
            if err != TPE_OK:
                return self.write_json(err)
            if not tp_password_verify(current_password, user_info['password']):
                return self.write_json(TPE_USER_AUTH)
            user_id = user_info['id']

        elif mode == 6:
            # 用户密码过期,在登录前进行修改
            try:
                username = args['username']
                current_password = args['password']
                password = args['new_password']
                captcha = args['captcha']
            except:
                return self.write_json(TPE_PARAM)

            code = self.get_session('captcha')
            if code is None:
                return self.write_json(TPE_CAPTCHA_EXPIRED, '验证码已失效')
            if code.lower() != captcha.lower():
                return self.write_json(TPE_CAPTCHA_MISMATCH, '验证码错误')

            self.del_session('captcha')

            err, user_info = user.get_by_username(username)
            if err != TPE_OK:
                return self.write_json(err)

            # xxx 如果是密码过期而在登录前修改密码,需要额外判断用户是否已经被锁定
            # 如果用户被禁用或锁定,在登录时会被拒绝,因此此处仍然允许其修改密码
            # if user_info['state'] != TP_STATE_NORMAL:
            #     if user_info['state'] == TP_STATE_LOCKED:
            #         return self.write_json(TPE_USER_LOCKED)
            #     elif user_info['state'] == TP_STATE_DISABLED:
            #         return self.write_json(TPE_USER_DISABLED)
            #     else:
            #         return self.write_json(TPE_FAILED)

            if not tp_password_verify(current_password, user_info['password']):
                return self.write_json(TPE_USER_AUTH)
            user_id = user_info['id']

        else:
            return self.write_json(TPE_PARAM)

        if user_id == 0:
            return self.write_json(TPE_PARAM)

        if mode == 1 or mode == 3:
            err, email, token = user.generate_reset_password_token(
                self, user_id)

            # generate an URL for reset password, valid in 24hr.
            reset_url = '{}://{}/user/reset-password?token={}'.format(
                self.request.protocol, self.request.host, token)

            err, msg = yield mail.tp_send_mail(
                email,
                'Teleport用户,您好!\n\n请访问以下链接以重设您的teleport登录密码。此链接将于本邮件寄出24小时之后失效。\n'
                '访问此链接,将会为您打开密码重置页面,然后您可以设定新密码。\n\n'
                '如果您并没有做重设密码的操作,请忽略本邮件,请及时联系您的系统管理员!\n\n'
                '{reset_url}\n\n\n\n'
                '[本邮件由teleport系统自动发出,请勿回复]'
                '\n\n'
                ''.format(reset_url=reset_url),
                subject='密码重置确认函')

            return self.write_json(err, msg)

        elif mode == 2 or mode == 4 or mode == 5 or mode == 6:
            if len(password) == 0:
                return self.write_json(TPE_PARAM)

            # 根据需要进行弱密码检测
            if tp_cfg().sys.password.force_strong:
                if not tp_check_strong_password(password):
                    return self.write_json(
                        TPE_FAILED, '密码强度太弱!强密码需要至少8个英文字符,必须包含大写字母、小写字母和数字。')

            password = tp_password_generate_secret(password)
            err = user.set_password(self, mode, user_id, password)

            if mode == 4 and err == TPE_OK:
                user.remove_reset_token(token)

            # 非用户自行修改密码的情况,都默认重置身份认证
            if not (mode == 5 or mode == 6) and err == TPE_OK:
                # print("reset oath secret")
                user.update_oath_secret(self, user_id, '')

            self.write_json(err)

        else:
            self.write_json(TPE_PARAM)
예제 #4
0
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            args['id'] = int(args['id'])
            args['role'] = int(args['role'])
            args['auth_type'] = int(args['auth_type'])
            args['username'] = args['username'].strip().lower()
            args['surname'] = args['surname'].strip()
            args['email'] = args['email'].strip()
            args['mobile'] = args['mobile'].strip()
            args['qq'] = args['qq'].strip()
            args['wechat'] = args['wechat'].strip()

            if args['valid_from'] == '':
                args['valid_from'] = 0
            else:
                args['valid_from'] = tp_timestamp_from_str(
                    args['valid_from'].strip(), '%Y-%m-%d %H:%M')
            if args['valid_to'] == '':
                args['valid_to'] = 0
            else:
                args['valid_to'] = tp_timestamp_from_str(
                    args['valid_to'].strip(), '%Y-%m-%d %H:%M')
            args['desc'] = args['desc'].strip()
        except:
            return self.write_json(TPE_PARAM)

        if len(args['username']) == 0:
            return self.write_json(TPE_PARAM)

        if args['id'] == -1:
            args['password'] = tp_gen_password(8)
            err, _ = user.create_user(self, args)
            if err == TPE_OK:
                if len(args['email']) == 0:
                    return self.write_json(TPE_OK)

                # 对于创建成功的用户,发送密码邮件函
                sys_smtp_password = tp_cfg().sys_smtp_password
                if len(sys_smtp_password) > 0:
                    web_url = '{}://{}'.format(self.request.protocol,
                                               self.request.host)
                    err, msg = yield mail.tp_send_mail(
                        args['email'],
                        '{surname} 您好!\n\n已为您创建teleport系统用户账号,现在可以使用以下信息登录teleport系统:\n\n'
                        '登录用户名:{username}\n'
                        '密码:{password}\n'
                        '地址:{web_url}\n\n\n\n'
                        '[本邮件由teleport系统自动发出,请勿回复]'
                        '\n\n'
                        ''.format(surname=args['surname'],
                                  username=args['username'],
                                  password=args['password'],
                                  web_url=web_url),
                        subject='用户密码函')
                    if err != TPE_OK:
                        return self.write_json(
                            TPE_OK, '用户账号创建成功,但发送密码函失败:{}'.format(msg))
                    else:
                        return self.write_json(TPE_OK)
            else:
                return self.write_json(err)
        else:
            err = user.update_user(self, args)
            self.write_json(err)
예제 #5
0
    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'))
예제 #6
0
    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)
예제 #7
0
파일: user.py 프로젝트: eomsoft/teleport
    def post(self):

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            mode = int(args['mode'])
        except:
            return self.write_json(TPE_PARAM)

        password = ''

        if mode == 1:
            # 管理员直接在后台给用户发送密码重置邮件
            err = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
            if err != TPE_OK:
                return self.write_json(err)

            try:
                user_id = int(args['id'])
            except:
                return self.write_json(TPE_PARAM)

        elif mode == 2:
            # 管理员直接在后台为用户重置密码
            err = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
            if err != TPE_OK:
                return self.write_json(err)

            try:
                user_id = int(args['id'])
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

        elif mode == 3:
            # 用户自行找回密码,需要填写用户名、邮箱、验证码
            try:
                username = args['username']
                email = args['email']
                captcha = args['captcha']
            except:
                return self.write_json(TPE_PARAM)

            code = self.get_session('captcha')
            if code is None:
                return self.write_json(TPE_CAPTCHA_EXPIRED, '验证码已失效')
            if code.lower() != captcha.lower():
                return self.write_json(TPE_CAPTCHA_MISMATCH, '验证码错误')

            self.del_session('captcha')
            err, user_info = user.get_by_username(username)
            if err != TPE_OK:
                return self.write_json(err)
            if user_info.email != email:
                return self.write_json(TPE_NOT_EXISTS)

            user_id = user_info.id

        elif mode == 4:
            # 用户通过密码重置邮件中的链接(有token验证),在页面上设置新密码,需要提供token、新密码
            try:
                token = args['token']
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

            err, user_id = user.check_reset_token(token)
            if err != TPE_OK:
                return self.write_json(err)

        elif mode == 5:
            # 用户输入当前密码和新密码进行设置
            try:
                current_password = args['current_password']
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

            err, user_info = user.get_by_username(self.get_current_user()['username'])
            if err != TPE_OK:
                return self.write_json(err)
            if not tp_password_verify(current_password, user_info['password']):
                return self.write_json(TPE_USER_AUTH)
            user_id = user_info['id']

        else:
            return self.write_json(TPE_PARAM)

        if user_id == 0:
            return self.write_json(TPE_PARAM)

        if mode == 1 or mode == 3:
            err, email, token = user.generate_reset_password_token(self, user_id)

            # generate an URL for reset password, valid in 24hr.
            reset_url = '{}://{}/user/reset-password?token={}'.format(self.request.protocol, self.request.host, token)

            err, msg = yield mail.tp_send_mail(
                email,
                'Teleport用户,您好!\n\n请访问以下链接以重设您的teleport登录密码。此链接将于本邮件寄出24小时之后失效。\n'
                '访问此链接,将会为您打开密码重置页面,然后您可以设定新密码。\n\n'
                '如果您并没有做重设密码的操作,请忽略本邮件,请及时联系您的系统管理员!\n\n'
                '{reset_url}\n\n\n\n'
                '[本邮件由teleport系统自动发出,请勿回复]'
                '\n\n'
                ''.format(reset_url=reset_url),
                subject='密码重置确认函'
            )

            return self.write_json(err, msg)

        elif mode == 2 or mode == 4 or mode == 5:
            if len(password) == 0:
                return self.write_json(TPE_PARAM)

            # 根据需要进行弱密码检测
            if tp_cfg().sys.password.force_strong:
                if not tp_check_strong_password(password):
                    return self.write_json(TPE_FAILED, '密码强度太弱!强密码需要至少8个英文字符,必须包含大写字母、小写字母和数字。')

            password = tp_password_generate_secret(password)
            err = user.set_password(self, user_id, password)

            if mode == 4 and err == TPE_OK:
                user.remove_reset_token(token)

            # 非用户自行修改密码的情况,都默认重置身份认证
            if mode != 5 and err == TPE_OK:
                print("reset oath secret")
                user.update_oath_secret(self, user_id, '')

            self.write_json(err)

        else:
            self.write_json(TPE_PARAM)
예제 #8
0
파일: user.py 프로젝트: eomsoft/teleport
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            args['id'] = int(args['id'])
            args['role'] = int(args['role'])
            args['auth_type'] = int(args['auth_type'])
            args['username'] = args['username'].strip().lower()
            args['surname'] = args['surname'].strip()
            args['email'] = args['email'].strip()
            args['mobile'] = args['mobile'].strip()
            args['qq'] = args['qq'].strip()
            args['wechat'] = args['wechat'].strip()
            args['desc'] = args['desc'].strip()
        except:
            return self.write_json(TPE_PARAM)

        if len(args['username']) == 0:
            return self.write_json(TPE_PARAM)

        if args['id'] == -1:
            args['password'] = tp_gen_password(8)
            err, _ = user.create_user(self, args)
            if err == TPE_OK:
                if len(args['email']) == 0:
                    return self.write_json(TPE_OK)

                # 对于创建成功的用户,发送密码邮件函
                sys_smtp_password = tp_cfg().sys_smtp_password
                if len(sys_smtp_password) > 0:
                    web_url = '{}://{}'.format(self.request.protocol, self.request.host)
                    err, msg = yield mail.tp_send_mail(
                        args['email'],
                        '{surname} 您好!\n\n已为您创建teleport系统用户账号,现在可以使用以下信息登录teleport系统:\n\n'
                        '登录用户名:{username}\n'
                        '密码:{password}\n'
                        '地址:{web_url}\n\n\n\n'
                        '[本邮件由teleport系统自动发出,请勿回复]'
                        '\n\n'
                        ''.format(surname=args['surname'], username=args['username'], password=args['password'], web_url=web_url),
                        subject='用户密码函'
                    )
                    if err != TPE_OK:
                        return self.write_json(TPE_OK, '用户账号创建成功,但发送密码函失败:{}'.format(msg))
                    else:
                        return self.write_json(TPE_OK)
            else:
                return self.write_json(err)
        else:
            err = user.update_user(self, args)
            self.write_json(err)
예제 #9
0
파일: user.py 프로젝트: eomsoft/teleport
    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'))
예제 #10
0
    def post(self):

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            mode = int(args['mode'])
        except:
            return self.write_json(TPE_PARAM)

        password = ''

        if mode == 1:
            # 管理员直接在后台给用户发送密码重置邮件
            err = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
            if err != TPE_OK:
                return self.write_json(err)

            try:
                user_id = int(args['id'])
            except:
                return self.write_json(TPE_PARAM)

        elif mode == 2:
            # 管理员直接在后台为用户重置密码
            err = self.check_privilege(TP_PRIVILEGE_USER_CREATE)
            if err != TPE_OK:
                return self.write_json(err)

            try:
                user_id = int(args['id'])
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

        elif mode == 3:
            # 用户自行找回密码,需要填写用户名、邮箱、验证码
            try:
                username = args['username']
                email = args['email']
                captcha = args['captcha']
            except:
                return self.write_json(TPE_PARAM)

            code = self.get_session('captcha')
            if code is None:
                return self.write_json(TPE_CAPTCHA_EXPIRED, '验证码已失效')
            if code.lower() != captcha.lower():
                return self.write_json(TPE_CAPTCHA_MISMATCH, '验证码错误')

            self.del_session('captcha')
            err, user_info = user.get_by_username(username)
            if err != TPE_OK:
                return self.write_json(err)
            if user_info.email != email:
                return self.write_json(TPE_NOT_EXISTS)

            user_id = user_info.id

        elif mode == 4:
            # 用户通过密码重置邮件中的链接(有token验证),在页面上设置新密码,需要提供token、新密码
            try:
                token = args['token']
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

            err, user_id = user.check_reset_token(token)
            if err != TPE_OK:
                return self.write_json(err)

        elif mode == 5:
            # 用户输入当前密码和新密码进行设置
            try:
                current_password = args['current_password']
                password = args['password']
            except:
                return self.write_json(TPE_PARAM)

            err, user_info = user.get_by_username(
                self.get_current_user()['username'])
            if err != TPE_OK:
                return self.write_json(err)
            if not tp_password_verify(current_password, user_info['password']):
                return self.write_json(TPE_USER_AUTH)
            user_id = user_info['id']

        else:
            return self.write_json(TPE_PARAM)

        if user_id == 0:
            return self.write_json(TPE_PARAM)

        if mode == 1 or mode == 3:
            err, email, token = user.generate_reset_password_token(
                self, user_id)

            # 生成一个密码重置链接,24小时有效
            # token = tp_generate_random(16)
            reset_url = '{}://{}/user/reset-password?token={}'.format(
                self.request.protocol, self.request.host, token)
            # reset_url = 'http://127.0.0.1/user/validate-password-reset-token?token=G66LXH0EOJ47OXTH7O5KBQ0PHXRSBXBVVFALI6JBJ8HNWUALWI35QECPJ8UV8DEQ'

            err, msg = yield mail.tp_send_mail(
                email,
                'Teleport用户,您好!\n\n请访问以下链接以重设您的teleport登录密码。此链接将于本邮件寄出24小时之后失效。\n'
                '访问此链接,将会为您打开密码重置页面,然后您可以设定新密码。\n\n'
                '如果您并没有做重设密码的操作,请忽略本邮件,请及时联系您的系统管理员!\n\n'
                '{reset_url}\n\n\n\n'
                '[本邮件由teleport系统自动发出,请勿回复]'
                '\n\n'
                ''.format(reset_url=reset_url),
                subject='密码重置确认函')

            return self.write_json(err, msg)

        elif mode == 2 or mode == 4 or mode == 5:
            if len(password) == 0:
                return self.write_json(TPE_PARAM)

            # 根据需要进行弱密码检测
            if tp_cfg().sys.password.force_strong:
                if not tp_check_strong_password(password):
                    return self.write_json(
                        TPE_FAILED, '密码强度太弱!强密码需要至少8个英文字符,必须包含大写字母、小写字母和数字。')

            password = tp_password_generate_secret(password)
            err = user.set_password(self, user_id, password)

            if mode == 4 and err == TPE_OK:
                user.remove_reset_token(token)

            self.write_json(err)

        else:
            self.write_json(TPE_PARAM)