示例#1
0
async def api_user_authenticate(request):
    """
    用户登录验证API函数
    :param request: 请求对象
    :return: 回响消息, 并且设置COOKIE
    """
    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    email = request_data.email
    password = request_data.password
    if not email:
        return data_error(u'非法邮箱账号')
    if not password:
        return data_error(u'非法密码')

    users = await UserAuth.find_all(where='email=?', args=[email])
    if len(users) == 0:
        return data_error(u'账号不存在')

    user = users[0]
    sha1_password = generate_sha1_password(user['id'], password)
    if user['password'] != sha1_password:
        return data_error(u'密码有误')

    cookie_name = configs.user_cookie.name
    cookie_secret = configs.user_cookie.secret
    cookie_str = user_cookie_generate(user['id'], 86400, cookie_secret)
    r = web.Response()
    r.set_cookie(cookie_name, cookie_str, max_age=86400, httponly=True)
    user['password'] = '******'
    r.content_type = 'application/json'
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    return r
示例#2
0
async def api_image_upload(request):
    """
    上传图片API函数
    :param request: 请求对象
    :return:
    """
    if not is_admin(request):
        return permission_error()

    ct = request.content_type.lower()
    if ct.startswith('application/json'):
        params = await request.json()
        if not isinstance(params, dict):
            return data_error()
    else:
        return data_error()

    image_name = None
    if 'name' in params:
        image_name = params['name']
    image_str = None
    if 'image' in params:
        image_str = params['image']
    if not image_name or not image_name.strip():
        return data_error(u'图片名不能为空')
    if not image_str or not image_str.strip():
        return data_error(u'图片内容不能为空')

    # 取消图片的原始名,只保留后缀名
    loc = image_name.find('.')
    if loc == -1:
        return data_error(u'图片名有误')
    image_name = image_name[loc:]

    # 先在数据库中生成一条图片的记录
    image = Image(url='xx')
    await image.save()

    # 使用图片数据的创建时间做为URL
    image_url = '/static/img/'
    image_url += str(int(image.created_at * 1000))
    image_url += image_name

    image.url = (configs.domain_name + image_url)
    await image.update()

    image_str = image_str.replace('data:image/png;base64,', '')
    image_str = image_str.replace('data:image/jpeg;base64,', '')
    image_data = base64.b64decode(image_str)

    image_path = '.'
    image_path += image_url
    file = open(image_path, 'wb')
    file.write(image_data)
    file.close()
    return image
示例#3
0
async def api_image_upload(request):
    """
    上传图片API函数
    :param request: 请求对象
    :return:
    """
    if not is_admin(request):
        return permission_error()

    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    image_name_ext = request_data.name
    image_str = request_data.image
    if not image_name_ext or not image_name_ext.strip():
        return data_error(u'图片名不能为空')
    if not image_str or not image_str.strip():
        return data_error(u'图片内容不能为空')

    # 取消图片的原始名,只保留后缀名
    loc = image_name_ext.find('.')
    if loc == -1:
        return data_error(u'图片名有误')
    image_name_ext = image_name_ext[loc:]

    # 先在数据库中生成一条图片的记录
    image = Image(url='xx')
    await image.save()

    # 使用图片数据的创建时间做为URL
    image_url = '/static/img/'

    # 使用年月创建文件夹
    dt = datetime.fromtimestamp(image.created_at)
    new_path = './static/img/%s/%s' % (dt.year, dt.month)
    os.makedirs(new_path, exist_ok=True)

    image_url += '%s/%s/%s%s%s%s' % \
                 (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
    image_url += image_name_ext

    image.url = (configs.domain_name + image_url)
    await image.update()

    image_str = image_str.replace('data:image/png;base64,', '')
    image_str = image_str.replace('data:image/jpeg;base64,', '')
    image_str = image_str.replace('data:image/gif;base64,', '')
    image_data = base64.b64decode(image_str)

    image_path = '.'
    image_path += image_url
    file = open(image_path, 'wb')
    file.write(image_data)
    file.close()
    return image
示例#4
0
async def api_comment_create(request):
    """
    创建评论API函数
    :param request: 请求
    :return: 返回响应消息
    """
    # 只有登录用户才能发表评论
    user = request.__user__
    if user is None:
        return data_error(u'请先登录')

    # 限制每10秒只能发送一条评论
    comments = await Comment.find_all('user_id=? and created_at > ?',
                                      [user.id, time.time() - 10.0])
    if len(comments) > 0:
        return data_error(u'评论过于频繁(10秒后再试)')

    # 获取评论内容
    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    # 检查评论内容
    content = request_data.content
    if not content or not content.strip():
        return data_error(u'评论内容不能为空')

    blog_id = request.match_info['blog_id']
    blog = await Blog.find(blog_id)
    if blog is None:
        return data_error(u'评论的博客不存在')

    # 检查评论目标人名称,如果为NULL,表示对博客直接评论
    target_user_name = request_data.target_name
    if not target_user_name or not target_user_name.strip():
        target_user_name = blog.user_name

    # 检查评论目标人id,如果为NULL,表示对博客直接评论
    target_user_id = request_data.target_id
    if not target_user_id or not target_user_id.strip():
        target_user_id = blog.user_id

    comment = Comment(blog_id=blog.id,
                      user_id=user.id,
                      user_name=user.name,
                      user_image=user.image,
                      target_user_id=target_user_id,
                      target_user_name=target_user_name,
                      content=content.strip())
    await comment.save()
    return comment
示例#5
0
async def api_image_delete(request):
    """
    删除博客API函数
    :param request: 请求
    :return:
    """
    if not is_admin(request):
        return permission_error()

    image_id = request.match_info['image_id']
    image = await Image.find(image_id)
    if not image:
        return data_error(u'非法image id')

    url = image.url
    await image.remove()

    url = url.replace(configs.domain_name, '')

    filename = '.'
    filename += url
    if os.path.exists(filename):
        os.remove(filename)

    return dict(id=image_id)
示例#6
0
async def blog_detail(request):
    """
    博客详细页面路由函数
    :param request: 请求对象
    :return: 博客详细页面
    """

    blog_id = request.match_info['blog_id']

    # 根据博客ID找到博客详细内容
    blog = await Blog.find(blog_id)
    if not blog:
        return data_error(u'非法blog id')

    # 阅读次数增加
    blog.read_times += 1
    await blog.update()

    # 找到指定博客ID的博客的评论
    comments = await Comment.find_all('blog_id=?', [blog_id],
                                      order_by='created_at asc')
    for c in comments:
        c.html_content = text2html(c.content)
    blog.html_content = markdown2.markdown(blog.content)
    return {
        '__template__': 'blog_detail.html',
        'blog': blog,
        'comments': comments
    }
示例#7
0
async def api_blog_update(request):
    """
    更新博客API函数
    :param request: 请求对象
    :return:
    """
    if not is_admin(request):
        return permission_error()

    ct = request.content_type.lower()
    if ct.startswith('application/json'):
        params = await request.json()
        if not isinstance(params, dict):
            return data_error()
    else:
        return data_error()

    blog_id = request.match_info['blog_id']

    name = None
    if 'name' in params:
        name = params['name']
    summary = None
    if 'summary' in params:
        summary = params['summary']
    content = None
    if 'content' in params:
        content = params['content']
    cover_image = None
    if 'cover_image' in params:
        cover_image = params['cover_image']
    blog_type = None
    if 'type' in params:
        blog_type = params['type']

    if not name or not name.strip():
        return data_error(u'博客名称不能为空')
    if not summary or not summary.strip():
        return data_error(u'博客摘要不能为空')
    if not content or not content.strip():
        return data_error(u'博客内容不能为空')
    if not cover_image or not cover_image.strip():
        return data_error(u'封面图片不能为空')
    if not blog_type or not blog_type.strip():
        return data_error(u'博客类型不能为空')

    blog = await Blog.find(blog_id)
    if not blog:
        return data_error(u'非法blog id')

    blog.name = name.strip()
    blog.summary = summary.strip()
    blog.content = content.strip()
    blog.cover_image = cover_image.strip()
    blog.type = blog_type.strip()
    await blog.update()
    return blog
示例#8
0
async def api_blog_create(request):
    """
    创建博客API函数
    :param request: 请求
    :return:
    """
    if not is_admin(request):
        return permission_error()

    ct = request.content_type.lower()
    if ct.startswith('application/json'):
        params = await request.json()
        if not isinstance(params, dict):
            return data_error()
    else:
        return data_error()

    name = None
    if 'name' in params:
        name = params['name']
    summary = None
    if 'summary' in params:
        summary = params['summary']
    content = None
    if 'content' in params:
        content = params['content']
    cover_image = None
    if 'cover_image' in params:
        cover_image = params['cover_image']
    blog_type = None
    if 'type' in params:
        blog_type = params['type']
    if not name or not name.strip():
        return data_error(u'博客名称不能为空')
    if not summary or not summary.strip():
        return data_error(u'博客摘要不能为空')
    if not content or not content.strip():
        return data_error(u'博客内容不能为空')
    if not cover_image or not cover_image.strip():
        return data_error(u'封面图片不能为空')
    if not blog_type or not blog_type.strip():
        return data_error(u'博客类型不能为空')

    blog = Blog(user_id=request.__user__['id'],
                user_name=request.__user__['name'],
                user_image=request.__user__['image'],
                name=name.strip(),
                summary=summary.strip(),
                content=content.strip(),
                cover_image=cover_image.strip(),
                read_times=0,
                type=blog_type)
    await blog.save()
    return blog
示例#9
0
async def api_blog_type_create(request):
    """
    创建博客类别API函数
    :param request: 请求对象
    :return: 博客类别数据
    """
    if not is_admin(request):
        return permission_error()

    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    name = request_data.name
    level = request_data.level
    if not name or not name.strip():
        return data_error(u'类别名称不能为空')
    if not level or not level.strip():
        return data_error(u'类别优先级不能为空')

    blog_type = BlogType(name=name.strip(), level=int(level.strip()))
    await blog_type.save()
    return blog_type
示例#10
0
async def api_blog_get_one(request):
    """
    获取指定ID的博客数据函数
    :param request: 请求对象
    :return: 博客数据
    """
    if not is_admin(request):
        return permission_error()

    blog_id = request.match_info['blog_id']
    blog = await Blog.find(blog_id)
    if not blog:
        return data_error(u'非法blog id')

    return blog
示例#11
0
async def api_comment_delete(request):
    """
    删除评论API函数
    :param request: 请求对象
    :return:
    """
    if not is_admin(request):
        return permission_error()

    comment_id = request.match_info['id']

    c = await Comment.find(comment_id)
    if c is None:
        return data_error(u'非法comment id')

    await c.remove()
    return dict(id=comment_id)
示例#12
0
async def api_blog_type_delete(request):
    """
    删除博客类别API函数
    :param request: 请求对象
    :return:
    """
    if not is_admin(request):
        return permission_error()

    type_id = request.match_info['type_id']

    # 根据博客类别ID找到类别
    blog_type = await BlogType.find(type_id)
    if not blog_type:
        return data_error(u'非法type id')

    await blog_type.remove()

    return dict(id=type_id)
示例#13
0
async def api_blog_delete(request):
    """
    删除博客API函数
    :param request: 请求对象
    :return:
    """
    if not is_admin(request):
        return permission_error()

    blog_id = request.match_info['blog_id']

    # 根据博客ID找到博客详细内容
    blog = await Blog.find(blog_id)
    if not blog:
        return data_error(u'非法blog id')

    await blog.remove()

    return dict(id=blog_id)
示例#14
0
async def api_blog_update(request):
    """
    更新博客API函数
    :param request: 请求对象
    :return:
    """
    if not is_admin(request):
        return permission_error()

    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    blog_id = request.match_info['blog_id']

    name = request_data.name
    summary = request_data.summary
    content = request_data.content
    cover_image = request_data.cover_image
    blog_type = request_data.type

    if not name or not name.strip():
        return data_error(u'博客名称不能为空')
    if not summary or not summary.strip():
        return data_error(u'博客摘要不能为空')
    if not content or not content.strip():
        return data_error(u'博客内容不能为空')
    if not cover_image or not cover_image.strip():
        return data_error(u'封面图片不能为空')
    if not blog_type or not blog_type.strip():
        return data_error(u'博客类型不能为空')

    blog = await Blog.find(blog_id)
    if not blog:
        return data_error(u'非法blog id')

    blog.name = name.strip()
    blog.summary = summary.strip()
    blog.content = content.strip()
    blog.cover_image = cover_image.strip()
    blog.type = blog_type.strip()
    await blog.update()
    return blog
示例#15
0
async def api_comment_create(request):
    """
    创建评论API函数
    :param request: 请求
    :return: 返回响应消息
    """
    # 只有登录用户才能发表评论
    user = request.__user__
    if user is None:
        return data_error(u'请先登录')

    # 限制每10秒只能发送一条评论
    comments = await Comment.find_all('user_id=? and created_at > ?',
                                      [user.id, time.time() - 10.0])
    if len(comments) > 0:
        return data_error(u'评论过于频繁(10秒后再试)')

    # 获取评论内容
    ct = request.content_type.lower()
    if ct.startswith('application/json'):
        params = await request.json()
        if not isinstance(params, dict):
            return data_error()
    else:
        return data_error()

    # 检查评论内容
    content = None
    if 'content' in params:
        content = params['content']
    if not content or not content.strip():
        return data_error(u'评论内容不能为空')

    blog_id = request.match_info['blog_id']
    blog = await Blog.find(blog_id)
    if blog is None:
        return data_error(u'评论的博客不存在')

    comment = Comment(blog_id=blog.id,
                      user_id=user.id,
                      user_name=user.name,
                      user_image=user.image,
                      content=content.strip())
    await comment.save()
    return comment
示例#16
0
async def api_user_authenticate(request):
    """
    用户登录验证API函数
    :param request: 请求对象
    :return: 回响消息, 并且设置COOKIE
    """
    ct = request.content_type.lower()
    if ct.startswith('application/json'):
        params = await request.json()
        if not isinstance(params, dict):
            return data_error()
    else:
        return data_error()

    email = None
    if 'email' in params:
        email = params['email']
    password = None
    if 'password' in params:
        password = params['password']

    if not email:
        return data_error(u'非法邮箱账号')
    if not password:
        return data_error(u'非法密码')

    users = await UserAuth.find_all(where='email=?', args=[email])
    if len(users) == 0:
        return data_error(u'账号不存在')

    user = users[0]
    sha1_password = generate_sha1_password(user['id'], password)
    if user['password'] != sha1_password:
        return data_error(u'密码有误')

    cookie_name = configs.user_cookie.name
    cookie_secret = configs.user_cookie.secret
    cookie_str = user_cookie_generate(user['id'], 86400, cookie_secret)
    r = web.Response()
    r.set_cookie(cookie_name, cookie_str, max_age=86400, httponly=True)
    user['password'] = '******'
    r.content_type = 'application/json'
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    return r
示例#17
0
async def api_blog_create(request):
    """
    创建博客API函数
    :param request: 请求
    :return:
    """
    if not is_admin(request):
        return permission_error()

    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    name = request_data.name
    summary = request_data.summary
    content = request_data.content
    cover_image = request_data.cover_image
    blog_type = request_data.type
    if not name or not name.strip():
        return data_error(u'博客名称不能为空')
    if not summary or not summary.strip():
        return data_error(u'博客摘要不能为空')
    if not content or not content.strip():
        return data_error(u'博客内容不能为空')
    if not cover_image or not cover_image.strip():
        return data_error(u'封面图片不能为空')
    if not blog_type or not blog_type.strip():
        return data_error(u'博客类型不能为空')

    blog = Blog(user_id=request.__user__['id'],
                user_name=request.__user__['name'],
                user_image=request.__user__['image'],
                name=name.strip(),
                summary=summary.strip(),
                content=content.strip(),
                cover_image=cover_image.strip(),
                read_times=0,
                type=blog_type)
    await blog.save()
    return blog
示例#18
0
async def api_github_login(request):
    """
    GitHub登录API函数
    :param request:
    :return:
    """
    qs_parser = QueryStringParser(request.query_string)
    github_code = qs_parser.code
    last_url = qs_parser.state
    if not github_code:
        return data_error('GitHub Code Lost')

    # 获取用户令牌
    access_token_url = 'https://github.com/login/oauth/access_token?client_id='
    access_token_url += configs.github.client_id
    access_token_url += '&client_secret='
    access_token_url += configs.github.client_secret
    access_token_url += '&redirect_uri='
    access_token_url += configs.github.redirect_uri
    access_token_url += '&code='
    access_token_url += github_code
    async with ClientSession() as session:
        async with session.post(access_token_url) as response:
            response_data = await response.text()

    data_parser = QueryStringParser(response_data)
    access_token = data_parser.access_token
    if not access_token:
        return data_error()

    user_url = 'https://api.github.com/user?access_token='
    user_url += access_token
    async with ClientSession() as session:
        async with session.get(user_url) as response:
            user_data = await response.json()

    user_id = None
    if 'id' in user_data:
        user_id = user_data['id']
    if not user_id:
        return data_error()

    user_name = None
    if 'login' in user_data:
        user_name = user_data['login']
    if not user_name:
        return data_error()
    user_image = None
    if 'avatar_url' in user_data:
        user_image = user_data['avatar_url']
    if not user_image:
        return data_error()

    # 更新或者保存用户信息
    user = await UserInfo.find(str(user_id))
    logging.info(user)
    if not user:
        user = UserInfo(id=user_id, name=user_name, image=user_image)
        await user.save()
    else:
        user.name = user_name
        user.image = user_image
        await user.update()

    # 生成用户COOKIE
    cookie_name = configs.user_cookie.name
    cookie_secret = configs.user_cookie.secret
    cookie_str = user_cookie_generate(str(user_id), 86400, cookie_secret)

    r = web.HTTPFound(last_url)
    r.set_cookie(cookie_name, cookie_str, max_age=86400, httponly=True)
    return r
示例#19
0
async def api_user_register(request):
    """
    用户注册API函数
    :param request: 请求对象
    :return: 注册成功则设置COOKIE,返回响应消息
    """
    _RE_EMAIL = re.compile(
        r'^[a-z0-9\.\-\_]+\@[a-z0-9\-\_]+(\.[a-z0-9\-\_]+){1,4}$')
    _RE_SHA1 = re.compile(r'^[0-9a-f]{40}$')

    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    name = request_data.name
    email = request_data.email
    password = request_data.password
    verify = request_data.verify

    # 检查验证码是否输入正确
    if not verify or not verify.strip():
        return data_error(u'非法验证码')
    verify_cookie_name = configs.verify_image_cookie.name
    cookie_secret = configs.verify_image_cookie.secret
    cookie_str = request.cookies.get(verify_cookie_name)
    cookie_str_input = verify_image_cookie_generate(verify.upper(),
                                                    cookie_secret)
    if not cookie_str == cookie_str_input:
        return data_error(u'验证码错误')

    # 检查用户数据是否合法
    if not name or not name.strip():
        return data_error(u'非法用户名')
    if not email or not _RE_EMAIL.match(email):
        return data_error(u'非法邮箱账号')
    if not password or not _RE_SHA1.match(password):
        return data_error(u'非法密码')

    # 检查用户邮箱是否已经被注册
    users = await UserAuth.find_all(where='email=?', args=[email])
    if len(users) > 0:
        return data_error(u'邮箱已经被使用')

    # 生成用户ID, 并且混合用户ID和密码进行SHA1加密
    uid = generate_id()
    sha1_password = generate_sha1_password(uid, password)

    # 将新用户数据保存到数据库中
    user = UserAuth(id=uid, email=email, password=sha1_password)
    await user.save()

    # 生成头像图片URL
    head_img_url = configs.domain_name
    head_img_url += '/static/img/head_%s.jpg' % random.randint(1, 15)
    user_info = UserInfo(id=uid, name=name.strip(), image=head_img_url)
    await user_info.save()

    # 生成COOKIE
    cookie_str = user_cookie_generate(user['id'], 86400,
                                      configs.user_cookie.secret)
    cookie_name = configs.user_cookie.name

    # 生成响应消息
    r = web.Response()
    # 删除用于验证验证码的COOKIE
    r.set_cookie(verify_cookie_name, '-deleted-', max_age=0, httponly=True)
    r.set_cookie(cookie_name, cookie_str, max_age=86400, httponly=True)
    user['password'] = '******'
    r.content_type = 'application/json'
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    return r
示例#20
0
async def api_weibo_login(request):
    """
    微博登录API函数
    :param request:
    :return:
    """

    request_data = RequestData(request)
    if not await request_data.json_load():
        return data_error(u'非法数据格式, 请使用JSON格式')

    # 取出用户id和访问令牌
    uid = request_data.uid
    if not uid:
        return data_error()
    access_token = request_data.access_token
    if not access_token or not access_token.strip():
        return data_error()

    # 获取用户数据
    url = 'https://api.weibo.com/2/users/show.json?access_token='
    url += access_token
    url += '&uid='
    url += str(uid)
    async with ClientSession() as session:
        async with session.get(url) as response:
            user_data = await response.json()
            logging.info(user_data)
            if not isinstance(user_data, dict):
                return data_error()

    user_name = None
    if 'screen_name' in user_data:
        user_name = user_data['screen_name']
    if not user_name:
        return data_error()
    user_image = None
    if 'avatar_hd' in user_data:
        user_image = user_data['avatar_hd']
    if not user_image:
        return data_error()

    # 更新或者保存用户信息
    user = await UserInfo.find(str(uid))
    logging.info(user)
    if not user:
        user = UserInfo(id=uid, name=user_name, image=user_image)
        await user.save()
    else:
        user.name = user_name
        user.image = user_image
        await user.update()

    # 生成用户COOKIE
    cookie_name = configs.user_cookie.name
    cookie_secret = configs.user_cookie.secret
    cookie_str = user_cookie_generate(str(uid), 86400, cookie_secret)
    r = web.Response()
    r.set_cookie(cookie_name, cookie_str, max_age=86400, httponly=True)
    r.content_type = 'application/json'
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    return r