def post(self, *args, **kwargs): menu_tab = self.get_argument('menu_tab', 1) params = self.params() params['uuid'] = Func.uuid32() params.pop('user_id', None) params.pop('menu_tab', None) params.pop('_xsrf', None) if not params.get('code', None): return self.error('授权码不能够为空') count = AdminMenu.Q.filter(AdminMenu.code == params['code']).count() if count > 0: return self.error('Code已被占用') path = params.get('path', None) if path[0:4] != 'http' and path[0:1] != '/': params['path'] = '/' + path user_id = self.current_user.get('uuid') role_id = self.current_user.get('role_id') if not self.super_role(): params['user_id'] = user_id menu = AdminMenu(**params) AdminMenu.session.add(menu) AdminMenu.session.commit() self.redirect('/admin/menu/index?#menu_tab=%s' % menu_tab)
class MemberOperationLog(BaseModel): """ user model """ __tablename__ = 'member_operation_log' uuid = Column(String(32), primary_key=True, nullable=False, default=Func.uuid32()) user_id = Column(String(32), ForeignKey('member.uuid')) # 用户账号: email or mobile or username account = Column(String(80), nullable=False) # 会员操作类型: email_reset_pwd mobile_reset_pwd username_reset_pwd activate_email action = Column(String(20), nullable=False) ip = Column(String(40), nullable=False) client = Column(String(20), nullable=True, default='web') utc_created_at = Column(TIMESTAMP, default=Func.utc_now) @property def created_at(self): return Func.dt_to_timezone(self.utc_created_at) @staticmethod def add_log(params): """激活邮件 [description] Arguments: params {[type]} -- [description] """ log = MemberOperationLog(**params) MemberOperationLog.session.add(log) MemberOperationLog.session.commit()
def register(params): user_id = Func.uuid32() params['uuid'] = user_id member = Member(**params) Member.session.add(member) Member.session.commit() return member
def email_reset_pwd(self, email): """使用Email充值密码发送邮件功能 """ if not Func.is_email(email): return self.error('Email格式不正确') token = self.get_secure_cookie(settings.token_key) if token: return self.error('邮件已发送,30分钟后重试') member = Member.Q.filter(Member.email == email).first() if member is None: return self.error('账户没有注册') if member.status == 0: return self.error('账户被禁用') self.success() subject = '[%s]找回密码' % sys_config('site_name') token = Func.uuid32() action_url = sys_config( 'site_url') + '/passport/forget.html?token=' + token localnow = Func.local_now() + datetime.timedelta(minutes=30) params = { 'username': member.username, 'expires': str(localnow), 'action_url': action_url, 'action_tips': '立即重置密码', } tmpl = 'common/email_content.html' content = self.render_string(tmpl, **params) # print('content', content) Func.sendmail({ 'to_addr': email, 'subject': subject, 'content': content }) save = { 'token': token, 'account': email, 'username': member.username, 'action': 'email_reset_pwd', } expires = time.mktime(localnow.timetuple()) self.set_secure_cookie(settings.token_key, str(save), expires=expires) return
def activate_email(self, email): """激活邮箱发送邮件功能 """ if not Func.is_email(email): return self.error('Email格式不正确') user_id = self.current_user.get('id') member = Member.Q.filter(Member.id == user_id).first() if member.email_activated: return self.error('已经激活了,请不要重复操作') token = self.get_secure_cookie(settings.token_key) if token: return self.error('邮件已发送,10分钟后重试') self.success() subject = '[%s]激活邮件' % sys_config('site_name') token = Func.uuid32() action_url = sys_config( 'site_url') + '/member/activate.html?token=' + token localnow = Func.local_now() + datetime.timedelta(minutes=10) params = { 'username': member.username, 'expires': str(localnow), 'action_url': action_url, 'action_tips': '立即激活邮箱', } tmpl = 'common/email_content.html' content = self.render_string(tmpl, **params) # print('content', content) Func.sendmail({ 'to_addr': email, 'subject': subject, 'content': content }) save = { 'token': token, 'account': email, 'username': member.username, 'action': 'email_reset_pwd', } expires = time.mktime(localnow.timetuple()) self.set_secure_cookie(settings.token_key, str(save), expires=expires) return
class UserLoginLog(BaseModel): """ user model """ __tablename__ = 'sys_admin_user_login_log' uuid = Column(String(32), primary_key=True, nullable=False, default=Func.uuid32()) user_id = Column(String(32), ForeignKey('sys_admin_user.uuid')) ip = Column(String(40), nullable=False) client = Column(String(20), nullable=True) utc_created_at = Column(TIMESTAMP, default=Func.utc_now) @property def created_at(self): return Func.dt_to_timezone(self.utc_created_at)
class MemberFriend(BaseModel): """ user model """ __tablename__ = 'member_friend' uuid = Column(String(32), primary_key=True, nullable=False, default=Func.uuid32()) user_id = Column(String(32), ForeignKey('member.uuid')) ip = Column(String(40), nullable=False) client = Column(String(20), nullable=True, default='web') utc_created_at = Column(TIMESTAMP, default=Func.utc_now) @property def created_at(self): return Func.dt_to_timezone(self.utc_created_at)
def post(self, *args, **kwargs): params = self.params() params['status'] = params.get('status', 0) if not params.get('username', None): return self.error('用户名不能为空') if not params.get('password', None): return self.error('密码不能为空') count = Member.Q.filter(Member.username == params['username']).count() if count > 0: return self.error('用户名已被占用') if Func.is_mobile(params.get('mobile', '')): count = Member.Q.filter(Member.mobile == params['mobile']).count() if count > 0: return self.error('电话号码已被占用', data=params) if Func.is_email(params.get('email', '')): count = Member.Q.filter(Member.email == params['email']).count() if count > 0: return self.error('Email已被占用') password = params.get('password') rsa_encrypt = params.get('rsa_encrypt', 0) if settings.login_pwd_rsa_encrypt and int( rsa_encrypt) == 1 and len(password) > 10: private_key = sys_config('sys_login_rsa_priv_key') password = RSAEncrypter.decrypt(password, private_key) params['password'] = make_password(password) params.pop('_xsrf', None) params.pop('rsa_encrypt', None) params['uuid'] = Func.uuid32() member = Member(**params) Member.session.add(member) Member.session.commit() return self.success(data=member.as_dict())
class Role(BaseModel): """ user model """ __tablename__ = 'sys_admin_role' uuid = Column(String(32), primary_key=True, nullable=False, default=Func.uuid32()) rolename = Column(String(40), nullable=False) permission = Column(Text, default='') sort = Column(Integer, nullable=False, default=20) # 状态:( 0 禁用;1 启用, 默认1) status = Column(Integer, nullable=False, default=1) utc_created_at = Column(TIMESTAMP, default=Func.utc_now) @property def created_at(self): return Func.dt_to_timezone(self.utc_created_at) @classmethod def option_html(cls, role_id=None): query = cls.session.query(Role) query = query.filter(Role.status == 1) rows = query.order_by(Role.sort.asc()).all() SysLogger.debug(query.statement) option_str = '' for row in rows: selected = 'selected' if role_id == row.uuid else '' option_str += '<option value="%s" %s>%s</option>' % ( row.uuid, selected, row.rolename) # SysLogger.debug('option_str: %s' % option_str) return option_str @classmethod def get_permission(cls, role_id): query = cls.session.query('permission') query = query.filter(Role.uuid == role_id) return query.scalar()
def login_success(user, handler): # 设置登录用户cookie信息 handler.set_curent_user(user) user_id = user.uuid login_count = user.login_count if user.login_count else 0 params = { 'login_count': login_count + 1, 'utc_last_login_at': Func.utc_now(), 'last_login_ip': handler.request.remote_ip, } User.Q.filter(User.uuid == user_id).update(params) params = { 'uuid': Func.uuid32(), 'user_id': user.uuid, 'client': 'web', 'ip': handler.request.remote_ip, } log = UserLoginLog(**params) UserLoginLog.session.add(log) UserLoginLog.session.commit() return True
def login_success(member, handler, client='web'): # 设置登录用户cookiex信息 handler.set_curent_user(member) user_id = member.uuid login_count = member.login_count if member.login_count else 0 params = { 'login_count': login_count + 1, 'utc_last_login_at': Func.utc_now(), 'last_login_ip': handler.request.remote_ip, } Member.Q.filter(Member.uuid == user_id).update(params) # 写登录日志 params2 = { 'uuid': Func.uuid32(), 'user_id': user_id, 'client': client, 'ip': handler.request.remote_ip, } log = MemberLoginLog(**params2) MemberLoginLog.session.add(log) MemberLoginLog.session.commit()
class User(BaseModel): """ user model """ __tablename__ = 'sys_admin_user' uuid = Column(String(32), primary_key=True, nullable=False, default=Func.uuid32()) role_id = Column(String(32), ForeignKey('sys_admin_role.uuid')) password = Column(String(128), nullable=False, default='') username = Column(String(40), nullable=False) mobile = Column(String(11), nullable=True) email = Column(String(80), nullable=True) permission = Column(Text, default='') login_count = Column(Integer, nullable=False, default=0) last_login_ip = Column(String(128), nullable=False, default='') # 用户状态:(0 锁定, 1正常, 默认1) status = Column(Integer, nullable=False, default=1) utc_last_login_at = Column(TIMESTAMP, nullable=True) utc_created_at = Column(TIMESTAMP, default=Func.utc_now) @property def last_login_at(self): return Func.dt_to_timezone(self.utc_last_login_at) @property def created_at(self): return Func.dt_to_timezone(self.utc_created_at) @property def role_permission(self): query = "select permission from sys_admin_role where uuid='%s'" % self.role_id permission = User.session.execute(query).scalar() try: return json.loads(permission) except Exception as e: raise e return [] @classmethod def get_permission(cls): try: return json.loads(cls.permission) except Exception as e: raise e return [] @staticmethod def login_success(user, handler): # 设置登录用户cookie信息 handler.set_curent_user(user) user_id = user.uuid login_count = user.login_count if user.login_count else 0 params = { 'login_count': login_count + 1, 'utc_last_login_at': Func.utc_now(), 'last_login_ip': handler.request.remote_ip, } User.Q.filter(User.uuid == user_id).update(params) params = { 'uuid': Func.uuid32(), 'user_id': user.uuid, 'client': 'web', 'ip': handler.request.remote_ip, } log = UserLoginLog(**params) UserLoginLog.session.add(log) UserLoginLog.session.commit() return True
class AdminMenu(BaseModel): """ user group map model """ __tablename__ = 'sys_admin_menu' uuid = Column(String(32), primary_key=True, nullable=False, default=Func.uuid32()) user_id = Column(String(32), ForeignKey('sys_admin_user.uuid'), nullable=False, default='') parent_id = Column(String(32), nullable=False, default='top') code = Column(String(64), nullable=True) title = Column(String(20), nullable=False) icon = Column(String(20), nullable=False) path = Column(String(200), nullable=False) param = Column(String(200), nullable=False) target = Column(String(20), nullable=False, default='_self') nav = Column(Integer, nullable=False) sort = Column(Integer, nullable=False, default=20) system = Column(Integer, nullable=False) status = Column(Integer, nullable=False) utc_created_at = Column(TIMESTAMP, default=Func.utc_now) @property def created_at(self): return Func.dt_to_timezone(self.utc_created_at) @classmethod def info(cls, uuid=None, path=None): """获取当前访问节点信息 [description] Keyword Arguments: uuid {str} -- [description] (default: {''}) Returns: [type] -- [description] """ query = cls.session.query(AdminMenu) if uuid: query = query.filter(AdminMenu.uuid == uuid) if path: path = path.split('?')[0] if path[-1:] == '/': path = path[0:-1] if path[-5:] == '.html': path = path[0:-5] query = query.filter(AdminMenu.path == path) row = query.first() row = row.as_dict() if row else None # SysLogger.debug(query.statement) return row @classmethod def brand_crumbs(cls, uuid): """获取当前节点的面包屑 [description] Arguments: uuid {[type]} -- [description] Returns: [type] -- [description] """ menu = [] row = cls.info(uuid=uuid) if row['parent_id'] != '' and row['parent_id'] != 'top': menu.append(row) child = cls.brand_crumbs(row['parent_id']) if len(child): menu.extend(child) return menu @classmethod def main_menu(cls, parent_id='top', status=1, level=0): """获取后台主菜单(一级 > 二级 > 三级) 后台顶部和左侧使用 Keyword Arguments: parent_id {str} -- 父ID (default: {'0'}) level {number} -- 层级数 (default: {0}) Returns: [type] -- [description] """ trees = [] if not len(trees): filds = [ 'uuid', 'code', 'parent_id', 'title', 'path', 'param', 'target', 'icon' ] query = cls.session.query(AdminMenu) if status is not None: query = query.filter(AdminMenu.status == status) query = query.filter(AdminMenu.nav == 1) rows = query.order_by(AdminMenu.sort.asc()).all() # print('query.statement: ', query.statement) for row in rows: row = row.as_dict(filds) if row.get('parent_id') != parent_id: continue if level == 5: return trees # 过滤没访问权限的节点 # if (!RoleModel::checkAuth($v['id'])) { # unset($data[$k]); # continue; # } row['children'] = cls.main_menu(row.get('uuid'), status, level + 1) trees.append(row) return trees @staticmethod def children(parent_id='top', status=None, level=0, user_id=''): """获取指定节点下的所有子节点(不含快捷收藏的菜单) """ trees = [] if not len(trees): filds = [ 'uuid', 'code', 'parent_id', 'title', 'path', 'param', 'target', 'icon', 'sort', 'status' ] query = AdminMenu.session.query(AdminMenu) if user_id: query = query.filter(AdminMenu.user_id == user_id) query = query.filter(AdminMenu.parent_id == parent_id) if status in [1, 0]: query = query.filter(AdminMenu.status == status) rows = query.order_by(AdminMenu.sort.asc()).all() data = [] for row in rows: if level == 5: return trees row = row.as_dict(filds) # 过滤没访问权限的节点 # if (!RoleModel::checkAuth($v['id'])) { # unset($data[$k]); # continue; # } row['children'] = AdminMenu.children(row.get('uuid'), status, level + 1) trees.append(row) return trees @staticmethod def menu_option(uuid=''): """菜单选项""" menus = AdminMenu.main_menu(status=None) if not len(menus) > 0: return '' option1 = '<option level="1" value="%s" %s>— %s</option>' option2 = '<option level="2" value="%s" %s>—— %s</option>' option3 = '<option level="3" value="%s" %s>——— %s</option>' html = '' for menu in menus: selected = 'selected' if uuid == menu.get('uuid', '') else '' title1 = menu.get('title', '') children1 = menu.get('children', []) html += option1 % (menu.get('uuid', ''), selected, title1) if not len(children1) > 0: continue for menu2 in children1: selected2 = 'selected' if uuid == menu2.get('uuid', '') else '' title2 = menu2.get('title', '') children2 = menu2.get('children', []) html += option2 % (menu2.get('uuid', ''), selected2, title2) if not len(children2) > 0: continue for menu3 in children2: selected3 = 'selected' if uuid == menu3.get('uuid', '') else '' title3 = menu3.get('title', '') html += option3 % (menu3.get('uuid', ''), selected3, title3) return html
def post(self, *args, **kwargs): """重置密码 """ token = self.get_argument('token', None) next = self.get_argument('next', '') password = self.get_argument('password', None) repass = self.get_argument('repass', '') rsa_encrypt = self.get_argument('rsa_encrypt', 0) token2 = self.get_secure_cookie(self.token_key) if not (token and token2): return self.error('Token不存在或已经过期') token2 = str(token2, encoding='utf-8') token2 = token2.replace('\'', '"') token2 = json_decode(token2) action = token2.get('action', '') account = token2.get('account', '') # print('token2 ', token2.get('token', ''), token) if token2.get('token', '') != token: return self.error('Token不匹配') if not password: return self.error('新密码不能为空') if settings.login_pwd_rsa_encrypt and int( rsa_encrypt) == 1 and len(password) > 10: private_key = sys_config('sys_login_rsa_priv_key') password = RSAEncrypter.decrypt(password, private_key) repass = RSAEncrypter.decrypt(repass, private_key) if repass != password: msg = '两次输入的密码不一致,请重新输入' msg = "%s, %s" % (password, repass) return self.error(msg) member = None if action == 'email_reset_pwd': member = Member.Q.filter(Member.email == account).first() else: return self.error('不支持的action') if member is None: return self.error('用户不存在') if int(member.status) == 0: return self.error('用户被“禁用”,请联系客服') user_id = member.uuid params = { 'password': make_password(password), } Member.Q.filter(Member.uuid == user_id).update(params) Member.session.commit() params = { 'uuid': Func.uuid32(), 'user_id': user_id, 'account': account, 'action': 'email_reset_pwd', 'ip': self.request.remote_ip, 'client': 'web', } MemberOperationLog.add_log(params) self.clear_cookie(self.token_key) return self.success(next=next)
class Member(BaseModel): """ user model """ __tablename__ = 'member' uuid = Column(String(32), primary_key=True, nullable=False, default=Func.uuid32()) password = Column(String(128), nullable=False, default='') username = Column(String(40), nullable=False) mobile = Column(String(11), nullable=True) email = Column(String(80), nullable=True) level_id = Column(Integer, nullable=False, default=0) # 经验值 experience = Column(Integer, nullable=False, default=0) # 性别(男 male ,女 female 隐藏 hide) sex = Column(String(10), nullable=False, default='hide') # 头像 avatar = Column(String(255), nullable=True, default='') # 签名 sign = Column(String(255), nullable=True, default='') login_count = Column(Integer, nullable=False, default=0) last_login_ip = Column(String(40), nullable=False, default='') deleted = Column(Integer, nullable=False, default=0) # 用户状态:(0 锁定, 1正常, 默认1) status = Column(Integer, nullable=False, default=1) utc_last_login_at = Column(TIMESTAMP, nullable=True) utc_created_at = Column(TIMESTAMP, default=Func.utc_now) ref_user_id = Column(String(32), default='') register_ip = Column(String(40), nullable=False, default='') # 客户端:web wechat android ios mobile register_client = Column(String(40), nullable=False, default='') sex_options = { 'hide': '保密', 'male': '男', 'female': '女', } @property def sex_option(self): return self.sex_options.get(self.sex, '保密') @property def last_login_at(self): return Func.dt_to_timezone(self.utc_last_login_at) @property def created_at(self): return Func.dt_to_timezone(self.utc_created_at) @property def email_activated(self): return self.check_email_activated(self.uuid, self.email) @staticmethod def get_info(user_id, fields='username,avatar,sign'): query = "select %s from member where uuid='%s'" % ( fields, user_id, ) info = Member.session.execute(query).first() return dict(info) @staticmethod def check_email_activated(user_id, email): query = "select count(*) from member_operation_log where user_id='%s' and account='%s' and action='activate_email'" % ( user_id, email) # print("query: ", query) value = Member.session.execute(query).scalar() return True if value > 0 else False @staticmethod def _friend_list(user_id, where=''): query = "select m.uuid as user_id,m.username,m.avatar,m.sign,f.group_id from member m left join member_friend f on m.uuid=f.to_user_id where f.from_user_id='%s' and m.status=1 and f.status=1 %s" % ( user_id, where) rows = Member.session.execute(query).fetchall() items = [] if rows: for row in rows: items.append(dict(row)) return items @staticmethod def friends_no_grouping(user_id): where = " and f.group_id='0'" return Member._friend_list(user_id, where) @staticmethod def friends_by_group(user_id, static_url): """ 按分组获取好友 """ _friend_list = Member._friend_list(user_id) # print('_friend_list: ', _friend_list) query = "select uuid, groupname from member_friendgroup where owner_user_id='%s'" % user_id grows = Member.session.execute(query).fetchall() grows = grows if grows else [] # print("grows: ", type(grows), grows) f_g_li = [] try: if len(grows) > 0: f_g_li += [{ 'id': group_id, 'groupname': groupname, 'list': [{ 'id': fnd.get('user_id'), 'username': fnd.get('username'), 'status': Online.get_online(fnd.get('user_id')), 'sign': fnd.get('sign'), 'avatar': fnd.get('avatar') } for fnd in _friend_list if fnd.get('group_id') == group_id] } for (group_id, groupname) in grows] # Member.friends_no_grouping(user_id) f_g_li += [{ 'id': '0', 'groupname': '未分组', 'list': [{ 'id': fnd.get('user_id'), 'username': fnd.get('username'), 'status': Online.get_online(fnd.get('user_id')), 'sign': fnd.get('sign'), 'avatar': static_url(fnd.get('avatar')) } for fnd in Member.friends_no_grouping(user_id)] }] except Exception as e: raise e return f_g_li @staticmethod def login_success(member, handler, client='web'): # 设置登录用户cookiex信息 handler.set_curent_user(member) user_id = member.uuid login_count = member.login_count if member.login_count else 0 params = { 'login_count': login_count + 1, 'utc_last_login_at': Func.utc_now(), 'last_login_ip': handler.request.remote_ip, } Member.Q.filter(Member.uuid == user_id).update(params) # 写登录日志 params2 = { 'uuid': Func.uuid32(), 'user_id': user_id, 'client': client, 'ip': handler.request.remote_ip, } log = MemberLoginLog(**params2) MemberLoginLog.session.add(log) MemberLoginLog.session.commit() @staticmethod def remove_avator(user_id, mavatar): try: query = "SELECT `file_md5` FROM `sys_attach_related` WHERE `related_table`='member' and `related_id`='%s';" % ( user_id) old_file_md5 = Member.session.execute(query).scalar() if old_file_md5: pass delq = "DELETE FROM `sys_attach_related` WHERE `file_md5`='%s';" Member.session.execute(delq % old_file_md5) delq = "DELETE FROM `sys_attach` WHERE `file_md5`='%s';" Member.session.execute(delq % old_file_md5) old_avatar = settings.STATIC_PATH + '/' + mavatar os.remove(old_avatar) except Exception as e: raise e return True @staticmethod def register(params): user_id = Func.uuid32() params['uuid'] = user_id member = Member(**params) Member.session.add(member) Member.session.commit() return member