Add CasaConnect function

This commit is contained in:
link 2022-04-06 12:10:51 +08:00
parent c3b2c1d599
commit dd0645ee0f
61 changed files with 9457 additions and 8454 deletions

2
UI

@ -1 +1 @@
Subproject commit 247c099bf14a2d9eb94bf7798e04d00dbc8f7efd Subproject commit 74fa1f8920aa23f40b04b87cc04ebef5c36b0890

View file

@ -14,11 +14,12 @@ RootPath = /casaOS
[server] [server]
HttpPort = 8089 HttpPort = 8089
UDPPort =
RunMode = release RunMode = release
ServerApi = https://api.casaos.zimaboard.com ServerApi = https://api.casaos.zimaboard.com
Handshake = Handshake = socket.casaos.io
Token = Token =
NickName = USBAutoMount = true
[user] [user]
@ -28,11 +29,7 @@ Email = user@gmail.com
Description = description Description = description
Initialized = false Initialized = false
Avatar = Avatar =
NickName =
[zerotier]
UserName = user
PWD = pwd
Token = yBKYyavr2RdFAIVN7iTpzlsB1o6CqTgm
[redis] [redis]
Host = 127.0.0.1:6379 Host = 127.0.0.1:6379
@ -48,4 +45,4 @@ Analyse =
[file] [file]
ShareDir = ShareDir =
DownloadDir = /DATA DownloadDir =

1
go.mod
View file

@ -50,6 +50,7 @@ require (
github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/assertions v1.2.0 // indirect github.com/smartystreets/assertions v1.2.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/spf13/afero v1.2.2
github.com/swaggo/gin-swagger v1.3.0 github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.3 github.com/swaggo/swag v1.7.3
github.com/tidwall/gjson v1.10.2 github.com/tidwall/gjson v1.10.2

1
go.sum
View file

@ -794,6 +794,7 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=

38
main.go
View file

@ -4,9 +4,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"runtime"
"time" "time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/cache" "github.com/IceWhaleTech/CasaOS/pkg/cache"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/sqlite" "github.com/IceWhaleTech/CasaOS/pkg/sqlite"
@ -29,6 +29,24 @@ func init() {
config.InitSetup(*configFlag) config.InitSetup(*configFlag)
config.UpdateSetup() config.UpdateSetup()
loger2.LogSetup() loger2.LogSetup()
sysType := runtime.GOOS
if sysType == "windows" {
config.AppInfo.ProjectPath = "C:\\CasaOS\\service"
config.Cfg.Section("app").Key("ProjectPath").SetValue("C:\\CasaOS\\service")
config.AppInfo.RootPath = "C:\\CasaOS"
config.Cfg.Section("app").Key("RootPath").SetValue("C:\\CasaOS")
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
if sysType == "darwin" {
config.AppInfo.ProjectPath = "./CasaOS/service"
config.Cfg.Section("app").Key("ProjectPath").SetValue("./CasaOS/service")
config.AppInfo.RootPath = "./CasaOS"
config.Cfg.Section("app").Key("RootPath").SetValue("./CasaOS")
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath) sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
//gredis.GetRedisConn(config.RedisInfo), //gredis.GetRedisConn(config.RedisInfo),
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger()) service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
@ -36,10 +54,10 @@ func init() {
go service.UDPService() go service.UDPService()
service.Summary = make(map[string]model.FileSummaryModel) fmt.Println("token", service.GetToken())
service.UDPAddressMap = make(map[string]string) service.UDPAddressMap = make(map[string]string)
//go service.SocketConnect() //go service.SocketConnect()
service.CancelList = make(map[string]string)
route.InitFunction() route.InitFunction()
go service.SendIPToServer() go service.SendIPToServer()
@ -69,20 +87,30 @@ func main() {
//gredis.Setup() //gredis.Setup()
r := route.InitRouter() r := route.InitRouter()
//service.SyncTask(sqliteDB) //service.SyncTask(sqliteDB)
cron2 := cron.New() //创建一个cron实例 cron2 := cron.New()
//every day execution //every day execution
err := cron2.AddFunc("0 0/5 * * * *", func() { err := cron2.AddFunc("0 0/5 * * * *", func() {
//service.PushIpInfo(*&config.ServerInfo.Token) //service.PushIpInfo(*&config.ServerInfo.Token)
//service.UpdataDDNSList(mysqldb) //service.UpdataDDNSList(mysqldb)
//service.SyncTask(sqliteDB) //service.SyncTask(sqliteDB)
service.SendIPToServer() service.SendIPToServer()
service.LoopFriend() service.LoopFriend()
}) })
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
// err = cron2.AddFunc("0/1 * * * * *", func() {
//启动/关闭 // //service.SendIPToServer()
// //service.LoopNet()
// })
// if err != nil {
// fmt.Println(err)
// }
cron2.Start() cron2.Start()
defer cron2.Stop() defer cron2.Stop()
s := &http.Server{ s := &http.Server{

View file

@ -1,7 +1,5 @@
package model package model
import "time"
type IOCountersStat struct { type IOCountersStat struct {
Name string `json:"name"` // interface name Name string `json:"name"` // interface name
BytesSent uint64 `json:"bytesSent"` // number of bytes sent BytesSent uint64 `json:"bytesSent"` // number of bytes sent
@ -15,5 +13,5 @@ type IOCountersStat struct {
Fifoin uint64 `json:"fifoin"` // total number of FIFO buffers errors while receiving Fifoin uint64 `json:"fifoin"` // total number of FIFO buffers errors while receiving
Fifoout uint64 `json:"fifoout"` // total number of FIFO buffers errors while sending Fifoout uint64 `json:"fifoout"` // total number of FIFO buffers errors while sending
State string `json:"state"` State string `json:"state"`
DateTime time.Time `json:"date_time"` Time int64 `json:"time"`
} }

View file

@ -45,3 +45,10 @@ type FileSummaryModel struct {
Size int64 `json:"size"` Size int64 `json:"size"`
Message string `json:"message"` Message string `json:"message"`
} }
type FriendsModel struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
NickName string `json:"nick_name"`
Desc string `json:"desc"`
ShareId string `json:"share_id"`
}

View file

@ -28,6 +28,8 @@ type ServerModel struct {
LockAccount bool LockAccount bool
Handshake string Handshake string
Token string Token string
UDPPort string
USBAutoMount string
} }
//服务配置 //服务配置
@ -50,13 +52,6 @@ type Result struct {
Data interface{} `json:"data" example:"返回结果"` Data interface{} `json:"data" example:"返回结果"`
} }
//zeritier相关
type ZeroTierModel struct {
UserName string
PWD string
Token string
}
//redis配置文件 //redis配置文件
type RedisModel struct { type RedisModel struct {
Host string Host string

9
model/user.go Normal file
View file

@ -0,0 +1,9 @@
package model
type UserInfo struct {
NickName string `json:"nick_name"`
Desc string `json:"desc"`
ShareId string `json:"share_id"`
Avatar string `json:"avatar"`
Version int `json:"version,omitempty"`
}

View file

@ -3,11 +3,11 @@ package model
import "time" import "time"
type Path struct { type Path struct {
Name string `json:"name"` Name string `json:"name"` //File name or document name
Path string `json:"path"` Path string `json:"path"` //Full path to file or folder
IsDir bool `json:"is_dir"` IsDir bool `json:"is_dir"` //Is it a folder
Date time.Time `json:"date"` Date time.Time `json:"date"`
Size int64 `json:"size"` Size int64 `json:"size"` //File Size
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
Label string `json:"label,omitempty"` Label string `json:"label,omitempty"`
} }

View file

@ -25,9 +25,6 @@ var AppInfo = &model.APPModel{}
//redis相关配置 //redis相关配置
var RedisInfo = &model.RedisModel{} var RedisInfo = &model.RedisModel{}
//zerotier相关
var ZeroTierInfo = &model.ZeroTierModel{}
//server相关 //server相关
var ServerInfo = &model.ServerModel{} var ServerInfo = &model.ServerModel{}
@ -56,7 +53,6 @@ func InitSetup(config string) {
mapTo("user", UserInfo) mapTo("user", UserInfo)
mapTo("app", AppInfo) mapTo("app", AppInfo)
mapTo("zerotier", ZeroTierInfo)
mapTo("redis", RedisInfo) mapTo("redis", RedisInfo)
mapTo("server", ServerInfo) mapTo("server", ServerInfo)
mapTo("system", SystemConfigInfo) mapTo("system", SystemConfigInfo)

View file

@ -1,13 +1,30 @@
package config package config
import "github.com/IceWhaleTech/CasaOS/pkg/utils/file" import (
"runtime"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
)
//检查目录是否存在 //检查目录是否存在
func mkdirDATAAll() { func mkdirDATAAll() {
dirArray := [7]string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"} sysType := runtime.GOOS
var dirArray []string
if sysType == "linux" {
dirArray = []string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
}
if sysType == "windows" {
dirArray = []string{"C:\\CasaOS\\DATA\\AppData", "C:\\CasaOS\\DATA\\Documents", "C:\\CasaOS\\DATA\\Downloads", "C:\\CasaOS\\DATA\\Gallery", "C:\\CasaOS\\DATA\\Media/Movies", "C:\\CasaOS\\DATA\\Media\\TV Shows", "C:\\CasaOS\\DATA\\Media\\Music"}
}
if sysType == "darwin" {
dirArray = []string{"./CasaOS/DATA/AppData", "./CasaOS/DATA/Documents", "./CasaOS/DATA/Downloads", "./CasaOS/DATA/Gallery", "./CasaOS/DATA/Media/Movies", "./CasaOS/DATA/Media/TV Shows", "./CasaOS/DATA/Media/Music"}
}
for _, v := range dirArray { for _, v := range dirArray {
file.IsNotExistMkDir(v) file.IsNotExistMkDir(v)
} }
} }
func UpdateSetup() { func UpdateSetup() {

View file

@ -31,7 +31,7 @@ func GetDb(projectPath string) *gorm.DB {
return nil return nil
} }
gdb = db gdb = db
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersionDownloadDBModel{}, model2.FriendModel{}) err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{})
if err != nil { if err != nil {
fmt.Println("检查和创建数据库出错", err) fmt.Println("检查和创建数据库出错", err)
} }

View file

@ -8,6 +8,8 @@ import (
"mime/multipart" "mime/multipart"
"os" "os"
"path" "path"
path2 "path"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
) )
@ -226,6 +228,17 @@ func CopyFile(src, dst string) error {
return os.Chmod(dst, srcinfo.Mode()) return os.Chmod(dst, srcinfo.Mode())
} }
//Check for duplicate file names
func GetNoDuplicateFileName(fullPath string) string {
path, fileName := filepath.Split(fullPath)
fileSuffix := path2.Ext(fileName)
filenameOnly := strings.TrimSuffix(fileName, fileSuffix)
for i := 0; Exists(fullPath); i++ {
fullPath = path2.Join(path, filenameOnly+"("+strconv.Itoa(i+1)+")"+fileSuffix)
}
return fullPath
}
// Dir copies a whole directory recursively // Dir copies a whole directory recursively
func CopyDir(src string, dst string) error { func CopyDir(src string, dst string) error {
var err error var err error

View file

@ -3,6 +3,7 @@ package httper
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -67,7 +68,8 @@ func Post(url string, data []byte, contentType string, head map[string]string) (
client := &http.Client{Timeout: 5 * time.Second} client := &http.Client{Timeout: 5 * time.Second}
resp, error := client.Do(req) resp, error := client.Do(req)
if error != nil { if error != nil {
panic(error) fmt.Println(error)
return
} }
defer resp.Body.Close() defer resp.Body.Close()

View file

@ -1 +0,0 @@
package utils

View file

@ -37,13 +37,18 @@ const (
FILE_DOES_NOT_EXIST = 60001 FILE_DOES_NOT_EXIST = 60001
FILE_READ_ERROR = 60002 FILE_READ_ERROR = 60002
FILE_DELETE_ERROR = 60003 FILE_DELETE_ERROR = 60003
DIR_NOT_EXISTS = 60004
//shortcuts //shortcuts
SHORTCUTS_URL_ERROR = 70001 SHORTCUTS_URL_ERROR = 70001
//persion //person
PERSION_REMOTE_ERROR = 80001 PERSON_REMOTE_ERROR = 80001
PERSION_DOWN_NOT_EXIST = 80002 PERSON_DOWN_NOT_EXIST = 80002
PERSON_EXIST_DOWNLOAD = 80003
PERSON_NOT_EXIST_USER = 80004
PERSON_EXIST_FRIEND = 80005
PERSON_MYSELF = 80006
) )
var MsgFlags = map[int]string{ var MsgFlags = map[int]string{
@ -82,12 +87,18 @@ var MsgFlags = map[int]string{
// //
FILE_DOES_NOT_EXIST: "File does not exist", FILE_DOES_NOT_EXIST: "File does not exist",
DIR_NOT_EXISTS: "Directory does not exist",
FILE_READ_ERROR: "File read error", FILE_READ_ERROR: "File read error",
FILE_DELETE_ERROR: "Delete error", FILE_DELETE_ERROR: "Delete error",
SHORTCUTS_URL_ERROR: "URL error", SHORTCUTS_URL_ERROR: "URL error",
PERSION_REMOTE_ERROR: "Remote connection error", PERSON_REMOTE_ERROR: "Remote connection error",
PERSION_DOWN_NOT_EXIST: "Download record does not exist", PERSON_DOWN_NOT_EXIST: "Download record does not exist",
PERSON_EXIST_DOWNLOAD: "The same download task exists",
PERSON_EXIST_FRIEND: "Friend already exist",
PERSON_NOT_EXIST_USER: "User does not exist",
PERSON_MYSELF: "You can not add yourself",
} }
//获取错误信息 //获取错误信息

View file

@ -1,47 +0,0 @@
package zerotier
import (
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/tidwall/gjson"
"net/http"
)
func PostData(url, token string, data string) interface{} {
body, code := httper2.ZeroTierPostJson(url, data, GetHead(token))
if code != http.StatusOK {
return ""
}
result := gjson.Parse(body)
return result.Value()
}
func GetData(url, token string) interface{} {
body, code := httper2.ZeroTierGet(url, GetHead(token))
if code != http.StatusOK {
return ""
}
result := gjson.Parse(body)
return result.Value()
}
func DeleteMember(url, token string) interface{} {
body, code := httper2.ZeroTierDelete(url, GetHead(token))
if code != http.StatusOK {
return ""
}
result := gjson.Parse(body)
return result.Value()
}
func GetHead(token string) map[string]string {
var head = make(map[string]string)
head["Authorization"] = "Bearer " + token
head["Content-Type"] = "application/json"
return head
}

View file

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"runtime"
"strconv" "strconv"
"time" "time"
@ -231,10 +232,10 @@ func CheckSerialDiskMount() {
} }
service.MyService.Disk().RemoveLSBLKCache() service.MyService.Disk().RemoveLSBLKCache()
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir") command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir")
} }
func Update2_3() { func Update2_3() {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh") command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")
} }
func CheckToken2_11() { func CheckToken2_11() {
if len(config.ServerInfo.Token) == 0 { if len(config.ServerInfo.Token) == 0 {
@ -253,20 +254,34 @@ func CheckToken2_11() {
// config.AppInfo.RootPath = "/casaOS" // config.AppInfo.RootPath = "/casaOS"
// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) // config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
// } // }
if len(config.FileSettingInfo.ShareDir) == 0 { sysType := runtime.GOOS
config.Cfg.Section("file").Key("ShareDir").SetValue("/DATA")
config.FileSettingInfo.ShareDir[0] = "/DATA"
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
if len(config.FileSettingInfo.DownloadDir) == 0 { if len(config.FileSettingInfo.DownloadDir) == 0 {
config.Cfg.Section("file").Key("DownloadDir").SetValue("/DATA/share") downloadPath := "/DATA/Downloads"
config.FileSettingInfo.DownloadDir = "/DATA/share" if sysType == "windows" {
downloadPath = "C:\\CasaOS\\DATA\\Downloads"
}
if sysType == "darwin" {
downloadPath = "~/CasaOS/DATA/Downloads"
}
config.Cfg.Section("file").Key("DownloadDir").SetValue(downloadPath)
config.FileSettingInfo.DownloadDir = downloadPath
file.IsNotExistMkDir(config.FileSettingInfo.DownloadDir) file.IsNotExistMkDir(config.FileSettingInfo.DownloadDir)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
} }
if len(config.UserInfo.Description) == 0 {
config.Cfg.Section("user").Key("Description").SetValue("nothing")
config.UserInfo.Description = "nothing"
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
if len(config.ServerInfo.Handshake) == 0 {
config.Cfg.Section("server").Key("Handshake").SetValue("socket.casaos.io")
config.ServerInfo.Handshake = "socket.casaos.io"
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
service.MyService.System().ExecUSBAutoMountShell(config.ServerInfo.USBAutoMount)
// str := []string{} // str := []string{}
// str = append(str, "ddd") // str = append(str, "ddd")
// str = append(str, "aaa") // str = append(str, "aaa")

View file

@ -18,6 +18,7 @@ var OnlineDemo bool = false
func InitRouter() *gin.Engine { func InitRouter() *gin.Engine {
r := gin.Default() r := gin.Default()
r.Use(middleware.Cors()) r.Use(middleware.Cors())
r.Use(gzip.Gzip(gzip.DefaultCompression)) r.Use(gzip.Gzip(gzip.DefaultCompression))
gin.SetMode(config.ServerInfo.RunMode) gin.SetMode(config.ServerInfo.RunMode)
@ -52,13 +53,16 @@ func InitRouter() *gin.Engine {
//chang head //chang head
v1UserGroup.POST("/head", v1.PostUserHead) v1UserGroup.POST("/head", v1.PostUserHead)
//chang user name //chang user name
v1UserGroup.PUT("/changusername", v1.PutUserName) v1UserGroup.PUT("/username", v1.PutUserName)
//chang pwd //chang pwd
v1UserGroup.PUT("/changuserpwd", v1.PutUserPwd) v1UserGroup.PUT("/password", v1.PutUserPwd)
//edit user info //edit user info
v1UserGroup.POST("/info", v1.PostUserChangeInfo) v1UserGroup.POST("/info", v1.PostUserChangeInfo)
v1UserGroup.PUT("/nick", v1.PutUserChangeNick) v1UserGroup.PUT("/nick", v1.PutUserChangeNick)
v1UserGroup.PUT("/desc", v1.PutUserChangeDesc) v1UserGroup.PUT("/desc", v1.PutUserChangeDesc)
v1UserGroup.POST("/person/info", v1.PostUserPersonInfo)
v1UserGroup.GET("/shareid", v1.GetUserShareID)
} }
@ -78,51 +82,6 @@ func InitRouter() *gin.Engine {
//获取系统信息 //获取系统信息
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo) v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
} }
v1ZeroTierGroup := v1Group.Group("/zerotier")
v1ZeroTierGroup.Use()
{
//获取zerotier token
v1ZeroTierGroup.POST("/login", v1.ZeroTierGetToken)
//注册zerotier
v1ZeroTierGroup.POST("/register", v1.ZeroTierRegister)
//是否需要登录
v1ZeroTierGroup.GET("/islogin", v1.ZeroTierIsNeedLogin)
//获取网络列表
v1ZeroTierGroup.GET("/list", v1.ZeroTierGetNetworkList)
//加入网络
v1ZeroTierGroup.POST("/join/:id", v1.ZeroTierJoinNetwork)
//离开网络
v1ZeroTierGroup.POST("/leave/:id", v1.ZeroTierLeaveNetwork)
//详情
v1ZeroTierGroup.GET("/info/:id", v1.ZeroTierGetNetworkGetInfo)
////网络状态
//v1ZeroTierGroup.GET("/status", v1.ZeroTierGetNetworkGetStatus)
//修改网络类型
//v1ZeroTierGroup.PUT("/type/:id", v1.ZeroTierEditType)
//修改网络类型
//v1ZeroTierGroup.PUT("/name/:id", v1.ZeroTierEditName)
//修改v6 assign
//v1ZeroTierGroup.PUT("/v6assign/:id", v1.ZeroTierEditV6Assign)
//修改 broadcast
//v1ZeroTierGroup.PUT("/broadcast/:id", v1.ZeroTierEditBroadcast)
//create new network
v1ZeroTierGroup.POST("/create", v1.ZeroTierCreateNetwork)
//获取用户列表
v1ZeroTierGroup.GET("/member/:id", v1.ZeroTierMemberList)
//修改用户信息
//v1ZeroTierGroup.PUT("/members/:id/auth/:mId", v1.ZeroTierMemberAuth)
//修改网络用户name
//v1ZeroTierGroup.PUT("/members/:id/name/:mId", v1.ZeroTierMemberName)
v1ZeroTierGroup.DELETE("/members/:id/del/:mId", v1.ZeroTierMemberDelete)
v1ZeroTierGroup.DELETE("/network/:id/del", v1.ZeroTierDeleteNetwork)
//修改网络用户bridge功能
//v1ZeroTierGroup.PUT("/members/:id/bridge/:mId", v1.ZeroTierMemberBridge)
v1ZeroTierGroup.PUT("/edit/:id", v1.ZeroTierEdit)
v1ZeroTierGroup.GET("/joined/list", v1.ZeroTierJoinedList)
v1ZeroTierGroup.PUT("/member/:id/edit/:mId", v1.ZeroTierMemberEdit)
}
v1DDNSGroup := v1Group.Group("/ddns") v1DDNSGroup := v1Group.Group("/ddns")
v1DDNSGroup.Use() v1DDNSGroup.Use()
{ {
@ -201,6 +160,9 @@ func InitRouter() *gin.Engine {
v1SysGroup.PUT("/port", v1.PutCasaOSPort) v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.POST("/kill", v1.PostKillCasaOS) v1SysGroup.POST("/kill", v1.PostKillCasaOS)
v1SysGroup.GET("/info", v1.Info) v1SysGroup.GET("/info", v1.Info)
v1SysGroup.PUT("/usb/off", v1.PutSystemOffUSBAutoMount)
v1SysGroup.GET("/usb/on", v1.PutSystemOnUSBAutoMount)
v1SysGroup.GET("/usb", v1.GetSystemUSBAutoMount)
} }
v1FileGroup := v1Group.Group("/file") v1FileGroup := v1Group.Group("/file")
v1FileGroup.Use() v1FileGroup.Use()
@ -216,6 +178,7 @@ func InitRouter() *gin.Engine {
v1FileGroup.POST("/create", v1.PostCreateFile) v1FileGroup.POST("/create", v1.PostCreateFile)
v1FileGroup.GET("/download", v1.GetDownloadFile) v1FileGroup.GET("/download", v1.GetDownloadFile)
v1FileGroup.GET("/new/download", v1.GetFileDownloadNew)
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir) v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
v1FileGroup.DELETE("/delete", v1.DeleteFile) v1FileGroup.DELETE("/delete", v1.DeleteFile)
v1FileGroup.PUT("/update", v1.PutFileContent) v1FileGroup.PUT("/update", v1.PutFileContent)
@ -289,19 +252,26 @@ func InitRouter() *gin.Engine {
{ {
v1SearchGroup.GET("/search", v1.GetSearchList) v1SearchGroup.GET("/search", v1.GetSearchList)
} }
v1PersonGroup := v1Group.Group("/persion") v1PersonGroup := v1Group.Group("/person")
v1PersonGroup.Use() v1PersonGroup.Use()
{ {
v1PersonGroup.GET("/test", v1.PersonTest) v1PersonGroup.GET("/test", v1.PersonTest)
v1PersonGroup.GET("/users", v1.GetPersionFriend) v1PersonGroup.GET("/users", v1.GetPersonFriend)
v1PersonGroup.POST("/user", v1.PostAddPersionFriend) v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend)
v1PersonGroup.GET("/directory", v1.GetPersionDirectory) v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend)
v1PersonGroup.GET("/file", v1.GetPersionFile) v1PersonGroup.GET("/directory", v1.GetPersonDirectory)
v1PersonGroup.GET("/refile/:uuid", v1.GetPersionReFile) v1PersonGroup.GET("/file", v1.GetPersonFile)
v1PersonGroup.PUT("/nick/:token", v1.PutPersionNick) v1PersonGroup.GET("/refile/:uuid", v1.GetPersonReFile)
v1PersonGroup.GET("/list", v1.GetPersionDownloadList) v1PersonGroup.PUT("/remarks/:shareid", v1.PutPersonRemarks)
v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersionDownloadFile) v1PersonGroup.GET("/list", v1.GetPersonDownloadList)
// v1PersonGroup.PUT("/state/:id", v1.PutPersionCancelDownload) //修改下载状态(开始暂停删除) v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile)
v1PersonGroup.POST("/share", v1.PostPersonShare)
v1PersonGroup.GET("/share", v1.GetPersonShare)
v1PersonGroup.POST("/down/dir", v1.PostPersonDownDir)
v1PersonGroup.GET("/down/dir", v1.GetPersonDownDir)
v1PersonGroup.PUT("/block/:shareid", v1.PutPersonBlock)
v1PersonGroup.GET("/public", v1.GetPersonPublic)
} }
v1AnalyseGroup := v1Group.Group("/analyse") v1AnalyseGroup := v1Group.Group("/analyse")

View file

@ -248,7 +248,7 @@ func ShareAppFile(c *gin.Context) {
// @Tags app // @Tags app
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /app/share [post] // @Router /app/shares [post]
func AppListResourceUsage() { func AppListResourceUsage() {
} }

View file

@ -7,6 +7,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
url2 "net/url"
"os" "os"
"path" "path"
"strconv" "strconv"
@ -17,6 +18,7 @@ import (
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/spf13/afero"
) )
func downloadReadFile(c *gin.Context) { func downloadReadFile(c *gin.Context) {
@ -157,16 +159,59 @@ func GetDownloadFile(c *gin.Context) {
//获取文件的名称 //获取文件的名称
fileName := path.Base(filePath) fileName := path.Base(filePath)
c.Header("Content-Type", "application/octet-stream") c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Disposition", "attachment; filename="+fileName) c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.Header("Content-Transfer-Encoding", "binary") c.Header("Content-Transfer-Encoding", "binary")
c.Header("Cache-Control", "no-cache") c.Header("Cache-Control", "no-cache")
c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Disposition", "attachment; filename="+fileName)
c.Header("Content-Transfer-Encoding", "binary")
c.File(filePath) c.File(filePath)
} }
// @Summary download
// @Produce application/json
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path query string true "path of file"
// @Success 200 {string} string "ok"
// @Router /file/new/download [get]
func GetFileDownloadNew(c *gin.Context) {
filePath := c.Query("path")
if len(filePath) == 0 {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
})
return
}
if !file.Exists(filePath) {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
})
return
}
//打开文件
fileStat, _ := os.Stat(filePath)
var AppFs = afero.NewOsFs()
fileT, _ := AppFs.Open(filePath)
//fileTmp, _ := os.Open(filePath)
//defer fileTmp.Close()
//获取文件的名称
//fileName := path.Base(filePath)
//c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
//在线
//c.Header("Content-Disposition", "inline")
// extraHeaders := map[string]string{
// "Content-Disposition": `attachment; filename="` + url2.PathEscape(fileName) + `"`,
// }
//c.Header("Cache-Control", "private")
//c.Header("Content-Type", "application/octet-stream")
http.ServeContent(c.Writer, c.Request, fileStat.Name(), fileStat.ModTime(), fileT)
}
// @Summary 获取目录列表 // @Summary 获取目录列表
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json

View file

@ -7,9 +7,12 @@ import (
"net/http" "net/http"
"reflect" "reflect"
"strconv" "strconv"
"strings"
"time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
@ -19,8 +22,10 @@ import (
) )
func PersonTest(c *gin.Context) { func PersonTest(c *gin.Context) {
token := c.Query("token") token := c.Query("token")
_, err := uuid.FromString(token)
fmt.Println(err)
//service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9") //service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9")
msg := model.MessageModel{} msg := model.MessageModel{}
@ -35,45 +40,48 @@ func PersonTest(c *gin.Context) {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(dd) fmt.Println(dd)
user := service.MyService.Casa().GetUserInfoByShareId(token)
if reflect.DeepEqual(user, model.UserInfo{}) {
fmt.Println("空数据")
}
fmt.Println(user)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} }
// @Summary retry download file // @Summary Retry the file that failed to download
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Param uui path string true "download uuid" // @Param uui path string true "download uuid"
// @Param path query string true "file path"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /persion/refile/{uuid} [get] // @Router /person/refile/{uuid} [get]
func GetPersionReFile(c *gin.Context) { func GetPersonReFile(c *gin.Context) {
path := c.Query("path") uid := c.Param("uuid")
uuid := c.Param("uuid") _, err := uuid.FromString(uid)
if err != nil {
if len(path) == 0 && len(uuid) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
task := service.MyService.Download().GetDownloadById(uuid) task := service.MyService.Download().GetDownloadById(uid)
if reflect.DeepEqual(task, model2.PersionDownloadDBModel{}) { if reflect.DeepEqual(task, model2.PersonDownloadDBModel{}) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSION_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSION_REMOTE_ERROR)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return return
} }
token := task.From token := task.From
if _, ok := service.UDPAddressMap[token]; !ok { if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSION_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSION_REMOTE_ERROR)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return return
} }
m := model.MessageModel{} m := model.MessageModel{}
m.Data = path m.Data = task.Path
m.From = config.ServerInfo.Token m.From = config.ServerInfo.Token
m.To = token m.To = token
m.Type = types.PERSONDOWNLOAD m.Type = types.PERSONDOWNLOAD
m.UUId = uuid m.UUId = uid
go service.Dial(m, false) go service.Dial(m, false)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
@ -82,35 +90,57 @@ func GetPersionReFile(c *gin.Context) {
// @Summary download file // @Summary download file
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Param token query string true "opponent token" // @Param share_id query string true "opponent share_id"
// @Param path query string true "file path" // @Param path query string true "file path"
// @Param file_name query string true "file name"
// @Param local_path query string true "local_path"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /persion/file [get] // @Router /person/file [get]
func GetPersionFile(c *gin.Context) { func GetPersonFile(c *gin.Context) {
path := c.Query("path") path := c.Query("path")
token := c.Query("token") localPath := c.Query("local_path")
if len(path) == 0 && len(token) == 0 { token := c.Query("share_id")
fileName := c.Query("file_name")
_, err := uuid.FromString(token)
if len(path) == 0 || err != nil || len(localPath) == 0 || len(fileName) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
if _, ok := service.UDPAddressMap[token]; !ok { if file.CheckNotExist(localPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSION_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSION_REMOTE_ERROR)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DIR_NOT_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.DIR_NOT_EXISTS)})
return return
} }
if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return
}
if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return
}
// task id // task id
uuid := uuid.NewV4().String() uuid := uuid.NewV4().String()
task := model2.PersionDownloadDBModel{} task := model2.PersonDownloadDBModel{}
task.UUID = uuid task.UUID = uuid
task.Name = "" task.Name = fileName
task.Length = 0 task.Length = 0
task.From = token task.From = token
task.Path = path
task.Size = 0 task.Size = 0
task.State = types.DOWNLOADAWAIT task.State = types.DOWNLOADAWAIT
task.Created = time.Now().Unix()
task.Type = 0 task.Type = 0
task.LocalPath = localPath
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
return
}
service.MyService.Download().AddDownloadTask(task) service.MyService.Download().AddDownloadTask(task)
m := model.MessageModel{} m := model.MessageModel{}
@ -127,79 +157,92 @@ func GetPersionFile(c *gin.Context) {
// @Summary delete download file records // @Summary delete download file records
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Param uuid path string true "download uuid" // @Param uuid path string true "download uuid"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /persion/file/{uuid} [delete] // @Router /person/file/{uuid} [delete]
func DeletePersionDownloadFile(c *gin.Context) { func DeletePersonDownloadFile(c *gin.Context) {
id := c.Param("uuid") id := c.Param("uuid")
if len(id) == 0 { _, err := uuid.FromString(id)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
task := service.MyService.Download().GetDownloadById(id)
if task.State == types.DOWNLOADING {
m := model.MessageModel{}
m.Data = ""
m.From = config.ServerInfo.Token
m.To = task.From
m.Type = types.PERSONCANCEL
m.UUId = task.UUID
service.CancelList[task.UUID] = task.UUID
service.Dial(m, false)
}
service.MyService.Download().DelDownload(id) service.MyService.Download().DelDownload(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} }
// @Summary get file download list // @Summary Get file download list
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Param state query int true "wait:1,downloading:1,pause:2,finish:3,error:4" Enums(0,1,2,4) // @Param state query int false "wait:0,downloading:1,pause:2,finish:3,error:4,finished:5" Enums(0,1,2,3,4,5)
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {object} []model2.PersonDownloadDBModel
// @Router /persion/list [get] // @Router /person/list [get]
func GetPersionDownloadList(c *gin.Context) { func GetPersonDownloadList(c *gin.Context) {
state := c.DefaultQuery("state", "") state := c.DefaultQuery("state", "")
list := service.MyService.Download().GetDownloadListByState(state) list := service.MyService.Download().GetDownloadListByState(state)
//if it is downloading, it need to add 'already' //if it is downloading, it need to add 'already'
if state == strconv.Itoa(types.DOWNLOADING) {
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
if list[i].State == types.DOWNLOADING {
tempDir := config.AppInfo.RootPath + "/temp" + "/" + list[i].UUID tempDir := config.AppInfo.RootPath + "/temp" + "/" + list[i].UUID
files, err := ioutil.ReadDir(tempDir) files, err := ioutil.ReadDir(tempDir)
if err == nil { if err == nil {
list[i].Already = len(files) list[i].Already = len(files)
} }
} }
list[i].Duration = time.Now().Unix() - list[i].Created
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
} }
// @Summary edit friend's nick // @Summary edit friend's remarks
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Param token path string true "token" // @Param remarks formData string true "remarks name"
// @Param nick formData string true "nick name"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /persion/nick/{token} [put] // @Router /person/remarks/{shareid} [put]
func PutPersionNick(c *gin.Context) { func PutPersonRemarks(c *gin.Context) {
token := c.Param("token") token := c.Param("shareid")
nick := c.PostForm("nick") _, err := uuid.FromString(token)
if len(token) == 0 || len(nick) == 0 { mark := c.PostForm("remarks")
if err != nil || len(mark) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
friend := model2.FriendModel{} friend := model2.FriendModel{}
friend.Token = token friend.Token = token
friend.NickName = nick friend.Mark = mark
service.MyService.Friend().EditFriendNick(friend) service.MyService.Friend().EditFriendMark(friend)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} }
// @Summary get friend list // @Summary get my friend list
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {object} []model2.FriendModel
// @Router /persion/users [get] // @Router /person/users [get]
func GetPersionFriend(c *gin.Context) { func GetPersonFriend(c *gin.Context) {
list := service.MyService.Friend().GetFriendList() list := service.MyService.Friend().GetFriendList()
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 { if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 {
@ -212,51 +255,79 @@ func GetPersionFriend(c *gin.Context) {
// @Summary add friend // @Summary add friend
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Param token formData int true "Opponent token"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /persion/user [post] // @Router /person/user/{shareids} [post]
func PostAddPersionFriend(c *gin.Context) { func PostAddPersonFriend(c *gin.Context) {
token := c.PostForm("token") token := c.Param("shareids")
if len(token) == 0 { tokenList := strings.Split(token, ",")
for _, v := range tokenList {
_, err := uuid.FromString(v)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
msg := model.MessageModel{} if v == config.ServerInfo.Token {
msg.Type = types.PERSONCONNECTION c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_MYSELF, Message: oasis_err2.GetMsg(oasis_err2.PERSON_MYSELF)})
msg.Data = token return
msg.From = config.ServerInfo.Token }
msg.To = token
msg.UUId = uuid.NewV4().String()
go service.Dial(msg, true) udb := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: v})
if !reflect.DeepEqual(udb, model2.FriendModel{Token: v}) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_FRIEND, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_FRIEND)})
return
}
user := service.MyService.Casa().GetUserInfoByShareId(v)
if reflect.DeepEqual(user, model.UserInfo{}) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_NOT_EXIST_USER, Message: oasis_err2.GetMsg(oasis_err2.PERSON_NOT_EXIST_USER)})
return
}
message := model.MessageModel{}
message.Type = types.PERSONCONNECTION
message.Data = v
message.From = config.ServerInfo.Token
message.To = v
message.UUId = uuid.NewV4().String()
go service.Dial(message, true)
friend := model2.FriendModel{} friend := model2.FriendModel{}
friend.Token = token friend.Token = v
friend.Avatar = user.Avatar
friend.Block = false
friend.NickName = user.NickName
friend.Profile = user.Desc
friend.Version = user.Version
service.MyService.Friend().AddFriend(friend) service.MyService.Friend().AddFriend(friend)
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} }
// @Summary get directory list // @Summary Get a list of directories
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags persion // @Tags person
// @Param token query string true "Opponent token" // @Param share_id query string true "Opponent share_id"
// @Param path query string true "dir path" // @Param path query string true "dir path"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {object} []model.Path
// @Router /persion/directory [get] // @Router /person/directory [get]
func GetPersionDirectory(c *gin.Context) { func GetPersonDirectory(c *gin.Context) {
path := c.Query("path") path := c.Query("path")
token := c.Query("token") token := c.Query("share_id")
if len(path) == 0 && len(token) == 0 { _, err := uuid.FromString(token)
if len(path) == 0 || err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
if _, ok := service.UDPAddressMap[token]; !ok { if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSION_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSION_REMOTE_ERROR)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return return
} }
uuid := uuid.NewV4().String() uuid := uuid.NewV4().String()
@ -282,3 +353,144 @@ func GetPersionDirectory(c *gin.Context) {
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: dataModel}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: dataModel})
} }
// @Summary Modify the download storage directory
// @Produce application/json
// @Accept multipart/form-data
// @Tags person
// @Security ApiKeyAuth
// @Param path formData string true "path"
// @Success 200 {string} string "ok"
// @Router /person/down/dir [post]
func PostPersonDownDir(c *gin.Context) {
downPath := c.PostForm("path")
if len(downPath) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if file.CheckNotExist(downPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DIR_NOT_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.DIR_NOT_EXISTS)})
return
}
config.Cfg.Section("file").Key("DownloadDir").SetValue(downPath)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
config.FileSettingInfo.DownloadDir = downPath
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get the download storage directory
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/down/dir [get]
func GetPersonDownDir(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.DownloadDir})
}
// @Summary Modify the shared directory
// @Produce application/json
// @Accept multipart/form-data
// @Tags person
// @Security ApiKeyAuth
// @Param share formData string true "share"
// @Success 200 {string} string "ok"
// @Router /person/share [post]
func PostPersonShare(c *gin.Context) {
share := c.PostForm("share")
if len(share) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
var list []string
json.Unmarshal([]byte(share), &list)
if len(list) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
for _, v := range list {
if !file.Exists(v) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
}
config.Cfg.Section("file").Key("ShareDir").SetValue(strings.Join(list, "|"))
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
config.FileSettingInfo.ShareDir = list
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get the shared directory
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/share [get]
func GetPersonShare(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.ShareDir})
}
// @Summary Modify disabled status
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param block formData bool false "Disable or not,Default:false "
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/block/{shareid} [put]
func PutPersonBlock(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
block, _ := strconv.ParseBool(c.PostForm("block"))
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
friend := model2.FriendModel{}
friend.Token = token
friend.Block = block
service.MyService.Friend().EditFriendBlock(friend)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Delete my friend
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/user/{shareid} [delete]
func DeletePersonFriend(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
friend := model2.FriendModel{}
friend.Token = token
service.MyService.Friend().DeleteFriend(friend)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get public person
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/public [delete]
func GetPersonPublic(c *gin.Context) {
list := service.MyService.Casa().GetPersonPublic()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
}

View file

@ -251,6 +251,60 @@ func PostKillCasaOS(c *gin.Context) {
os.Exit(0) os.Exit(0)
} }
// @Summary Turn off usb auto-mount
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/usg/off [put]
func PutSystemOffUSBAutoMount(c *gin.Context) {
service.MyService.System().UpdateUSBAutoMount("False")
service.MyService.System().ExecUSBAutoMountShell("False")
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
})
}
// @Summary Turn off usb auto-mount
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/usb [get]
func GetSystemUSBAutoMount(c *gin.Context) {
state := "True"
if config.ServerInfo.USBAutoMount == "False" {
state = "False"
}
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: state,
})
}
// @Summary Turn off usb auto-mount
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/usb/on [put]
func PutSystemOnUSBAutoMount(c *gin.Context) {
service.MyService.System().UpdateUSBAutoMount("True")
service.MyService.System().ExecUSBAutoMountShell("True")
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
})
}
// @Summary system info // @Summary system info
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@ -374,7 +428,7 @@ func Info(c *gin.Context) {
if n.Name == netCardName { if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n)) item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name)) item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
item.DateTime = time.Now() item.Time = time.Now().Unix()
newNet = append(newNet, item) newNet = append(newNet, item)
break break
} }

View file

@ -121,7 +121,7 @@ func PostUserHead(c *gin.Context) {
// @Param oldname formData string true "Old user name" // @Param oldname formData string true "Old user name"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/changusername [put] // @Router /user/username [put]
func PutUserName(c *gin.Context) { func PutUserName(c *gin.Context) {
if config.ServerInfo.LockAccount { if config.ServerInfo.LockAccount {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)})
@ -142,14 +142,14 @@ func PutUserName(c *gin.Context) {
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags user // @Tags user
// @Param pwd formData string true "Password" // @Param pwd formData string true "Password"
// @Param oldpwd formData string true "Old password" // @Param old_pwd formData string true "Old password"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/changuserpwd [put] // @Router /user/password [put]
func PutUserPwd(c *gin.Context) { func PutUserPwd(c *gin.Context) {
oldpwd := c.PostForm("oldpwd") oldPwd := c.PostForm("old_pwd")
pwd := c.PostForm("pwd") pwd := c.PostForm("pwd")
if config.UserInfo.PWD != oldpwd { if config.UserInfo.PWD != oldPwd {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)})
return return
} }
@ -199,7 +199,7 @@ func PostUserChangeInfo(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
} }
// @Summary edit user info // @Summary edit user nick
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags user // @Tags user
@ -211,17 +211,18 @@ func PutUserChangeNick(c *gin.Context) {
nickName := c.PostForm("nick_name") nickName := c.PostForm("nick_name")
if len(nickName) > 0 { if len(nickName) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
user_service.SetUser("", "", "", "", "", nickName) user_service.SetUser("", "", "", "", "", nickName)
data := make(map[string]string, 1) data := make(map[string]string, 1)
data["nick_name"] = config.UserInfo.NickName data["nick_name"] = config.UserInfo.NickName
go service.MyService.Casa().PushUserInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
} }
// @Summary edit user info // @Summary edit user description
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags user // @Tags user
@ -232,13 +233,38 @@ func PutUserChangeNick(c *gin.Context) {
func PutUserChangeDesc(c *gin.Context) { func PutUserChangeDesc(c *gin.Context) {
desc := c.PostForm("description") desc := c.PostForm("description")
if len(desc) > 0 { if len(desc) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
user_service.SetUser("", "", "", "", desc, "") user_service.SetUser("", "", "", "", desc, "")
data := make(map[string]string, 1) data := make(map[string]string, 1)
data["description"] = config.UserInfo.Description data["description"] = config.UserInfo.Description
go service.MyService.Casa().PushUserInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
}
// @Summary Modify user person information (Initialization use)
// @Produce application/json
// @Accept multipart/form-data
// @Tags user
// @Param nick_name formData string false "user nick name"
// @Param description formData string false "Description"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/person/info [post]
func PostUserPersonInfo(c *gin.Context) {
desc := c.PostForm("description")
nickName := c.PostForm("nick_name")
if len(desc) == 0 || len(nickName) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
user_service.SetUser("", "", "", "", desc, nickName)
data := make(map[string]string, 2)
data["description"] = config.UserInfo.Description
data["nick_name"] = config.UserInfo.NickName
go service.MyService.Casa().PushUserInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
} }
@ -262,3 +288,14 @@ func GetUserInfo(c *gin.Context) {
Data: u, Data: u,
}) })
} }
// @Summary Get my shareId
// @Produce application/json
// @Accept application/json
// @Tags user
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/shareid [get]
func GetUserShareID(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.ServerInfo.Token})
}

View file

@ -1,475 +0,0 @@
package v1
import (
json2 "encoding/json"
"net/http"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
)
// @Summary 登录zerotier获取token
// @Produce application/json
// @Accept multipart/form-data
// @Tags zerotier
// @Param username formData string true "User name"
// @Param pwd formData string true "password"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zerotier/login [post]
func ZeroTierGetToken(c *gin.Context) {
username := c.PostForm("username")
pwd := c.PostForm("pwd")
if len(username) == 0 || len(pwd) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
errInfo := service.MyService.ZeroTier().GetToken(username, pwd)
if len(errInfo) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.GET_TOKEN_ERROR)})
} else {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
}
// @Summary 注册zerotier
// @Produce application/json
// @Accept multipart/form-data
// @Tags zerotier
// @Param firstName formData string true "first name"
// @Param pwd formData string true "password"
// @Param email formData string true "email"
// @Param lastName formData string true "last name"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zerotier/register [post]
func ZeroTierRegister(c *gin.Context) {
firstName := c.PostForm("firstName")
pwd := c.PostForm("pwd")
email := c.PostForm("email")
lastName := c.PostForm("lastName")
if len(firstName) == 0 || len(pwd) == 0 || len(email) == 0 || len(lastName) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
errInfo := service.MyService.ZeroTier().ZeroTierRegister(email, lastName, firstName, pwd)
if len(errInfo) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} else {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: errInfo})
}
}
// @Summary 是否需要登录zerotier
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Success 200 {string} string "false:需要登录true:不需要登录"
// @Router /zerotier/islogin [get]
func ZeroTierIsNeedLogin(c *gin.Context) {
if len(config.ZeroTierInfo.Token) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: false})
} else {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: true})
}
}
// @Summary 获取zerotier网络列表
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zerotier/list [get]
func ZeroTierGetNetworkList(c *gin.Context) {
jsonList, joined := service.MyService.ZeroTier().ZeroTierNetworkList(config.ZeroTierInfo.Token)
rdata := make(map[string]interface{})
rdata["network_list"] = jsonList
rdata["joined"] = joined
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: rdata})
}
// @Summary 获取zerotier网络详情
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Param id path string true "network id"
// @Success 200 {string} string "ok"
// @Router /zerotier/info/{id} [get]
func ZeroTierGetNetworkGetInfo(c *gin.Context) {
id := c.Param("id")
if len(id) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
info, joined := service.MyService.ZeroTier().ZeroTierGetInfo(config.ZeroTierInfo.Token, id)
rdata := make(map[string]interface{})
rdata["info"] = info
rdata["joined"] = joined
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: rdata})
}
//// @Summary 获取zerotier网络状态
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Success 200 {string} string "ok"
//// @Router /zerotier/status [get]
//func ZeroTierGetNetworkGetStatus(c *gin.Context) {
// status := service.MyService.ZeroTier().ZeroTierGetStatus(config.ZeroTierInfo.Token)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: status})
//}
//// @Summary 修改网络类型
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Param id path string true "network id"
//// @Param type formData string true "Private true/false"
//// @Success 200 {string} string "ok"
//// @Router /zerotier/type/{id} [put]
//func ZeroTierEditType(c *gin.Context) {
// id := c.Param("id")
// t := c.PostForm("type")
// if len(id) == 0 || len(t) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// postData := `{"config":{"private":` + t + `}}`
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
//}
//// @Summary 修改名称
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Param id path string true "network id"
//// @Param name formData string true "需要过滤特殊字符串"
//// @Success 200 {string} string "ok"
//// @Router /zerotier/name/{id} [put]
//func ZeroTierEditName(c *gin.Context) {
// id := c.Param("id")
// name := c.PostForm("name")
// if len(id) == 0 || len(name) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// postData := `{"config":{"name":"` + name + `"}}`
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
//}
//// @Summary V6Assign (注意三个属性需要一起传过来,不传的会被zerotier设置成false)
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Param id path string true "network id"
//// @Param v6plan formData string false "true/false"
//// @Param rfc formData string false "true/false"
//// @Param auto formData string false "true/false"
//// @Success 200 {string} string "ok"
//// @Router /zerotier/v6assign/{id} [put]
//func ZeroTierEditV6Assign(c *gin.Context) {
// id := c.Param("id")
// v6plan := c.PostForm("v6plan")
// rfc := c.PostForm("rfc")
// auto := c.PostForm("auto")
// if len(id) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// var spicing string
// if len(v6plan) > 0 {
// spicing = `"6plane":` + v6plan
// }
// if len(rfc) > 0 {
// if len(spicing) > 0 {
// spicing += ","
// }
// spicing += `"rfc4193":` + rfc
// }
//
// if len(auto) > 0 {
// if len(spicing) > 0 {
// spicing += ","
// }
// spicing += `"zt":` + auto
// }
// postData := `{"config":{"v6AssignMode":{` + spicing + `}}}`
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
//}
//// @Summary Broadcast
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Param id path string true "network id"
//// @Param broadcast formData string true "true/false"
//// @Success 200 {string} string "ok"
//// @Router /zerotier/broadcast/{id} [put]
//func ZeroTierEditBroadcast(c *gin.Context) {
// id := c.Param("id")
// broadcast := c.PostForm("broadcast")
// if len(id) == 0 || len(broadcast) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// postData := `{"config":{"enableBroadcast":` + broadcast + `}}`
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
//}
// @Summary 网络列表
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Param id path string true "network id"
// @Success 200 {string} string "ok"
// @Router /zerotier/member/{id} [get]
func ZeroTierMemberList(c *gin.Context) {
id := c.Param("id")
if len(id) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
info := service.MyService.ZeroTier().MemberList(config.ZeroTierInfo.Token, id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}
// @Summary create new network
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zerotier/create [post]
func ZeroTierCreateNetwork(c *gin.Context) {
info := service.MyService.ZeroTier().CreateNetwork(config.ZeroTierInfo.Token)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}
//// @Summary 通过/拒绝客户端
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Param id path string true "network id"
//// @Param mId path string true "member_id"
//// @Param auth formData string true "true/false"
//// @Success 200 {string} string "ok"
//// @Router /zerotier/member/{id}/auth/{mId} [put]
//func ZeroTierMemberAuth(c *gin.Context) {
// id := c.Param("id")
// mId := c.Param("mId")
// auth := c.PostForm("auth")
// if len(id) == 0 || len(mId) == 0 || len(auth) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// postData := `{"config":{"authorized":` + auth + `}}`
// info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, postData, id, mId)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
//}
//// @Summary 修改名字
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Param id path string true "network id"
//// @Param mId path string true "member_id"
//// @Param name formData string true "name"
//// @Success 200 {string} string "ok"
//// @Router /zerotier/member/{id}/name/{mId} [put]
//func ZeroTierMemberName(c *gin.Context) {
// id := c.Param("id")
// mId := c.Param("mId")
// name := c.PostForm("name")
// if len(id) == 0 || len(mId) == 0 || len(name) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// postData := `{"name":"` + name + `"}`
// info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, postData, id, mId)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
//}
//// @Summary 修改桥接
//// @Produce application/json
//// @Accept application/json
//// @Tags zerotier
//// @Security ApiKeyAuth
//// @Param id path string true "network id"
//// @Param mId path string true "member_id"
//// @Param bridge formData string true "true/false"
//// @Success 200 {string} string "ok"
//// @Router /zerotier/member/{id}/bridge/{mId} [put]
//func ZeroTierMemberBridge(c *gin.Context) {
// id := c.Param("id")
// mId := c.Param("mId")
// bridge := c.PostForm("bridge")
// if len(id) == 0 || len(mId) == 0 || len(bridge) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// postData := `{"config":{"activeBridge":` + bridge + `}}`
// info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, postData, id, mId)
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
//}
// @Summary 修改网络
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Param id path string true "network id"
// @Param json formData string true "json数据"
// @Success 200 {string} string "ok"
// @Router /zerotier/edit/{id} [put]
func ZeroTierEdit(c *gin.Context) {
id := c.Param("id")
json := c.PostForm("json")
if len(id) == 0 || len(json) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, json, id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}
// @Summary 获取已加入的网络
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zerotier/joined/list [get]
func ZeroTierJoinedList(c *gin.Context) {
info := service.MyService.ZeroTier().GetJoinNetworks()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: json2.RawMessage(info)})
}
// @Summary 修改网络用户信息
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Param id path string true "network id"
// @Param mId path string true "mId"
// @Param json formData string true "json数据"
// @Success 200 {string} string "ok"
// @Router /zerotier/member/{id}/edit/{mId} [put]
func ZeroTierMemberEdit(c *gin.Context) {
id := c.Param("id")
mId := c.Param("mId")
json := c.PostForm("json")
if len(id) == 0 || len(json) == 0 || len(mId) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, json, id, mId)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}
// @Summary 删除网络中的用户
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Param id path string true "network id"
// @Param mId path string true "member_id"
// @Success 200 {string} string "ok"
// @Router /zerotier/member/{id}/del/{mId} [delete]
func ZeroTierMemberDelete(c *gin.Context) {
id := c.Param("id")
mId := c.Param("mId")
if len(id) == 0 || len(mId) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
info := service.MyService.ZeroTier().DeleteMember(config.ZeroTierInfo.Token, id, mId)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}
// @Summary 删除网络
// @Produce application/json
// @Accept application/json
// @Tags zerotier
// @Security ApiKeyAuth
// @Param id path string true "network id"
// @Success 200 {string} string "ok"
// @Router /zerotier/network/{id}/del [delete]
func ZeroTierDeleteNetwork(c *gin.Context) {
id := c.Param("id")
if len(id) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
info := service.MyService.ZeroTier().DeleteNetwork(config.ZeroTierInfo.Token, id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}
// @Summary 加入网络
// @Produce application/json
// @Accept multipart/form-data
// @Tags zerotier
// @Param id path string true "network id"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zerotier/join/{id} [post]
func ZeroTierJoinNetwork(c *gin.Context) {
networkId := c.Param("id")
if len(networkId) != 16 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
for _, v := range networkId {
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
}
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary 获取zerotier网络列表
// @Produce application/json
// @Accept multipart/form-data
// @Tags zerotier
// @Param id path string true "network id"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zerotier/leave/{id} [post]
func ZeroTierLeaveNetwork(c *gin.Context) {
networkId := c.Param("id")
if len(networkId) != 16 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
for _, v := range networkId {
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
}
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}

View file

@ -73,7 +73,7 @@ func NetInfo(c *gin.Context) {
if n.Name == netCardName { if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n)) item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name)) item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
item.DateTime = time.Now() item.Time = time.Now().Unix()
newNet = append(newNet, item) newNet = append(newNet, item)
break break
} }

View file

@ -22,6 +22,9 @@ type CasaService interface {
PushHeart(id, t string, language string) PushHeart(id, t string, language string)
PushAppAnalyse(uuid, t string, name, language string) PushAppAnalyse(uuid, t string, name, language string)
PushConnectionStatus(uuid, err string, from, to, event string) PushConnectionStatus(uuid, err string, from, to, event string)
PushUserInfo()
GetUserInfoByShareId(shareId string) model.UserInfo
GetPersonPublic() (list []model.FriendsModel)
} }
type casaService struct { type casaService struct {
@ -118,7 +121,6 @@ func GetToken() string {
} }
go func() { go func() {
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil) str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
t <- gjson.Get(str, "data").String() t <- gjson.Get(str, "data").String()
}() }()
auth = <-t auth = <-t
@ -178,13 +180,54 @@ func (o *casaService) PushConnectionStatus(uuid, err string, from, to, event str
head["Authorization"] = GetToken() head["Authorization"] = GetToken()
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/app", b, "application/json", head) infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/connect", b, "application/json", head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
}
func (o *casaService) PushUserInfo() {
m := model.UserInfo{}
m.Desc = config.UserInfo.Description
m.Avatar = config.UserInfo.Avatar
m.NickName = config.UserInfo.NickName
m.ShareId = config.ServerInfo.Token
b, _ := json.Marshal(m)
head := make(map[string]string)
head["Authorization"] = GetToken()
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/user/info", b, "application/json", head)
info := model.ServerAppList{} info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info) json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
} }
func (o *casaService) GetUserInfoByShareId(shareId string) model.UserInfo {
head := make(map[string]string)
head["Authorization"] = GetToken()
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/user/info/"+shareId, head)
info := model.UserInfo{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
return info
}
func (o *casaService) GetPersonPublic() (list []model.FriendsModel) {
head := make(map[string]string)
head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/person/public", head)
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
return list
}
func NewCasaService() CasaService { func NewCasaService() CasaService {
return &casaService{} return &casaService{}
} }

View file

@ -6,43 +6,51 @@ import (
) )
type DownloadService interface { type DownloadService interface {
AddDownloadTask(m model2.PersionDownloadDBModel) //添加下载任务 AddDownloadTask(m model2.PersonDownloadDBModel) //添加下载任务
EditDownloadState(m model2.PersionDownloadDBModel) //只修改状态 EditDownloadState(m model2.PersonDownloadDBModel) //只修改状态
SaveDownload(m model2.PersionDownloadDBModel) SaveDownload(m model2.PersonDownloadDBModel)
DelDownload(uuid string) DelDownload(uuid string)
GetDownloadById(uuid string) model2.PersionDownloadDBModel GetDownloadById(uuid string) model2.PersonDownloadDBModel
GetDownloadListByState(state string) []model2.PersionDownloadDBModel GetDownloadListByState(state string) []model2.PersonDownloadDBModel
SetDownloadError(m model2.PersionDownloadDBModel) SetDownloadError(m model2.PersonDownloadDBModel)
GetDownloadListByPath(m model2.PersonDownloadDBModel) int
} }
type downloadService struct { type downloadService struct {
db *gorm.DB db *gorm.DB
} }
func (d *downloadService) AddDownloadTask(m model2.PersionDownloadDBModel) { func (d *downloadService) GetDownloadListByPath(m model2.PersonDownloadDBModel) int {
var list []model2.PersonDownloadDBModel
d.db.Select("path").Where("path = ? AND `from` = ? AND state = 0", m.Path, m.From).Find(&list)
return len(list)
}
func (d *downloadService) AddDownloadTask(m model2.PersonDownloadDBModel) {
d.db.Create(&m) d.db.Create(&m)
} }
func (d *downloadService) EditDownloadState(m model2.PersionDownloadDBModel) { func (d *downloadService) EditDownloadState(m model2.PersonDownloadDBModel) {
d.db.Model(&m).Where("uuid = ?", m.UUID).Update("state", m.State) d.db.Model(&m).Where("uuid = ?", m.UUID).Update("state", m.State)
} }
//failed during download //failed during download
func (d *downloadService) SetDownloadError(m model2.PersionDownloadDBModel) { func (d *downloadService) SetDownloadError(m model2.PersonDownloadDBModel) {
d.db.Model(&m).Updates(m) d.db.Model(&m).Updates(m)
} }
func (d *downloadService) DelDownload(uuid string) { func (d *downloadService) DelDownload(uuid string) {
var m model2.PersionDownloadDBModel var m model2.PersonDownloadDBModel
d.db.Where("uuid = ?", uuid).Delete(&m) d.db.Where("uuid = ?", uuid).Delete(&m)
} }
func (d *downloadService) GetDownloadById(uuid string) model2.PersionDownloadDBModel { func (d *downloadService) GetDownloadById(uuid string) model2.PersonDownloadDBModel {
var m model2.PersionDownloadDBModel var m model2.PersonDownloadDBModel
d.db.Model(m).Where("uuid = ?", uuid).First(&m) d.db.Model(m).Where("uuid = ?", uuid).First(&m)
return m return m
} }
func (d *downloadService) GetDownloadListByState(state string) (list []model2.PersionDownloadDBModel) { func (d *downloadService) GetDownloadListByState(state string) (list []model2.PersonDownloadDBModel) {
if len(state) == 0 { if len(state) == 0 {
d.db.Find(&list) d.db.Find(&list)
} else { } else {
d.db.Where("state = ?", state).Find(&list) d.db.Where("state = ?", state).Find(&list)
} }
@ -50,7 +58,7 @@ func (d *downloadService) GetDownloadListByState(state string) (list []model2.Pe
return return
} }
func (d *downloadService) SaveDownload(m model2.PersionDownloadDBModel) { func (d *downloadService) SaveDownload(m model2.PersonDownloadDBModel) {
d.db.Save(&m) d.db.Save(&m)
} }
func NewDownloadService(db *gorm.DB) DownloadService { func NewDownloadService(db *gorm.DB) DownloadService {

View file

@ -10,7 +10,8 @@ import (
type FriendService interface { type FriendService interface {
AddFriend(m model2.FriendModel) AddFriend(m model2.FriendModel)
DeleteFriend(m model2.FriendModel) DeleteFriend(m model2.FriendModel)
EditFriendNick(m model2.FriendModel) EditFriendMark(m model2.FriendModel)
EditFriendBlock(m model2.FriendModel)
GetFriendById(m model2.FriendModel) model2.FriendModel GetFriendById(m model2.FriendModel) model2.FriendModel
GetFriendList() (list []model2.FriendModel) GetFriendList() (list []model2.FriendModel)
UpdateAddFriendType(m model2.FriendModel) UpdateAddFriendType(m model2.FriendModel)
@ -27,17 +28,19 @@ func (p *friendService) AddFriend(m model2.FriendModel) {
func (p *friendService) DeleteFriend(m model2.FriendModel) { func (p *friendService) DeleteFriend(m model2.FriendModel) {
p.db.Where("token = ?", m.Token).Delete(&m) p.db.Where("token = ?", m.Token).Delete(&m)
} }
func (p *friendService) EditFriendNick(m model2.FriendModel) { func (p *friendService) EditFriendMark(m model2.FriendModel) {
p.db.Model(&m).Where("token = ?", m.Token).Update("nick_name", m.NickName) p.db.Model(&m).Where("token = ?", m.Token).Update("mark", m.Mark)
}
func (p *friendService) EditFriendBlock(m model2.FriendModel) {
p.db.Model(&m).Where("token = ?", m.Token).Update("block", m.Block)
} }
func (p *friendService) GetFriendById(m model2.FriendModel) model2.FriendModel { func (p *friendService) GetFriendById(m model2.FriendModel) model2.FriendModel {
p.db.Model(m).Where("token = ?", m.Token).First(&m) p.db.Model(m).Where("token = ?", m.Token).First(&m)
return m return m
} }
func (p *friendService) GetFriendList() (list []model2.FriendModel) { func (p *friendService) GetFriendList() (list []model2.FriendModel) {
p.db.Select("nick_name", "avatar", "name", "profile", "token", "state").Find(&list) p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Find(&list)
return list return list
} }

View file

@ -1,21 +1,24 @@
package model package model
type PersionDownloadDBModel struct { type PersonDownloadDBModel struct {
UUID string `gorm:"column:uuid;primary_key" json:"uuid"` UUID string `gorm:"column:uuid;primary_key" json:"uuid"`
State int `json:"state"` // State int `json:"state"` //
Type int `json:"type"` //defult 1 Type int `json:"type"` //defult 1
Name string `json:"name"` //file name Name string `json:"name"` //file name
Size int64 `json:"size"` //file size Size int64 `json:"size"` //file size
BlockSize int `json:"block_size"` BlockSize int `json:"block_size"` //Size of each file block
Length int `json:"length"` //slice length Length int `json:"length"` //slice length
Hash string `json:"hash"` Hash string `json:"hash"` //File hash value
Error string `json:"error"` Error string `json:"error"` //
From string `json:"from"` From string `json:"from"` //Error message
Already int `json:"already" gorm:"-"` Path string `json:"path"` //Full path to the file
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"` Already int `json:"already" gorm:"-"` //Folder blocks that have been downloaded
UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"` LocalPath string `json:"local_path"` //The address where the file is saved after download
Duration int64 `json:"duration" gorm:"-"` //Length of time
Created int64 `gorm:"autoCreateTime" json:"created"`
Updated int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated"`
} }
func (p *PersionDownloadDBModel) TableName() string { func (p *PersonDownloadDBModel) TableName() string {
return "o_persion_download" return "o_person_download"
} }

View file

@ -1,15 +1,17 @@
package model package model
type FriendModel struct { type FriendModel struct {
State int `json:"state"` //备用 State int `json:"state"` //Reserved
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"` CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"` UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
NickName string `json:"nick_name"` //custom name NickName string `json:"nick_name"`
Avatar string `json:"avatar"` //头像 Mark string `json:"mark"` //Remarks
Name string `json:"name"` Block bool `json:"block"` //Disable or not
Avatar string `json:"avatar"` //User avatar
Token string `gorm:"column:token;primary_key" json:"token"` Token string `gorm:"column:token;primary_key" json:"token"`
Profile string `json:"profile"` Profile string `json:"profile"` //Description
OnLine bool `json:"on_line" gorm:"-"` OnLine bool `json:"on_line" gorm:"-"`
Version int `json:"version"`
} }
func (p *FriendModel) TableName() string { func (p *FriendModel) TableName() string {

View file

@ -18,6 +18,7 @@ type NotifyServer interface {
DelLog(id string) DelLog(id string)
GetList(c int) (list []model.AppNotify) GetList(c int) (list []model.AppNotify)
MarkRead(id string, state int) MarkRead(id string, state int)
SendText(m model.AppNotify)
} }
type notifyServer struct { type notifyServer struct {
@ -102,6 +103,26 @@ func SendMeg() {
// } // }
} }
func (i notifyServer) SendText(m model.AppNotify) {
list := []model.AppNotify{}
list = append(list, m)
json, _ := json2.Marshal(list)
var temp []*websocket.Conn
for _, v := range WebSocketConns {
err := v.WriteMessage(1, json)
if err == nil {
temp = append(temp, v)
}
}
WebSocketConns = temp
if len(WebSocketConns) == 0 {
SocketRun = false
}
}
func NewNotifyService(db *gorm.DB) NotifyServer { func NewNotifyService(db *gorm.DB) NotifyServer {
return &notifyServer{db: db} return &notifyServer{db: db}
} }

View file

@ -17,6 +17,7 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper" "github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper" httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
"github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go"
@ -32,6 +33,7 @@ type personService struct {
} }
var IpInfo model.PersionModel var IpInfo model.PersionModel
var CancelList map[string]string
func PushIpInfo(token string) { func PushIpInfo(token string) {
@ -63,9 +65,16 @@ var StreamList map[string]quic.Stream
var ServiceMessage chan model.MessageModel var ServiceMessage chan model.MessageModel
func UDPService() { func UDPService() {
port := 0
if len(config.ServerInfo.UDPPort) > 0 {
port, _ = strconv.Atoi(config.ServerInfo.UDPPort)
if port != 0 && !port2.IsPortAvailable(port, "udp") {
port = 0
}
}
srcAddr := &net.UDPAddr{ srcAddr := &net.UDPAddr{
IP: net.IPv4zero, Port: 9904} IP: net.IPv4zero, Port: port}
var err error var err error
UDPConn, err = net.ListenUDP("udp", srcAddr) UDPConn, err = net.ListenUDP("udp", srcAddr)
if err != nil { if err != nil {
@ -146,6 +155,7 @@ func ProcessingContent(stream quic.Stream) {
prefixByte := make([]byte, 6) prefixByte := make([]byte, 6)
_, err := io.ReadFull(stream, prefixByte) _, err := io.ReadFull(stream, prefixByte)
if err != nil { if err != nil {
fmt.Println(err)
return return
} }
prefixLength, err := strconv.Atoi(string(prefixByte)) prefixLength, err := strconv.Atoi(string(prefixByte))
@ -166,15 +176,23 @@ func ProcessingContent(stream quic.Stream) {
//nothing //nothing
continue continue
} else if m.Type == types.PERSONDIRECTORY { } else if m.Type == types.PERSONDIRECTORY {
friend := model2.FriendModel{}
friend.Token = m.From
var list []model.Path var list []model.Path
rFriend := MyService.Friend().GetFriendById(friend)
if !reflect.DeepEqual(rFriend, model2.FriendModel{Token: m.From}) && !rFriend.Block {
if m.Data.(string) == "" || m.Data.(string) == "/" { if m.Data.(string) == "" || m.Data.(string) == "/" {
for _, v := range config.FileSettingInfo.ShareDir { for _, v := range config.FileSettingInfo.ShareDir {
tempList := MyService.ZiMa().GetDirPath(v) //tempList := MyService.ZiMa().GetDirPath(v)
list = append(list, tempList...) temp := MyService.ZiMa().GetDirPathOne(v)
list = append(list, temp)
} }
} else { } else {
list = MyService.ZiMa().GetDirPath(m.Data.(string)) list = MyService.ZiMa().GetDirPath(m.Data.(string))
} }
} else {
list = []model.Path{}
}
m.To = m.From m.To = m.From
m.Data = list m.Data = list
m.From = config.ServerInfo.Token m.From = config.ServerInfo.Token
@ -185,6 +203,7 @@ func ProcessingContent(stream quic.Stream) {
SendFileData(stream, m.Data.(string), m.From, m.UUId) SendFileData(stream, m.Data.(string), m.From, m.UUId)
break break
} else if m.Type == types.PERSONADDFRIEND { } else if m.Type == types.PERSONADDFRIEND {
fmt.Println("有用户来请求加好友", m)
friend := model2.FriendModel{} friend := model2.FriendModel{}
dataModelByte, _ := json.Marshal(m.Data) dataModelByte, _ := json.Marshal(m.Data)
err := json.Unmarshal(dataModelByte, &friend) err := json.Unmarshal(dataModelByte, &friend)
@ -196,7 +215,7 @@ func ProcessingContent(stream quic.Stream) {
mi := model2.FriendModel{} mi := model2.FriendModel{}
mi.Avatar = config.UserInfo.Avatar mi.Avatar = config.UserInfo.Avatar
mi.Profile = config.UserInfo.Description mi.Profile = config.UserInfo.Description
mi.Name = config.UserInfo.NickName mi.NickName = config.UserInfo.NickName
m.To = m.From m.To = m.From
m.Data = mi m.Data = mi
m.Type = types.PERSONADDFRIEND m.Type = types.PERSONADDFRIEND
@ -210,19 +229,34 @@ func ProcessingContent(stream quic.Stream) {
} else { } else {
delete(UDPAddressMap, m.From) delete(UDPAddressMap, m.From)
} }
mi := model2.FriendModel{} // mi := model2.FriendModel{}
mi.Avatar = config.UserInfo.Avatar // mi.Avatar = config.UserInfo.Avatar
mi.Profile = config.UserInfo.Description // mi.Profile = config.UserInfo.Description
mi.Name = config.UserInfo.NickName // mi.NickName = config.UserInfo.NickName
mi.Token = config.ServerInfo.Token // mi.Token = config.ServerInfo.Token
user := MyService.Casa().GetUserInfoByShareId(m.From)
friend := model2.FriendModel{}
friend.Token = m.From
friend.Avatar = user.Avatar
friend.Block = false
friend.NickName = user.NickName
friend.Profile = user.Avatar
friend.Version = user.Version
MyService.Friend().AddFriend(friend)
msg := model.MessageModel{} msg := model.MessageModel{}
msg.Type = types.PERSONADDFRIEND msg.Type = types.PERSONHELLO
msg.Data = mi msg.Data = ""
msg.To = m.From msg.To = m.From
msg.From = config.ServerInfo.Token msg.From = config.ServerInfo.Token
msg.UUId = m.UUId msg.UUId = m.UUId
Dial(msg, false) Dial(msg, false)
break
} else if m.Type == types.PERSONCANCEL {
CancelList[m.UUId] = "cancel"
break break
} else { } else {
//不应有不做返回的数据 //不应有不做返回的数据
@ -289,6 +323,9 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
bufferedReader := bufio.NewReader(f) bufferedReader := bufio.NewReader(f)
buf := make([]byte, blockSize) buf := make([]byte, blockSize)
defer stream.Close()
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
tran := model.TranFileModel{} tran := model.TranFileModel{}
@ -313,8 +350,11 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
prefixLength := file.PrefixLength(len(b)) prefixLength := file.PrefixLength(len(b))
dataLength := file.DataLength(len(buf[:n])) dataLength := file.DataLength(len(buf[:n]))
data := append(append(append(prefixLength, b...), dataLength...), buf[:n]...) data := append(append(append(prefixLength, b...), dataLength...), buf[:n]...)
stream.Write(data) if _, ok := CancelList[uuid]; ok {
} delete(CancelList, uuid)
defer stream.Close() return nil
}
stream.Write(data)
}
return nil return nil
} }

View file

@ -21,7 +21,6 @@ type Repository interface {
User() UserService User() UserService
Docker() DockerService Docker() DockerService
//Redis() RedisService //Redis() RedisService
ZeroTier() ZeroTierService
ZiMa() ZiMaService ZiMa() ZiMaService
Casa() CasaService Casa() CasaService
Disk() DiskService Disk() DiskService
@ -45,7 +44,6 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
user: NewUserService(), user: NewUserService(),
docker: NewDockerService(log), docker: NewDockerService(log),
//redis: NewRedisService(rp), //redis: NewRedisService(rp),
zerotier: NewZeroTierService(),
zima: NewZiMaService(), zima: NewZiMaService(),
casa: NewCasaService(), casa: NewCasaService(),
disk: NewDiskService(log, db), disk: NewDiskService(log, db),
@ -68,7 +66,6 @@ type store struct {
ddns DDNSService ddns DDNSService
user UserService user UserService
docker DockerService docker DockerService
zerotier ZeroTierService
zima ZiMaService zima ZiMaService
casa CasaService casa CasaService
disk DiskService disk DiskService
@ -123,9 +120,6 @@ func (c *store) Docker() DockerService {
return c.docker return c.docker
} }
func (c *store) ZeroTier() ZeroTierService {
return c.zerotier
}
func (c *store) ZiMa() ZiMaService { func (c *store) ZiMa() ZiMaService {
return c.zima return c.zima
} }

View file

@ -18,6 +18,8 @@ type SystemService interface {
UpdateAssist() UpdateAssist()
UpSystemPort(port string) UpSystemPort(port string)
GetTimeZone() string GetTimeZone() string
UpdateUSBAutoMount(state string)
ExecUSBAutoMountShell(state string)
} }
type systemService struct { type systemService struct {
log loger.OLog log loger.OLog
@ -37,6 +39,15 @@ func (s *systemService) GetTimeZone() string {
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetTimeZone") return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetTimeZone")
} }
func (s *systemService) ExecUSBAutoMountShell(state string) {
if state == "False" {
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;USB_Remove_File")
} else {
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;USB_Move_File")
}
}
func (s *systemService) GetSystemConfigDebug() []string { func (s *systemService) GetSystemConfigDebug() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo") return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
} }
@ -51,6 +62,11 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
} }
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
} }
func (s *systemService) UpdateUSBAutoMount(state string) {
config.ServerInfo.USBAutoMount = state
config.Cfg.Section("system").Key("USBAutoMount").SetValue(state)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
func (s *systemService) UpSystemPort(port string) { func (s *systemService) UpSystemPort(port string) {
if len(port) > 0 && port != config.ServerInfo.HttpPort { if len(port) > 0 && port != config.ServerInfo.HttpPort {
config.Cfg.Section("server").Key("HttpPort").SetValue(port) config.Cfg.Section("server").Key("HttpPort").SetValue(port)

View file

@ -10,6 +10,7 @@ import (
"io/ioutil" "io/ioutil"
"net" "net"
"os" "os"
path2 "path"
"strconv" "strconv"
"time" "time"
@ -32,29 +33,52 @@ func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
Message = make(chan model.MessageModel) Message = make(chan model.MessageModel)
_, port, err := net.SplitHostPort(UDPConn.LocalAddr().String())
if config.ServerInfo.UDPPort != port {
config.ServerInfo.UDPPort = port
config.Cfg.Section("server").Key("UDPPort").SetValue(port)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
p, err := strconv.Atoi(port)
srcAddr := &net.UDPAddr{ srcAddr := &net.UDPAddr{
IP: net.IPv4zero, Port: 9904} //注意端口必须固定 IP: net.IPv4zero, Port: p} //注意端口必须固定
addr := UDPAddressMap[msg.To] addr := UDPAddressMap[msg.To]
ticker := msg.To ticket := msg.To
if server { if server {
addr = config.ServerInfo.Handshake + ":9527" addr = config.ServerInfo.Handshake + ":9527"
ticker = "bench" ticket = "bench"
} }
dstAddr, err := net.ResolveUDPAddr("udp", addr) dstAddr, err := net.ResolveUDPAddr("udp", addr)
//DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6"如果laddr不是nil将使用它作为本地地址否则自动选择一个本地地址。 //DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6"如果laddr不是nil将使用它作为本地地址否则自动选择一个本地地址。
//(conn)UDPConn代表一个UDP网络连接实现了Conn和PacketConn接口 //(conn)UDPConn代表一个UDP网络连接实现了Conn和PacketConn接口
session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticker), quic_helper.GetQUICConfig()) session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
if err != nil { if err != nil {
go MyService.Casa().PushConnectionStatus(m.UUId, err.Error(), m.From, m.To, m.Type) if msg.Type == types.PERSONDOWNLOAD {
task := MyService.Download().GetDownloadById(msg.UUId)
task.Error = err.Error()
task.State = types.DOWNLOADERROR
MyService.Download().SetDownloadError(task)
}
if config.SystemConfigInfo.Analyse != "False" {
go MyService.Casa().PushConnectionStatus(msg.UUId, err.Error(), msg.From, msg.To, msg.Type)
}
return m, err return m, err
} }
stream, err := session.OpenStreamSync(ctx) stream, err := session.OpenStreamSync(ctx)
if err != nil { if err != nil {
go MyService.Casa().PushConnectionStatus(m.UUId, err.Error(), m.From, m.To, m.Type) if msg.Type == types.PERSONDOWNLOAD {
task := MyService.Download().GetDownloadById(msg.UUId)
task.Error = err.Error()
task.State = types.DOWNLOADERROR
MyService.Download().SetDownloadError(task)
}
if config.SystemConfigInfo.Analyse != "False" {
go MyService.Casa().PushConnectionStatus(msg.UUId, err.Error(), msg.From, msg.To, msg.Type)
}
session.CloseWithError(1, err.Error()) session.CloseWithError(1, err.Error())
return m, err return m, err
} }
@ -66,7 +90,9 @@ func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error)
go ReadContent(stream) go ReadContent(stream)
result := <-Message result := <-Message
stream.Close() stream.Close()
go MyService.Casa().PushConnectionStatus(m.UUId, "OK", m.From, m.To, m.Type) if config.SystemConfigInfo.Analyse != "False" {
go MyService.Casa().PushConnectionStatus(msg.UUId, "OK", msg.From, msg.To, msg.Type)
}
return result, nil return result, nil
} }
@ -88,8 +114,6 @@ func SendData(stream quic.Stream, m model.MessageModel) {
stream.Write(data) stream.Write(data)
} }
var Summary map[string]model.FileSummaryModel
//读取数据 //读取数据
func ReadContent(stream quic.Stream) { func ReadContent(stream quic.Stream) {
for { for {
@ -97,6 +121,12 @@ func ReadContent(stream quic.Stream) {
_, err := io.ReadFull(stream, prefixByte) _, err := io.ReadFull(stream, prefixByte)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
time.Sleep(time.Second * 1)
for k, v := range CancelList {
tempPath := config.AppInfo.RootPath + "/temp" + "/" + v
fmt.Println(file.RMDir(tempPath))
delete(CancelList, k)
}
break break
} }
prefixLength, err := strconv.Atoi(string(prefixByte)) prefixLength, err := strconv.Atoi(string(prefixByte))
@ -112,12 +142,14 @@ func ReadContent(stream quic.Stream) {
} }
m := model.MessageModel{} m := model.MessageModel{}
err = json.Unmarshal(messageByte, &m) err = json.Unmarshal(messageByte, &m)
fmt.Println("客户端", m)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
break break
} }
if m.Type == types.PERSONDOWNLOAD { if m.Type == types.PERSONDOWNLOAD {
dataModelByte, _ := json.Marshal(m.Data) dataModelByte, _ := json.Marshal(m.Data)
dataModel := model.TranFileModel{} dataModel := model.TranFileModel{}
err := json.Unmarshal(dataModelByte, &dataModel) err := json.Unmarshal(dataModelByte, &dataModel)
@ -149,31 +181,34 @@ func ReadContent(stream quic.Stream) {
fmt.Println("hash不匹配", hash, dataModel.Hash) fmt.Println("hash不匹配", hash, dataModel.Hash)
continue continue
} }
tempPath := config.AppInfo.RootPath + "/temp" + "/" + m.UUId tempPath := config.AppInfo.RootPath + "/temp" + "/" + m.UUId
file.IsNotExistMkDir(tempPath) file.IsNotExistMkDir(tempPath)
filepath := tempPath + "/" + strconv.Itoa(dataModel.Index) filepath := tempPath + "/" + strconv.Itoa(dataModel.Index)
tempFile, err := os.Stat(filepath) _, err = os.Stat(filepath)
if os.IsNotExist(err) || tempFile.Size() == 0 { if os.IsNotExist(err) {
err = ioutil.WriteFile(filepath, dataByte, 0644) err = ioutil.WriteFile(filepath, dataByte, 0644)
task := model2.PersionDownloadDBModel{} task := model2.PersonDownloadDBModel{}
task.UUID = m.UUId task.UUID = m.UUId
if err != nil {
task.Error = err.Error() task.Error = err.Error()
task.State = types.DOWNLOADERROR task.State = types.DOWNLOADERROR
MyService.Download().SetDownloadError(task) MyService.Download().SetDownloadError(task)
}
} else { } else {
if file.GetHashByPath(filepath) != dataModel.Hash { if file.GetHashByPath(filepath) != dataModel.Hash {
os.Remove(filepath) os.Remove(filepath)
err = ioutil.WriteFile(filepath, dataByte, 0644) err = ioutil.WriteFile(filepath, dataByte, 0644)
task := model2.PersionDownloadDBModel{} task := model2.PersonDownloadDBModel{}
task.UUID = m.UUId task.UUID = m.UUId
if err != nil {
task.Error = err.Error() task.Error = err.Error()
task.State = types.DOWNLOADERROR task.State = types.DOWNLOADERROR
MyService.Download().SetDownloadError(task) MyService.Download().SetDownloadError(task)
} }
} }
}
files, err := ioutil.ReadDir(tempPath) files, err := ioutil.ReadDir(tempPath)
if err != nil { if err != nil {
@ -181,21 +216,21 @@ func ReadContent(stream quic.Stream) {
continue continue
} }
if len(files) >= dataModel.Length { if len(files) >= dataModel.Length {
summary := Summary[m.UUId] summary := MyService.Download().GetDownloadById(m.UUId)
file.SpliceFiles(tempPath, config.FileSettingInfo.DownloadDir+"/"+summary.Name, dataModel.Length, 0) summary.State = types.DOWNLOADFINISH
if file.GetHashByPath(config.FileSettingInfo.DownloadDir+"/"+summary.Name) == summary.Hash { MyService.Download().EditDownloadState(summary)
fullPath := file.GetNoDuplicateFileName(path2.Join(summary.LocalPath, summary.Name))
file.SpliceFiles(tempPath, fullPath, dataModel.Length, 0)
if file.GetHashByPath(fullPath) == summary.Hash {
file.RMDir(tempPath) file.RMDir(tempPath)
task := model2.PersionDownloadDBModel{} summary.State = types.DOWNLOADFINISHED
task.UUID = m.UUId MyService.Download().EditDownloadState(summary)
task.State = types.DOWNLOADFINISH
MyService.Download().EditDownloadState(task)
delete(Summary, m.UUId)
} else { } else {
os.Remove(config.FileSettingInfo.DownloadDir + "/" + summary.Name) os.Remove(config.FileSettingInfo.DownloadDir + "/" + summary.Name)
task := model2.PersionDownloadDBModel{}
task.UUID = m.UUId summary.State = types.DOWNLOADERROR
task.State = types.DOWNLOADERROR summary.Error = "hash mismatch"
MyService.Download().EditDownloadState(task) MyService.Download().SetDownloadError(summary)
} }
break break
@ -205,42 +240,55 @@ func ReadContent(stream quic.Stream) {
dataModel := model.FileSummaryModel{} dataModel := model.FileSummaryModel{}
dataModelByte, _ := json.Marshal(m.Data) dataModelByte, _ := json.Marshal(m.Data)
err := json.Unmarshal(dataModelByte, &dataModel) err := json.Unmarshal(dataModelByte, &dataModel)
if err != nil {
fmt.Println(err) fmt.Println(err)
}
task := model2.PersionDownloadDBModel{} task := MyService.Download().GetDownloadById(m.UUId)
task.UUID = m.UUId fullPath := path2.Join(task.LocalPath, task.Name)
task.Name = dataModel.Name
task.Length = dataModel.Length
task.Size = dataModel.Size
task.State = types.DOWNLOADING task.State = types.DOWNLOADING
task.BlockSize = dataModel.BlockSize
task.Hash = dataModel.Hash
task.Type = 0
task.From = m.From
if len(dataModel.Message) > 0 { if len(dataModel.Message) > 0 {
task.State = types.DOWNLOADERROR task.State = types.DOWNLOADERROR
task.Error = dataModel.Message task.Error = dataModel.Message
} }
if file.Exists(fullPath) && file.GetHashByPath(fullPath) == dataModel.Hash {
task.State = types.DOWNLOADFINISHED
go func(from, uuid string) {
m := model.MessageModel{}
m.Data = ""
m.From = config.ServerInfo.Token
m.To = from
m.Type = types.PERSONCANCEL
m.UUId = uuid
CancelList[uuid] = uuid
Dial(m, false)
}(task.From, task.UUID)
}
task.UUID = m.UUId
task.Name = dataModel.Name
task.Length = dataModel.Length
task.Size = dataModel.Size
task.BlockSize = dataModel.BlockSize
task.Hash = dataModel.Hash
task.Type = 0
task.From = m.From
MyService.Download().SaveDownload(task) MyService.Download().SaveDownload(task)
Summary[m.UUId] = dataModel
} else if m.Type == types.PERSONCONNECTION { } else if m.Type == types.PERSONCONNECTION {
if len(m.Data.(string)) > 0 { if len(m.Data.(string)) > 0 {
UDPAddressMap[m.From] = m.Data.(string) UDPAddressMap[m.From] = m.Data.(string)
} else { } else {
delete(UDPAddressMap, m.From) delete(UDPAddressMap, m.From)
} }
mi := model2.FriendModel{} // mi := model2.FriendModel{}
mi.Avatar = config.UserInfo.Avatar // mi.Avatar = config.UserInfo.Avatar
mi.Profile = config.UserInfo.Description // mi.Profile = config.UserInfo.Description
mi.Name = config.UserInfo.NickName // mi.NickName = config.UserInfo.NickName
mi.Token = config.ServerInfo.Token // mi.Token = config.ServerInfo.Token
msg := model.MessageModel{} msg := model.MessageModel{}
msg.Type = types.PERSONADDFRIEND msg.Type = types.PERSONHELLO
msg.Data = mi msg.Data = ""
msg.To = m.From msg.To = m.From
msg.From = config.ServerInfo.Token msg.From = config.ServerInfo.Token
msg.UUId = m.UUId msg.UUId = m.UUId
@ -248,10 +296,21 @@ func ReadContent(stream quic.Stream) {
Message <- m Message <- m
break break
} else if m.Type == "get_ip" { } else if m.Type == "get_ip" {
notify := model2.AppNotify{}
notify.CustomId = m.From
if len(m.Data.(string)) == 0 { if len(m.Data.(string)) == 0 {
if _, ok := UDPAddressMap[m.From]; ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
go MyService.Notify().SendText(notify)
}
delete(UDPAddressMap, m.From) delete(UDPAddressMap, m.From)
Message <- m
break break
} }
if _, ok := UDPAddressMap[m.From]; !ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LIVE
go MyService.Notify().SendText(notify)
}
UDPAddressMap[m.From] = m.Data.(string) UDPAddressMap[m.From] = m.Data.(string)
Message <- m Message <- m
break break
@ -264,7 +323,7 @@ func ReadContent(stream quic.Stream) {
func SendIPToServer() { func SendIPToServer() {
msg := model.MessageModel{} msg := model.MessageModel{}
msg.Type = "hello" msg.Type = types.PERSONHELLO
msg.Data = "" msg.Data = ""
msg.From = config.ServerInfo.Token msg.From = config.ServerInfo.Token
msg.To = config.ServerInfo.Token msg.To = config.ServerInfo.Token
@ -282,9 +341,10 @@ func LoopFriend() {
msg.From = config.ServerInfo.Token msg.From = config.ServerInfo.Token
msg.To = list[i].Token msg.To = list[i].Token
msg.UUId = uuid.NewV4().String() msg.UUId = uuid.NewV4().String()
Dial(msg, true) Dial(msg, true)
msg.Type = "hello" msg.Type = types.PERSONHELLO
msg.Data = "" msg.Data = ""
msg.From = config.ServerInfo.Token msg.From = config.ServerInfo.Token
msg.To = list[i].Token msg.To = list[i].Token
@ -292,6 +352,19 @@ func LoopFriend() {
if _, ok := UDPAddressMap[list[i].Token]; ok { if _, ok := UDPAddressMap[list[i].Token]; ok {
go Dial(msg, false) go Dial(msg, false)
} }
go func(shareId string) {
user := MyService.Casa().GetUserInfoByShareId(shareId)
m := model2.FriendModel{}
m.Token = shareId
friend := MyService.Friend().GetFriendById(m)
if friend.Version != user.Version {
friend.Avatar = user.Avatar
friend.NickName = user.NickName
friend.Profile = user.Desc
friend.Version = user.Version
MyService.Friend().UpdateOrCreate(friend)
}
}(list[i].Token)
} }
} }

View file

@ -1,353 +0,0 @@
package service
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"math/rand"
"net/http"
"strconv"
"strings"
"time"
"unicode"
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/IceWhaleTech/CasaOS/pkg/zerotier"
"github.com/PuerkitoBio/goquery"
"github.com/tidwall/gjson"
)
type ZeroTierService interface {
GetToken(username, pwd string) string
ZeroTierRegister(email, lastName, firstName, password string) string
ZeroTierNetworkList(token string) (interface{}, []string)
ZeroTierJoinNetwork(networkId string)
ZeroTierLeaveNetwork(networkId string)
ZeroTierGetInfo(token, id string) (interface{}, []string)
ZeroTierGetStatus(token string) interface{}
EditNetwork(token string, data string, id string) interface{}
CreateNetwork(token string) interface{}
MemberList(token string, id string) interface{}
EditNetworkMember(token string, data string, id, mId string) interface{}
DeleteMember(token string, id, mId string) interface{}
DeleteNetwork(token, id string) interface{}
GetJoinNetworks() string
NetworkIdFilter(letter rune) bool
}
type zerotierStruct struct {
}
var client http.Client
func (c *zerotierStruct) ZeroTierJoinNetwork(networkId string) {
command2.OnlyExec(`zerotier-cli join ` + networkId)
}
func (c *zerotierStruct) ZeroTierLeaveNetwork(networkId string) {
command2.OnlyExec(`zerotier-cli leave ` + networkId)
}
//登录并获取token
func (c *zerotierStruct) GetToken(username, pwd string) string {
if len(config.ZeroTierInfo.Token) > 0 {
return config.ZeroTierInfo.Token
} else {
return LoginGetToken(username, pwd)
}
}
func (c *zerotierStruct) ZeroTierRegister(email, lastName, firstName, password string) string {
url := "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/registrations?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=state"
action, cookies, _ := ZeroTierGet(url, nil, 4)
var buff bytes.Buffer
buff.WriteString("email=")
buff.WriteString(email)
buff.WriteString("&password=")
buff.WriteString(password)
buff.WriteString("&password-confirm=")
buff.WriteString(password)
buff.WriteString("&user.attributes.marketingOptIn=true")
buff.WriteString("&firstName")
buff.WriteString(firstName)
buff.WriteString("&lastName")
buff.WriteString(lastName)
action, errInfo, _ := ZeroTierPost(buff, action, cookies, false)
if len(errInfo) > 0 {
return errInfo
}
action, _, _ = ZeroTierGet(action, cookies, 5)
return ""
}
//固定请求head
func GetHead() map[string]string {
var head = make(map[string]string, 4)
head["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
head["Accept-Language"] = "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"
head["Connection"] = "keep-alive"
head["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
return head
}
//登录并获取token会出现账号密码错误和邮箱未验证情况目前未出现其他情况
func LoginGetToken(username, pwd string) string {
//拿到登录的action
var loginUrl = "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/auth?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=states"
action, cookies, _ := ZeroTierGet(loginUrl, nil, 1)
if len(action) == 0 {
//没有拿到action页面结构变了
return ""
}
//登录
var str bytes.Buffer
str.WriteString("username=")
str.WriteString(username)
str.WriteString("&password=")
str.WriteString(pwd)
str.WriteString("&credentialId=&login=Log+In")
url, logingErrInfo, _ := ZeroTierPost(str, action, cookies, true)
action, cookies, isLoginOk := ZeroTierGet(url, cookies, 2)
if isLoginOk {
//登录成功可以继续调用api
randomTokenUrl := "https://my.zerotier.com/api/randomToken"
json, _, _ := ZeroTierGet(randomTokenUrl, cookies, 3)
//获取一个随机token
token := gjson.Get(json, "token")
userInfoUrl := "https://my.zerotier.com/api/status"
json, _, _ = ZeroTierGet(userInfoUrl, cookies, 3)
//拿到用户id
userId := gjson.Get(json, "user.id")
//设置新token
addTokenUrl := "https://my.zerotier.com/api/user/" + userId.String() + "/token"
data := make(map[string]string)
rand.Seed(time.Now().UnixNano())
data["tokenName"] = "oasis-token-" + strconv.Itoa(rand.Intn(1000))
data["token"] = token.String()
head := make(map[string]string)
head["Content-Type"] = "application/json"
_, statusCode := httper2.ZeroTierPost(addTokenUrl, data, head, cookies)
if statusCode == http.StatusOK {
config.Cfg.Section("zerotier").Key("Token").SetValue(token.String())
config.Cfg.SaveTo("conf/conf.ini")
config.ZeroTierInfo.Token = token.String()
}
} else {
//登录错误信息
if len(logingErrInfo) > 0 {
return logingErrInfo
} else {
//验证邮箱
action, _, _ = ZeroTierGet(url, cookies, 5)
return "You need to verify your email address to activate your account."
}
}
return ""
}
// t 1:获取action2登录成功后拿session可能需要验证有了或登录失败 3:随机生成token 4:注册页面拿action 5:注册成功后拿验证邮箱的地址
func ZeroTierGet(url string, cookies []*http.Cookie, t uint8) (action string, c []*http.Cookie, isExistSession bool) {
isExistSession = false
action = ""
c = []*http.Cookie{}
request, _ := http.NewRequest(http.MethodGet, url, nil)
for k, v := range GetHead() {
request.Header.Add(k, v)
}
for _, cookie := range cookies {
request.AddCookie(cookie)
}
resp, err := client.Do(request)
if err != nil {
return
}
defer resp.Body.Close()
c = resp.Cookies()
if t == 1 {
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return
}
action, _ = doc.Find("#kc-form-login").Attr("action")
return
} else if t == 2 {
for _, cookie := range resp.Cookies() {
if cookie.Name == "pgx-session" {
isExistSession = true
break
}
}
//判断是否登录成功,如果需要验证邮箱,则返回验证邮箱的地址。
if resp.StatusCode == http.StatusFound && len(resp.Header.Get("Location")) > 0 {
action = resp.Header.Get("Location")
}
return
} else if t == 3 {
//返回获取到的字符串
byteArr, _ := ioutil.ReadAll(resp.Body)
action = string(byteArr)
} else if t == 4 {
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return
}
action, _ = doc.Find("#kc-register-form").Attr("action")
return
} else if t == 5 {
doc, _ := goquery.NewDocumentFromReader(resp.Body)
fmt.Println(doc.Html())
action, _ = doc.Find("#kc-info-wrapper a").Attr("href")
return
}
return
}
//模拟提交表单
func ZeroTierPost(str bytes.Buffer, action string, cookies []*http.Cookie, isLogin bool) (url, errInfo string, err error) {
req, err := http.NewRequest(http.MethodPost, action, strings.NewReader(str.String()))
if err != nil {
return "", "", errors.New("newrequest error")
}
for k, v := range GetHead() {
req.Header.Set(k, v)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
for _, cookie := range cookies {
req.AddCookie(cookie)
}
res, err := client.Do(req)
defer res.Body.Close()
if err != nil {
return "", "", errors.New("request error")
}
if !isLogin {
//注册成功
if res.StatusCode == http.StatusFound && len(res.Header.Get("Location")) > 0 {
return res.Header.Get("Location"), "", nil
} else {
register, _ := goquery.NewDocumentFromReader(res.Body)
firstErr := strings.TrimSpace(register.Find("#input-error-firstname").Text())
lastErr := strings.TrimSpace(register.Find("#input-error-lastname").Text())
emailErr := strings.TrimSpace(register.Find("#input-error-email").Text())
pwdErr := strings.TrimSpace(register.Find("#input-error-password").Text())
var errD strings.Builder
if len(firstErr) > 0 {
errD.WriteString(firstErr + ",")
}
if len(lastErr) > 0 {
errD.WriteString(lastErr + ",")
}
if len(emailErr) > 0 {
errD.WriteString(emailErr + ",")
}
if len(pwdErr) > 0 {
errD.WriteString(pwdErr + ",")
}
return "", errD.String(), nil
}
} else {
if res.StatusCode == http.StatusFound && len(res.Header.Get("Location")) > 0 {
return res.Header.Get("Location"), "", nil
}
doc, err := goquery.NewDocumentFromReader(res.Body)
if err != nil {
return "", "", errors.New("request error")
}
errDesc := doc.Find("#input-error").Text()
if len(errDesc) > 0 {
return "", strings.TrimSpace(errDesc), nil
}
}
return "", "", nil
}
//获取zerotile网络列表和本地用户已加入的网络
func (c *zerotierStruct) ZeroTierNetworkList(token string) (interface{}, []string) {
url := "https://my.zerotier.com/api/network"
return zerotier.GetData(url, token), command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
}
// get network info
func (c *zerotierStruct) ZeroTierGetInfo(token, id string) (interface{}, []string) {
url := "https://my.zerotier.com/api/network/" + id
info := zerotier.GetData(url, token)
return info, command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
}
//get status
func (c *zerotierStruct) ZeroTierGetStatus(token string) interface{} {
url := "https://my.zerotier.com/api/v1/status"
info := zerotier.GetData(url, token)
return info
}
func (c *zerotierStruct) EditNetwork(token string, data string, id string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id
info := zerotier.PostData(url, token, data)
return info
}
func (c *zerotierStruct) EditNetworkMember(token string, data string, id, mId string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
info := zerotier.PostData(url, token, data)
return info
}
func (c *zerotierStruct) MemberList(token string, id string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id + "/member"
info := zerotier.GetData(url, token)
return info
}
func (c *zerotierStruct) DeleteMember(token string, id, mId string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
info := zerotier.DeleteMember(url, token)
return info
}
func (c *zerotierStruct) DeleteNetwork(token, id string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id
info := zerotier.DeleteMember(url, token)
return info
}
func (c *zerotierStruct) CreateNetwork(token string) interface{} {
url := "https://my.zerotier.com/api/v1/network"
info := zerotier.PostData(url, token, "{}")
return info
}
func (c *zerotierStruct) GetJoinNetworks() string {
json := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetLocalJoinNetworks")
return json
}
func (c *zerotierStruct) NetworkIdFilter(letter rune) bool {
if unicode.IsNumber(letter) || unicode.IsLetter(letter) {
return true
} else {
return false
}
}
func NewZeroTierService() ZeroTierService {
//初始化client
client = http.Client{Timeout: 30 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse //禁止重定向
},
}
return &zerotierStruct{}
}

View file

@ -4,10 +4,12 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unsafe"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
@ -32,12 +34,15 @@ type ZiMaService interface {
GetNetState(name string) string GetNetState(name string) string
GetSysInfo() host.InfoStat GetSysInfo() host.InfoStat
GetDirPath(path string) []model.Path GetDirPath(path string) []model.Path
GetDirPathOne(path string) (m model.Path)
MkdirAll(path string) (int, error) MkdirAll(path string) (int, error)
CreateFile(path string) (int, error) CreateFile(path string) (int, error)
RenameFile(oldF, newF string) (int, error) RenameFile(oldF, newF string) (int, error)
GetCpuInfo() []cpu.InfoStat GetCpuInfo() []cpu.InfoStat
} }
var NetArray [][]model.IOCountersStat
type zima struct { type zima struct {
} }
@ -84,10 +89,19 @@ func (c *zima) GetDirPath(path string) []model.Path {
ls, _ := ioutil.ReadDir(path) ls, _ := ioutil.ReadDir(path)
dirs := []model.Path{} dirs := []model.Path{}
if len(path) > 0 { if len(path) > 0 {
for _, l := range ls { for _, l := range ls {
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir(), Date: l.ModTime(), Size: l.Size()}) filePath := filepath.Join(path, l.Name())
link, err := filepath.EvalSymlinks(filePath)
if err != nil {
link = filePath
}
temp := model.Path{Name: l.Name(), Path: filePath, IsDir: l.IsDir(), Date: l.ModTime(), Size: l.Size()}
if filePath != link {
file, _ := os.Stat(link)
temp.IsDir = file.IsDir()
}
dirs = append(dirs, temp)
} }
} else { } else {
dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()}) dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()})
@ -95,6 +109,21 @@ func (c *zima) GetDirPath(path string) []model.Path {
return dirs return dirs
} }
func (c *zima) GetDirPathOne(path string) (m model.Path) {
f, err := os.Stat(path)
if err != nil {
return
}
m.IsDir = f.IsDir()
m.Name = f.Name()
m.Path = path
m.Size = f.Size()
m.Date = f.ModTime()
return
}
//获取系统信息 //获取系统信息
func (c *zima) GetSysInfo() host.InfoStat { func (c *zima) GetSysInfo() host.InfoStat {
info, _ := host.Info() info, _ := host.Info()
@ -174,3 +203,41 @@ func (c *zima) RenameFile(oldF, newF string) (int, error) {
func NewZiMaService() ZiMaService { func NewZiMaService() ZiMaService {
return &zima{} return &zima{}
} }
func LoopNet() {
netList := MyService.ZiMa().GetNetInfo()
nets := MyService.ZiMa().GetNet(true)
num := 0
for i := 0; i < len(netList); i++ {
for _, netCardName := range nets {
if netList[i].Name == netCardName {
var netArray []model.IOCountersStat
if len(NetArray) < (num + 1) {
netArray = []model.IOCountersStat{}
} else {
netArray = NetArray[num]
}
item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
item.Time = time.Now().Unix()
if len(netArray) >= 60 {
netArray = netArray[1:]
}
netArray = append(netArray, item)
if len(NetArray) < (num + 1) {
NetArray = append(NetArray, []model.IOCountersStat{})
}
NetArray[num] = netArray
num++
break
}
}
}
}

View file

@ -1,13 +1,6 @@
#!/bin/bash #!/bin/bash
#add in v0.2.3
version_0_2_3() {
((EUID)) && sudo_cmd="sudo"
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
}
# add in v0.2.5 # add in v0.2.5
@ -16,7 +9,9 @@ readonly CASA_DEPANDS="curl smartmontools parted fdisk ntfs-3g"
version_0_2_5() { version_0_2_5() {
install_depends "$CASA_DEPANDS" install_depends "$CASA_DEPANDS"
} }
version_0_2_11() {
sysctl -w net.core.rmem_max=2500000
}
#Install Depends #Install Depends
install_depends() { install_depends() {
@ -35,6 +30,6 @@ install_depends() {
fi fi
} }
version_0_2_3
version_0_2_5 version_0_2_5
version_0_2_11

View file

@ -245,9 +245,13 @@ do_umount() {
if [[ -z ${MOUNT_POINT} ]]; then if [[ -z ${MOUNT_POINT} ]]; then
${log} "Warning: ${DEVICE} is not mounted" ${log} "Warning: ${DEVICE} is not mounted"
else else
/bin/kill -9 $(lsof ${MOUNT_POINT})
umount -l ${DEVICE} umount -l ${DEVICE}
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}" ${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
/bin/rmdir "${MOUNT_POINT}" if [ "`ls -A ${MOUNT_POINT}`" = "" ]; then
/bin/rm -fr "${MOUNT_POINT}"
fi
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
fi fi
@ -325,3 +329,16 @@ TarFolder() {
#查看固定文件夹大小 #查看固定文件夹大小
du -sh /DATA du -sh /DATA
} }
USB_Move_File() {
((EUID)) && sudo_cmd="sudo"
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
}
USB_Remove_File() {
((EUID)) && sudo_cmd="sudo"
$sudo_cmd rm -fr /etc/udev/rules.d/11-usb-mount.rules
$sudo_cmd rm -fr /etc/systemd/system/usb-mount@.service
}

View file

@ -12,7 +12,7 @@ DEVBASE=$2
DEVICE="/dev/${DEVBASE}" DEVICE="/dev/${DEVBASE}"
# See if this drive is already mounted, and if so where # See if this drive is already mounted, and if so where
MOUNT_POINT=$(lsblk -o name,mountpoint | grep ${DEVICE} | awk '{print $2}') MOUNT_POINT=$(lsblk -l -p -o name,mountpoint | grep ${DEVICE} | awk '{print $2}')
do_mount() { do_mount() {
@ -112,9 +112,12 @@ do_umount() {
if [[ -z ${MOUNT_POINT} ]]; then if [[ -z ${MOUNT_POINT} ]]; then
${log} "Warning: ${DEVICE} is not mounted" ${log} "Warning: ${DEVICE} is not mounted"
else else
#/bin/kill -9 $(lsof ${MOUNT_POINT})
umount -l ${DEVICE} umount -l ${DEVICE}
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}" ${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
/bin/rmdir "${MOUNT_POINT}" if [ "`ls -A ${MOUNT_POINT}`" = "" ]; then
/bin/rm -fr "${MOUNT_POINT}"
fi
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
fi fi

View file

@ -10,6 +10,8 @@ const (
NOTIFY_TYPE_NEED_CONFIRM NOTIFY_TYPE_NEED_CONFIRM
NOTIFY_TYPE_ERROR NOTIFY_TYPE_ERROR
NOTIFY_TYPE_INSTALL_LOG NOTIFY_TYPE_INSTALL_LOG
NOTIFY_TYPE_PERSION_FIRNED_LEAVE
NOTIFY_TYPE_PERSION_FIRNED_LIVE
) )
const ( const (

View file

@ -6,3 +6,4 @@ const PERSONSUMMARY = "summary"
const PERSONCONNECTION = "connection" const PERSONCONNECTION = "connection"
const PERSONDIRECTORY = "directory" const PERSONDIRECTORY = "directory"
const PERSONHELLO = "hello" const PERSONHELLO = "hello"
const PERSONCANCEL = "cancel" // Cancel Download

View file

@ -6,4 +6,5 @@ const (
DOWNLOADPAUSE DOWNLOADPAUSE
DOWNLOADFINISH DOWNLOADFINISH
DOWNLOADERROR DOWNLOADERROR
DOWNLOADFINISHED
) )

View file

@ -1,5 +1,5 @@
package types package types
const CURRENTVERSION = "0.2.10" const CURRENTVERSION = "0.3.0"
const BODY = "<li>Added CasaOS own file manager</li><li>Fixed the problem of failed to create storage space</li>" const BODY = "<li>Add CasaConnect function, now you can share private files peer-to-peer with your friends.</li><li>Add a widget for network traffic monitoring</li><li>Updated the initial directory of Files to the Root directory</li><li>Fix the application ipv6 opening problem</li>"

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="linearGradient1911" x1="25.085" x2="25.085" y1="24.031" y2="26.412" gradientTransform="translate(-35.822,-21.385)" gradientUnits="userSpaceOnUse">
<stop stop-color="#fcbc19" stop-opacity=".99608" offset="0"/>
<stop stop-color="#f4b61f" offset="1"/>
</linearGradient>
<linearGradient id="linearGradient4625" x1=".52918" x2="16.404" y1="5.0665" y2="5.0665" gradientTransform="translate(-17.925)" gradientUnits="userSpaceOnUse">
<stop stop-color="#b78815" offset="0"/>
<stop stop-color="#e2b24b" stop-opacity="0" offset="1"/>
</linearGradient>
<linearGradient id="linearGradient1951" x1="100" x2="133.19" y1="17.453" y2="51.606" gradientTransform="matrix(.26458 0 0 .26458 -38.033 -.13539)" gradientUnits="userSpaceOnUse">
<stop stop-color="#fce798" offset="0"/>
<stop stop-color="#ffc937" offset="1"/>
</linearGradient>
<linearGradient id="linearGradient11110" x1=".52917" x2="16.404" y1="5.3815" y2="5.3815" gradientTransform="translate(-17.925)" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff" offset="0"/>
<stop stop-color="#fff" stop-opacity="0" offset="1"/>
</linearGradient>
<linearGradient id="linearGradient1119" x1="8.4665" x2="8.4665" y1="6.0853" y2="9.4879" gradientUnits="userSpaceOnUse">
<stop stop-color="#fddb7a" offset="0"/>
<stop stop-color="#ffd970" offset="1"/>
</linearGradient>
<linearGradient id="linearGradient1284" x1="8.4665" x2="8.4665" y1="10.26" y2="13.229" gradientUnits="userSpaceOnUse">
<stop stop-color="#ffd96e" offset="0"/>
<stop stop-color="#ffd561" offset="1"/>
</linearGradient>
<linearGradient id="linearGradient1272" x1="-3.9033" x2="-3.9033" y1="7.7839" y2="15.613" gradientTransform="translate(12.362 -2.1249)" gradientUnits="userSpaceOnUse">
<stop stop-color="#c68d00" offset="0"/>
<stop stop-color="#a67100" offset="1"/>
</linearGradient>
</defs>
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="translate(17.925 4.2e-5)">
<path d="m-16.728 2.2489c-0.3653 0-0.66145 0.32575-0.66145 0.72759v2.9636c-0.0026 0.02629-0.0072 0.052-0.0072 0.07906v7.9373c0 0.40184 0.29614 0.72759 0.66144 0.72759h14.552c0.36531 0 0.66144-0.32575 0.66144-0.72759v-9.393c0-0.40184-0.29614-0.72759-0.66144-0.72759v5.16e-4h-8.1993l-0.89864-1.1095s-0.36607-0.478-1.0583-0.478h-1.3229z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="url(#linearGradient1911)" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stop-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;isolation:auto;mix-blend-mode:normal;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
<path d="m-9.5646 3.8364c-0.11312 0.0018-0.30848-0.01542-0.51986 0.09508-0.73647 0.37946-0.77226 0.59366-1.557 0.71415h-4.9608c-0.21986 0-0.41824 0.08855-0.56171 0.23202-0.13937 0.13936-0.22041 0.33333-0.2253 0.54569v0.2775c0.0049-0.21236 0.08593-0.40633 0.2253-0.54569 0.14347-0.14347 0.34185-0.23202 0.56171-0.23202h4.9608c0.78472-0.1205 0.82051-0.33469 1.557-0.71415 0.21138-0.1105 0.40673-0.09328 0.51986-0.09508h7.3828c0.18216 3.65e-4 0.3472 0.08101 0.46663 0.21239 0.1197 0.13167 0.19378 0.31377 0.19378 0.51469v-0.2775c0-0.20092-0.07408-0.38302-0.19378-0.51469-0.11943-0.13137-0.28447-0.21202-0.46663-0.21239h-1.1652zm-7.8247 2.1037c-0.0026 0.02629-0.0067 0.05201-0.0067 0.07906v0.2775c0-0.02705 0.0041-0.05277 0.0067-0.07906z" fill="url(#linearGradient4625)" opacity=".001" stroke-width=".26458"/>
<path d="m-17.396 13.674v0.28215c0 0.20092 0.07357 0.3825 0.19327 0.51417s0.28553 0.21342 0.46818 0.21342h14.552c0.18265 0 0.34796-0.08175 0.46766-0.21342s0.19378-0.31325 0.19378-0.51417v-0.28215c0 0.20092-0.07409 0.3825-0.19378 0.51417-0.1197 0.13167-0.28501 0.21342-0.46766 0.21342h-14.552c-0.18265 0-0.34848-0.08176-0.46818-0.21342s-0.19327-0.31325-0.19327-0.51417z" fill="#e4a729" fill-opacity=".99608" stroke-width=".26458"/>
<path d="m-10.383 4.0979s-0.35919 0.47868-1.1575 0.79218c-0.03271 0.00587-0.06509 0.011575-0.10077 0.017052h-4.9608c-0.21986 0-0.41824 0.088552-0.56171 0.23202-0.13937 0.13936-0.22042 0.33333-0.2253 0.54569v0.51675c-0.0026 0.02629-0.0067 0.05201-0.0067 0.07906v7.3953c0 0.20092 0.07357 0.3825 0.19327 0.51417s0.28553 0.21342 0.46818 0.21342h14.552c0.18265 0 0.34796-0.08175 0.46766-0.21342s0.19378-0.31325 0.19378-0.51417v-8.851c0-0.20092-0.07408-0.38302-0.19378-0.51469-0.11945-0.13137-0.28449-0.21202-0.46665-0.21239h-7.4821z" fill="url(#linearGradient1951)"/>
<path d="m-10.383 4.0979s-0.35919 0.47868-1.1575 0.79218c-0.03271 0.00587-0.06509 0.011575-0.10077 0.017052h-4.9608c-0.21986 0-0.41824 0.088552-0.56171 0.23202-0.13937 0.13936-0.22041 0.33333-0.2253 0.54569v0.38446c0.0049-0.21236 0.08593-0.40633 0.2253-0.54569 0.14347-0.14347 0.34185-0.23202 0.56171-0.23202h4.9608c0.03568-0.00548 0.06806-0.011184 0.10077-0.017052 0.75911-0.26303 1.2883-0.79218 1.2883-0.79218h8.0707c0.18216 3.704e-4 0.34718 0.081016 0.46663 0.21239 0.1197 0.13167 0.19378 0.31377 0.19378 0.51469v-0.38446c0-0.20092-0.07408-0.38302-0.19378-0.51469-0.11945-0.13137-0.28447-0.21202-0.46663-0.21239h-7.4821zm-7.0062 2.1037c-0.0026 0.02629-0.0067 0.05201-0.0067 0.07906v0.38446c0-0.02705 0.0041-0.05277 0.0067-0.07906z" fill="url(#linearGradient11110)" opacity=".3"/>
</g>
<circle cx="8.4665" cy="9.525" r="3.9687" fill="url(#linearGradient1272)" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1726"/>
<g transform="matrix(.77756 0 0 .77756 10.567 2.0159)">
<g transform="matrix(1.0741 0 0 1.0741 -11.796 -.7153)">
<circle cx="8.4665" cy="7.8051" r="1.7198" fill="url(#linearGradient1119)" stroke-linecap="round" stroke-linejoin="round" stroke-width=".34395" style="paint-order:stroke fill markers"/>
<path d="m5.2916 11.064 5.4e-6 -0.14432c0-0.43295 0.43294-0.72158 0.72157-0.72158h4.9067c0.28863 0 0.72158 0.28863 0.72158 0.72158v0.14432c0 1.3096-1.416 2.1647-3.1749 2.1647-1.7589 0-3.1749-0.85514-3.1749-2.1647z" fill="url(#linearGradient1284)" stroke-width=".14049"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

View file

@ -20,7 +20,7 @@
<title> <title>
CasaOS CasaOS
</title> </title>
<link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/5.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head> <link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/5.js" rel="prefetch"><link href="/ui/js/6.js" rel="prefetch"><link href="/ui/js/7.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head>
<body> <body>
<noscript> <noscript>

View file

@ -1,26 +1,26 @@
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{ (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{
/***/ "./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/defineProperty.js": /***/ "./node_modules/@babel/runtime/helpers/esm/defineProperty.js":
/*!******************************************************************************************************!*\ /*!*******************************************************************!*\
!*** ./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/defineProperty.js ***! !*** ./node_modules/@babel/runtime/helpers/esm/defineProperty.js ***!
\******************************************************************************************************/ \*******************************************************************/
/*! exports provided: default */ /*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return _defineProperty; });\nfunction _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\n//# sourceURL=webpack:///./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/defineProperty.js?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return _defineProperty; });\nfunction _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\n//# sourceURL=webpack:///./node_modules/@babel/runtime/helpers/esm/defineProperty.js?");
/***/ }), /***/ }),
/***/ "./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/objectSpread2.js": /***/ "./node_modules/@babel/runtime/helpers/esm/objectSpread2.js":
/*!*****************************************************************************************************!*\ /*!******************************************************************!*\
!*** ./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/objectSpread2.js ***! !*** ./node_modules/@babel/runtime/helpers/esm/objectSpread2.js ***!
\*****************************************************************************************************/ \******************************************************************/
/*! exports provided: default */ /*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return _objectSpread2; });\n/* harmony import */ var core_js_modules_es_object_keys_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.keys.js */ \"./node_modules/core-js/modules/es.object.keys.js\");\n/* harmony import */ var core_js_modules_es_object_keys_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_keys_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_symbol_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.symbol.js */ \"./node_modules/core-js/modules/es.symbol.js\");\n/* harmony import */ var core_js_modules_es_symbol_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_symbol_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_array_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.array.filter.js */ \"./node_modules/core-js/modules/es.array.filter.js\");\n/* harmony import */ var core_js_modules_es_array_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptor_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.object.get-own-property-descriptor.js */ \"./node_modules/core-js/modules/es.object.get-own-property-descriptor.js\");\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptor_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_get_own_property_descriptor_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_web_dom_collections_for_each_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/web.dom-collections.for-each.js */ \"./node_modules/core-js/modules/web.dom-collections.for-each.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_for_each_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_for_each_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptors_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.object.get-own-property-descriptors.js */ \"./node_modules/core-js/modules/es.object.get-own-property-descriptors.js\");\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptors_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_get_own_property_descriptors_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _defineProperty_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./defineProperty.js */ \"./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/defineProperty.js\");\n\n\n\n\n\n\n\n\nfunction ownKeys(object, enumerableOnly) {\n var keys = Object.keys(object);\n\n if (Object.getOwnPropertySymbols) {\n var symbols = Object.getOwnPropertySymbols(object);\n\n if (enumerableOnly) {\n symbols = symbols.filter(function (sym) {\n return Object.getOwnPropertyDescriptor(object, sym).enumerable;\n });\n }\n\n keys.push.apply(keys, symbols);\n }\n\n return keys;\n}\n\nfunction _objectSpread2(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? arguments[i] : {};\n\n if (i % 2) {\n ownKeys(Object(source), true).forEach(function (key) {\n Object(_defineProperty_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"])(target, key, source[key]);\n });\n } else if (Object.getOwnPropertyDescriptors) {\n Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));\n } else {\n ownKeys(Object(source)).forEach(function (key) {\n Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));\n });\n }\n }\n\n return target;\n}\n\n//# sourceURL=webpack:///./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/objectSpread2.js?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return _objectSpread2; });\n/* harmony import */ var core_js_modules_es_object_keys_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.keys.js */ \"./node_modules/core-js/modules/es.object.keys.js\");\n/* harmony import */ var core_js_modules_es_object_keys_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_keys_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_symbol_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.symbol.js */ \"./node_modules/core-js/modules/es.symbol.js\");\n/* harmony import */ var core_js_modules_es_symbol_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_symbol_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_array_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.array.filter.js */ \"./node_modules/core-js/modules/es.array.filter.js\");\n/* harmony import */ var core_js_modules_es_array_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptor_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.object.get-own-property-descriptor.js */ \"./node_modules/core-js/modules/es.object.get-own-property-descriptor.js\");\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptor_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_get_own_property_descriptor_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_web_dom_collections_for_each_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/web.dom-collections.for-each.js */ \"./node_modules/core-js/modules/web.dom-collections.for-each.js\");\n/* harmony import */ var core_js_modules_web_dom_collections_for_each_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_collections_for_each_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptors_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.object.get-own-property-descriptors.js */ \"./node_modules/core-js/modules/es.object.get-own-property-descriptors.js\");\n/* harmony import */ var core_js_modules_es_object_get_own_property_descriptors_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_get_own_property_descriptors_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _defineProperty_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./defineProperty.js */ \"./node_modules/@babel/runtime/helpers/esm/defineProperty.js\");\n\n\n\n\n\n\n\n\nfunction ownKeys(object, enumerableOnly) {\n var keys = Object.keys(object);\n\n if (Object.getOwnPropertySymbols) {\n var symbols = Object.getOwnPropertySymbols(object);\n\n if (enumerableOnly) {\n symbols = symbols.filter(function (sym) {\n return Object.getOwnPropertyDescriptor(object, sym).enumerable;\n });\n }\n\n keys.push.apply(keys, symbols);\n }\n\n return keys;\n}\n\nfunction _objectSpread2(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? arguments[i] : {};\n\n if (i % 2) {\n ownKeys(Object(source), true).forEach(function (key) {\n Object(_defineProperty_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"])(target, key, source[key]);\n });\n } else if (Object.getOwnPropertyDescriptors) {\n Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));\n } else {\n ownKeys(Object(source)).forEach(function (key) {\n Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));\n });\n }\n }\n\n return target;\n}\n\n//# sourceURL=webpack:///./node_modules/@babel/runtime/helpers/esm/objectSpread2.js?");
/***/ }), /***/ }),
@ -125,6 +125,17 @@ eval("module.exports = function isValidHostname(value) {\n if (typeof value !==
/***/ }), /***/ }),
/***/ "./node_modules/uuid-validate/index.js":
/*!*********************************************!*\
!*** ./node_modules/uuid-validate/index.js ***!
\*********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("/* WEBPACK VAR INJECTION */(function(Buffer) {// Regular expression used for basic parsing of the uuid.\nvar pattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Unparses a UUID buffer to a string. From node-uuid:\n * https://github.com/defunctzombie/node-uuid/blob/master/uuid.js\n *\n * Copyright (c) 2010-2012 Robert Kieffer\n * MIT License - http://opensource.org/licenses/mit-license.php\n *\n * @param {Buffer} buf\n * @param {Number=0} offset\n * @return {String}\n */\nvar _byteToHex = [];\nfor (var i = 0; i < 256; i++) {\n _byteToHex[i] = (i + 0x100).toString(16).substr(1);\n}\n\nfunction unparse(buf, offset) {\n var i = offset || 0, bth = _byteToHex;\n return bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]];\n}\n\n/**\n * Determines whether the uuid is valid, converting\n * it from a buffer if necessary.\n *\n * @param {String|Buffer} uuid\n * @param {Number=} version\n * @return {Boolean}\n */\nmodule.exports = function (uuid, version) {\n var parsedUuid;\n // If the uuid is a biffer, parse it...\n if (Buffer.isBuffer(uuid)) {\n parsedUuid = unparse(uuid);\n }\n // If it's a string, it's already good.\n else if (Object.prototype.toString.call(uuid) === '[object String]') {\n parsedUuid = uuid;\n }\n // Otherwise, it's not valid.\n else {\n return false;\n }\n\n parsedUuid = parsedUuid.toLowerCase();\n\n // All UUIDs fit a basic schema. Match that.\n if (!pattern.test(parsedUuid)) {\n return false;\n }\n\n // Now extract the version...\n if (version === undefined) {\n version = extractVersion(parsedUuid);\n } else if (extractVersion(parsedUuid) !== version) {\n return false;\n }\n\n switch (version) {\n // For certain versions, the checks we did up to this point are fine.\n case 1:\n case 2:\n return true;\n\n // For versions 3 and 4, they must specify a variant.\n case 3:\n case 4:\n case 5:\n return ['8', '9', 'a', 'b'].indexOf(parsedUuid.charAt(19)) !== -1;\n\n default:\n // We should only be able to reach this if the consumer explicitly\n // provided an invalid version. Prior to extractVersion we check\n // that it's 1-4 in the regex.\n throw new Error('Invalid version provided.');\n }\n};\n\n/**\n * Extracts the version from the UUID, which is (by definition) the M in\n * xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx\n *\n * @param {String} uuid\n * @return {Number}\n */\nvar extractVersion = module.exports.version = function (uuid) {\n return uuid.charAt(14)|0;\n};\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../buffer/index.js */ \"./node_modules/buffer/index.js\").Buffer))\n\n//# sourceURL=webpack:///./node_modules/uuid-validate/index.js?");
/***/ }),
/***/ "./node_modules/vee-validate/dist/rules.js": /***/ "./node_modules/vee-validate/dist/rules.js":
/*!*************************************************!*\ /*!*************************************************!*\
!*** ./node_modules/vee-validate/dist/rules.js ***! !*** ./node_modules/vee-validate/dist/rules.js ***!
@ -149,17 +160,6 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ }), /***/ }),
/***/ "./src/assets/img/account/default-avatar.svg":
/*!***************************************************!*\
!*** ./src/assets/img/account/default-avatar.svg ***!
\***************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("module.exports = __webpack_require__.p + \"img/default-avatar.ab3b9bda.svg\";\n\n//# sourceURL=webpack:///./src/assets/img/account/default-avatar.svg?");
/***/ }),
/***/ "./src/plugins/vee-validate.js": /***/ "./src/plugins/vee-validate.js":
/*!*************************************!*\ /*!*************************************!*\
!*** ./src/plugins/vee-validate.js ***! !*** ./src/plugins/vee-validate.js ***!
@ -168,7 +168,7 @@ eval("module.exports = __webpack_require__.p + \"img/default-avatar.ab3b9bda.svg
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@vue/babel-preset-app/node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! is-valid-hostname */ \"./node_modules/is-valid-hostname/index.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__);\n\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_vue_babel_preset_app_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])('rfc1123', {\n validate: function validate(value) {\n return is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default()(value);\n },\n message: 'You entered an invalid RFC1123 hostname'\n});\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! is-valid-hostname */ \"./node_modules/is-valid-hostname/index.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var uuid_validate__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! uuid-validate */ \"./node_modules/uuid-validate/index.js\");\n/* harmony import */ var uuid_validate__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(uuid_validate__WEBPACK_IMPORTED_MODULE_4__);\n\n\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])('rfc1123', {\n validate: function validate(value) {\n return is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default()(value);\n },\n message: 'You entered an invalid RFC1123 hostname'\n});\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])('uuid', {\n validate: function validate(value) {\n return uuid_validate__WEBPACK_IMPORTED_MODULE_4___default()(value);\n },\n message: 'You entered an invalid share ID'\n});\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?");
/***/ }) /***/ })

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

119
web/js/6.js Normal file

File diff suppressed because one or more lines are too long

74
web/js/7.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long