ffip / HiPerBridge

A GUI for HiPer Network Framework. 一个为 HiPer 跨区域组网模块制作的极简轻量型图形界面
https://www.the.bb
GNU Affero General Public License v3.0
15 stars 4 forks source link

需求 事件响应插件支持 #29

Closed lorki closed 2 years ago

lorki commented 2 years ago

计划表

描述

所有插件文件夹放置于addons目录下 文件夹结构为

addons/myip --package.json --other_file.ext

--

Package.json 内容

{
    "package": {
        "name": "GetMyIP",
        "version": "1.0.3",
        "repo": "https://github.com/who/getmyip"
    },
    "action": {
        "type": "net",
        "event": "join"
    },
    "script": {
        "windows": {
            "privilege": true,
            "shell": "cmd",
            "command": [
                "curl ipinfo.io > ip.log"
            ]
        },
        "darwin": {
            "privilege": false,
            "shell": "zsh",
            "command": [
                "curl ipinfo.io > ip.log"
            ]
        },
        "linux": {
            "privilege": false,
            "shell": "bash",
            "command": [
                "curl ipinfo.io > ip.log"
            ]
        },
    }
}

以上代表意思为在 启动入网 的时候 执行 curl ipinfo.io > ip.logrepo 地址和 版本号 是方便后续做插件更新检查和更新下载。

lorki commented 2 years ago

初期可能会常用的触发事件有:

system.start 软件启动 system.stop 软件关闭 net.join 网络加入 net.leave 网络断开 net.error 网络故障 net.request 网络请求 net.vist 网络被访问 time.1000 每隔1秒触发(此处间隔可自定义)

Steve-xmh commented 2 years ago

我觉得咱说的伪代码可能不是一个东西(合掌)

lorki commented 2 years ago

我觉得咱说的伪代码可能不是一个东西(合掌)

后来我想了想,没必要到伪代码级别。也就是每个入口插个桩

lorki commented 2 years ago

@Steve-xmh 考虑安全性,因为会内置系统SHELL操作,建议新开一个仓库为HiPer_Bridge_Addons,对官方验证切收录的插件统一存放,对其package.json进行sha1校验。

即该仓库根目录结构为 README.MD addons_list.json addons/ --getmyip --minecraft-broadcast --.... --more_addons/ ----package.json ----other_file....

addons_list.json 结构


{
    "getmyip": [
        {
            "package.json": "a345ae2ad0ffee63e1bd952f82d7dc7241bd6456"
        }
    ],
    "minecraft-broadcast": [
        {
            "package.json": "8ae6b68f0eaa126f8e3efa6fffb2207356a37426"
        },
        {
            "os": "linux",
            "mcb": "5856cb76f8a12cafddefa5efc228365cdfdb37fd"
        },
         {
            "os": "darwin",
            "mcb": "f3e972df8d203cec4e9fd543c819f1085fc5478e"
        },
        {
            "os": "windows",
            "mcb.exe": "9ee67fe14860a67607477cc96afb826e041e94a8"
        }
    ]
}

带os标签意味着该文件仅在对应系统存在

Steve-xmh commented 2 years ago

个人还是更倾向于定制一个简练的语言来定制化简易的插件,而不是使用 JSON

即使 Rust 里有 Serde JSON 这样足够简便的解序列化框架,随着数据类型的增多二进制体积的大小会不可避免的增大

如果要压程序大小的话,定制一个描述语言最合适

至于插件库,是你自己的活(合掌)

lorki commented 2 years ago

个人还是更倾向于定制一个简练的语言来定制化简易的插件,而不是使用 JSON

即使 Rust 里有 Serde JSON 这样足够简便的解序列化框架,随着数据类型的增多二进制体积的大小会不可避免的增大

如果要压程序大小的话,定制一个描述语言最合适

至于插件库,是你自己的活(合掌)

以实际为准,json只是其中一种工具(表现形式

lorki commented 2 years ago

参考Cato的Cosole部分:

package stdin

import (
    "bufio"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
    "regexp"
    "strings"

    "bitbucket.org/pwq/cato/core/client"
    "bitbucket.org/pwq/cato/lib/conf/env"
    hc "bitbucket.org/pwq/cato/lib/net/http/client"
)

func Console() {
    var cmd string
    for {
        scanner := bufio.NewScanner(os.Stdin)
        for {
            scanner.Scan()
            cmd = scanner.Text()
            go Excute(cmd)
        }

    }
}

type status struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
}

func Excute(cmd string) (s status) {
    re := regexp.MustCompile(`\d+\.\d+\.\d+\.\d+\:\d+|\w+`)
    cmds := re.FindAllString(cmd, -1)
    for i := len(cmds); i < 10; i++ {
        cmds = append(cmds, "")
    }

    switch cmds[0] {
    case "exit":
        os.Exit(0)
    case "ufw":
        switch cmds[1] {
        case "user":
            switch cmds[2] {
            case "add":
                if cmds[3] == "" {
                    client.DefaultClient.Log.Info("ufw user add - Add a user to whitelist")
                    client.DefaultClient.Log.Info("ufw user add <id>")
                    client.DefaultClient.Log.Info("eg.")
                    client.DefaultClient.Log.Info("ufw user add mixa1zVNN4oCw3Mfw2D8FinqNsB")
                    s = status{
                        Code:    2110,
                        Message: `{"command":"ufw user add","detail":["ufw user add - Add a user to whitelist","ufw user add <id>","eg.","ufw user add mixa1zVNN4oCw3Mfw2D8FinqNsB"]}`,
                    }
                    return
                }
                cmds[3] += `/`
                if !strings.Contains(client.DefaultClient.Cfg.CoverUser, cmds[3]) {
                    client.DefaultClient.Cfg.CoverUser += cmds[3]
                }
                client.DefaultClient.Log.Warn("The user has been allow to access!")
                s = status{
                    Code:    2111,
                    Message: strings.ReplaceAll(`{"command":"cmd","status":true}`, "cmd", cmd),
                }
                return
            case "del":
                if cmds[3] == "" {
                    client.DefaultClient.Log.Info("ufw user del - Remove from a user whitelist")
                    client.DefaultClient.Log.Info("ufw user del <id>")
                    client.DefaultClient.Log.Info("eg.")
                    client.DefaultClient.Log.Info("ufw user del mixa1zVNN4oCw3Mfw2D8FinqNsB")
                    s = status{
                        Code:    2120,
                        Message: `{"command":"ufw user del","detail":["ufw user del - Remove from a user whitelist","ufw user del <id>","eg.","ufw user del mixa1zVNN4oCw3Mfw2D8FinqNsB"]}`,
                    }
                    return
                }
                cmds[3] += `/`
                if strings.Contains(client.DefaultClient.Cfg.CoverUser, cmds[3]) {
                    client.DefaultClient.Cfg.CoverUser = strings.ReplaceAll(client.DefaultClient.Cfg.CoverUser, cmds[3], ``)
                }
                client.DefaultClient.Log.Warn("The user has been removed from the whitelist")
                s = status{
                    Code:    2121,
                    Message: strings.ReplaceAll(`{"command":"cmd","status":true}`, "cmd", cmd),
                }
                return
            case "list":
                if client.DefaultClient.Cfg.CoverUser == `` {
                    client.DefaultClient.Log.Info("No users")
                    s = status{
                        Code:    2130,
                        Message: strings.ReplaceAll(strings.ReplaceAll(`{"command":"cmd","detail":result,"status":true}`, "cmd", cmd), "result", "null"),
                    }
                    return
                }
                userList := strings.Split(client.DefaultClient.Cfg.CoverUser, `/`)
                s = status{
                    Code:    2131,
                    Message: strings.ReplaceAll(strings.ReplaceAll(`{"command":"cmd","detail":result,"status":true}`, "cmd", cmd), "result", fmt.Sprintf("%#v", userList)),
                }
                if env.Value.System.LogFormat == "json" {
                    fmt.Printf("%#v\n", userList)
                    return
                }
                client.DefaultClient.Log.Info("Allow Users:")
                for _, user := range userList {
                    client.DefaultClient.Log.Info(user)
                }
                return
            default:
                client.DefaultClient.Log.Info("ufw user add - Add a user to whitelist")
                client.DefaultClient.Log.Info("ufw user del - Remove from a user whitelist")
                client.DefaultClient.Log.Info("ufw user list - Show user whitelist")
                s = status{
                    Code:    2100,
                    Message: `{"command":"ufw user","detail":["ufw user add - Add a user to whitelist","ufw user del - Remove from a user whitelist","ufw user list - Show user whitelist"]}`,
                }
                return
            }
        case "net":
            switch cmds[2] {
            case "add":
                if cmds[3] == "" {
                    client.DefaultClient.Log.Info("ufw net add - Add a IP address to blacklist")
                    client.DefaultClient.Log.Info("ufw net add <ip>")
                    client.DefaultClient.Log.Info("eg.")
                    client.DefaultClient.Log.Info("ufw net add 12.34.56.78")
                    s = status{
                        Code:    2240,
                        Message: `{"command":"ufw net add","detail":["ufw net add - Add a IP address to blacklist","ufw net add <ip>","eg.","ufw net add 12.34.56.78"]}`,
                    }
                    return
                }
                cmds[3] += `/`
                if !strings.Contains(client.DefaultClient.Cfg.CoverAddr, cmds[3]) {
                    client.DefaultClient.Cfg.CoverAddr += cmds[3]
                }
                client.DefaultClient.Log.Warn("The IP address has been blocked to access!")
                s = status{
                    Code:    2241,
                    Message: strings.ReplaceAll(`{"command":"cmd","status":true}`, "cmd", cmd),
                }
                return
            case "del":
                if cmds[3] == "" {
                    client.DefaultClient.Log.Info("ufw net del - Remove from a IP address whitelist")
                    client.DefaultClient.Log.Info("ufw net del <ip>")
                    client.DefaultClient.Log.Info("eg.")
                    client.DefaultClient.Log.Info("ufw net del 12.34.56.78")
                    s = status{
                        Code:    2250,
                        Message: `{"command":"ufw net del","detail":["net del - Remove from a IP address whitelist","ufw net del <ip>","eg.","ufw net del 12.34.56.78"]}`,
                    }
                    return
                }
                cmds[3] += `/`
                if strings.Contains(client.DefaultClient.Cfg.CoverAddr, cmds[3]) {
                    client.DefaultClient.Cfg.CoverAddr = strings.ReplaceAll(client.DefaultClient.Cfg.CoverAddr, cmds[3], ``)
                }
                client.DefaultClient.Log.Warn("The IP address has been removed from the blacklist")
                s = status{
                    Code:    2251,
                    Message: strings.ReplaceAll(`{"command":"cmd","status":true}`, "cmd", cmd),
                }
                return
            case "blacklist":
                if client.DefaultClient.Cfg.CoverAddr == `` {
                    client.DefaultClient.Log.Info("No IP address")
                    s = status{
                        Code:    2260,
                        Message: strings.ReplaceAll(strings.ReplaceAll(`{"command":"cmd","detail":result,"status":true}`, "cmd", cmd), "result", "null"),
                    }
                    return
                }
                addrList := strings.Split(client.DefaultClient.Cfg.CoverAddr, `/`)
                if env.Value.System.LogFormat == "json" {
                    fmt.Printf("%#v\n", addrList)
                    s = status{
                        Code:    2261,
                        Message: strings.ReplaceAll(strings.ReplaceAll(`{"command":"cmd","detail":result,"status":true}`, "cmd", cmd), "result", fmt.Sprintf("%#v", addrList)),
                    }
                    return
                }
                client.DefaultClient.Log.Info("Blocked IP address(These IP address will be denied access):")
                for _, addr := range addrList {
                    client.DefaultClient.Log.Info(addr)
                }
                return
            default:
                client.DefaultClient.Log.Info("ufw net open - Join and enable network whitelist")
                client.DefaultClient.Log.Info("ufw net close - Remove from network whitelist")
                client.DefaultClient.Log.Info("ufw net whitelist - Show network whitelist")
                client.DefaultClient.Log.Info("-")
                client.DefaultClient.Log.Info("ufw net add - Add a IP to blacklist")
                client.DefaultClient.Log.Info("ufw net del - Remove a IP from blacklist")
                client.DefaultClient.Log.Info("ufw net blacklist - Show network blacklist")
                s = status{
                    Code:    2200,
                    Message: "",
                }
                return
            }
        default:
            client.DefaultClient.Log.Info("ufw user - User request filter")
            client.DefaultClient.Log.Info("ufw net - Network request filter")
            s = status{
                Code:    2000,
                Message: `{"command":"ufw","detail":["ufw user - User request filter","ufw net - Network request filter"]}`,
            }
            return
        }
    case "load":
        if cmd[5:] == "" {
            client.DefaultClient.Log.Info("load - Load a console script from a file")
            client.DefaultClient.Log.Info("load <file_path>")
            client.DefaultClient.Log.Info("eg.")
            client.DefaultClient.Log.Info("load ./script.cs")
            s = status{
                Code:    3000,
                Message: `{"command":"load","detail":["load - Load a console script from a file","load <file_path>","eg.","load ./script.cs","load https://endpoint.the.bb/script/8cbXXevV6JQk.cs"]}`,
            }
            return
        }
        var script []byte
        if cmd[5:13] == "https://" || cmd[5:12] == "http://" {
            h := hc.Client{Request: &hc.Request{Method: "GET", Url: cmd[5:]}}
            if h.Result.Status != 200 {
                client.DefaultClient.Log.Warn("Script load failed: fetch failed!")
                s = status{
                    Code:    3001,
                    Message: strings.ReplaceAll(`{"command":"cmd","detail":"Script load failed: fetch failed!","status":false}`, "cmd", cmd),
                }
                return
            }
            script = h.Result.Body
        } else {
            var err error
            script, err = ioutil.ReadFile(cmd[5:])
            if err != nil {
                client.DefaultClient.Log.Warnf("Script load failed: %v", err)
                s = status{
                    Code:    3001,
                    Message: strings.ReplaceAll(strings.ReplaceAll(`{"command":"cmd","detail":"result","status":false}`, "cmd", cmd), "result", fmt.Sprintf("%v", err)),
                }
                return
            }
        }
        client.DefaultClient.Log.Infof("Script load (%s):", cmd[5:])
        sub := strings.Split(string(script), "\n")
        s = status{
            Code:    3001,
            Message: strings.ReplaceAll(strings.ReplaceAll(`{"command":"cmd","detail":result,"status":false}`, "cmd", cmd), "result", fmt.Sprintf("%#v", sub)),
        }
        for i := 0; i < len(sub); i++ {
            client.DefaultClient.Log.Info(sub[i])
            go Excute(sub[i])
        }
    case "api":
        switch cmds[1] {
        case "password":
            if cmds[2] == "" {
                client.DefaultClient.Log.Info("api password - Set api contorl password")
                client.DefaultClient.Log.Info("api password <password>")
                client.DefaultClient.Log.Info("eg.")
                client.DefaultClient.Log.Info("api password dH5GMYBqaNDZxx7k")
                s = status{
                    Code:    4100,
                    Message: `{"command":"ufw user add","detail":["ufw user add - Add a user to blacklist","ufw user add <id>","eg.","ufw user add mixa1zVNN4oCw3Mfw2D8FinqNsB"]}`,
                }
                return
            }
            env.Value.Service.HttpPassword = cmds[2]
            s = status{
                Code:    4101,
                Message: strings.ReplaceAll(`{"command":"cmd","status":true}`, "cmd", cmd),
            }
            client.DefaultClient.Log.Warnf("new api password is:%s", env.Value.Service.HttpPassword)
            return
        default:
            client.DefaultClient.Log.Info("api password - Set api contorl password")
            s = status{
                Code:    4000,
                Message: `{"command":"api","detail":["api password - Api contorl password"]}`,
            }
            return
        }
    case "env":
        switch cmds[1] {
        case "set":
            if len(cmds) < 4 {
                cmds = nil
            }
            switch cmds[2] {
            case "region":
                env.Value.System.Region = cmds[3]
            case "zone":
                env.Value.System.Zone = cmds[3]
            case "hostname":
                env.Value.System.Hostname = cmds[3]
            case "ip":
                env.Value.System.IP = cmds[3]
            case "appid":
                env.Value.System.AppID = cmds[3]
            case "color":
                env.Value.System.Color = cmds[3]
            default:
                client.DefaultClient.Log.Info("env set - Set enviroment value")
                client.DefaultClient.Log.Info("env set <key> <value>")
                client.DefaultClient.Log.Info("eg.")
                client.DefaultClient.Log.Info("keys:region,zone,hostname,env,ip,appid,color")
                client.DefaultClient.Log.Info("env set region sh")
                client.DefaultClient.Log.Info("env set hostname sh001")
                s = status{
                    Code:    5100,
                    Message: `{"command":"ufw user","detail":["ufw user add - Add a user to whitelist","ufw user del - Remove from a user whitelist","ufw user list - Show user whitelist"]}`,
                }
                return
            }
            s = status{
                Code:    5101,
                Message: strings.ReplaceAll(`{"command":"cmd","status":true}`, "cmd", cmd),
            }
            client.DefaultClient.Log.Warnf("new %s is:%s", cmds[2], env.Value.Service.HttpPassword)
            return
        case "get":
            bjson, _ := json.Marshal(env.Value)
            client.DefaultClient.Log.Infof("ENV-VAL: %+v", string(bjson))
            s = status{
                Code:    5200,
                Message: strings.ReplaceAll(strings.ReplaceAll(`{"command":"cmd","detail":result,"status":true}`, "cmd", cmd), "result", fmt.Sprintf("%+v", string(bjson))),
            }
            return
        default:
            client.DefaultClient.Log.Info("env set - Set enviroment value")
            client.DefaultClient.Log.Info("env get - Get enviroment value")
            s = status{
                Code:    5000,
                Message: `{"command":"env","detail":["env set - Set enviroment value","env get - Get enviroment value"]}`,
            }
            return
        }
    default:
        client.DefaultClient.Log.Warn("Cato - 1.2.1 x Release")
        client.DefaultClient.Log.Info("api - Http Api Service Options")
        client.DefaultClient.Log.Info("env - Environment value Options")
        client.DefaultClient.Log.Info("ufw - Uncomplicated FireWall")
        client.DefaultClient.Log.Info("exit - Exit Cato")
        s = status{
            Code:    1,
            Message: `{"command":"help","detail":["api - Http Api Service Options","env - Environment value Options","net - Network Pipes Options","ufw - Uncomplicated FireWall"]}`,
        }
        return
    }
    return
}
lorki commented 2 years ago

顺便还做了个Console的api

func Exec(writer http.ResponseWriter, request *http.Request) {
    body, _ := ioutil.ReadAll(request.Body)
    command := gjson.GetBytes(body, "command").Str
    if gjson.GetBytes(body, "password").Str != env.Value.Service.HttpPassword {
        _, _ = writer.Write([]byte("{\"error\":\"permission denied\"}"))
        return
    }
    result := stdin.Excute(command)
    data, _ := json.Marshal(result)
    data = bytes.ReplaceAll(data, []byte(`\`), nil)
    data = bytes.ReplaceAll(data, []byte(`:"{`), []byte(`:{`))
    data = bytes.ReplaceAll(data, []byte(`}"}`), []byte(`}}`))
    writer.Header().Add("Content-Type", "application/json; charset=utf-8")
    writer.Header().Add("Access-Control-Allow-Origin", "*")
    _, _ = writer.Write(data)
}
lorki commented 2 years ago

要什么伪代码,直接上轮子

我觉得咱说的伪代码可能不是一个东西(合掌)

Steve-xmh commented 2 years ago

插件添加删除功能无期限推迟,详情请查阅插件开发说明