Exemple #1
0
def get(request, name, oid, key=None, speed=False):
    hmupName = str2Hump(name)

    try:
        redisData = r.get(key)
        if redisData and speed:
            res = pickle.loads(redisData)
            print('get by redis')
        else:
            res = query.get(hmupName, oid)
            print('get by db')
            if speed:
                r.set(key, pickle.dumps(res), ex=REDIS_SPEED_TIME)
    except:
        print('redis error; get by db')
        res = query.get(hmupName, oid)

    if isinstance(res, dict):
        return ok(res)
    elif res == 404:
        return fail('数据库中没有' + name + '这个表', 404, 404)
    elif res == 4042:
        return fail('没有这条数据', 404, 404)
    elif res == 4043:
        return fail(name + '数据库中没有数据', 404, 404)
    elif res == 503:
        return fail('数据查询失败', 503)
    else:
        return fail('服务器内部错误', 500, 500)
Exemple #2
0
async def login(request):
    dat = request.json
    manageData = {'username': '******', 'password': '******'}

    res = fail('参数错误', 400)

    # 检查入参是否正确
    if not checkParam(['account', 'password'], dat):
        del res.cookies['session']
        return res

    # 从传参中解密密码
    password = rsaDecrypt(PRIVATE_KEY_PATH, dat['password'])

    # 检查用户名密码是否正确
    if dat['account'] != manageData['username'] \
            or password != manageData['password']:
        res = fail('用户名或密码错误', 400)
        del res.cookies['session']
        return res

    # 正常处理
    token = makeToken(dat['account'], 'manage')
    res = ok(token)
    res.cookies['session'] = token
    res.cookies['session']['httponly'] = True

    return res
Exemple #3
0
async def tree_channel(request):
    sourceData = rest.getList({
        'pagesize': -1,
        'sort': '-sort,-id'
    }, 'channel', 'treeChannel', True)
    if sourceData == 1:
        return fail('服务器内部错误', 500, 500)
    if sourceData['total'] < 1:
        return fail('您当前还没有添加任何栏目')

    sourceList = sourceData['list']

    def makeTree(pid, arr):
        res = []
        for i in arr:
            if i['pid'] == pid:
                rep = makeTree(i['id'], arr)
                if len(rep) != 0:
                    i['children'] = rep
                res.append(i)
        return res

    res = makeTree(0, sourceList)

    return ok(res)
Exemple #4
0
async def put(request, oid):
    # 检查必填参数
    checkParam(['account', 'old_password', 'new_password'], request)

    # 检查密码是否符合要求
    oldPw = rsaDecrypt(KEY_PATH, request['old_password'])
    newPw = rsaDecrypt(KEY_PATH, request['new_password'])
    newPwLen = len(newPw)
    if oldPw == newPw:
        return fail('新密码不能与原密码相同')
    if newPwLen < 6 or newPwLen > 16:
        return fail('密码长度不能小于6位或大于16位')
    if not re.match(r'^[a-zA-Z0-9_]+$', newPw):
        return fail('密码只能是大小写字母加数字以及下划线的组合')

    # 检查原密码和数据库存储密码是否一致
    saveManage = getItem('manages', oid)
    savePw = rsaDecrypt(KEY_PATH, saveManage['password'])
    if oldPw != savePw:
        return fail('原密码不正确')

    # 检查用户名是否被修改
    account = request['account']
    if account != saveManage['username']:
        return fail('用户名不能被修改')

    # 将参数整理为数据库所需字段
    request['username'] = request.pop('account')
    request['password'] = request.pop('new_password')
    request.pop('old_password')
Exemple #5
0
def delete(request, name, oid):
    hmupName = str2Hump(name)
    res = query.delete(hmupName, oid)
    if isinstance(res, dict):
        return ok(res)
    elif res == 400:
        return fail('您要删除的数据不存在', 400)
    elif res == 404:
        return fail('数据库中没有' + name + '这个表', 404, 404)
    elif res == 503:
        return fail('数据删除失败', 503)
    else:
        return fail('服务器内部错误', 500, 500)
Exemple #6
0
def post(request, name):
    hmupName = str2Hump(name)
    res = query.post(hmupName, request)
    if isinstance(res, dict):
        return ok(res)
    elif res == 400:
        return fail('参数错误', 400)
    elif res == 404:
        return fail('数据库中没有' + name + '这个表', 404, 404)
    elif res == 503:
        return fail('数据添加失败', 503)
    else:
        return fail('服务器内部错误', 500, 500)
Exemple #7
0
def ls(request, name):
    hmupName = str2Hump(name)
    res = query.ls(hmupName, request)
    if isinstance(res, dict):
        return ok(res['list'], res['total'])
    elif res == 400:
        return fail('参数错误', 400)
    elif res == 404:
        return fail('数据库中没有' + name + '这个表', 404)
    elif res == 503:
        return fail('数据查询失败', 503)
    else:
        return fail('服务器内部错误', 500, 500)
async def post(request):
    data = request['data']
    for i in data:
        # 检查必填参数
        if not checkParam(['account', 'password'], i):
            return fail('参数错误', 400)

        account = i['account']
        # 检查添加的用户名在数据库中是否存在
        saveData = getList({'username': account}, 'manages')
        if saveData != 1 and saveData['total'] >= 1:
            return fail('数据库已有用户名为' + account + '的管理员', 400)
        # 数据库存储字段名为 username 所以这里要改名
        i['username'] = i.pop('account')
Exemple #9
0
async def upload(request):
    # 字节码转16进制字符串
    def bytes2hex(bytes):
        hexstr = u""
        for i in range(10):
            t = u"%x" % bytes[i]
            if len(t) % 2:
                hexstr += u"0"
            hexstr += t
        return hexstr.lower()

    # 根据16进制字符串获取文件后缀
    def getSuffix(hexStr):
        print(hexStr)
        for i in SUPPORT_TYPE:
            if i in hexStr:
                return SUPPORT_TYPE[i]
        return 400

    # 判断参数是否正确
    if not request.files and not request.files.get('file'):
        return fail('参数错误', 400)
    image = request.files.get('file').body

    # 判断文件是否支持
    imageSuffix = getSuffix(bytes2hex(image))
    if imageSuffix == 400:
        return fail('不支持的文件类型', 400)

    # 组织图片存储路径
    m1 = hashlib.md5()
    m1.update(image)
    md5Name = m1.hexdigest()

    saveDir = UPLOAD_PATH + md5Name[0:2] + '/'
    savePath = saveDir + md5Name[2:] + '.' + imageSuffix
    resPath = '/' + md5Name[0:2] + '/' + md5Name[2:] + '.' + imageSuffix

    # 如果文件夹不存在,就创建文件夹
    if not os.path.exists(saveDir):
        os.makedirs(saveDir)

    # 将文件写入到硬盘
    tempFile = open(savePath, 'wb')
    tempFile.write(image)
    tempFile.close()

    # 给客户端返回结果
    return ok({"path": resPath})
Exemple #10
0
def get(request, name, oid):
    hmupName = str2Hump(name)
    res = query.get(hmupName, oid)
    if isinstance(res, dict):
        return ok(res)
    elif res == 404:
        return fail('数据库中没有' + name + '这个表', 404)
    elif res == 4042:
        return fail('没有这条数据', 404)
    elif res == 4043:
        return fail(name + '数据库中没有数据', 404)
    elif res == 503:
        return fail('数据查询失败', 503)
    else:
        return fail('服务器内部错误', 500, 500)
Exemple #11
0
async def delete(request, oid):
    # 如果要删除的ID的长度,大于或数据库中所有管理员的条数,则不允许删除
    # 因为必须保证系统中有至少一个管理员
    idLen = len(oid.split(','))
    saveData = getList({'pagesize': -1}, 'manages')
    if saveData != 1 and idLen >= saveData['total']:
        return fail('你不能删除所有管理员', 400)
Exemple #12
0
async def post(request):
    for i in request['data']:
        # 判断必填字段
        if not 'title' in i:
            return fail('标题不能为空', 400)
        elif not 'channel_id' in i:
            return fail('栏目ID不能为空', 400)
        elif not isInt(i['channel_id']):
            return fail('栏目ID只能是数字', 400)
        elif not 'edit_type' in i:
            return fail('编辑器类别不能为空', 400)
        elif i['edit_type'] != 'HTML' and i['edit_type'] != 'MD':
            return fail('编辑器类别指定错误', 400)

        # 根据编辑器类别,输出文章内容
        if i['edit_type'] == 'MD':
            if not 'markdown' in i:
                return fail('文章内容不能为空', 400)
            # 转化markdown格式
            i['content'] = markdown.markdown(i['markdown'])

        if i['edit_type'] == 'HTML':
            if not 'content' in i:
                return fail('文章内容不能为空', 400)

        # 如果没有传入简介信息,则根据文章内容截取
        if i.get('description') == None or i.get('description') == '':
            i['description'] = filterHtml(i['content'])[0:200].replace(
                '\n', '')

        if i.get('hits') == None or i.get('hits') == '':
            i['hits'] = 0

        if i.get('isdelete') == None or i.get('hits') == '':
            i['isdelete'] = 'NO'
Exemple #13
0
async def logout(request):
    session = request.cookies.get('session')
    res = fail('退出失败', 401, 401)
    cs = checkSession(session)
    if cs == 0:
        clearSession(session)
        res = ok('退出成功')
    del res.cookies['session']
    return res
Exemple #14
0
 async def post(self, request, name):
     data = request.json
     if data:
         if 'batch_additon' in data and isinstance(data['batch_additon'],
                                                   list):
             data = {'data': data['batch_additon']}
         else:
             data = {'data': [data]}
         return await doProcess(app, name, request, data, 'post')
     else:
         return fail('数据不能为空', 400)
Exemple #15
0
async def login(request):

    # 先检查参数是否正确
    req = json.loads(request.body)
    checkParam(['account', 'password'], req)

    # 根据用户名,从数据库中读取管理员信息
    accRes = json.loads(rest.ls({'username': req['account']}, 'manages').body)

    # 判断查询结果是否正常
    if accRes['status'] == 0:

        # 判断是否查到该管理员
        if len(accRes['data']['list']) >= 1:

            # 处理管路员密码
            acc = accRes['data']['list'][0]
            accPw = rsaDecrypt(KEY_PATH, acc['password'])
            reqPw = rsaDecrypt(KEY_PATH, req['password'])
            reqPwLen = len(reqPw)
            if reqPwLen < 6 or reqPwLen > 16:
                res =  fail('密码长度为 6-16 位')
                del res.cookies['session']
                return res
            elif accPw != reqPw:
                res =  fail('密码不正确')
                del res.cookies['session']
                return res
            else:
                session = makeSession(req['account'], 'manage')
                res = ok('登录成功')
                res.cookies['session'] = session
                res.cookies['session']['httponly'] = True
                return res
        else:
            res = fail('用户名不正确')
            del res.cookies['session']
            return res
    else:
        return fail('服务器内部错误', 503)
Exemple #16
0
def middleHandle(request, prefix, authType = 'black', authList = {},\
         checkLogin = True, anyList = {}):
    if prefix in request.url:
        urlArr = request.url.split(prefix)[1].split('?')[0].split('/')
        method = request.method
        apiName = urlArr[0].lower()

        # 检查请求路径是否合法
        if len(urlArr) == 0 or len(urlArr) > 2:
            return fail('请求路径不合法', 404, 404)

        # 全局请求方法检查
        if len(urlArr) == 1 and not method in ['GET', 'POST']:
            return fail('不被允许的请求方法', 405, 405)
        if len(urlArr) == 2 and not method in ['GET', 'PUT', 'DELETE']:
            return fail('不被允许的请求方法', 405, 405)

        # 检查请求方法自定义名单处理
        for i in authList:
            m = 'LS' if len(urlArr) == 1 and method == 'GET' else method
            if apiName == i.lower():
                # 黑名单处理
                if authType == 'black' and m in authList[i]:
                    return fail('该请求未被授权', 405, 405)
                # 白名单处理
                if authType == 'white' and not m in authList[i]:
                    return fail('该请求未被授权', 405, 405)

        # 检查接口是否在免登陆列表
        noAnyApi = checkLogin
        if noAnyApi:
            for i in anyList:
                if apiName == i.lower():
                    noAnyApi = False

        # 校验是否登录
        if noAnyApi:
            session = request.cookies.get('session')
            cs = checkSession(session)
            if cs == 1:
                return fail('没有权限', 401, 401)
            elif cs == 2:
                return fail('登录超时', 401, 401)
            elif cs == 4:
                return fail('请重新登录', 401, 401)
            elif cs == 0:
                updataSession(session)
Exemple #17
0
async def check(request):
    # 根据请求路径,找到请求对应的接口前缀
    prefix = None
    rep = None
    for i in c.PREFIX:
        if request.headers['host'] + c.PREFIX[i] in request.url:
            prefix = c.PREFIX[i]
    # 处理后台接口中间处理
    if prefix == '/api/v1/be/':
        rep = middleHandle(request, prefix, 'black', c.BLACK_AUTH, True,
                           c.ANONYMOUS_API)
    # 处理前台接口中间处理
    elif prefix == '/api/v1/fe/':
        rep = middleHandle(request, prefix, 'white', c.WHITE_AUTH, False)
    # 处理非法请求地址
    else:
        rep = fail('请求路径不合法', 404, 404)
    # 处理结果为非空,则直接return
    if rep:
        return rep
Exemple #18
0
async def post(request):
    dat = request['data']
    if len(dat) > 1:
        return fail('站点信息不能更新多条数据', 400, 400)
    return rest.put(dat[0], 'site', 'first')
Exemple #19
0
async def put(request, oid):
    return fail('不被允许的请求方法', 405)
Exemple #20
0
async def delete(request, oid):
    return fail('不被允许的请求方法', 405)
Exemple #21
0
async def upimg(request):

    # 判断参数是否正确
    if not request.files and not request.files.get('file'):
        return fail('request args is error', 412)
    image = request.files.get('file').body

    # 判断文件是否支持
    imageSuffix = getSuffix(bytes2hex(image))
    if imageSuffix == 'error':
        return fail('image type is error', 415)

    # 组织图片存储路径
    m1 = hashlib.md5()
    m1.update(image)
    md5Name = m1.hexdigest()

    saveDir = STATIC_DIR + '/' + md5Name[0:2] + '/'
    savePath = saveDir + md5Name[2:] + '.' + imageSuffix
    resPath = md5Name + '.' + imageSuffix

    # 如果文件夹不存在,就创建文件夹
    if not os.path.exists(saveDir):
        os.makedirs(saveDir)

    # 上传文件附带参数处理
    if 'data' in request.form and imageSuffix != 'svg':
        # 检查参数是否是 json
        params_text = request.form['data'][0]
        if not isDictStr(params_text):
            return fail('form data must be Json String', 412)
        params = json.loads(params_text)

        # 读取原图信息
        sImg = Image.open(BytesIO(image))
        sw, sh = sImg.size

        # PNG 和 JPG 图片的处理
        if imageSuffix != 'gif':
            oImg = sImg
            # 处理缩放图片
            if 'zoom' in params:
                zoom = params['zoom']
                if not isNum(zoom):
                    return fail('zoom value must be Positive integer', 412)
                # 如果原图尺寸小于缩放尺寸,则直接保存
                if sw <= zoom and sh <= zoom:
                    saveImage(savePath, image)
                else:
                    oImg = zoomImg(sImg, sw, sh, zoom)
            # 处理水印参数
            mParam = calcMarkParams(params)
            if not isinstance(mParam, dict) and mParam != False:
                return mParam
            if isinstance(mParam, dict):
                oImg = makeMark(oImg, mParam)
            # 保存图片
            oImg.save(savePath, checkSuffix(imageSuffix))
            oImg.close()

        # 处理 gif 图片
        else:
            oImg = sImg
            # 将 gif 拆解为一组照片
            tempGIf = hackGif(sImg, savePath)
            tempImgPath = tempGIf[0]
            tempDirPath = tempGIf[1]
            gifDur = tempGIf[2] / 1000
            tempImg = []
            # 压缩每一张照片
            for i in tempImgPath:
                tmp = Image.open(i)
                if 'zoom' in params:
                    zoom = params['zoom']
                    if not isNum(zoom):
                        return fail('zoom value must be Positive integer', 412)
                    # 如果原图尺寸小于缩放尺寸,则直接保存
                    if sw > zoom and sh > zoom:
                        tmp = zoomImg(tmp, sw, sh, zoom)
                # 处理水印参数
                mParam = calcMarkParams(params)
                if not isinstance(mParam, dict) and mParam != False:
                    return mParam
                if isinstance(mParam, dict):
                    tmp = makeMark(tmp, mParam)
                tmp.save(i, 'PNG')
                tempImg.append(imageio.imread(i))
            # 将拆解出来的图片重新组装为gif图片
            imageio.mimsave(savePath, tempImg, 'GIF', duration=gifDur)
            # 删除临时文件夹
            shutil.rmtree(tempDirPath)

    else:
        saveImage(savePath, image)

    # 给客户端返回结果
    return ok({"path": resPath})
Exemple #22
0
 async def put(self, request, name, oid):
     data = request.json
     if data:
         return await doProcess(app, name, request, data, 'put', oid)
     else:
         return fail('数据不能为空', 400)
Exemple #23
0
def returnNotFound(request, exception):
    return fail(request.url + '没有找到', 404, 404)
Exemple #24
0
def calcMarkParams(params):
    if not 'mark' in params:
        return False
    # 确定是否包含水印参数以及水印的类型
    mark = params['mark']
    if not 'type' in mark:
        return fail('mark must has type field', 412)
    mType = mark['type']
    if not mark['type'] in ['img', 'text']:
        return fail('mark type must be "img" or "text"', 412)

    # 默认水印位置为图片右下角
    mParam = {'type': mType, 'location': ['right', 'bottom']}

    # 如果参数中包含水印位置参数,则重设水印位置参数
    if 'location' in mark:
        mLoca = mark['location']
        if not isinstance(mLoca, list):
            return fail('mark location must be array', 412)
        if len(mLoca) != 2:
            return fail('mark location array length must be 2', 412)
        if not mLoca[0] in ['left', 'right', 'center']:
            return fail(
                'mark location[0] value must in "left", "right", "center"',
                412)
        if not mLoca[1] in ['top', 'bottom', 'center']:
            return fail(
                'mark location[1] value must in "top", "bottom", "center"',
                412)
        mParam['location'] = mLoca

    # 图片水印参数处理
    if mType == 'img':
        # 图片水印必须包含水印图片名称
        if not 'imgName' in mark:
            return fail('image mark must has "imgName" field', 412)
        # 根据水印图片名称组织水印图片路径并判断水印是否存在
        mImgName = mark['imgName']
        markPath = STATIC_DIR + '/' + mImgName[0:2] + '/' + mImgName[2:]
        if not hasFile(markPath):
            return fail('image mark was not found', 412)
        mParam['imgPath'] = markPath
        # 读取水印图片并获取其宽高设为默认水印大小
        mImg = Image.open(markPath)
        mW, mH = mImg.size
        mParam['imgSize'] = [mW, mH]
        # 若果包含水印大小参数则重设水印大小
        if 'imgSize' in mark:
            imgSize = mark['imgSize']
            if not isinstance(imgSize, list):
                return fail('mark imgSize must be array', 412)
            if len(imgSize) != 2:
                return fail('mark imgSize array length must be 2', 412)
            for i in imgSize:
                if not isNum(i):
                    return fail(
                        'mark imgSize array value must be Positive integer',
                        412)
            mParam['imgSize'] = imgSize
    # 文字水印参数处理
    if mType == 'text':
        # 文字水印必须包含文字信息
        if not 'text' in mark:
            return fail('Text mark must has text field', 412)
        mText = mark['text']
        if not isinstance(mText, str):
            return fail('Text mark text field must be String', 412)
        if len(mText) > 20:
            return fail('Text mark text field max length is 20', 412)
        mParam['text'] = mText
        # 处理颜色参数,默认为白色
        mParam['color'] = '#FFFFFF'
        if 'color' in mark:
            if not isColor(mark['color']):
                return fail('mark color value must be a color String', 412)
            mParam['color'] = mark['color']
        # 处理文字大小参数,默认为20,最小值为18
        mParam['size'] = 20
        if 'size' in mark:
            mSize = mark['size']
            if not isNum(mark['size']):
                return fail('mark font size value must be Positive integer',
                            412)
            if mSize > 18:
                mParam['size'] = mSize
            else:
                mParam['size'] = 18
        # 处理文字字体参数
        if 'ttf' in mark:
            mTtf = mark['ttf']
            if not isinstance(mTtf, str):
                return fail('Text mark ttf field must be String', 412)
            mParam['ttf'] = findTtfPath(mTtf)

    return mParam