Kaynağa Gözat

Add merge json (#1079)

link 2 yıl önce
ebeveyn
işleme
280ad4fcf9
7 değiştirilmiş dosya ile 284 ekleme ve 79 silme
  1. 69 2
      main.go
  2. 11 0
      model/zima.go
  3. 24 0
      pkg/utils/ip_helper/ip.go
  4. 69 73
      route/v1.go
  5. 10 0
      route/v1/system.go
  6. 0 4
      route/v2.go
  7. 101 0
      service/system.go

+ 69 - 2
main.go

@@ -5,21 +5,27 @@ package main
 import (
 	"context"
 	_ "embed"
+	"encoding/base64"
+	"encoding/json"
 	"flag"
 	"fmt"
 	"net"
 	"net/http"
 	"path/filepath"
+	"strconv"
 	"time"
 
 	"github.com/IceWhaleTech/CasaOS-Common/model"
 	"github.com/IceWhaleTech/CasaOS-Common/utils/constants"
 	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
+	"github.com/tidwall/gjson"
+	"golang.org/x/net/websocket"
 
 	util_http "github.com/IceWhaleTech/CasaOS-Common/utils/http"
 
 	"github.com/IceWhaleTech/CasaOS/codegen/message_bus"
 	"github.com/IceWhaleTech/CasaOS/common"
+	model2 "github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/cache"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
@@ -80,7 +86,8 @@ func init() {
 	service.GetCPUThermalZone()
 
 	route.InitFunction()
-
+	go SendToSocket(service.MyService.System().GetDeviceInfo())
+	service.MyService.System().GenreateSystemEntry()
 	///
 	//service.MountLists = make(map[string]*mountlib.MountPoint)
 	//configfile.Install()
@@ -101,7 +108,7 @@ func main() {
 	if *versionFlag {
 		return
 	}
-
+	go Special(service.MyService)
 	v1Router := route.InitV1Router()
 
 	v2Router := route.InitV2Router()
@@ -229,3 +236,63 @@ func main() {
 		panic(err)
 	}
 }
+func Special(myservice service.Repository) {
+	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Access-Control-Allow-Origin", "*")
+		m := myservice.System().GetDeviceInfo()
+		jsonData, err := json.Marshal(m)
+		if err != nil {
+			fmt.Println("Error:", err)
+			http.Error(w, "Internal Server Error", http.StatusInternalServerError)
+			return
+		}
+		w.Header().Set("Content-Type", "application/json")
+		fmt.Fprintln(w, string(jsonData))
+	})
+
+	if err := http.ListenAndServe(":9527", nil); err != nil {
+		fmt.Println("Error:", err)
+	}
+
+}
+
+func SendToSocket(m model2.DeviceInfo) {
+	if len(m.DeviceSN) == 0 {
+		//TODO:需要更换socket地址,需要放开sn的判断
+		//return
+	}
+	by, _ := json.Marshal(m)
+	base64Str := base64.StdEncoding.EncodeToString(by)
+	var count int = 1
+	for i := 0; i < 10; i++ {
+		wsURL := fmt.Sprintf("ws://%s/server/zima%s", "52.193.63.104:3060", "?device="+base64Str)
+		ws, err := websocket.Dial(wsURL, "", "http://localhost")
+		if err != nil {
+			logger.Error("connect websocket err"+strconv.Itoa(i), zap.Any("error", err))
+			time.Sleep(time.Second * 1)
+			continue
+		}
+		defer ws.Close()
+
+		logger.Info("subscribed to", zap.Any("url", wsURL))
+		for {
+			msg := make([]byte, 1024)
+			n, err := ws.Read(msg)
+			if err != nil {
+				logger.Error("err", zap.Any("err", err.Error()))
+				break
+			}
+			message := msg[:n]
+			t := gjson.GetBytes(message, "type")
+			if t.Str == "ping" {
+				ws.Write([]byte(`{"type":"pong"}`))
+				count++
+			}
+			if count > 600 {
+				return
+			}
+		}
+	}
+	logger.Error("error when try to connect to message bus")
+
+}

+ 11 - 0
model/zima.go

@@ -23,3 +23,14 @@ type Path struct {
 	Write      bool                   `json:"write"`
 	Extensions map[string]interface{} `json:"extensions"`
 }
+
+type DeviceInfo struct {
+	LanIpv4     []string `json:"lan_ipv4"`
+	Port        int      `json:"port"`
+	DeviceName  string   `json:"device_name"`
+	DeviceModel string   `json:"device_model"`
+	DeviceSN    string   `json:"device_sn"`
+	Initialized bool     `json:"initialized"`
+	OS_Version  string   `json:"os_version"`
+	Hash        string   `json:"hash"`
+}

+ 24 - 0
pkg/utils/ip_helper/ip.go

@@ -1,6 +1,7 @@
 package ip_helper
 
 import (
+	"fmt"
 	"net"
 	"strings"
 
@@ -56,7 +57,30 @@ func GetDeviceAllIP(port string) []string {
 	}
 	return address
 }
+func GetDeviceAllIPv4() map[string]string {
+	address := make(map[string]string)
+	addrs, err := net.Interfaces()
+	if err != nil {
+		return address
+	}
+	for _, a := range addrs {
+		if a.Flags&net.FlagLoopback != 0 || a.Flags&net.FlagUp == 0 {
+			continue
+		}
+		addrs, err := a.Addrs()
+		if err != nil {
+			fmt.Println("Error:", err)
+			continue
+		}
 
+		for _, addr := range addrs {
+			if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
+				address[a.Name] = ipnet.IP.String()
+			}
+		}
+	}
+	return address
+}
 func HasLocalIP(ip net.IP) bool {
 	if ip.IsLoopback() {
 		return true

+ 69 - 73
route/v1.go

@@ -41,11 +41,7 @@ func InitV1Router() *gin.Engine {
 	r.GET("/v1/recover/:type", v1.GetRecoverStorage)
 	v1Group := r.Group("/v1")
 
-	v1Group.Use(jwt.ExceptLocalhost(
-		func() (*ecdsa.PublicKey, error) {
-			return external.GetPublicKey(config.CommonInfo.RuntimePath)
-		},
-	))
+	v1Group.Use(jwt.ExceptLocalhost(func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) }))
 	{
 
 		v1SysGroup := v1Group.Group("/sys")
@@ -79,6 +75,7 @@ func InitV1Router() *gin.Engine {
 			// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
 			v1SysGroup.GET("/proxy", v1.GetSystemProxy)
 			v1SysGroup.PUT("/state/:state", v1.PutSystemState)
+			v1SysGroup.GET("/entry", v1.GetSystemEntry)
 		}
 		v1PortGroup := v1Group.Group("/port")
 		v1PortGroup.Use()
@@ -86,79 +83,78 @@ func InitV1Router() *gin.Engine {
 			v1PortGroup.GET("/", v1.GetPort)              // app/port
 			v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port
 		}
-
-		v1FileGroup := v1Group.Group("/file")
-		v1FileGroup.Use()
-		{
-			v1FileGroup.GET("", v1.GetDownloadSingleFile) // download/:path
-			v1FileGroup.POST("", v1.PostCreateFile)
-			v1FileGroup.PUT("", v1.PutFileContent)
-			v1FileGroup.PUT("/name", v1.RenamePath)
-			// file/rename
-			v1FileGroup.GET("/content", v1.GetFilerContent) // file/read
-
-			// File uploads need to be handled separately, and will not be modified here
-			//v1FileGroup.POST("/upload", v1.PostFileUpload)
-			v1FileGroup.POST("/upload", v1.PostFileUpload)
-			v1FileGroup.GET("/upload", v1.GetFileUpload)
-			// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
-			v1FileGroup.GET("/ws", v1.ConnectWebSocket)
-			v1FileGroup.GET("/peers", v1.GetPeers)
-		}
-		v1CloudGroup := v1Group.Group("/cloud")
-		v1CloudGroup.Use()
-		{
-			v1CloudGroup.GET("", v1.ListStorages)
-			v1CloudGroup.DELETE("", v1.UmountStorage)
-		}
-		v1DriverGroup := v1Group.Group("/driver")
-		v1DriverGroup.Use()
-		{
-			v1DriverGroup.GET("", v1.ListDriverInfo)
-		}
-
-		v1FolderGroup := v1Group.Group("/folder")
-		v1FolderGroup.Use()
-		{
-			v1FolderGroup.PUT("/name", v1.RenamePath)
-			v1FolderGroup.GET("", v1.DirPath)   ///file/dirpath
-			v1FolderGroup.POST("", v1.MkdirAll) ///file/mkdir
-			v1FolderGroup.GET("/size", v1.GetSize)
-			v1FolderGroup.GET("/count", v1.GetFileCount)
-		}
-		v1BatchGroup := v1Group.Group("/batch")
-		v1BatchGroup.Use()
-		{
-
-			v1BatchGroup.DELETE("", v1.DeleteFile) // file/delete
-			v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
-			v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) // file/operate
-			v1BatchGroup.GET("", v1.GetDownloadFile)
-		}
+		// v1FileGroup := v1Group.Group("/file")
+		// v1FileGroup.Use()
+		// {
+		// 	v1FileGroup.GET("", v1.GetDownloadSingleFile) // download/:path
+		// 	v1FileGroup.POST("", v1.PostCreateFile)
+		// 	v1FileGroup.PUT("", v1.PutFileContent)
+		// 	v1FileGroup.PUT("/name", v1.RenamePath)
+		// 	// file/rename
+		// 	v1FileGroup.GET("/content", v1.GetFilerContent) // file/read
+
+		// 	// File uploads need to be handled separately, and will not be modified here
+		// 	//v1FileGroup.POST("/upload", v1.PostFileUpload)
+		// 	v1FileGroup.POST("/upload", v1.PostFileUpload)
+		// 	v1FileGroup.GET("/upload", v1.GetFileUpload)
+		// 	// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
+		// 	v1FileGroup.GET("/ws", v1.ConnectWebSocket)
+		// 	v1FileGroup.GET("/peers", v1.GetPeers)
+		// }
+		// v1CloudGroup := v1Group.Group("/cloud")
+		// v1CloudGroup.Use()
+		// {
+		// 	v1CloudGroup.GET("", v1.ListStorages)
+		// 	v1CloudGroup.DELETE("", v1.UmountStorage)
+		// }
+		// v1DriverGroup := v1Group.Group("/driver")
+		// v1DriverGroup.Use()
+		// {
+		// 	v1DriverGroup.GET("", v1.ListDriverInfo)
+		// }
+
+		// v1FolderGroup := v1Group.Group("/folder")
+		// v1FolderGroup.Use()
+		// {
+		// 	v1FolderGroup.PUT("/name", v1.RenamePath)
+		// 	v1FolderGroup.GET("", v1.DirPath)   ///file/dirpath
+		// 	v1FolderGroup.POST("", v1.MkdirAll) ///file/mkdir
+		// 	v1FolderGroup.GET("/size", v1.GetSize)
+		// 	v1FolderGroup.GET("/count", v1.GetFileCount)
+		// }
+		// v1BatchGroup := v1Group.Group("/batch")
+		// v1BatchGroup.Use()
+		// {
+
+		// 	v1BatchGroup.DELETE("", v1.DeleteFile) // file/delete
+		// 	v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
+		// 	v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) // file/operate
+		// 	v1BatchGroup.GET("", v1.GetDownloadFile)
+		// }
 		v1ImageGroup := v1Group.Group("/image")
 		v1ImageGroup.Use()
 		{
 			v1ImageGroup.GET("", v1.GetFileImage)
 		}
-		v1SambaGroup := v1Group.Group("/samba")
-		v1SambaGroup.Use()
-		{
-			v1ConnectionsGroup := v1SambaGroup.Group("/connections")
-			v1ConnectionsGroup.Use()
-			{
-				v1ConnectionsGroup.GET("", v1.GetSambaConnectionsList)
-				v1ConnectionsGroup.POST("", v1.PostSambaConnectionsCreate)
-				v1ConnectionsGroup.DELETE("/:id", v1.DeleteSambaConnections)
-			}
-			v1SharesGroup := v1SambaGroup.Group("/shares")
-			v1SharesGroup.Use()
-			{
-				v1SharesGroup.GET("", v1.GetSambaSharesList)
-				v1SharesGroup.POST("", v1.PostSambaSharesCreate)
-				v1SharesGroup.DELETE("/:id", v1.DeleteSambaShares)
-				v1SharesGroup.GET("/status", v1.GetSambaStatus)
-			}
-		}
+		// v1SambaGroup := v1Group.Group("/samba")
+		// v1SambaGroup.Use()
+		// {
+		// 	v1ConnectionsGroup := v1SambaGroup.Group("/connections")
+		// 	v1ConnectionsGroup.Use()
+		// 	{
+		// 		v1ConnectionsGroup.GET("", v1.GetSambaConnectionsList)
+		// 		v1ConnectionsGroup.POST("", v1.PostSambaConnectionsCreate)
+		// 		v1ConnectionsGroup.DELETE("/:id", v1.DeleteSambaConnections)
+		// 	}
+		// 	v1SharesGroup := v1SambaGroup.Group("/shares")
+		// 	v1SharesGroup.Use()
+		// 	{
+		// 		v1SharesGroup.GET("", v1.GetSambaSharesList)
+		// 		v1SharesGroup.POST("", v1.PostSambaSharesCreate)
+		// 		v1SharesGroup.DELETE("/:id", v1.DeleteSambaShares)
+		// 		v1SharesGroup.GET("/status", v1.GetSambaStatus)
+		// 	}
+		// }
 		v1NotifyGroup := v1Group.Group("/notify")
 		v1NotifyGroup.Use()
 		{

+ 10 - 0
route/v1/system.go

@@ -24,6 +24,7 @@ import (
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
 	"github.com/IceWhaleTech/CasaOS/types"
 	"github.com/gin-gonic/gin"
+	"github.com/tidwall/gjson"
 )
 
 // @Summary check version
@@ -371,3 +372,12 @@ func PortCheck(c *gin.Context) {
 	t := c.DefaultQuery("type", "tcp")
 	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)})
 }
+
+func GetSystemEntry(c *gin.Context) {
+	entry := service.MyService.System().GetSystemEntry()
+	if !gjson.Valid(entry) {
+		c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: ""})
+		return
+	}
+	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: entry})
+}

+ 0 - 4
route/v2.go

@@ -76,10 +76,6 @@ func InitV2Router() http.Handler {
 			// return true
 		},
 		ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) {
-			// claims, code := jwt.Validate(token) // TODO - needs JWT validation
-			// if code != common_err.SUCCESS {
-			// 	return nil, echo.ErrUnauthorized
-			// }
 			valid, claims, err := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
 			if err != nil || !valid {
 				return nil, echo.ErrUnauthorized

+ 101 - 0
service/system.go

@@ -1,6 +1,7 @@
 package service
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
 	"io/ioutil"
@@ -15,10 +16,14 @@ import (
 
 	"github.com/IceWhaleTech/CasaOS-Common/utils/file"
 	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
+	"github.com/IceWhaleTech/CasaOS/common"
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
+	"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
+	"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
+	"github.com/tidwall/gjson"
 	"go.uber.org/zap"
 
 	"github.com/shirou/gopsutil/v3/cpu"
@@ -49,6 +54,7 @@ type SystemService interface {
 	GetDiskInfo() *disk.UsageStat
 	GetSysInfo() host.InfoStat
 	GetDeviceTree() string
+	GetDeviceInfo() model.DeviceInfo
 	CreateFile(path string) (int, error)
 	RenameFile(oldF, newF string) (int, error)
 	MkdirAll(path string) (int, error)
@@ -57,9 +63,104 @@ type SystemService interface {
 	GetMacAddress() (string, error)
 	SystemReboot() error
 	SystemShutdown() error
+	GetSystemEntry() string
+	GenreateSystemEntry()
 }
 type systemService struct{}
 
+func (c *systemService) GetDeviceInfo() model.DeviceInfo {
+	m := model.DeviceInfo{}
+	m.OS_Version = common.VERSION
+	err, portStr := MyService.Gateway().GetPort()
+	if err != nil {
+		m.Port = 80
+	} else {
+		port := gjson.Get(portStr, "data")
+		if len(port.Raw) == 0 {
+			m.Port = 80
+		} else {
+			p, err := strconv.Atoi(port.Raw)
+			if err != nil {
+				m.Port = 80
+			} else {
+				m.Port = p
+			}
+		}
+	}
+	allIpv4 := ip_helper.GetDeviceAllIPv4()
+	ip := []string{}
+	nets := MyService.System().GetNet(true)
+	for _, n := range nets {
+		if v, ok := allIpv4[n]; ok {
+			{
+				ip = append(ip, v)
+			}
+		}
+	}
+
+	m.LanIpv4 = ip
+	h, err := host.Info() /*  */
+	if err == nil {
+		m.DeviceName = h.Hostname
+	}
+	mb := model.BaseInfo{}
+
+	err = json.Unmarshal(file.ReadFullFile(config.AppInfo.DBPath+"/baseinfo.conf"), &mb)
+	if err == nil {
+		m.Hash = mb.Hash
+	}
+
+	osRelease, _ := file.ReadOSRelease()
+	m.DeviceModel = osRelease["MODEL"]
+	m.DeviceSN = osRelease["SN"]
+	res := httper.Get("http://127.0.0.1:"+strconv.Itoa(m.Port)+"/v1/users/status", nil)
+	init := gjson.Get(res, "data.initialized")
+	m.Initialized, _ = strconv.ParseBool(init.Raw)
+
+	return m
+}
+func (c *systemService) GenreateSystemEntry() {
+	modelsPath := "/var/lib/casaos/www/modules"
+	entryFileName := "entry.json"
+	entryFilePath := filepath.Join(config.AppInfo.DBPath, "db", entryFileName)
+	file.IsNotExistCreateFile(entryFilePath)
+
+	dir, err := os.ReadDir(modelsPath)
+	if err != nil {
+		logger.Error("read dir error", zap.Error(err))
+		return
+	}
+	json := "["
+	for _, v := range dir {
+		data, err := os.ReadFile(filepath.Join(modelsPath, v.Name(), entryFileName))
+		if err != nil {
+			logger.Error("read entry file error", zap.Error(err))
+			continue
+		}
+		json += string(data) + ","
+	}
+	json = strings.TrimRight(json, ",")
+	json += "]"
+	err = os.WriteFile(entryFilePath, []byte(json), 0666)
+	if err != nil {
+		logger.Error("write entry file error", zap.Error(err))
+		return
+	}
+
+}
+func (c *systemService) GetSystemEntry() string {
+	entryFilePath := filepath.Join(config.AppInfo.DBPath, "db", "entry.json")
+	_, err := os.Open(entryFilePath)
+	if os.IsNotExist(err) {
+		return ""
+	}
+	by, err := os.ReadFile(entryFilePath)
+	if err != nil {
+		logger.Error("read entry file error", zap.Error(err))
+		return ""
+	}
+	return string(by)
+}
 func (c *systemService) GetMacAddress() (string, error) {
 	interfaces, err := net.Interfaces()
 	if err != nil {