libf 2 years ago
parent
commit
a84709cfab

+ 246 - 0
json_importer_gen_v2/InitJsonImporter.js

@@ -0,0 +1,246 @@
+
+//默认值设置
+defaultinput = {
+    classname: "/cncc/action/test",
+    clsoption: "with ttl=10 day, version=true, nickname='test'",
+    data: null,
+    datafilename: "",
+    datafiledir: "/opt/cncc/ITIL/change_main",
+    jsfilename: "/script/cncc/ITIL/测试.js",
+    fieldmap: {id: "jid"},
+    fields: {idUnique: "string,key"},
+    mustfield: "id,idUnique",
+};
+inputmapping = {
+    "change": {
+        classname: "/cncc/action/change_main",
+        datafiledir: "/opt/cncc/ITIL/change_main",
+        jsfilename: "/script/cncc/ITIL/变更单.js",
+        clsoption: "with ttl=10 day, version=true, nickname='change_main'",
+    },
+    "event": {
+        classname: "/cncc/action/event",
+        datafiledir: "/opt/cncc/ITIL/event",
+        jsfilename: "/script/cncc/ITIL/事件单.js",
+        clsoption: "with ttl=10 day, version=true, nickname='event'",
+    },
+    "problem": {
+        classname: "/cncc/action/problem",
+        datafiledir: "/opt/cncc/ITIL/problem",
+        jsfilename: "/script/cncc/ITIL/问题单.js",
+        clsoption: "with ttl=10 day, version=true, nickname='problem'",
+    },
+    "report": {
+        classname: "/cncc/action/report",
+        datafiledir: "/opt/cncc/ITIL/report",
+        jsfilename: "/script/cncc/ITIL/报备.js",
+        clsoption: "with ttl=10 day, version=true, nickname='report'",
+    },
+    "device_power_on_off": {
+        classname: "/cncc/action/device_power_on_off",
+        datafiledir: "/opt/cncc/ITIL/device_power_on_off",
+        jsfilename: "/script/cncc/ITIL/设备上下电.js",
+        clsoption: "with ttl=10 day, version=true, nickname='device_power_on_off'",
+    },
+    "data_collect": {
+        classname: "/cncc/action/data_collect",
+        datafiledir: "/opt/cncc/ITIL/data_collect",
+        jsfilename: "/script/cncc/ITIL/数据获取.js",
+        clsoption: "with ttl=10 day, version=true, nickname='data_collect'",
+    },
+    "drill": {
+        classname: "/cncc/action/drill",
+        datafiledir: "/opt/cncc/ITIL/drill",
+        jsfilename: "/script/cncc/ITIL/应急演练.js",
+        clsoption: "with ttl=10 day, version=true, nickname='drill'",
+    },
+    "implement": {
+        classname: "/cncc/action/implement",
+        datafiledir: "/opt/cncc/ITIL/implement",
+        jsfilename: "/script/cncc/ITIL/项目实施或巡检.js",
+        clsoption: "with ttl=10 day, version=true, nickname='implement'",
+    }
+};
+
+// 输入输出参数格式化
+input = INPUT;
+output = {};
+try {
+    input = decodeURIComponent(input);
+} catch(e) {}
+try {
+    input = base64.decode(input);
+} catch(e) {}
+try {
+    input = JSON.parse(input);
+    input = JSON.parse(input);
+} catch(e) {}
+
+// 通用函数
+function isempty(o) {
+    if (o) {
+        for (var k in o){
+            return false;
+        }
+    } 
+    return true;
+}
+
+// 主执行阶段
+function main() {
+    output.info = {};
+    output.info.p0 = {name: "确认参数"};
+    p = inputmapping[input.name];
+    if (p) {
+        for (var k in p) {
+            defaultinput[k] = p[k];
+        }
+    }
+    server = input.server;
+    if (!server) {
+        server = defaultinput.server;
+    }
+    author = input.author;
+    if (!author) {
+        author = defaultinput.author;
+    }
+    classname = input.classname;
+    if (!classname) {
+        classname = defaultinput.classname;
+    }
+    if (classname[0] != "/") {
+        throw ("classname必须以 / 开头");
+    }
+    if (classname.substring(0,8) == "/matrix/") {
+        throw ("classname不能以 /matrix/ 开头");
+    }
+    data = input.data;
+    if (isempty(data)) {
+        data = defaultinput.data;
+        if (isempty(data)) {
+            datafilename = input.datafilename;
+            if (!datafilename) {
+                datafilename = defaultinput.datafilename;
+            }
+            if (datafilename) {
+                try {
+                    data = dfs.read(datafilename);
+                    data = JSON.parse(data);
+                } catch(e) {}
+            }
+        }
+        if (isempty(data)) {
+            datafiledir = input.datafiledir;
+            if (!datafiledir) {
+                if (classname == defaultinput.classname) {
+                    datafiledir = defaultinput.datafiledir;
+                } else {
+                    datafiledir = "/opt" + classname;
+                }
+            }
+            // 读取所有文件,综合数据
+            data = {};
+            files = dfs.readdir(datafiledir);
+            for (i = 0; i < files.length; i++) { 
+                try {
+                    adat = dfs.read(files[i].fullname);
+                    adat = JSON.parse(adat);
+                    if (typeof(adat) != "object") {
+                        throw("只接收JSON对象数据");
+                    }
+                    for (var k in adat) {
+                        if (!data[k]) {
+                            data[k] = adat[k];
+                        } else if (adat[k]) {
+                            if (typeof(adat[k]) == "object") {
+                                if (JSON.stringify(adat[k]).length > JSON.stringify(data[k]).length) {
+                                    data[k] = adat[k];
+                                }
+                            } else if (typeof(adat[k]) == "string") {
+                                if (typeof(data[k]) != "string") {
+                                    data[k] = adat[k];
+                                } else if (adat[k].length > data[k].length) {
+                                    data[k] = adat[k];
+                                }
+                            } else if (typeof(adat[k]) == "number") {
+                                if (typeof(data[k]) == "number") {
+                                    if ((""+adat[k]).indexOf(".")>=0) {
+                                        data[k] = adat[k];
+                                    }
+                                }
+                            } else if (typeof(adat[k]) == "boolean") {
+                                if (typeof(data[k]) != "boolean") {
+                                    data[k] = ""+adat[k];
+                                }
+                            }
+                        }
+                    }
+                } catch(e) {}
+            }
+        }
+    }
+    jsfilename = input.jsfilename;
+    if (!jsfilename) {
+        jsfilename = defaultinput.jsfilename;
+    }
+    clsoption = input.clsoption;
+    if (!clsoption) {
+        clsoption = defaultinput.clsoption;
+    }
+    fieldmap = input.fieldmap;
+    if (!fieldmap) {
+        fieldmap = defaultinput.fieldmap;
+    }
+    mustfield = input.mustfield;
+    if (!mustfield) {
+        mustfield = defaultinput.mustfield;
+    }
+    fields = input.fields;
+    if (!fields) {
+        fields = defaultinput.fields;
+    }
+    reqinput = {
+        classname: classname, 
+        jsfilename: jsfilename,
+        clsoption: clsoption, 
+        fieldmap: fieldmap,
+        fields: fields,
+        mustfield: mustfield,
+        data: data,
+    };
+    output.info.p1 = {name:"生成类"};
+    output.info.p1.result = alterClass(reqinput)
+    if (output.info.p1.result.error) {
+        return;
+    }
+    output.info.p2 = {name:"生成脚本"};
+    output.info.p2.result = generateJsonImporterJS(reqinput)
+    if (output.info.p2.result.error) {
+        return;
+    }
+    output.info.p3 = {name:"激活脚本"};
+    output.info.p3.result = activeServerJS(jsfilename)
+    if (output.info.p3.result.error) {
+        return;
+    }
+    output.info.p4 = {name:"验证测试"};
+    output.info.p4.result = runServerJS(jsfilename, data)
+    if (output.info.p4.result.error) {
+        return;
+    }
+    output.info.p5 = {name:"完成"};
+}
+try {
+    main();
+} catch(e) {
+    if (typeof(e) == "object") {
+        output.error = e;
+    } else if (typeof(e) == "string") {
+        output.error = "错误:" + e;
+    } else {
+        output.error = JSON.stringify(e);
+    }
+}
+
+// 返回输出信息
+OUTPUT = output;

+ 75 - 0
json_importer_gen_v2/JsonImporter.template.js

@@ -0,0 +1,75 @@
+// ___classname___ JSON数据导入程序
+// ___datetime_now___ 由 JsonImportGen.js 自动生成,请勿手动修改
+    
+// 输入输出参数格式化
+input = INPUT;
+try {
+    input = decodeURIComponent(input);
+} catch(e) {}
+try {
+    input = base64.decode(input);
+} catch(e) {}
+try {
+    input = JSON.parse(input);
+    input = JSON.parse(input);
+} catch(e) {}
+output = {};
+
+testcfg = {}
+try {
+    testcfg = JSON.parse(etcd.get("/api/test.json"));
+} catch(e) {}
+function teststoredfs() {
+    // 输入JSON临时存入DFS
+    dir = "/opt___classname___";
+    dtm = new Date().toJSON().replace(/[\-\:\.TZ ]/mg, "");
+    fn = dir + "/" + dtm;
+    if (input.id) {
+        fn += "." + input.id;
+    } else {
+        fn += "_" + _.random(0, 1000000);
+    }
+    fn += ".json";
+    dfs.write(fn, JSON.stringify(input, " ", 4));
+    output.filename = fn;
+    // 刪除旧交件
+    files = dfs.readdir(dir);
+    dt = Date.now() - 1000 * 3600 * 24 * 10;
+    for (i = 0; i < files.length; i++) {
+        if (files[i].mtime < dt) {
+            dfs.remove(files[i].fullname);
+        }
+    }
+    // 留最后10个
+    files.sort(function(a,b){ return a.mtime-b.mtime; });
+    for (i = 0; i < files.length-10; i++) {
+        dfs.remove(files[i].fullname);
+    }
+}
+// 主执行阶段
+try {
+    if (testcfg.storedfs) {
+        teststoredfs();
+    }
+    // 数据合法性检查
+    if (___datacheck___) {}
+    // mql定义
+    mql = `___mql___`;
+    // 执行mql
+    ret = odb.mql(mql, ___values___);
+    // 打印完成信息
+    output.info=___datainfo___;
+    log.info(output.info);
+} catch(e) {
+    if (typeof(e) == "object") {
+        output.error = e;
+    } else if (typeof(e) == "string") {
+        output.error = "插库错误:" + e;
+    } else {
+        output.error = JSON.stringify(e);
+    }
+    log.error(output.error);
+}
+
+// 返回输出信息
+OUTPUT = output;

+ 10 - 0
json_importer_gen_v2/config.js

@@ -0,0 +1,10 @@
+cfg = {
+    server: "http://27.193.12.228:8080",
+    author: base64.encode("meta.admin:admin"),
+};
+try{
+    etc = JSON.parse(etcd.get("api/cfg.json"))
+    for(k in etc) {
+        cfg[k] = etc[k]
+    }
+}catch(e){}

+ 436 - 0
json_importer_gen_v2/jsonImporterFuncs.js

@@ -0,0 +1,436 @@
+// JSON 对象数据导入数据库的函数库
+
+// 应用配置信息
+eval(dfs.read("/script/matrix/utils/config.js"))
+
+// 根据 JSON 对象数据建类或新增字段
+// classname 类名
+// clsoption 建类选项
+// data      数据示例
+// fieldmap  字段名映射,参数中指定的字段名均为JSON对象中的属性名,默认将 camelStyle 转换为 snake_style 
+// fields    字段类型
+function alterClass(input) {
+    // 返回信息
+    output = {}
+    // 参数检查
+    if (!input.classname) { // like /cncc/itil/project
+        throw ("需要指定classname");
+    }
+    if (input.classname[0] != "/") { // like /cncc/itil/project
+        throw ("classname必须以 / 开头");
+    }
+    if (!input.data || typeof(input.data)!="object") {
+        throw ("data必须指定为一个对象");
+    }
+    // 检查父类是否存在,不存在就创建
+    cns = input.classname.split("/");
+    clsname = "";
+    for (var cni = 1; cni < cns.length - 1; cni++) {
+        clsname += "/" + cns[cni];
+        odb.mql("create class if not exists " + clsname + "()");
+    }
+    pclsname = clsname;
+    clsname += "/" + cns[cns.length - 1];
+
+    // 提取现有类的字段信息
+    clsexist = false;
+    clsfields = {};
+    try {
+        fieldslist = odb.classfields(clsname);
+        for (var fi = 0; fi < fieldslist.length; fi++) {
+            fld = fieldslist[fi];
+            fname = fld.name;
+            if (/^\w+\:.*/.test(fname)) {
+                fname = fname.replace(/^\w+\:/, ""); 
+            }
+            if (fname && fld.ftype) {
+                clsfields[fname] = {
+                    iskey: fld.iskey,
+                    ftype: fld.ftype,
+                };
+            }
+        }
+        clsexist = true;
+    } catch(e) {}
+    if (!clsexist) {
+        try {
+            fieldslist = odb.classfields(pclsname);
+            for (var fi = 0; fi < fieldslist.length; fi++) {
+                fld = fieldslist[fi];
+                fname = fld.name;
+                if (/^\w+\:.*/.test(fname)) {
+                    fname = fname.replace(/^\w+\:/, ""); 
+                }
+                if (fname && fld.ftype) {
+                    clsfields[fname] = {
+                        iskey: fld.iskey,
+                        ftype: fld.ftype,
+                    };
+                }
+            }
+        } catch(e) {}
+    }
+    output.info.clsfields = clsfields;
+
+    // 通过参数确定的字段类型信息
+    fields = input.fields;
+    if (!fields) {
+        fields = {};
+    }
+    // 字段名映射,参数中指定的字段名均为JSON对象中的属性名,默认将 camelStyle 转换为 snake_style
+    fieldmap = input.fieldmap;
+    if (!fieldmap) {
+        fieldmap = {};
+    }
+    // 反向字段名映射,类中的字段名映射为JSON对象中的属性名
+    xfieldmap = {};
+    // 类中的字段名列表,用于排序
+    xfieldslist = [];
+    // 类字段类型信息
+    xfields = {};
+    xpks = [];
+    for (var jk in input.data) {
+        xk = fieldmap[jk];
+        // 通过参数确定的字段类型信息
+        if (!xk) {
+            // 默认将 camelStyle 转换为 snake_style
+            xk = "j_"; // 区别于其它字段,自动创建的字段以 j_ 开头
+            for (var i = 0; i < jk.length; i++) {
+                if (jk[i] >= 'A' && jk[i] <= 'Z') {
+                    xk += "_" + jk[i].toLowerCase();
+                } else {
+                    xk += jk[i];
+                }
+            }
+            fieldmap[jk] = xk;
+        }
+        xfieldslist.push(xk);
+        xfieldmap[xk] = jk;
+        dt = fields[jk];
+        if (dt && dt.indexOf(",key") > 0) {
+            dt = dt.replace(",key", "");
+            xpks.push(xk);
+        }
+        switch (dt) {
+        case "date":
+        case "time":
+        case "datetime":
+            dt = "timestamp";
+            break;
+        case "int":
+        case "integer":
+            dt = "bigint";
+            break;
+        case "number":
+        case "float":
+            dt = "double";
+            break;
+        case "text":
+            dt = "text";
+            break;
+        case "string":
+            dt = "varchar";
+            break;
+        case "boolean":
+            dt = "boolean";
+            break;
+        }
+        if (!dt) {
+            // 没有明确定义的字段类型
+            // 根据数据判断类型
+            dt = "varchar";
+            d = input.data[jk];
+            if (d || d == "" || d == 0 || d == false) { 
+                switch (typeof(d)) {
+                case 'object':
+                    // 转为text
+                    dt = "text"; 
+                    break;
+                case 'number':
+                    // 是否为整数
+                    if ((""+d).indexOf(".")<0) {
+                        dt = "bigint";
+                    } else {
+                        dt = "double";
+                    }
+                    break;
+                case 'boolean':
+                    dt = "boolean";
+                    break;
+                case 'string':
+                default:
+                    // 是否为日期时间
+                    if (/_time/.test(xk) || /_date/.test(xk)) {
+                        dt = "timestamp";
+                    } else {
+                        dt = "varchar";
+                    }
+                    break;
+                }
+            } else {
+                if (/_time/.test(xk) || /_date/.test(xk)) {
+                    dt = "timestamp";
+                } else {
+                    dt = "varchar";
+                }
+            }
+        }
+        xfields[xk] = dt;
+    }
+    output.info.xfields = xfields;
+    
+    if (!clsexist) {
+        // 类不存在,自动创建类
+        mql = "create class if not exists " + clsname + "(";
+        indexes = "indexes(";
+        for (var fi = 0; fi < xfieldslist.length; fi++) {
+            xk = xfieldslist[fi];
+            if (xk in {"id":"", "class":"", "name":"", "day":"", "tags":"", "vtime":""}) {
+                throw("内部使用字段名 " + xk + ",需要映射成其它名称");
+            }
+            if (clsfields[xk] && clsfields[xk].ftype != xfields[xk]) {
+                throw ("类继承字段 "+ xk +" 信息不一致,"+clsfields[xk].ftype + "!=" + xfields[xk]+",需手动干预");
+            }
+            mql += fi==0 ? "\n": ",\n";
+            mql += xk + " " + xfields[xk];
+            if (fi > 0) {
+                indexes += ",";
+            }
+            indexes += xk;
+        }
+        indexes += ")";
+        mql += ",\n" + indexes;
+        if (xpks.length > 0) {
+            mql += ",\n";
+            mql += "keys(";
+            for (var pki = 0; pki < xpks.length; pki++) {
+                if (pki > 0) {
+                    mql += ",";
+                }
+                mql += xpks[pki];
+            }
+            mql += ")";
+        }
+        mql += "\n";
+        mql += ")";
+        if (input.clsoption) {
+            mql += input.clsoption;
+        }
+        odb.mql(mql);
+        output.info = {mql:mql};
+    } else {
+        // 类已存在,检查主键信息是否存在
+        for (var pki = 0; pki < xpks.length; pki++) {
+            xk = xpks[pki];
+            if (!clsfields[xk] || !clsfields[xk].iskey) {
+                throw ("已经存在同名类主键 "+ xk +" 信息不一致,需手动干预");
+            }
+        }
+        // 追加字段
+        mql = "alter class " + clsname + " add index column";
+        addn = 0;
+        for (var fi = 0; fi < xfieldslist.length; fi++) {
+            xk = xfieldslist[fi];
+            if (!clsfields[xk]) {
+                mql += (addn == 0)?" ":", ";
+                mql += xk + " " + xfields[xk];
+                addn++;
+            } else if (clsfields[xk].ftype != xfields[xk]) {
+                throw ("已经存在同名类字段 "+ xk +" 信息不一致,需手动干预");
+            }
+        }
+        if (addn > 0) {
+            odb.mql(mql);
+            output.info = {mql:mql};
+        }
+    }
+    return output
+}
+
+// 根据 JSON 数据生成导入脚本
+function generateJsonImporterJS(input) {
+    output = {}
+    // 参数检查
+    if (!input.classname) { // like /cncc/itil/project
+        throw ("需要指定classname");
+    }
+    if (input.classname[0] != "/") { // like /cncc/itil/project
+        throw ("classname必须以 / 开头");
+    }
+    sjsfn = input.jsfilename;
+    if (!sjsfn) {
+        sjsfn = "/script" + input.classname; // like /script/cncc/itil/project
+    }
+    if (sjsfn.substring(0, 8) != "/script/") {
+        throw ("jsfilename必须以 /script/ 开头");
+    }
+    sjsfn = sjsfn.replace(/\.js$/, "");
+    output.file = sjsfn;
+
+    dtm = new Date().toJSON();
+    mql = "insert into " + input.classname + " (\n";
+    mql_values = ") values (\n";
+    mql_end = ")";
+    values = "";
+    fieldmap = input.fieldmap;
+    if (!fieldmap) {
+        fieldmap = {};
+    }
+    xfieldmap = {};
+    xfields = [];
+    clsfields = {};
+    try {
+        fieldslist = odb.classfields(input.classname);
+        for (var fi = 0; fi < fieldslist.length; fi++) {
+            fld = fieldslist[fi];
+            fname = fld.name;
+            if (/^\w+\:.*/.test(fname)) {
+                fname = fname.replace(/^\w+\:/, ""); 
+            }
+            if (fname && fld.ftype) {
+                clsfields[fname] = {
+                    iskey: fld.iskey,
+                    ftype: fld.ftype,
+                };
+            }
+        }
+    } catch(e) {}
+    for (var k in input.data) {
+        xk = fieldmap[k];
+        if (!xk) {
+            xk = "j_"; // 区别于其它字段,自动创建的字段以 j_ 开头
+            for (var i = 0; i < k.length; i++) {
+                if (k[i] >= 'A' && k[i] <= 'Z') {
+                    xk += "_" + k[i].toLowerCase();
+                } else {
+                    xk += k[i];
+                }
+            }
+            fieldmap[k] = xk;
+        }
+        xfields.push(xk);
+        xfieldmap[xk] = k;
+    }
+    xfields.sort();
+    fsep = ",";
+    for (var i = 0; i < xfields.length; i++) {
+        if (i == xfields.length - 1) {
+            fsep = "";
+        }
+        xk = xfields[i];
+        k = xfieldmap[xk];
+        mql += xk + fsep + "\n";
+        mql_values += "?" + fsep + "\n";
+        values += "    ";
+        v = input.data[k];
+        if (!clsfields[xk]) {
+            throw("字段不存在", xk)
+        }
+        switch (clsfields[xk].ftype) {
+        case "text":
+        case "varchar":
+            if (typeof(v) == "object") {
+                values += "JSON.stringify(";
+                values += "input." + k + ", \" \", 4)" + fsep;
+                values += JSON.stringify(v, " ", 4).replace(/^/mg, "            // ").replace(/            /, " ");
+            } else {
+                values += "\"\"+";
+                values += "input." + k + fsep;
+                values += (""+v).replace(/^/mg, "            // ").replace(/            /, " ");
+            }
+            break;
+        default:
+            values += "input." + k + fsep;
+            values += (""+v).replace(/^/mg, "            // ").replace(/            /, " ");
+        }
+        values += "\n    ";
+    }
+    mql += mql_values + mql_end;
+    values = "\n    " + values;
+
+    datainfo = "{";
+    datacheck = "";
+    if (input.mustfield) {
+        ids = input.mustfield.split(",");
+        for (var i = 0; i < ids.length; i++) {
+            id = ids[i];
+            if (i > 0) {
+                datacheck += "\n    ";
+            }
+            datacheck += "if (!input." + id + ") {\n    ";
+            datacheck += "    throw (\"输入参数必须为对象,且指定属性" + id + "\");\n    ";
+            datacheck += "}";
+            if (i == 0) {
+                datainfo += "\n    ";
+            } else {
+                datainfo += ",\n    ";
+            }
+            datainfo += "    " + id + ": input." + id;
+        }
+    }
+    datainfo += "\n    ";
+    datainfo += "}";
+
+    importjs = dfs.read("/script/matrix/utils/JsonImporter.template.js");
+    importjs = importjs.replace(/___istesting___/mg, input.istesting);
+    importjs = importjs.replace(/___classname___/mg, input.classname);
+    importjs = importjs.replace(/___datetime_now___/mg, dtm);
+    importjs = importjs.replace(/if\s*\(\s*___datacheck___\s*\)\s*\{.*\}/mg, datacheck);
+    importjs = importjs.replace(/___mql___/mg, mql);
+    importjs = importjs.replace(/___values___/mg, values);
+    importjs = importjs.replace(/___datainfo___/mg, datainfo);
+
+    output.content = importjs;
+
+    dfs.write(sjsfn + ".js", importjs);
+    return output
+}
+
+// 激活脚本,生成的脚本文件需要激活后才能生效
+function activeServerJS(jsfilename) {
+    result = {}
+    calljsfp = encodeURIComponent(jsfilename.replace(/\/script/, ""));
+    http.do("POST", 
+        cfg.server+"/fs/tolocal/script"+calljsfp+"?issys=true",
+        {"Authorization": "Basic "+cfg.author},
+        '',
+        function(response){
+            // success func
+            ret = response.data;
+            if (ret.message) {
+                result = ret.message;
+            } else {
+                result = ret;
+            }
+        },
+        function(response){
+            // error func
+            result.error = response.data;
+        });
+    return result;
+}
+
+// 验证测试执行脚本
+function runServerJS(jsfilename, data) {
+    result = {}
+    reqinput = encodeURIComponent(base64.encode(JSON.stringify(data)));
+    calljsfp = encodeURIComponent(jsfilename.replace(/\/script/, ""));
+    http.do("POST", 
+        server+"/script/exec/js?filepath="+calljsfp+"&input="+reqinput,
+        {"Authorization": "Basic "+author},
+        '',
+        function(response){
+            // success func
+            ret = response.data;
+            if (ret.message) {
+                result = ret.message;
+            } else {
+                result = ret;
+            }
+        },
+        function(response){
+            // error func
+            result.error = response.data;
+        });
+    return result;
+}