예제 #1
0
async def system_log_list(request: sanic.Request):
    if isinstance(request.json, dict):
        page = request.json.get('page', 0)
        page_size = request.json.get('page_size', 35)
        filter = request.json.get('filter', {})

        if isinstance(page, int) and isinstance(page_size, int) and isinstance(
                filter, dict):
            system_log_scalars = (await request.ctx.db_session.execute(
                select(SystemLog).order_by(SystemLog.log_id.desc()).offset(
                    page * page_size).limit(page_size))).scalars()

            count = (await request.ctx.db_session.execute(
                select(func.count('1')).select_from(SystemLog))).scalar()

            system_logs = []
            for log in system_log_scalars:
                log.log_time = log.log_time.strftime('%Y-%m-%d %H:%M:%S')
                system_logs.append(log)

            paged = PagedResponse(payload=system_logs,
                                  total_page=ceil(count / page_size),
                                  curr_page=page)
            return json(Response.success('', paged))

        else:
            return json(Response.invalid('无效参数'))
    else:
        return json(Response.invalid('无效参数'))
async def delete_catalog(request: sanic.Request):
    if isinstance(request.json, dict):
        catalog_id = request.json.get('catalog_id', None)

        if isinstance(catalog_id, int):
            query = select(HttpRuleCatalog).where(
                HttpRuleCatalog.catalog_id == catalog_id)
            catalog = (await request.ctx.db_session.execute(query)).scalar()
            if catalog is not None:
                # 删除分类和其下的所有规则
                query = select(HttpRule).where(
                    HttpRule.catalog_id == catalog_id)

                rules = (await request.ctx.db_session.execute(query)).scalars()
                for rule in rules:
                    await request.ctx.db_session.delete(rule)
                await request.ctx.db_session.delete(catalog)
                await request.ctx.db_session.commit()
                return json(Response.success('删除成功'))
            else:
                return json(Response.failed('分类不存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #3
0
async def modify(request: sanic.Request):
    if isinstance(request.json, dict):
        filename = request.json.get('filename', None)
        new_filename = request.json.get('new_filename', None)
        content = request.json.get('content', None)

        if isinstance(filename, str):
            filename = secure_filename_with_directory(filename)
            path = join(system_config.UPLOAD_PATH, filename)
            if exists(path) and not isdir(path):
                response = Response.success('修改成功')

                if isinstance(content, str):
                    await write_file(path, content.encode())

                if isinstance(new_filename, str):
                    new_filename = secure_filename_with_directory(new_filename)
                    new_path = join(system_config.UPLOAD_PATH, new_filename)
                    if not exists(new_path):
                        try:
                            rename(path, new_path)
                        except FileNotFoundError:
                            response = Response.failed('重命名失败, 请确认新文件所在文件夹存在')
                    else:
                        response = Response.failed('重命名失败, 目标文件名已存在')

                return json(response)
            else:
                return json(Response.failed('文件不存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #4
0
async def delete_all(request: sanic.Request):
    if isinstance(request.json, dict):
        delete_check = request.json.get('delete', False)
        if isinstance(delete_check, bool) and delete_check:
            await request.ctx.db_session.execute(delete(DNSLog))
            await request.ctx.db_session.commit()
            return json(Response.success('清空成功'))
        else:
            return json(Response.invalid('无效请求'))
    else:
        return json(Response.invalid('无效请求'))
예제 #5
0
async def modify(request: sanic.Request):
    if isinstance(request.json, dict):
        rule_id = request.json.get('rule_id', None)
        rule_type = request.json.get('rule_type', None)
        path = request.json.get('path', None)
        filename = request.json.get('filename', None)
        write_log = request.json.get('write_log', None)
        send_mail = request.json.get('send_mail', None)
        comment = request.json.get('comment', None)
        catalog_id = request.json.get('catalog_id', None)

        if isinstance(rule_id, int):
            query = select(HttpRule).where(HttpRule.rule_id == rule_id)
            rule = (await request.ctx.db_session.execute(query)).scalar()
            if rule is not None:
                if isinstance(path, str):
                    query = select(HttpRule).where(HttpRule.path == path)
                    result = (await
                              request.ctx.db_session.execute(query)).scalar()
                    if result is None or result.rule_id == rule_id:
                        rule.path = path
                    else:
                        return json(Response.failed('路径已经存在'))

                if isinstance(catalog_id, int):
                    query = select(HttpRuleCatalog).where(
                        HttpRuleCatalog.catalog_id == catalog_id)
                    result = (await
                              request.ctx.db_session.execute(query)).scalar()
                    if result is not None:
                        rule.catalog_id = catalog_id
                    else:
                        return json(Response.failed('分类不存在'))

                if isinstance(filename, str):
                    rule.filename = filename
                if isinstance(write_log, bool):
                    rule.write_log = write_log
                if isinstance(send_mail, bool):
                    rule.send_mail = send_mail
                if isinstance(comment, str):
                    rule.comment = comment
                if rule_type in constants.RULE_TYPES:
                    rule.rule_type = rule_type

                request.ctx.db_session.add(rule)
                await request.ctx.db_session.commit()
                return json(Response.success('修改成功'))
            else:
                return json(Response.failed('规则不存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #6
0
async def delete_all(request: sanic.Request):
    if isinstance(request.json, dict):
        delete = request.json.get('delete', None)

        if isinstance(delete, bool) and delete:
            temp_files = listdir(system_config.TEMP_FILE_PATH)
            for filename in temp_files:
                path = join(system_config.TEMP_FILE_PATH, filename)
                unlink(path)
            return json(Response.success("清空成功"))
        else:
            return json(Response.invalid('无效请求'))
    else:
        return json(Response.invalid('无效请求'))
예제 #7
0
async def download(request: sanic.Request):
    if isinstance(request.json, dict):
        filename = request.json.get('filename', None)
        if isinstance(filename, str):
            filename = secure_filename(filename)
            path = join(system_config.TEMP_FILE_PATH, filename)
            if exists(path) and not isdir(path):
                return await sanic.response.file(path, filename=filename)
            else:
                return json(Response.failed('文件不存在'), 500)
        else:
            return json(Response.invalid('参数无效'), 400)
    else:
        return json(Response.invalid('参数无效'), 400)
예제 #8
0
async def delete(request: sanic.Request):
    if isinstance(request.json, dict):
        filename = request.json.get('filename', None)
        if isinstance(filename, str):
            filename = secure_filename_with_directory(filename)
            path = join(system_config.UPLOAD_PATH, filename)
            if exists(path) and not isdir(path):
                unlink(path)
                return json(Response.success('删除成功'))
            else:
                return json(Response.failed('删除的文件不存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #9
0
async def login(request: sanic.Request):
    if isinstance(request.json, dict):
        username = request.json.get('username', None)
        password = request.json.get('password', None)

        user: typing.Union[None, User] = (await request.ctx.db_session.execute(
            select(User).where(User.username == username))).scalar()

        if isinstance(username, str) and isinstance(password, str) and \
                (user is not None) and compare_digest(passwd_hash(password, system_config.PASSWORD_SALT), user.password):
            token = sign_token(user.user_id)

            if system_config.BEHIND_PROXY:
                client_ip = request.headers.get(constants.REAL_IP_HEADER)
            else:
                client_ip = request.ip

            log_content = f'Login with username [{username}] in [{client_ip} | {get_region_from_ip(client_ip)}]'
            await add_system_log(request.ctx.db_session, log_content,
                                 constants.LOG_TYPE_LOGIN)

            return json(
                Response.success('登录成功', {
                    'token': token,
                    'user_type': user.user_type
                }))
        else:
            return json(Response.failed('用户名或密码错误'))
    else:
        return json(Response.invalid('无效请求'))
예제 #10
0
async def add_directory(request: sanic.Request):
    if isinstance(request.json, dict):
        directory_name = request.json.get('directory_name', None)
        if isinstance(directory_name,
                      str) and len(secure_filename(directory_name)) > 0:
            directory_name = secure_filename(directory_name)
            full_path = join(system_config.UPLOAD_PATH, directory_name)
            if not exists(full_path):
                mkdir(full_path)
                return json(Response.success('创建成功'))
            else:
                return json(Response.failed('文件夹已存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #11
0
async def delete_directory(request: sanic.Request):
    if isinstance(request.json, dict):
        directory_name = request.json.get('directory_name', None)
        if isinstance(directory_name,
                      str) and len(secure_filename(directory_name)) > 0:
            directory_name = secure_filename(directory_name)
            full_path = join(system_config.UPLOAD_PATH, directory_name)
            if exists(full_path) and not isfile(full_path):
                shutil.rmtree(full_path)
                return json(Response.success('删除成功'))
            else:
                return json(Response.failed('文件夹不存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #12
0
async def change_password(request: sanic.Request):
    target_user = request.json.get('target_user', None)
    original_password = request.json.get('original_password', None)
    new_password = request.json.get('new_password', None)

    if target_user is None and isinstance(original_password, str) and isinstance(new_password, str) \
            and compare_digest(request.ctx.user.password, passwd_hash(original_password, system_config.PASSWORD_SALT)):

        request.ctx.user.password = passwd_hash(new_password,
                                                system_config.PASSWORD_SALT)
        request.ctx.db_session.add(request.ctx.user)

        await request.ctx.db_session.commit()
        return json(Response.success('修改成功'))
    elif target_user is not None and request.ctx.user.user_type == constants.USER_TYPE_SUPER_ADMIN \
            and isinstance(new_password, str) and isinstance(target_user, str):
        # 超级用户修改普通用户不需要原密码
        user = (await request.ctx.db_session.execute(
            select(User).where(User.username == target_user))).scalar()
        if user is not None and user.user_type == constants.USER_TYPE_NORMAL:
            user.password = passwd_hash(new_password,
                                        system_config.PASSWORD_SALT)
            request.ctx.db_session.add(request.ctx.user)

            await request.ctx.db_session.commit()
            return json(Response.success('修改成功'))
        else:
            return json(Response.failed('用户不存在'))
    else:
        return json(Response.invalid('原密码错误'))
예제 #13
0
async def dns_log_list(request: sanic.Request):
    if isinstance(request.json, dict):
        page = request.json.get('page', 0)
        page_size = request.json.get('page_size', 35)
        filter = request.json.get('filter', {})

        if isinstance(page, int) and isinstance(page_size, int) and isinstance(
                filter, dict):
            query = select(DNSLog)
            count_query = select(func.count('1')).select_from(DNSLog)

            available_filter = {
                'client_ip': DNSLog.client_ip.__eq__,
                'domain': DNSLog.domain.__eq__,
                'dns_type': DNSLog.dns_type.__eq__,
                'time_before': DNSLog.log_time.__le__,
                'time_after': DNSLog.log_time.__ge__
            }

            for key in filter:
                if isinstance(filter[key],
                              (str, int)) and key in available_filter:
                    query = query.where(available_filter[key](filter[key]))
                    count_query = count_query.where(available_filter[key](
                        filter[key]))

            dns_log_scalars = (await request.ctx.db_session.execute(
                query.order_by(DNSLog.log_id.desc()).offset(
                    page * page_size).limit(page_size))).scalars()
            count = (await
                     request.ctx.db_session.execute(count_query)).scalar()

            dns_logs = []
            for i in dns_log_scalars:
                # 也可以在入库的时候计算地区, 在这里输出时计算是因为感觉存储大量地址挺浪费空间的 233, 而计算不用太耗时间
                i.region = get_region_from_ip(i.client_ip)
                i.log_time = i.log_time.strftime('%Y-%m-%d %H:%M:%S')
                dns_logs.append(i)

            paged = PagedResponse(payload=dns_logs,
                                  total_page=ceil(count / page_size),
                                  curr_page=page)
            return json(Response.success('', paged))
        else:
            return json(Response.invalid('无效请求'))
    else:
        return json(Response.invalid('无效请求'))
예제 #14
0
async def modify(request: sanic.Request):
    if isinstance(request.json, dict):
        key = request.json.get('key', None)
        value = request.json.get('value', None)

        if isinstance(key, str) and value is not None:
            _, mutable = system_config.get_config_privileges(key)
            if mutable and isinstance(value,
                                      system_config.get_config_type(key)):
                setattr(system_config, key, value)
                return json(Response.success('修改成功'))
            else:
                return json(Response.failed('目标配置无法修改或者类型不正确'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #15
0
async def delete(request: sanic.Request):
    if isinstance(request.json, dict):
        rule_id = request.json.get('rule_id', None)

        if isinstance(rule_id, int):
            query = select(HttpRule).where(HttpRule.rule_id == rule_id)
            rule = (await request.ctx.db_session.execute(query)).scalar()

            if rule is not None:
                await request.ctx.db_session.delete(rule)
                await request.ctx.db_session.commit()
                return json(Response.success('删除成功'))
            else:
                return json(Response.failed('规则不存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
async def add_catalog(request: sanic.Request):
    if isinstance(request.json, dict):
        catalog_name = request.json.get('catalog_name', None)

        if isinstance(catalog_name, str):
            query = select(HttpRuleCatalog).where(
                HttpRuleCatalog.catalog_name == catalog_name)
            catalog = (await request.ctx.db_session.execute(query)).scalar()
            if catalog is None:
                catalog = HttpRuleCatalog(catalog_name=catalog_name)
                request.ctx.db_session.add(catalog)
                await request.ctx.db_session.commit()
                return json(Response.success('创建成功'))
            else:
                return json(Response.failed('已有此分类'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #17
0
async def add(request: sanic.Request):
    file = request.files.get('file', None)
    if file:
        filename = secure_filename_with_directory(file.name)
        path = join(system_config.UPLOAD_PATH, filename)
        if not exists(path):
            asyncio.create_task(write_file(path, file.body))
            return json(Response.success('上传成功'))
        else:
            return json(Response.failed('已存在同名文件'))
    else:
        return json(Response.invalid('无效参数'))
예제 #18
0
async def preview(request: sanic.Request):
    if isinstance(request.json, dict):
        filename = request.json.get('filename', None)
        if isinstance(filename, str):
            filename = secure_filename(filename)
            path = join(system_config.TEMP_FILE_PATH, filename)
            if exists(path) and not isdir(path):
                if getsize(path) < system_config.MAX_PREVIEW_SIZE:
                    content = await read_file(path)
                    try:
                        content = content.decode('utf-8')
                        return json(Response.success('', content))
                    except Exception:
                        return json(Response.failed('文件不是纯文本, 无法预览'))
                else:
                    json(Response.failed('文件过大, 无法预览'))
            else:
                return json(Response.failed('文件不存在或者为文件夹'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #19
0
async def modify_directory(request: sanic.Request):
    if isinstance(request.json, dict):
        directory_name = request.json.get('directory_name', None)
        new_directory_name = request.json.get('new_directory_name', None)

        if isinstance(
                directory_name,
                str) and len(secure_filename(directory_name)) > 0 and len(
                    secure_filename(new_directory_name)) > 0:
            full_path = join(system_config.UPLOAD_PATH,
                             secure_filename(directory_name))
            new_full_path = join(system_config.UPLOAD_PATH,
                                 secure_filename(new_directory_name))

            if exists(full_path) and not exists(new_full_path):
                rename(full_path, new_full_path)
                return json(Response.success('重命名成功'))
            else:
                return json(Response.failed('目标文件夹名已存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #20
0
async def add(request: sanic.Request):
    if isinstance(request.json, dict):
        path = request.json.get('path', None)
        rule_type = request.json.get('rule_type', None)
        filename = request.json.get('filename', None)
        write_log = request.json.get('write_log', None)
        send_mail = request.json.get('send_mail', None)
        comment = request.json.get('comment', None)
        catalog_id = request.json.get('catalog_id', None)

        if isinstance(path, str) and isinstance(filename, str) and isinstance(write_log, bool) \
                and isinstance(send_mail, bool) and isinstance(comment, str) and isinstance(catalog_id, int) and rule_type in constants.RULE_TYPES:
            query = select(HttpRuleCatalog).where(
                HttpRuleCatalog.catalog_id == catalog_id)
            catalog = (await request.ctx.db_session.execute(query)).scalar()
            if catalog is not None:
                query = select(HttpRule).where(HttpRule.path == path)
                rule = (await request.ctx.db_session.execute(query)).scalar()
                if rule is None:
                    rule = HttpRule(path=path,
                                    rule_type=rule_type,
                                    filename=filename,
                                    write_log=write_log,
                                    send_mail=send_mail,
                                    comment=comment,
                                    catalog_id=catalog_id)
                    request.ctx.db_session.add(rule)
                    await request.ctx.db_session.commit()
                    return json(Response.success('添加成功'))
                else:
                    return json(Response.failed('已经存在此规则'))
            else:
                return json(Response.failed('分类不存在'))
        else:
            return json(Response.invalid('参数无效'))
    else:
        return json(Response.invalid('参数无效'))
예제 #21
0
async def delete(request: sanic.Request):
    username = request.json.get('username', None)

    if isinstance(username, str):
        user = (await request.ctx.db_session.execute(
            select(User).where(User.username == username))).scalar()
        # 只能删除普通用户
        if user is not None and user.user_type == constants.USER_TYPE_NORMAL:
            await request.ctx.db_session.delete(user)
            await request.ctx.db_session.commit()
            return json(Response.success('删除成功'))
        else:
            return json(Response.failed('用户不存在'))
    else:
        return json(Response.invalid('无效请求'))
예제 #22
0
async def register(request: sanic.Request):
    username = request.json.get('username', None)
    password = request.json.get('password', None)

    user = (await request.ctx.db_session.execute(
        select(User).where(User.username == username))).scalar()
    if user is None:
        if isinstance(username, str) and isinstance(
                password, str) and len(username) < 255:
            user = User(username=username,
                        password=passwd_hash(password,
                                             system_config.PASSWORD_SALT),
                        user_type=constants.USER_TYPE_NORMAL)
            request.ctx.db_session.add(user)
            await request.ctx.db_session.commit()
            return json(Response.success('注册成功'))
        else:
            return json(Response.invalid('无效请求'))
    else:
        return json(Response.failed('用户名已经被注册'))