Exemple #1
0
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
    }
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
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)
Exemple #6
0
 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)
Exemple #7
0
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)
Exemple #8
0
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)
Exemple #9
0
 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)
Exemple #10
0
    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)
Exemple #11
0
    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
Exemple #12
0
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
Exemple #13
0
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