def get_post_base_body(post): main_category = None post_type = post.get_post_type() title = post.get_title() if post_type in {POST_TYPES.TOPIC, POST_TYPES.BOARD}: main_category = 'forum' elif post_type in {POST_TYPES.WIKI,}: main_category = 'wiki' if post_type is POST_TYPES.COMMENT: post: Comment if post.related_type in {POST_TYPES.TOPIC, POST_TYPES.BOARD}: main_category = 'forum' elif post_type in {POST_TYPES.WIKI, }: main_category = 'wiki' return { 'id': to_hex(post.id), 'state': post.state, 'visible': post.visible, 'time': post.time * 1000, 'user_id': to_hex(post.user_id), 'type': post_type, 'title': title, # 扩展 'indexed_time': int(time.time() * 1000), 'main_category': main_category }
async def send_register_activation(user): act_code = to_hex(user.gen_activation_code()) act_url = f'{config.SITE_URL}/account/activation?uid={user.id.hex()}&code={act_code}' content = f'''Email 地址验证<br/><br/> 您好,{user.nickname}。<br/> 欢迎来到 {config.SITE_NAME} 社区。<br/><br/> 您收到这封邮件,是由于在 {config.SITE_NAME} 进行了新用户注册,或用户修改 Email 使用了这个邮箱地址。<br/> 如果您并没有访问过 {config.SITE_NAME},或没有进行上述操作,请忽略这封邮件。<br/><br/> 如果您进行了新用户注册,或者修改 Email 使用了这个邮箱地址,我们需要对您的地址有效性进行验证以避免垃圾邮件或地址被滥用。<br/><br/> 点击下面的链接激活账号:<br/> <a href="{act_url}" target="_blank">{act_url}</a><br/> (如果上面不是链接形式,请将该地址手工复制到浏览器地址栏中打开以完成验证)<br/><br/> 考虑到安全问题,此链接在72个小时内有效。<br/> 感谢您的访问,祝您使用愉快!<br/><br/> 此致,<br/> {config.SITE_NAME} 管理团队<br/> {config.SITE_URL}<br/> ''' return await send(f'{user.nickname} <{user.email}>', f'[{config.SITE_NAME}] Email 地址验证', content)
async def send_reg_code_email(email, code): act_code = to_hex(code) act_url = f'{config.SITE_URL}/account/signup_by_email_done?email={email}&code={act_code}' content = f'''Email 地址验证<br/><br/> 您好,初次见面。<br/> 欢迎来到 {config.SITE_NAME} 社区。<br/><br/> 您收到这封邮件,是由于在 {config.SITE_NAME} 进行了新用户注册,或用户修改 Email 使用了这个邮箱地址。<br/> 如果您并没有访问过 {config.SITE_NAME},或没有进行上述操作,请忽略这封邮件。<br/><br/> 如果您进行了新用户注册,或者修改 Email 使用了这个邮箱地址,我们需要对您的地址有效性进行验证以避免垃圾邮件或地址被滥用。<br/><br/> 点击下面的链接激活账号:<br/> <a href="{act_url}" target="_blank">{act_url}</a><br/> (如果上面不是链接形式,请将该地址手工复制到浏览器地址栏中打开以完成验证)<br/><br/> 此链接在72个小时内有效。<br/> 感谢您的访问,祝您使用愉快!<br/><br/> 此致,<br/> {config.SITE_NAME} 管理团队<br/> {config.SITE_URL}<br/> ''' return await send(f'行路人 <{email}>', f'[{config.SITE_NAME}] Email 地址验证', content)
def es_update_comment(id): post: CommentModel = CommentModel.get_by_id(id) if not post: return u: UserModel = UserModel.get_by_id(post.user_id) if not u: return p = POST_TYPES.get_post(post.related_type, post.related_id) body = get_post_base_body(post) body.update({ 'user_nickname': u.nickname, 'content': post.content, 'brief': post.content[:100], 'related_title': p.get_title() if p else None, 'related_type': post.related_type, 'related_id': to_hex(post.related_id) }) es.index(index=INDEX_NAME, doc_type="doc", id=to_hex(post.id), body=body)
def update_all(reset=False): if reset: try: es.indices.delete(index=INDEX_NAME) except elasticsearch.exceptions.NotFoundError: pass create_index() for i in Topic.select(Topic.id): print('topic', to_hex(i.id)) es_update_topic(i.id) for i in WikiArticle.select(WikiArticle.id): print('wiki', to_hex(i.id)) es_update_wiki(i.id) for i in Comment.select(Comment.id): print('comment', to_hex(i.id)) es_update_comment(i.id)
def new_with_user(cls, user_id: bytes, hashes: bytes, filename: str, filesize: int): key = to_hex(hashes) values = { 'user_id': user_id, 'key': key, 'filename': filename, 'size': filesize } return cls.new(**values)
def es_update_topic(id): post: TopicModel = TopicModel.get_by_id(id) if not post: return u: UserModel = UserModel.get_by_id(post.user_id) if not u: return body = get_post_base_body(post) body.update({ 'user_nickname': u.nickname, 'content': post.content, 'brief': post.content[:100] }) es.index(index=INDEX_NAME, doc_type="doc", id=to_hex(post.id), body=body)
def es_update_wiki(id): post: WikiArticleModel = WikiArticleModel.get_by_id(id) if not post: return if post.flag: return u: UserModel = UserModel.get_by_id(post.user_id) if not u: return body = get_post_base_body(post) body.update({ 'user_nickname': u.nickname, 'content': post.content, 'ref': post.ref, 'brief': post.content[:100] }) es.index(index=INDEX_NAME, doc_type="doc", id=to_hex(post.id), body=body)
async def get_userid(self): if self.current_user: self.finish(RETCODE.SUCCESS, {'id': to_hex(self.current_user.id)}) else: self.finish(RETCODE.PERMISSION_DENIED)
async def info(self): """ 一些后端信息,一般是首次打开页面时获得 :return: """ results = { 'POST_TYPES': POST_TYPES.to_dict(), 'POST_TYPES_TXT': POST_TYPES.txt, 'POST_STATE': POST_STATE.to_dict(), 'POST_STATE_TXT': POST_STATE.txt, 'POST_VISIBLE': POST_VISIBLE.to_dict(), 'POST_VISIBLE_TXT': POST_VISIBLE.txt, 'MANAGE_OPERATION': MANAGE_OPERATION.to_dict(), 'MANAGE_OPERATION_TXT': MANAGE_OPERATION.txt, 'USER_GROUP': USER_GROUP.to_dict(), 'USER_GROUP_TXT': USER_GROUP.txt, 'USER_GROUP_TO_ROLE': USER_GROUP.GROUP_TO_ROLE, 'NOTIF_TYPE': NOTIF_TYPE.to_dict(), 'BACKEND_CONFIG': { 'SITE_NAME': config.SITE_NAME, 'SITE_LOGO_TEXT': config.SITE_LOGO_TEXT, 'SITE_TITLE_TEXT': config.SITE_TITLE_TEXT, 'SITE_URL': config.SITE_URL, 'SITE_CONTACT_EMAIL': config.SITE_CONTACT_EMAIL, 'ABOUT_PAGE_ENABLE': config.ABOUT_PAGE_ENABLE, 'ABOUT_CUSTOM_HTML': config.ABOUT_CUSTOM_HTML, 'SIGNUP_LICENSE_HTML': config.SIGNUP_LICENSE_HTML, 'FOOTER_EXTRA_HTML': config.FOOTER_EXTRA_HTML, 'USER_SECURE_AUTH_FRONTEND_SALT': config.USER_SECURE_AUTH_FRONTEND_SALT, 'WIKI_ENABLE': config.WIKI_ENABLE, 'SEARCH_ENABLE': config.SEARCH_ENABLE, 'USER_NICKNAME_MIN': config.USER_NICKNAME_MIN, 'USER_NICKNAME_MAX': config.USER_NICKNAME_MAX, 'USER_NICKNAME_CN_FOR_REG_MIN': config.USER_NICKNAME_CN_FOR_REG_MIN, 'USER_NICKNAME_FOR_REG_MIN': config.USER_NICKNAME_FOR_REG_MIN, 'USER_NICKNAME_FOR_REG_MAX': config.USER_NICKNAME_FOR_REG_MAX, 'USER_PASSWORD_MIN': config.USER_PASSWORD_MIN, 'USER_PASSWORD_MAX': config.USER_PASSWORD_MAX, 'TOPIC_TITLE_LENGTH_MIN': config.TOPIC_TITLE_LENGTH_MIN, 'TOPIC_TITLE_LENGTH_MAX': config.TOPIC_TITLE_LENGTH_MAX, 'TOPIC_CONTENT_LENGTH_MAX': config.TOPIC_CONTENT_LENGTH_MAX, 'EMAIL_ACTIVATION_ENABLE': config.EMAIL_ACTIVATION_ENABLE, 'UPLOAD_ENABLE': config.UPLOAD_ENABLE, 'UPLOAD_BACKEND': config.UPLOAD_BACKEND, 'UPLOAD_STATIC_HOST': config.UPLOAD_STATIC_HOST, 'UPLOAD_QINIU_DEADLINE_OFFSET': config.UPLOAD_QINIU_DEADLINE_OFFSET, 'UPLOAD_QINIU_IMAGE_STYLE_TOPIC': config.UPLOAD_QINIU_IMAGE_STYLE_TOPIC, }, 'retcode': RETCODE.to_dict(), 'retinfo_cn': RETCODE.txt_cn, 'extra': { 'midnight_time': get_today_start_timestamp() } } # 每日首次访问奖励 if self.current_user: user = self.current_user results['user'] = { 'id': to_hex(user.id), 'daily_reward': user.daily_access_reward() } self.finish(RETCODE.SUCCESS, results)
async def create_user(self, password, email=None, phone=None) -> User: values = {} nprefix = config.USER_NICKNAME_AUTO_PREFIX + '_' if config.POST_ID_GENERATOR != config.AutoGenerator: # 若不使用数据库生成id uid = User.gen_id() values['id'] = uid.to_bin() values['nickname'] = nprefix + uid.to_hex() values['is_new_user'] = True values['change_nickname_chance'] = 1 if email: values['email'] = email.lower() if phone: values['phone'] = phone # 密码 ret = User.gen_password_and_salt(password) values.update(ret) values['group'] = USER_GROUP.NORMAL values['state'] = POST_STATE.NORMAL # 注册IP地址 values['ip_registered'] = await get_fuzz_ip(self) # 生成 access_token values.update(User.gen_key()) values['time'] = int(time.time()) try: uid = User.insert(values).execute() u = User.get_by_pk(uid) except peewee.IntegrityError as e: db.rollback() if e.args[0].startswith('duplicate key'): return self.finish(RETCODE.ALREADY_EXISTS) return self.finish(RETCODE.FAILED) except peewee.DatabaseError: db.rollback() return self.finish(RETCODE.FAILED) times = 3 success = False u.nickname = nprefix + to_hex(u.id.tobytes()) # 尝试填充用户名 while times >= 0: try: if u.number == 1: u.group = USER_GROUP.ADMIN u.save() success = True break except peewee.DatabaseError: db.rollback() times -= 1 u.nickname = nprefix + to_hex(os.urandom(8)) if not success: return self.finish(RETCODE.FAILED) # 清理现场 if email: await User.reg_code_cleanup(email) # 添加统计记录 post_stats_new(POST_TYPES.USER, u.id) UserNotifLastInfo.new(u.id) return u
async def test_user_signout(): user_info = await test_user_signin_success() resp = await invoke_interface(app, UserView.signout, headers={'AccessToken': to_hex(user_info['data']['access_token'])}) assert resp.ret_val['code'] == RETCODE.SUCCESS
def at_replace(text: str, find_by_nicknames_func) -> Tuple[str, Set[str], Union[Mapping[str, Any], None]]: new_text, times = re_at.subn('\x01\\1\x01', text) old_matched = set(re_at3.findall(text)) # 已经标注过的 matched = set(re_at2.findall(new_text)) - old_matched # 新增的 if find_by_nicknames_func: data = {} for i in find_by_nicknames_func(matched): data[i.nickname] = i new_matched = data.keys() for i in matched - new_matched: new_text = new_text.replace('\x01%s\x01' % i, '@%s' % i) for i in data.values(): new_text = new_text.replace('\x01%s\x01' % i.nickname, '\x01%s-%s\x01' % (to_hex(i.id), i.nickname)) return new_text, set(new_matched), data return new_text, matched, None