Пример #1
0
def login():
    res = dict(code=1, msg=None)
    usr = request.form.get("username")
    pwd = request.form.get("password")
    #: 定义是否设置cookie状态
    set_state = is_true(request.form.get("set_state"))
    is_secure = False if request.url_root.split("://")[0] == "http" else True
    max_age = 7200
    if is_true(request.form.get("remember")):
        #: Remember me 7d
        max_age = 604800
    #: 登录接口钩子
    try:
        if g.cfg.site_auth:
            so = current_app.extensions["hookmanager"].proxy(g.cfg.site_auth)
            if so and hasattr(so, "login_api"):
                result = so.login_api(usr, pwd, set_state, max_age, is_secure)
                if result and isinstance(result, Response):
                    return result
    except (ValueError, TypeError, Exception) as e:
        logger.warning(e, exc_info=True)
    if usr and username_pat.match(usr) and pwd and len(pwd) >= 6:
        ak = rsp("accounts")
        usr = usr.lower()
        if g.rc.sismember(ak, usr):
            userinfo = g.rc.hgetall(rsp("account", usr))
            if is_true(g.cfg.disable_login) and \
                    not is_true(userinfo.get("is_admin")):
                res.update(msg="Normal user login has been disabled")
                return res
            password = userinfo.get("password")
            if password and check_password_hash(password, pwd):
                expire = get_current_timestamp() + max_age
                sid = "%s.%s.%s" % (usr, expire,
                                    sha256("%s:%s:%s:%s" %
                                           (usr, password, expire,
                                            current_app.config["SECRET_KEY"])))
                sid = b64encode(sid.encode("utf-8")).decode("utf-8")
                res.update(
                    code=0,
                    sid=sid,
                    expire=expire,
                    # is_admin=is_true(userinfo.get("is_admin"))
                )
                if set_state:
                    res = make_response(jsonify(res))
                    res.set_cookie(key="dSid",
                                   value=sid,
                                   max_age=max_age,
                                   httponly=True,
                                   secure=is_secure)
            else:
                res.update(msg="Password verification failed")
        else:
            res.update(msg="No valid username found")
    else:
        res.update(msg="The username or password parameter error")
    return res
Пример #2
0
def authorized():
    """ Client SSO 单点登录、注销入口, 根据`Action`参数判断是`ssoLogin`还是`ssoLogout` """
    Action = request.args.get("Action")
    if Action == "ssoLogin":
        # 单点登录
        ticket = request.args.get("ticket")
        if request.method == "GET" and ticket and g.signin == False:
            resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_ticket"), dict(ticket=ticket, app_name=SSO["app_name"], get_userinfo=True, get_userbind=False))
            logger.debug("SSO check ticket resp: {}".format(resp))
            if resp and isinstance(resp, dict) and "success" in resp and "uid" in resp:
                if resp["success"] is True:
                    uid = resp["uid"]
                    sid = resp["sid"]
                    expire = int(resp["expire"])
                    # 获取用户信息,若不需要,可将get_userinfo=True改为False,并注释下两行
                    g.userinfo = resp["userinfo"].get("data") or dict()
                    set_userinfo(uid, g.userinfo, expire)
                    logger.debug(g.userinfo)
                    # 授权令牌验证通过,设置局部会话,允许登录
                    sessionId = set_sessionId(uid=uid, seconds=expire, sid=sid)
                    response = make_response(redirect(get_redirect_url("front.index")))
                    response.set_cookie(key="sessionId", value=sessionId, max_age=expire, httponly=True, secure=False if request.url_root.split("://")[0] == "http" else True)
                    return response
    elif Action == "ssoLogout":
        # 单点注销
        ReturnUrl = request.args.get("ReturnUrl") or get_referrer_url() or url_for("front.index", _external=True)
        NextUrl   = "{}/signOut?ReturnUrl={}".format(sso_server, ReturnUrl)
        app_name  = request.args.get("app_name")
        if request.method == "GET" and NextUrl and app_name and g.signin == True and app_name == SSO["app_name"]:
            response = make_response(redirect(NextUrl))
            response.set_cookie(key="sessionId", value="", expires=0)
            return response
    elif Action == "ssoConSync":
        # 数据同步:参数中必须包含大写的hmac_sha256(app_name:app_id:app_secret)的signature值
        signature = request.args.get("signature")
        if request.method == "POST" and signature and signature == hmac_sha256("{}:{}:{}".format(SSO["app_name"], SSO["app_id"], SSO["app_secret"])).upper():
            try:
                data = json.loads(request.form.get("data"))
                ct = data["CallbackType"]
                cd = data["CallbackData"]
                uid = data["uid"]
                token = data["token"]
            except Exception,e:
                logger.warning(e)
            else:
                logger.info("ssoConSync with uid: {} -> {}: {}".format(uid, ct, cd))
                resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_sync"), dict(token=token, uid=uid))
                if resp and isinstance(resp, dict) and resp.get("success") is True:
                    # 之后根据不同类型的ct处理cd
                    logger.debug("ssoConSync is ok")
                    if ct == "user_profile":
                        g.userinfo.update(cd)
                    elif ct == "user_avatar":
                        g.userinfo["avatar"] = cd
                    return jsonify(msg="Synchronization completed", success=set_userinfo(uid, g.userinfo), app_name=SSO["app_name"])
Пример #3
0
def QueryRollbackSQL(taskId, backup_mysql_url):
    """查询任务执行成功后的SQL回滚语句"""
    res = dict(code=1, msg=None)
    if taskId and isinstance(taskId, int) and backup_mysql_url:
        dbbackup = create_mysql_engine(backup_mysql_url)
        dblocal = create_mysql_engine()
        sql = "SELECT executeResult FROM incetops_task WHERE taskId=%s AND status=0"
        data = dblocal.get(sql, taskId)
        if data and isinstance(data, dict) and data.get("executeResult"):
            result = json.loads(data["executeResult"])
            rollback_sqls = []
            for row in result:
                if row.get('backup_dbname'
                           ) and row.get('backup_dbname') != 'None':
                    backup_dbname = row.get("backup_dbname")
                    opid_time = row.get("sequence").replace("'", "")
                    rowdata = dict(opid_time=opid_time,
                                   backup_dbname=backup_dbname,
                                   sql=None,
                                   rollback=None,
                                   errmsg=None)
                    # 以下是实际查询操作
                    sql_table = "select sql_statement,tablename from {}.$_$Inception_backup_information$_$ where opid_time=%s".format(
                        backup_dbname)
                    try:
                        table_data = dbbackup.get(sql_table, opid_time)
                    except Exception, e:
                        logger.warning(e)
                        res.update(msg=str(e))
                    else:
                        if not table_data:
                            rowdata["errmsg"] = "Get table data error"
                        else:
                            rowdata["sql"] = table_data["sql_statement"]
                            sql_back = "select rollback_statement from {}.{} where opid_time=%s".format(
                                backup_dbname, table_data['tablename'])
                            back_data = dbbackup.query(sql_back, opid_time)
                            if not back_data:
                                rowdata["errmsg"] = "Get rollback data error"
                            else:
                                rowdata["rollback"] = "\n".join([
                                    i["rollback_statement"] for i in back_data
                                    if isinstance(i, dict)
                                    and "rollback_statement" in i
                                ])
                        rollback_sqls.append(rowdata)
                else:
                    continue
            if rollback_sqls:
                res.update(code=0, data=rollback_sqls)
            else:
                res.update(code=2, msg=res["msg"] or "No rollback sql")
        else:
            res.update(msg="Invaild task")
Пример #4
0
    def get_statistic(self):
        """统计数据
        # 直接mysql计算各类型百分比,返回4位float
            select format(sum((usedb)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) usedb_rate, format(sum((deleting)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) deleting_rate, format(sum((inserting)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) inserting_rate, format(sum((updating)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) updating_rate, format(sum((selecting)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) selecting_rate, format(sum((altertable)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) altertable_rate, format(sum((createtable)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) createtable_rate, format(sum((droptable)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) droptable_rate, format(sum((createdb)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) createdb_rate, format(sum((truncating)/(usedb+deleting+inserting+updating+selecting+altertable+createtable+droptable+createdb+truncating))/count(1), 4) truncating_rate from inception.statistic;

        # 查询各类型总数量
            select format(sum(usedb), 0) usedb,format(sum(deleting), 0) deleting,format(sum(inserting), 0) inserting,format(sum(updating), 0) updating,format(sum(selecting), 0) selecting,format(sum(altertable), 0) altertable,format(sum(createtable), 0) createtable,format(sum(droptable), 0) droptable,format(sum(createdb), 0) createdb,format(sum(truncating), 0) truncating from inception.statistic;

        # 暂时只统计了大分类,alter子分类图表参考http://echarts.baidu.com/examples/editor.html?c=pie-nest
        """
        res = dict(code=1, msg=None)
        sql = 'select format(sum(usedb), 0) usedb,format(sum(deleting), 0) deleting,format(sum(inserting), 0) inserting,format(sum(updating), 0) updating,format(sum(selecting), 0) selecting,format(sum(altertable), 0) altertable,format(sum(createtable), 0) createtable,format(sum(droptable), 0) droptable,format(sum(createdb), 0) createdb,format(sum(truncating), 0) truncating,format(sum(renaming), 0) renaming,format(sum(createindex), 0) createindex,format(sum(dropindex), 0) dropindex,format(sum(addcolumn), 0) addcolumn,format(sum(dropcolumn), 0) dropcolumn,format(sum(changecolumn), 0) changecolumn,format(sum(alteroption), 0) alteroption,format(sum(alterconvert), 0) alterconvert from inception.statistic'
        try:
            backup_mysql = create_mysql_engine(PLUGINS["IncetOps"]["DefaultBackupDatabase"])
            data = backup_mysql.get(sql)
        except Exception,e:
            res.update(msg=str(e))
            logger.warning(e, exc_info=True)
Пример #5
0
def shamgr(sha):
    """图片查询、删除接口"""
    res = dict(code=1)
    gk = rsp("index", "global")
    ik = rsp("image", sha)
    dk = rsp("index", "deleted")
    if request.method == "GET":
        if g.rc.sismember(gk, sha):
            data = g.rc.hgetall(ik)
            u, n = data["src"], data["filename"]
            data.update(
                senders=json.loads(data["senders"]) if g.is_admin else None,
                ctime=int(data["ctime"]),
                tpl=dict(HTML="<img src='%s' alt='%s'>" % (u, n),
                         rST=".. image:: %s" % u,
                         Markdown="![%s](%s)" % (n, u)))
            res.update(code=0, data=data)
        else:
            return abort(404)
    elif request.method == "DELETE":
        if not g.signin:
            return abort(403)
        if g.rc.sismember(gk, sha):
            #: 图片所属用户
            #: - 如果不是匿名,那么判断请求用户是否属所属用户或管理员
            #: - 如果是匿名上传,那么只有管理员有权删除
            info = g.rc.hgetall(ik)
            husr = info.get("user")
            if g.is_admin or (g.userinfo.username == husr):
                pipe = g.rc.pipeline()
                pipe.srem(gk, sha)
                pipe.sadd(dk, sha)
                pipe.hset(ik, "status", "deleted")
                pipe.srem(rsp("index", "user", husr), sha)
                try:
                    pipe.execute()
                except RedisError:
                    res.update(msg="Program data storage service error")
                else:
                    res.update(code=0)
                    try:
                        #: 删除图片尝试执行senders的upimg_delete方法
                        #: 后端钩子未禁用时才会执行删除
                        #: TODO 无论禁用与否都删除?
                        senders = json.loads(info.get("senders"))
                        for i in senders:
                            current_app.extensions["hookmanager"].proxy(
                                i["sender"]).upimg_delete(
                                    sha=sha,
                                    upload_path=info["upload_path"],
                                    filename=info["filename"],
                                    basedir=(join(current_app.root_path,
                                                  current_app.static_folder,
                                                  UPLOAD_FOLDER)
                                             if i["sender"] == "up2local" else
                                             i.get("basedir")),
                                    save_result=i)
                    except (ValueError, AttributeError, Exception) as e:
                        logger.warning(e, exc_info=True)
            else:
                return abort(403)
        else:
            return abort(404)
    else:
        return abort(405)
    return res
Пример #6
0
def shamgr(sha):
    """图片查询、删除接口"""
    res = dict(code=1, msg=None)
    gk = rsp("index", "global")
    ik = rsp("image", sha)
    dk = rsp("index", "deleted")
    if request.method == "GET":

        def get_url_with_suffix(d, _type):
            """根据type返回src"""
            if g.userinfo and "parsed_ucfg_url_rule_switch" in g.userinfo and \
                    is_true(g.userinfo.parsed_ucfg_url_rule_switch.get(_type)):
                return "%s%s" % (d["src"],
                                 g.userinfo.parsed_ucfg_url_rule.get(
                                     d["sender"], ""))
            return d["src"]

        if g.rc.sismember(gk, sha):
            data = g.rc.hgetall(ik)
            n = data["filename"]
            data.update(
                senders=json.loads(data["senders"]) if g.is_admin else None,
                ctime=int(data["ctime"]),
                tpl=dict(URL="%s" % get_url_with_suffix(data, "url"),
                         HTML="<img src='%s' alt='%s'>" %
                         (get_url_with_suffix(data, "html"), n),
                         rST=".. image:: %s" %
                         get_url_with_suffix(data, "rst"),
                         Markdown="![%s](%s)" %
                         (n, get_url_with_suffix(data, "markdown"))))
            res.update(code=0, data=data)
        else:
            return abort(404)
    elif request.method == "DELETE":
        if not g.signin:
            return abort(403)
        if g.rc.sismember(gk, sha):
            #: 图片所属用户
            #: - 如果不是匿名,那么判断请求用户是否属所属用户或管理员
            #: - 如果是匿名上传,那么只有管理员有权删除
            info = g.rc.hgetall(ik)
            husr = info.get("user")
            if g.is_admin or (g.userinfo.username == husr):
                pipe = g.rc.pipeline()
                pipe.srem(gk, sha)
                pipe.sadd(dk, sha)
                pipe.hset(ik, "status", "deleted")
                pipe.srem(rsp("index", "user", husr), sha)
                try:
                    pipe.execute()
                except RedisError:
                    res.update(msg="Program data storage service error")
                else:
                    res.update(code=0)
                    try:
                        #: 删除图片尝试执行senders的upimg_delete方法
                        #: 后端钩子未禁用时才会执行删除
                        #: TODO 无论禁用与否都删除?
                        senders = json.loads(info.get("senders"))
                        for i in senders:
                            current_app.extensions["hookmanager"].proxy(
                                i["sender"]).upimg_delete(
                                    sha=sha,
                                    upload_path=info["upload_path"],
                                    filename=info["filename"],
                                    basedir=(join(current_app.root_path,
                                                  current_app.static_folder,
                                                  UPLOAD_FOLDER)
                                             if i["sender"] == "up2local" else
                                             i.get("basedir")),
                                    save_result=i)
                    except (ValueError, AttributeError, Exception) as e:
                        logger.warning(e, exc_info=True)
            else:
                return abort(403)
        else:
            return abort(404)
    elif request.method == "PUT":
        Action = request.args.get("Action") or request.form.get("Action")
        if Action == "updateAlbum":
            if not g.signin:
                return abort(403)
            if not g.rc.sismember(gk, sha):
                return abort(404)
            #: 更改相册名,允许图片所属用户或管理员修改,允许置空
            album = request.form.get("album")
            shaOwner = g.rc.hget(ik, "user")
            if g.userinfo.username == shaOwner or g.is_admin:
                try:
                    g.rc.hset(ik, "album", album)
                except RedisError:
                    res.update(msg="Program data storage service error")
                else:
                    res.update(code=0)
            else:
                return abort(403)
    else:
        return abort(405)
    return res