Selaa lähdekoodia

0.3.4 (#385)

* delete connect

* update user

* change branch

* API feedback (#341)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* change branch

* update route

* change branch

* Update route.go

* 0.3.4 Function development completed

* Update system.go

* update ui

* Completed v0.3.4 and released alpha

Co-authored-by: Tiger Wang (王豫) <tigerwang@outlook.com>
link 3 vuotta sitten
vanhempi
commit
6f98995e7d
100 muutettua tiedostoa jossa 1157 lisäystä ja 4161 poistoa
  1. 1 1
      UI
  2. 2 2
      alpha.md
  3. 1 9
      conf/conf.conf.sample
  4. 2 6
      go.mod
  5. 0 68
      go.sum
  6. 2 37
      main.go
  7. 3 3
      middleware/gin.go
  8. 0 27
      model/app-analyse.go
  9. 9 0
      model/app.go
  10. 4 5
      model/category.go
  11. 12 2
      model/disk.go
  12. 5 5
      model/docker.go
  13. 11 10
      model/manifest.go
  14. 0 16
      model/notify/person.go
  15. 19 0
      model/notify/storage.go
  16. 0 54
      model/person.go
  17. 1 8
      model/sys_common.go
  18. 1 1
      pkg/config/init.go
  19. 3 4
      pkg/docker/helper.go
  20. 16 2
      pkg/sqlite/db.go
  21. 6 18
      pkg/utils/common_err/e.go
  22. 18 55
      pkg/utils/jwt/jwt.go
  23. 28 66
      pkg/utils/jwt/jwt_helper.go
  24. 1 4
      pkg/utils/version/version.go
  25. 3 158
      route/init.go
  26. 1 11
      route/periodical.go
  27. 147 154
      route/route.go
  28. 27 15
      route/v1/app.go
  29. 134 135
      route/v1/disk.go
  30. 132 111
      route/v1/docker.go
  31. 62 78
      route/v1/file.go
  32. 0 804
      route/v1/person.go
  33. 0 107
      route/v1/shortcuts.go
  34. 17 0
      route/v1/storage.go
  35. 0 27
      route/v1/sync.go
  36. 57 135
      route/v1/system.go
  37. 216 268
      route/v1/user.go
  38. 54 36
      service/app.go
  39. 33 109
      service/casa.go
  40. 2 1
      service/docker.go
  41. 0 33
      service/down_record.go
  42. 0 66
      service/download.go
  43. 0 155
      service/friend.go
  44. 6 7
      service/model/o_container.go
  45. 0 16
      service/model/o_down_record.go
  46. 0 24
      service/model/o_download.go
  47. 0 21
      service/model/o_friend.go
  48. 0 17
      service/model/o_shortcuts.go
  49. 4 4
      service/model/o_user.go
  50. 16 17
      service/notify.go
  51. 0 482
      service/person.go
  52. 2 0
      service/rely.go
  53. 28 49
      service/service.go
  54. 0 34
      service/shortcuts.go
  55. 11 21
      service/system.go
  56. 0 503
      service/udpconn.go
  57. 9 35
      service/user.go
  58. 2 2
      types/system.go
  59. 9 9
      web/browserconfig.xml
  60. 14 14
      web/favicon.svg
  61. BIN
      web/img/1-small.1b74d2ba.png
  62. BIN
      web/img/Android-DeviceID.b57fefc8.png
  63. BIN
      web/img/Android-Menu.ed4df0da.png
  64. BIN
      web/img/Android-NewDevice.f00af2cb.png
  65. BIN
      web/img/Android-NewDeviceAdd.784d2f18.png
  66. BIN
      web/img/Android-NewFolder.d71dc444.png
  67. BIN
      web/img/Android-NewFolderCreate.b3521b45.png
  68. BIN
      web/img/Android-ShowDeviceID.f7e46fb8.png
  69. BIN
      web/img/Windows-DeviceID.2e929f75.png
  70. BIN
      web/img/Windows-NewDevice.c9f2471d.png
  71. BIN
      web/img/Windows-NewDeviceSave.fe1078b1.png
  72. BIN
      web/img/Windows-NewFolder.5305cc41.png
  73. BIN
      web/img/Windows-NewFolderSave.9ce2312f.png
  74. BIN
      web/img/Windows-ShowID.1000f319.png
  75. 25 25
      web/img/icon/safari-pinned-tab.svg
  76. BIN
      web/img/macOS-Config.f419628a.png
  77. BIN
      web/img/macOS-DeviceID.968cc84d.png
  78. BIN
      web/img/macOS-NewFolder.fa9e37d0.png
  79. BIN
      web/img/macOS-NewFolderSave.6f3f247d.png
  80. BIN
      web/img/macOS-ShowID.c822acc3.png
  81. BIN
      web/img/macOS-icon.ae9e0906.png
  82. 0 1
      web/img/syncthing.257e4f51.svg
  83. 0 1
      web/img/windows.d98029c3.svg
  84. 1 1
      web/index.html
  85. 0 0
      web/js/0.js
  86. 0 4
      web/js/1.js
  87. 0 12
      web/js/10.js
  88. 0 4
      web/js/11.js
  89. 0 4
      web/js/12.js
  90. 0 4
      web/js/13.js
  91. 0 4
      web/js/14.js
  92. 0 4
      web/js/15.js
  93. 0 4
      web/js/16.js
  94. 0 4
      web/js/17.js
  95. 0 4
      web/js/18.js
  96. 0 8
      web/js/2.js
  97. 0 4
      web/js/3.js
  98. 0 4
      web/js/4.js
  99. 0 4
      web/js/5.js
  100. 0 4
      web/js/6.js

+ 1 - 1
UI

@@ -1 +1 @@
-Subproject commit 7af1bf549dd35c93f48b6c501204a4efe57e8d6b
+Subproject commit bca27426e1f398c31fb6c5c23885482326514f6e

+ 2 - 2
alpha.md

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-06-27 11:37:26
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-01 15:51:29
+ * @LastEditTime: 2022-07-21 18:12:31
  * @FilePath: /CasaOS/alpha.md
  * @Description: 
  * @Website: https://www.casaos.io
@@ -17,7 +17,7 @@ There is a risk of data loss in non-release versions, so please be careful to ba
 
 ## Install/Update
 
-``` curl -fsSL https://get.casaos.io | bash -s -- -v v0.3.3-alpha ```
+``` curl -fsSL https://get.casaos.io | bash -s -- -v v0.3.4-alpha ```
 
 ## Check change log
 

+ 1 - 9
conf/conf.conf.sample

@@ -15,18 +15,10 @@ TempPath    = /var/lib/casaos/temp
 
 [server]
 HttpPort = 80
-UDPPort = 
 RunMode = release
 ServerApi = https://api.casaos.io/casaos-api
 Handshake = socket.casaos.io
 Token = 
 USBAutoMount =
 
-
-[system]
-WidgetList =
-
-
-[file]
-ShareDir =
-DownloadDir =
+[system]

+ 2 - 6
go.mod

@@ -19,12 +19,10 @@ require (
 	github.com/docker/go-connections v0.4.0
 	github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
 	github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
-	github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
 	github.com/gin-contrib/gzip v0.0.2
 	github.com/gin-gonic/gin v1.7.2
 	github.com/go-ini/ini v1.62.0
 	github.com/go-ole/go-ole v1.2.5 // indirect
-	github.com/go-openapi/spec v0.20.4 // indirect
 	github.com/go-playground/validator/v10 v10.6.1 // indirect
 	github.com/gogo/googleapis v1.4.1 // indirect
 	github.com/golang-jwt/jwt/v4 v4.4.1
@@ -38,9 +36,9 @@ require (
 	github.com/jinzhu/copier v0.3.2
 	github.com/json-iterator/go v1.1.11 // indirect
 	github.com/klauspost/compress v1.13.6 // indirect
+	github.com/kr/text v0.2.0 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
 	github.com/lucas-clemente/quic-go v0.25.0
-	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mattn/go-isatty v0.0.14 // indirect
 	github.com/mattn/go-sqlite3 v1.14.11 // indirect
 	github.com/mholt/archiver/v3 v3.5.1
@@ -50,7 +48,6 @@ require (
 	github.com/opencontainers/selinux v1.8.5 // indirect
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pkg/errors v0.9.1
-	github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109
 	github.com/prometheus/procfs v0.7.3 // indirect
 	github.com/robfig/cron v1.2.0
 	github.com/satori/go.uuid v1.2.0
@@ -58,8 +55,6 @@ require (
 	github.com/sirupsen/logrus v1.8.1
 	github.com/smartystreets/assertions v1.2.0 // indirect
 	github.com/smartystreets/goconvey v1.6.4 // indirect
-	github.com/swaggo/gin-swagger v1.3.0
-	github.com/swaggo/swag v1.7.3
 	github.com/tidwall/gjson v1.10.2
 	github.com/tklauser/go-sysconf v0.3.6 // indirect
 	github.com/ugorji/go v1.2.6 // indirect
@@ -71,6 +66,7 @@ require (
 	golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
 	golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect
 	golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
+	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
 	golang.org/x/tools v0.1.7 // indirect
 	google.golang.org/appengine v1.6.7 // indirect

+ 0 - 68
go.sum

@@ -59,8 +59,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
 github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
-github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
-github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
 github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
@@ -85,17 +83,13 @@ github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5
 github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
 github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
 github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY=
 github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -328,8 +322,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
 github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b h1:r13MvtFTtnvxtuKK7z0ZSQ2EfMmTzWDHwfDvGCoqUQE=
-github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b/go.mod h1:EfR6AU78zUiZ36oVS5YrmTzc2um3zDXWPx4L4st++jo=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
 github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
@@ -340,15 +332,10 @@ github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXt
 github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w=
 github.com/gin-contrib/gzip v0.0.2 h1:VMBkd4ZB1Hl7e1lOA5gEZ/qdD3d9vLIq57xKWgPCCV8=
 github.com/gin-contrib/gzip v0.0.2/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc=
-github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
-github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
-github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
 github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
 github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
 github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
@@ -372,29 +359,13 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
 github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
 github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
 github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
-github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
-github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
-github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
-github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
-github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
-github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
 github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
-github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
-github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
-github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
-github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
 github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
-github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@@ -563,9 +534,6 @@ github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/
 github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
 github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
-github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -611,14 +579,10 @@ github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3m
 github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
 github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
-github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
 github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
 github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
@@ -630,8 +594,6 @@ github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaI
 github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
@@ -676,7 +638,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
 github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
 github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
 github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
 github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@@ -749,8 +710,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
-github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109 h1:h9WYaTCQJ7hap8C5vQniEum2YZbc+iRad/ROafTjy10=
-github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109/go.mod h1:U7VCLF6LMHzOFD/6Kww2MTQuwaNeEA1U1dOxFyZBoBE=
 github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -799,7 +758,6 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4=
 github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
-github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
 github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
 github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
@@ -868,12 +826,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
-github.com/swaggo/gin-swagger v1.3.0 h1:eOmp7r57oUgZPw2dJOjcGNMse9cvXcI4tTqBcnZtPsI=
-github.com/swaggo/gin-swagger v1.3.0/go.mod h1:oy1BRA6WvgtCp848lhxce7BnWH4C8Bxa0m5SkWx+cS0=
-github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
-github.com/swaggo/swag v1.7.3 h1:ucB7irEdRrhjmW+Z1Ss4GjO68oPKQFjSgOR8BCAvcbU=
-github.com/swaggo/swag v1.7.3/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI=
 github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -896,12 +848,9 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
 github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
-github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc=
 github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
 github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
-github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
-github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
 github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
 github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
 github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
@@ -911,7 +860,6 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
 github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
 github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
 github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
@@ -1018,7 +966,6 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1033,7 +980,6 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -1062,10 +1008,8 @@ golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
@@ -1098,9 +1042,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1112,7 +1054,6 @@ golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1163,13 +1104,11 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1213,9 +1152,7 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
@@ -1251,7 +1188,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
 golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
@@ -1375,15 +1311,12 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
-gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
-gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
 gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@@ -1407,7 +1340,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=

+ 2 - 37
main.go

@@ -24,7 +24,6 @@ var sqliteDB *gorm.DB
 
 var configFlag = flag.String("c", "", "config address")
 var dbFlag = flag.String("db", "", "db path")
-var showUserInfo = flag.Bool("show-user-info", false, "show user info")
 var resetUser = flag.Bool("ru", false, "reset user")
 var user = flag.String("user", "", "user name")
 
@@ -42,10 +41,6 @@ func init() {
 	service.Cache = cache.Init()
 
 	service.GetToken()
-	service.UDPAddressMap = make(map[string]string)
-	//go service.SocketConnect()
-	service.CancelList = make(map[string]string)
-	service.InternalInspection = make(map[string][]string)
 	service.NewVersionApp = make(map[string]string)
 	route.InitFunction()
 
@@ -67,15 +62,7 @@ func init() {
 // @BasePath /v1
 func main() {
 	service.NotifyMsg = make(chan notify.Message, 10)
-	if *showUserInfo {
-		fmt.Println("CasaOS User Info")
-		fmt.Println("UserName:" + config.UserInfo.UserName)
-		fmt.Println("Password:" + config.UserInfo.PWD)
-		return
-	}
-	fmt.Println("Reset User", *resetUser)
 	if *resetUser {
-
 		if user == nil || len(*user) == 0 {
 			fmt.Println("user is empty")
 			return
@@ -89,21 +76,11 @@ func main() {
 		userData.Password = encryption.GetMD5ByStr(password)
 		service.MyService.User().UpdateUserPassword(userData)
 		fmt.Println("User reset successful")
-		fmt.Println("UserName:" + userData.UserName)
+		fmt.Println("UserName:" + userData.Username)
 		fmt.Println("Password:" + password)
 		return
 	}
-	go func() {
-		service.UDPService()
-		service.SendIPToServer()
-	}()
 	go route.SocketInit(service.NotifyMsg)
-	go func() {
-		for i := 0; i < 1000; i++ {
-			time.Sleep(2 * time.Second)
-			//service.NotifyMsg <- strconv.Itoa(i)
-		}
-	}()
 
 	//model.Setup()
 	//gredis.Setup()
@@ -111,20 +88,8 @@ func main() {
 	//service.SyncTask(sqliteDB)
 	cron2 := cron.New()
 	//every day execution
-	err := cron2.AddFunc("0 0/5 * * * *", func() {
-		//service.PushIpInfo(*&config.ServerInfo.Token)
-		//service.UpdataDDNSList(mysqldb)
-		//service.SyncTask(sqliteDB)
-
-		service.SendIPToServer()
 
-		service.LoopFriend()
-		//service.MyService.App().CheckNewImage()
-	})
-	if err != nil {
-		fmt.Println(err)
-	}
-	err = cron2.AddFunc("0/5 * * * * *", func() {
+	err := cron2.AddFunc("0/5 * * * * *", func() {
 		if service.ClientCount > 0 {
 			//route.SendNetINfoBySocket()
 			//route.SendCPUBySocket()

+ 3 - 3
middleware/gin.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2021-10-08 10:29:08
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-21 15:10:03
+ * @LastEditTime: 2022-07-13 11:26:12
  * @FilePath: /CasaOS/middleware/gin.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -26,14 +26,14 @@ func Cors() gin.HandlerFunc {
 		c.Header("Access-Control-Allow-Origin", "*")
 		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
 		//允许跨域设置可以返回其他子段,可以自定义字段
-		c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
+		c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With")
 		// 允许浏览器(客户端)可以解析的头部 (重要)
 		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
 		//c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
 		//设置缓存时间
 		c.Header("Access-Control-Max-Age", "172800")
 		c.Header("Access-Control-Allow-Credentials", "true")
-		c.Set("content-type", "application/json")
+		c.Set("Content-Type", "application/json")
 		//}
 
 		//允许类型校验

+ 0 - 27
model/app-analyse.go

@@ -1,27 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2022-03-18 11:40:55
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-05-13 14:48:01
- * @FilePath: /CasaOS/model/app-analyse.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package model
-
-type AppAnalyse struct {
-	Name     string `json:"name"`
-	Type     string `json:"type"`
-	UUId     string `json:"uuid"`
-	Language string `json:"language"`
-	Version  string `json:"version"`
-}
-
-type ConnectionStatus struct {
-	From  string `json:"from"`
-	To    string `json:"to"`
-	Error string `json:"error"`
-	UUId  string `json:"uuid"`
-	Event string `json:"event"`
-}

+ 9 - 0
model/app.go

@@ -13,6 +13,15 @@ type ServerAppListCollection struct {
 	Version   string          `json:"version"`
 }
 
+// @tiger - 对于用于出参的数据结构,静态信息(例如 title)和
+//          动态信息(例如 state、query_count)应该划分到不同的数据结构中
+//
+//          这样的好处是
+//          1 - 多次获取动态信息时可以减少出参复杂度,因为静态信息只获取一次就好
+//          2 - 在未来的迭代中,可以降低维护成本(所有字段都展开放在一个层级维护成本略高)
+//
+//          另外,一些针对性字段,例如 Docker 相关的,可以用 map 来保存。
+//          这样在未来增加多态 App,例如 Snap,不需要维护多个结构,或者一个结构保存不必要的字段
 type ServerAppList struct {
 	Id             uint      `gorm:"column:id;primary_key" json:"id"`
 	Title          string    `json:"title"`

+ 4 - 5
model/category.go

@@ -2,10 +2,9 @@
  * @Author: link a624669980@163.com
  * @Date: 2022-05-16 17:37:08
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-22 17:45:53
+ * @LastEditTime: 2022-07-13 10:46:38
  * @FilePath: /CasaOS/model/category.go
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-
+ * @Description:
  */
 package model
 
@@ -18,7 +17,7 @@ type CategoryList struct {
 	//CreatedAt time.Time `json:"created_at"`
 	//
 	//UpdatedAt time.Time `json:"updated_at"`
-	Font  string `json:"font"`
+	Font  string `json:"font"` // @tiger - 如果这个和前端有关,应该不属于后端的出参范围,而是前端去界定
 	Name  string `json:"name"`
-	Count uint   `json:"count"`
+	Count uint   `json:"count"` // @tiger - count 属于动态信息,应该单独放在一个出参结构中(原因见另外一个关于 静态/动态 出参的注释)
 }

+ 12 - 2
model/disk.go

@@ -1,3 +1,13 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-07-13 10:43:45
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-07-13 11:00:04
+ * @FilePath: /CasaOS/model/disk.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
 package model
 
 type LSBLKModel struct {
@@ -53,8 +63,8 @@ type DriveUSB struct {
 	Size  uint64 `json:"size"`
 	Used  uint64 `json:"use"`
 	Model string `json:"model"`
-	Mount bool   `json:"mount"` //是否完全挂载
-	Avail uint64 `json:"avail"` //可用空间
+	Mount bool   `json:"mount"`
+	Avail uint64 `json:"avail"`
 }
 
 type Storage struct {

+ 5 - 5
model/docker.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2021-12-08 18:10:25
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-14 17:20:36
+ * @LastEditTime: 2022-07-13 10:49:16
  * @FilePath: /CasaOS/model/docker.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -11,8 +11,8 @@
 package model
 
 type DockerStatsModel struct {
-	Icon  string      `json:"icon"`
-	Title string      `json:"title"`
-	Data  interface{} `json:"data"`
-	Pre   interface{} `json:"pre"`
+	Icon     string      `json:"icon"`
+	Title    string      `json:"title"`
+	Data     interface{} `json:"data"`
+	Previous interface{} `json:"previous"`
 }

+ 11 - 10
model/manifest.go

@@ -104,16 +104,17 @@ func (p *PathArray) Scan(input interface{}) error {
 //}
 
 type CustomizationPostData struct {
-	CustomId     string    `json:"custom_id"`
-	Origin       string    `json:"origin"`
-	NetworkModel string    `json:"network_model"`
-	Index        string    `json:"index"`
-	Icon         string    `json:"icon"`
-	Image        string    `json:"image"`
-	Envs         EnvArray  `json:"envs"`
-	Ports        PortArray `json:"ports"`
-	Volumes      PathArray `json:"volumes"`
-	Devices      PathArray `json:"devices"`
+	ContainerName string    `json:"container_name"`
+	CustomId      string    `json:"custom_id"`
+	Origin        string    `json:"origin"`
+	NetworkModel  string    `json:"network_model"`
+	Index         string    `json:"index"`
+	Icon          string    `json:"icon"`
+	Image         string    `json:"image"`
+	Envs          EnvArray  `json:"envs"`
+	Ports         PortArray `json:"ports"`
+	Volumes       PathArray `json:"volumes"`
+	Devices       PathArray `json:"devices"`
 	//Port         string    `json:"port,omitempty"`
 	PortMap     string   `json:"port_map"`
 	CpuShares   int64    `json:"cpu_shares"`

+ 0 - 16
model/notify/person.go

@@ -1,16 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2022-05-27 18:42:42
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-05-27 18:43:08
- * @FilePath: /CasaOS/model/notify/person.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package notify
-
-type Person struct {
-	ShareId string `json:"share_id"`
-	Type    string `json:"type"`
-}

+ 19 - 0
model/notify/storage.go

@@ -0,0 +1,19 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-07-15 10:43:00
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-07-15 10:56:17
+ * @FilePath: /CasaOS/model/notify/storage.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package notify
+
+type StorageMessage struct {
+	Type   string `json:"type"`   //sata,usb
+	Action string `json:"action"` //remove add
+	Path   string `json:"path"`
+	Volume string `json:"volume"`
+	Size   uint64 `json:"size"`
+}

+ 0 - 54
model/person.go

@@ -1,54 +0,0 @@
-package model
-
-import "time"
-
-type PersionModel struct {
-	Token     string    `json:"token"`
-	Ips       []string  `json:"ips"`
-	CreatedAt time.Time `json:"created_at"`
-	UpdatedAt time.Time `json:"updated_at"`
-}
-
-//记录链接状态
-type ConnectState struct {
-	From      string    `json:"from"`
-	To        string    `json:"to"`
-	Type      string    `json:"type"` //current state 1:ready 2:ok
-	CreatedAt time.Time `json:"created_at"`
-	UUId      string    `json:"uuid"` //对接标识
-}
-type MessageModel struct {
-	Type string      `json:"type"`
-	Data interface{} `json:"data"`
-	UUId string      `json:"uuid"`
-	From string      `json:"from"`
-	To   string      `json:"to"`
-}
-
-type TranFileModel struct {
-	Hash   string `json:"hash"` //Verify current fragment integrity
-	Length int    `json:"length"`
-	Index  int    `json:"index"`
-}
-
-//需要获取文件详情
-type FileDetailModel struct {
-	Path string `json:"path"`
-}
-
-//返回文件详情
-type FileSummaryModel struct {
-	Hash      string `json:"hash"` //Verify file
-	Name      string `json:"name"`
-	BlockSize int    `json:"block_size"`
-	Length    int    `json:"length"`
-	Size      int64  `json:"size"`
-	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"`
-}

+ 1 - 8
model/sys_common.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-05-13 18:15:46
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-16 17:50:56
+ * @LastEditTime: 2022-07-14 11:02:06
  * @FilePath: /CasaOS/model/sys_common.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -37,9 +37,7 @@ type ServerModel struct {
 	RunMode      string
 	ServerApi    string
 	LockAccount  bool
-	Handshake    string
 	Token        string
-	UDPPort      string
 	USBAutoMount string
 	SocketPort   string
 }
@@ -76,12 +74,7 @@ type RedisModel struct {
 }
 
 type SystemConfig struct {
-	ConfigStr  string `json:"config_str"`
-	WidgetList string `json:"widget_list"`
 	ConfigPath string `json:"config_path"`
-	SyncPort   string `json:"sync_port"`
-	SyncKey    string `json:"sync_key"`
-	Analyse    string `json:"analyse"`
 }
 
 type CasaOSGlobalVariables struct {

+ 1 - 1
pkg/config/init.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-05-13 18:15:46
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-21 16:01:26
+ * @LastEditTime: 2022-07-14 10:58:45
  * @FilePath: /CasaOS/pkg/config/init.go
  * @Description:
  * @Website: https://www.casaos.io

+ 3 - 4
pkg/docker/helper.go

@@ -6,7 +6,6 @@ import (
 	"fmt"
 	"io"
 	"regexp"
-	"strconv"
 	"sync"
 	"time"
 
@@ -15,7 +14,7 @@ import (
 	"golang.org/x/crypto/ssh"
 )
 
-func NewSshClient(user, password string) (*ssh.Client, error) {
+func NewSshClient(user, password string, port string) (*ssh.Client, error) {
 
 	// connet to ssh
 	// addr = fmt.Sprintf("%s:%d", host, port)
@@ -32,7 +31,7 @@ func NewSshClient(user, password string) (*ssh.Client, error) {
 	//} else {
 	//	config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
 	//}
-	addr := fmt.Sprintf("%s:%d", "127.0.0.1", 22)
+	addr := fmt.Sprintf("%s:%s", "127.0.0.1", port)
 	c, err := ssh.Dial("tcp", addr, config)
 	if err != nil {
 		return nil, err
@@ -396,7 +395,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
 			if err = json2.Unmarshal(p, &msgObj); err != nil {
 				writer.Write(p)
 			} else if msgObj.Type == wsMsgResize {
-				writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
+				//writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
 			}
 		}
 	}

+ 16 - 2
pkg/sqlite/db.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-05-13 18:15:46
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-22 18:50:44
+ * @LastEditTime: 2022-07-11 18:10:53
  * @FilePath: /CasaOS/pkg/sqlite/db.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -42,8 +42,22 @@ func GetDb(dbPath string) *gorm.DB {
 		return nil
 	}
 	gdb = db
-	err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{}, model2.PersonDownRecordDBModel{}, model2.UserDBModel{})
+
+	db.Exec(`alter table o_user rename to old_user;
+
+	create table o_users ( id integer primary key,username text,password text,role text,email text,nickname text,avatar text,description text,created_at datetime,updated_at datetime);
+	
+	insert into o_users select id,user_name,password,role,email,nick_name,avatar,description,created_at,updated_at from old_user;
+	
+	drop table old_user;
+	drop table o_user;	
+	`)
+
+	err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.UserDBModel{})
 	db.Exec("DROP TABLE IF EXISTS o_application")
+	db.Exec("DROP TABLE IF EXISTS o_friend")
+	db.Exec("DROP TABLE IF EXISTS o_person_download")
+	db.Exec("DROP TABLE IF EXISTS o_person_down_record")
 	if err != nil {
 		loger.Error("check or create db error", zap.Any("error", err))
 	}

+ 6 - 18
pkg/utils/common_err/e.go

@@ -2,10 +2,11 @@ package common_err
 
 const (
 	SUCCESS          = 200
-	ERROR            = 500
-	INVALID_PARAMS   = 400
+	SERVICE_ERROR    = 500
+	CLIENT_ERROR     = 400
 	ERROR_AUTH_TOKEN = 401
 
+	INVALID_PARAMS = 4000
 	//user
 	PWD_INVALID              = 10001
 	PWD_IS_EMPTY             = 10002
@@ -49,19 +50,12 @@ const (
 
 	//shortcuts
 	SHORTCUTS_URL_ERROR = 70001
-
-	//person
-	PERSON_REMOTE_ERROR   = 80001
-	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{
 	SUCCESS:          "ok",
-	ERROR:            "fail",
+	SERVICE_ERROR:    "Fail",
+	CLIENT_ERROR:     "Fail",
 	INVALID_PARAMS:   "Parameters Error",
 	ERROR_AUTH_TOKEN: "Error auth token",
 
@@ -108,12 +102,6 @@ var MsgFlags = map[int]string{
 	FILE_DELETE_ERROR:   "Delete error",
 	SHORTCUTS_URL_ERROR: "URL error",
 
-	PERSON_REMOTE_ERROR:             "Remote connection error",
-	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",
 	COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
 }
 
@@ -123,5 +111,5 @@ func GetMsg(code int) string {
 	if ok {
 		return msg
 	}
-	return MsgFlags[ERROR]
+	return MsgFlags[SERVICE_ERROR]
 }

+ 18 - 55
pkg/utils/jwt/jwt.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2021-09-30 18:18:14
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-24 10:02:46
+ * @LastEditTime: 2022-07-18 17:30:38
  * @FilePath: /CasaOS/pkg/utils/jwt/jwt.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -16,67 +16,26 @@ import (
 	jwt "github.com/golang-jwt/jwt/v4"
 )
 
-// type Claims struct {
-// 	UserName string `json:"username"`
-// 	PassWord string `json:"password"`
-// 	Id       int    `json:"id"`
-// 	jwt.RegisteredClaims
-// }
-
-// var jwtSecret []byte
-
-// //创建token
-// func GenerateToken(username, password string, id int, issuer string, t time.Duration) (string, error) {
-// 	clims := Claims{
-// 		username,
-// 		password,
-// 		id,
-// 		jwt.RegisteredClaims{
-// 			ExpiresAt: jwt.NewNumericDate(time.Now().Add(t)),
-// 			IssuedAt:  jwt.NewNumericDate(time.Now()),
-// 			NotBefore: jwt.NewNumericDate(time.Now()),
-// 			Issuer:    issuer,
-// 		},
-// 	}
-
-// 	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, clims)
-// 	token, err := tokenClaims.SignedString(jwtSecret)
-// 	return token, err
-
-// }
-
-// //解析token
-// func ParseToken(token string) (*Claims, error) {
-// 	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
-// 		return jwtSecret, nil
-// 	})
-// 	if tokenClaims != nil {
-// 		if clims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
-// 			return clims, nil
-// 		}
-// 	}
-// 	return nil, err
-// }
-
-//****************** soon to be removed ******************
-
 type Claims struct {
-	UserName string `json:"username"`
+	Username string `json:"username"`
 	PassWord string `json:"password"`
-	jwt.StandardClaims
+	Id       int    `json:"id"`
+	jwt.RegisteredClaims
 }
 
 var jwtSecret []byte
 
 //创建token
-func GenerateToken(username, password string) (string, error) {
-	expireTime := time.Now().AddDate(999, 0, 0)
+func GenerateToken(username, password string, id int, issuer string, t time.Duration) (string, error) {
 	clims := Claims{
 		username,
 		password,
-		jwt.StandardClaims{
-			ExpiresAt: expireTime.Unix(),
-			Issuer:    "gin-blog",
+		id,
+		jwt.RegisteredClaims{
+			ExpiresAt: jwt.NewNumericDate(time.Now().Add(t)),
+			IssuedAt:  jwt.NewNumericDate(time.Now()),
+			NotBefore: jwt.NewNumericDate(time.Now()),
+			Issuer:    issuer,
 		},
 	}
 
@@ -87,13 +46,17 @@ func GenerateToken(username, password string) (string, error) {
 }
 
 //解析token
-func ParseToken(token string) (*Claims, error) {
+func ParseToken(token string, valid bool) (*Claims, error) {
 	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
 		return jwtSecret, nil
 	})
 	if tokenClaims != nil {
-		if clims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
-			return clims, nil
+		if clims, ok := tokenClaims.Claims.(*Claims); ok {
+			if valid && tokenClaims.Valid {
+				return clims, nil
+			} else if !valid {
+				return clims, nil
+			}
 		}
 	}
 	return nil, err

+ 28 - 66
pkg/utils/jwt/jwt_helper.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-06-17 14:01:25
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-04 16:26:22
+ * @LastEditTime: 2022-07-18 17:31:15
  * @FilePath: /CasaOS/pkg/utils/jwt/jwt_helper.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -11,65 +11,16 @@
 package jwt
 
 import (
-	"net/http"
+	"fmt"
+	"strconv"
+	"time"
 
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
+	loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
 	"github.com/gin-gonic/gin"
 )
 
-// func JWT() gin.HandlerFunc {
-// 	return func(c *gin.Context) {
-// 		var code int
-// 		code = common_err.SUCCESS
-// 		token := c.GetHeader("Authorization")
-// 		if len(token) == 0 {
-// 			token = c.Query("token")
-// 		}
-// 		if token == "" {
-// 			code = common_err.INVALID_PARAMS
-// 		}
-
-// 		claims, err := ParseToken(token)
-// 		//_, err := ParseToken(token)
-// 		if err != nil {
-// 			code = common_err.ERROR_AUTH_TOKEN
-// 		} else if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("casaos", true) {
-// 			code = common_err.ERROR_AUTH_TOKEN
-// 		}
-// 		if code != common_err.SUCCESS {
-// 			c.JSON(code, model.Result{Success: code, Message: common_err.GetMsg(code)})
-// 			c.Abort()
-// 			return
-// 		}
-// 		c.Request.Header.Add("user_id", strconv.Itoa(claims.Id))
-// 		c.Next()
-// 	}
-// }
-
-// //get AccessToken
-// func GetAccessToken(username, pwd string, id int) string {
-// 	token, err := GenerateToken(username, pwd, id, "casaos", 3*time.Hour*time.Duration(1))
-// 	if err == nil {
-// 		return token
-// 	} else {
-// 		loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
-// 		return ""
-// 	}
-// }
-
-// func GetRefreshToken(username, pwd string, id int) string {
-// 	token, err := GenerateToken(username, pwd, id, "fresh", 7*24*time.Hour*time.Duration(1))
-// 	if err == nil {
-// 		return token
-// 	} else {
-// 		loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
-// 		return ""
-// 	}
-// }
-
-//*************** soon to be removed *****************
-
 func JWT() gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var code int
@@ -82,32 +33,43 @@ func JWT() gin.HandlerFunc {
 			code = common_err.INVALID_PARAMS
 		}
 
-		//claims, err := ParseToken(token)
-		_, err := ParseToken(token)
+		claims, err := ParseToken(token, false)
+
+		//_, err := ParseToken(token)
 		if err != nil {
 			code = common_err.ERROR_AUTH_TOKEN
-
+		} else if (c.Request.URL.Path == "/v1/file" || c.Request.URL.Path == "/v1/image" || c.Request.URL.Path == "/v1/file/upload" || c.Request.URL.Path == "/v1/batch") && claims.VerifyIssuer("casaos", true) {
+			//Special treatment
+		} else if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("casaos", true) {
+			code = common_err.ERROR_AUTH_TOKEN
 		}
-		//else if time.Now().Unix() > claims.ExpiresAt {
-		//	code = oasis_err2.ERROR_AUTH_TOKEN
-		//}
-
 		if code != common_err.SUCCESS {
-			c.JSON(http.StatusOK, model.Result{Success: code, Message: common_err.GetMsg(code)})
+			c.JSON(code, model.Result{Success: code, Message: common_err.GetMsg(code)})
 			c.Abort()
 			return
 		}
+		c.Request.Header.Add("user_id", strconv.Itoa(claims.Id))
 		c.Next()
 	}
 }
 
-//获取token
-func GetToken(username, pwd string) string {
-	token, err := GenerateToken(username, pwd)
+//get AccessToken
+func GetAccessToken(username, pwd string, id int) string {
+	token, err := GenerateToken(username, pwd, id, "casaos", 3*time.Hour*time.Duration(1))
+	if err == nil {
+		return token
+	} else {
+		loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
+		return ""
+	}
+}
+
+func GetRefreshToken(username, pwd string, id int) string {
+	token, err := GenerateToken(username, pwd, id, "refresh", 7*24*time.Hour*time.Duration(1))
 	if err == nil {
 		return token
 	} else {
-		//loger2.NewOLoger().Fatal(fmt.Sprintf("Get Token Fail: %V", err))
+		loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
 		return ""
 	}
 }

+ 1 - 4
pkg/utils/version/version.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-05-13 18:15:46
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-29 14:29:34
+ * @LastEditTime: 2022-07-21 15:27:53
  * @FilePath: /CasaOS/pkg/utils/version/version.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -33,9 +33,6 @@ func IsNeedUpdate(version model.Version) (bool, model.Version) {
 	for i := 0; i < len(v1); i++ {
 		a, _ := strconv.Atoi(v1[i])
 		b, _ := strconv.Atoi(v2[i])
-		if i == 0 && a > b {
-			continue
-		}
 		if a > b {
 			return true, version
 		}

+ 3 - 158
route/init.go

@@ -1,30 +1,21 @@
 package route
 
 import (
-	"encoding/xml"
-	"fmt"
 	"os"
-	"path/filepath"
-	"runtime"
 	"strconv"
 	"strings"
-	"time"
 
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/model/system_app"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
 	"github.com/IceWhaleTech/CasaOS/service"
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
 	uuid "github.com/satori/go.uuid"
 )
 
 func InitFunction() {
-	go checkSystemApp()
+
 	ShellInit()
 	CheckSerialDiskMount()
 
@@ -35,132 +26,6 @@ func InitFunction() {
 	MoveUserToDB()
 }
 
-var syncIsExistence = false
-
-func installSyncthing(appId string) {
-
-	var appInfo model.ServerAppList
-	m := model.CustomizationPostData{}
-	var dockerImage string
-	var dockerImageVersion string
-	appInfo = service.MyService.Casa().GetServerAppInfo(appId, "system", "us_en")
-	dockerImage = appInfo.Image
-	dockerImageVersion = appInfo.ImageVersion
-
-	if len(appInfo.ImageVersion) == 0 {
-		dockerImageVersion = "latest"
-	}
-
-	if appInfo.NetworkModel != "host" {
-		for i := 0; i < len(appInfo.Ports); i++ {
-			if p, _ := strconv.Atoi(appInfo.Ports[i].ContainerPort); port.IsPortAvailable(p, appInfo.Ports[i].Protocol) {
-				appInfo.Ports[i].CommendPort = strconv.Itoa(p)
-			} else {
-				if appInfo.Ports[i].Protocol == "tcp" {
-					if p, err := port.GetAvailablePort("tcp"); err == nil {
-						appInfo.Ports[i].CommendPort = strconv.Itoa(p)
-					}
-				} else if appInfo.Ports[i].Protocol == "upd" {
-					if p, err := port.GetAvailablePort("udp"); err == nil {
-						appInfo.Ports[i].CommendPort = strconv.Itoa(p)
-					}
-				}
-			}
-
-			if appInfo.Ports[i].Type == 0 {
-				appInfo.PortMap = appInfo.Ports[i].CommendPort
-			}
-		}
-	}
-
-	for i := 0; i < len(appInfo.Devices); i++ {
-		if !file.CheckNotExist(appInfo.Devices[i].ContainerPath) {
-			appInfo.Devices[i].Path = appInfo.Devices[i].ContainerPath
-		}
-	}
-	if len(appInfo.Tip) > 0 {
-		appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
-	}
-
-	appInfo.MaxMemory = service.MyService.System().GetMemInfo()["total"].(uint64) >> 20
-
-	id := uuid.NewV4().String()
-
-	// step:下载镜像
-	err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, "", "")
-	if err != nil {
-		//pull image error
-		fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
-		return
-	}
-	for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
-		time.Sleep(time.Second)
-	}
-
-	m.CpuShares = 50
-	m.Envs = appInfo.Envs
-	m.Memory = int64(appInfo.MaxMemory)
-	m.Origin = "system"
-	m.PortMap = appInfo.PortMap
-	m.Ports = appInfo.Ports
-	m.Restart = "always"
-	m.Volumes = appInfo.Volumes
-	m.NetworkModel = appInfo.NetworkModel
-	m.Label = id
-	m.CustomId = id
-	containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m)
-	if err != nil {
-		fmt.Println("container create error", err)
-		// create container error
-		return
-	}
-
-	//step:start container
-	err = service.MyService.Docker().DockerContainerStart(containerId)
-	if err != nil {
-		//start container error
-		return
-	}
-
-	checkSystemApp()
-}
-
-// check if the system application is installed
-func checkSystemApp() {
-	list := service.MyService.App().GetSystemAppList()
-	for _, v := range list {
-		info, err := service.MyService.Docker().DockerContainerInfo(v.ID)
-		if err != nil {
-			continue
-		}
-		if strings.Contains(info.Config.Image, "linuxserver/syncthing") {
-			if v.State != "running" {
-				//step:start container
-				service.MyService.Docker().DockerContainerStart(v.ID)
-			}
-			syncIsExistence = true
-			if config.SystemConfigInfo.SyncPort != v.Labels["web"] {
-				config.SystemConfigInfo.SyncPort = v.Labels["web"]
-			}
-
-			path := ""
-			for _, i := range info.Mounts {
-				if i.Destination == "/config" {
-					path = i.Source
-					break
-				}
-			}
-			content := file.ReadFullFile(filepath.Join(path, "config.xml"))
-			syncConfig := &system_app.SyncConfig{}
-			xml.Unmarshal(content, &syncConfig)
-			config.SystemConfigInfo.SyncKey = syncConfig.Key
-			break
-		}
-	}
-	if !syncIsExistence {
-		installSyncthing("74")
-	}
-}
 func CheckSerialDiskMount() {
 	// check mount point
 	dbList := service.MyService.Disk().GetSerialAll()
@@ -216,31 +81,11 @@ func CheckToken2_11() {
 		config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
 	}
 
-	sysType := runtime.GOOS
-	if len(config.FileSettingInfo.DownloadDir) == 0 {
-		downloadPath := "/DATA/Downloads"
-		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)
-		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)
-	}
 
 	if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") {
 		service.MyService.System().UpdateUSBAutoMount("False")
@@ -279,9 +124,9 @@ func MoveUserToDB() {
 
 	if len(config.UserInfo.UserName) > 0 && service.MyService.User().GetUserInfoByUserName(config.UserInfo.UserName).Id == 0 {
 		user := model2.UserDBModel{}
-		user.UserName = config.UserInfo.UserName
+		user.Username = config.UserInfo.UserName
 		user.Email = config.UserInfo.Email
-		user.NickName = config.UserInfo.NickName
+		user.Nickname = config.UserInfo.NickName
 		user.Password = encryption.GetMD5ByStr(config.UserInfo.PWD)
 		user.Role = "admin"
 		user = service.MyService.User().CreateUser(user)

+ 1 - 11
route/periodical.go

@@ -2,17 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-07-01 15:11:36
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-01 15:16:00
- * @FilePath: /CasaOS/route/periodical.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2022-05-27 15:55:36
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-29 16:47:19
+ * @LastEditTime: 2022-07-21 15:25:07
  * @FilePath: /CasaOS/route/periodical.go
  * @Description:
  * @Website: https://www.casaos.io

+ 147 - 154
route/route.go

@@ -23,6 +23,7 @@ func InitRouter() *gin.Engine {
 	r.Use(middleware.WriteLog())
 	r.Use(gzip.Gzip(gzip.DefaultCompression))
 	gin.SetMode(config.ServerInfo.RunMode)
+
 	r.StaticFS("/ui", http.FS(web.Static))
 	r.GET("/", WebUIHome)
 	// r.StaticFS("/assets", http.Dir("./static/assets"))
@@ -31,199 +32,191 @@ func InitRouter() *gin.Engine {
 	//	c.Redirect(http.StatusMovedPermanently, "ui/")
 	//})
 
-	r.POST("/v1/user/register/:key", v1.PostUserRegister)
-	r.POST("/v1/user/login", v1.PostUserLogin) //
-	r.GET("/v1/user/all/name", v1.GetUserAllUserName)
-
-	r.GET("/v1/sys/init/check", v1.GetSystemInitCheck)
-	r.GET("/v1/guide/check", v1.GetGuideCheck)
-	r.GET("/v1/debug", v1.GetSystemConfigDebug)
-	r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
-	r.GET("/v1/user/info/:id", v1.GetUserInfo)
-	r.GET("/v1/user/avatar/:id", v1.GetUserAvatar)
-	r.GET("/v1/user/image", v1.GetUserImage)
-
-	//get user info
-	r.GET("/v1/person/shareid", v1.GetPersonShareId)
-	r.GET("/v1/sys/socket/port", v1.GetSystemSocketPort)
-	//r.POST("/v1/user/refresh/token", v1.PostUserRefreshToken)
+	r.POST("/v1/users/register", v1.PostUserRegister)
+	r.POST("/v1/users/login", v1.PostUserLogin)
+	r.GET("/v1/users/name", v1.GetUserAllUsername) //all/name
+	r.POST("/v1/user/refresh", v1.PostUserRefreshToken)
+	// No short-term modifications
+	r.GET("/v1/users/image", v1.GetUserImage)
+
+	r.GET("/v1/users/status", v1.GetUserStatus) //init/check
+	//r.GET("/v1/guide/check", v1.GetGuideCheck)         // /v1/sys/guide_check
+	r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
+
+	r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port
+
 	v1Group := r.Group("/v1")
 
 	v1Group.Use(jwt2.JWT())
 	{
-		v1UserGroup := v1Group.Group("/user")
-		v1UserGroup.Use()
+		v1UsersGroup := v1Group.Group("/users")
+		v1UsersGroup.Use()
 		{
+			v1UsersGroup.GET("/current", v1.GetUserInfo)
+			v1UsersGroup.PUT("/current", v1.PutUserInfo)
+			v1UsersGroup.PUT("/current/password", v1.PutUserPassword)
+
+			v1UsersGroup.GET("/current/custom/:key", v1.GetUserCustomConf)
+			v1UsersGroup.POST("/current/custom/:key", v1.PostUserCustomConf)
+			v1UsersGroup.DELETE("/current/custom/:key", v1.DeleteUserCustomConf)
+
+			v1UsersGroup.POST("/current/image/:key", v1.PostUserUploadImage)
+			v1UsersGroup.PUT("/current/image/:key", v1.PutUserImage)
+			//v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage)
+			v1UsersGroup.DELETE("/current/image", v1.DeleteUserImage)
+
+			//v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
+			//v1UserGroup.GET("/avatar", v1.GetUserAvatar)
+			v1UsersGroup.DELETE("/:id", v1.DeleteUser)
+			v1UsersGroup.GET("/:username", v1.GetUserInfoByUsername)
+			v1UsersGroup.DELETE("", v1.DeleteUserAll)
+		}
 
-			//****************** New version needs to be modified start ******************
-			//chang user name
-			v1UserGroup.PUT("/username", v1.PutUserName)
-			v1UserGroup.PUT("/password", v1.PutUserPwd)
-			v1UserGroup.PUT("/nick", v1.PutUserNick)
-			v1UserGroup.PUT("/desc", v1.PutUserDesc)
-			v1UserGroup.GET("/info", v1.GetUserInfoByUserName)
-			v1UserGroup.GET("/custom/:id/:key", v1.GetUserCustomConf)
-			v1UserGroup.POST("/custom/:id/:key", v1.PostUserCustomConf)
-			v1UserGroup.DELETE("/custom/:id/:key", v1.DeleteUserCustomConf)
-			v1UserGroup.POST("/upload/image/:id/:key", v1.PostUserUploadImage)
-			v1UserGroup.POST("/file/image/:id/:key", v1.PostUserFileImage)
-			v1UserGroup.DELETE("/image/:id", v1.DeleteUserImage)
-			//****************** New version needs to be modified end ******************
-
-			//****************** soon to be removed start ******************
-			v1UserGroup.POST("/person/info", v1.PostUserPersonInfo)
-			v1UserGroup.GET("/shareid", v1.GetUserShareID)
-			//****************** soon to be removed  end ******************
-
-			//v1UserGroup.GET("/info", v1.GetUserInfo)
-
-			v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
-			v1UserGroup.GET("/avatar", v1.GetUserAvatar)
-			v1UserGroup.DELETE("/delete/:id", v1.DeleteUser)
+		v1AppsGroup := v1Group.Group("/apps")
+		v1AppsGroup.Use()
+		{
+			v1AppsGroup.GET("", v1.AppList) //list
+			v1AppsGroup.GET("/:id", v1.AppInfo)
+		}
+		v1ContainerGroup := v1Group.Group("/container")
+		v1ContainerGroup.Use()
+		{
+			v1ContainerGroup.GET("", v1.MyAppList) ///my/list
+			v1ContainerGroup.GET("/usage", v1.AppUsageList)
+			v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo)    ///update/:id/info
+			v1ContainerGroup.GET("/:id/logs", v1.ContainerLog)      // /app/logs/:id
+			v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) //app/install/config
+
+			v1ContainerGroup.GET("/:id/state", v1.GetContainerState) //app/state/:id ?state=install_progress
+			// there are problems, temporarily do not deal with
+			v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) //app/terminal/:id
+			v1ContainerGroup.POST("", v1.InstallApp)                 //app/install
+			//v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
+
+			v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting
+
+			v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id
+			v1ContainerGroup.DELETE("/:id", v1.UnInstallApp)     //app/uninstall/:id
+			//Not used
+			v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate)
+			//Not used
+			v1ContainerGroup.POST("/share", v1.ShareAppFile)
 
 		}
-		v1AppGroup := v1Group.Group("/app")
-		v1AppGroup.Use()
+		v1AppCategoriesGroup := v1Group.Group("/app-categories")
+		v1AppCategoriesGroup.Use()
 		{
-			//获取我的已安装的列表
-			v1AppGroup.GET("/my/list", v1.MyAppList)
-			//
-			v1AppGroup.GET("/usage", v1.AppUsageList)
-			//app详情
-			v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
-			//获取未安装的列表
-			v1AppGroup.GET("/list", v1.AppList)
-			//获取端口
-			v1AppGroup.GET("/port", v1.GetPort)
-			//检查端口
-			v1AppGroup.GET("/check/:port", v1.PortCheck)
-
-			v1AppGroup.GET("/category", v1.CategoryList)
-
-			v1AppGroup.GET("/terminal/:id", v1.DockerTerminal)
-			//app容器详情
-			v1AppGroup.GET("/info/:id", v1.ContainerInfo)
-			//app容器日志
-			v1AppGroup.GET("/logs/:id", v1.ContainerLog)
-			//暂停或启动容器
-			v1AppGroup.PUT("/state/:id", v1.ChangAppState)
-			//安装app
-			v1AppGroup.POST("/install", v1.InstallApp)
-			//卸载app
-			v1AppGroup.DELETE("/uninstall/:id", v1.UnInstallApp)
-			//获取进度
-			v1AppGroup.GET("/state/:id", v1.GetContainerState)
-			//更新容器配置
-			v1AppGroup.PUT("/update/:id/setting", v1.UpdateSetting)
-			//获取可能新数据
-			v1AppGroup.GET("/update/:id/info", v1.ContainerUpdateInfo)
-			v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
-			v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
-			v1AppGroup.PUT("/update/:id", v1.PutAppUpdate)
-			v1AppGroup.POST("/share", v1.ShareAppFile)
+			v1AppCategoriesGroup.GET("", v1.CategoryList)
 		}
 
 		v1SysGroup := v1Group.Group("/sys")
 		v1SysGroup.Use()
 		{
-			v1SysGroup.GET("/version/check", v1.GetSystemCheckVersion)
-			v1SysGroup.GET("/hardware/info", v1.GetSystemHardwareInfo)
+			v1SysGroup.GET("/version", v1.GetSystemCheckVersion) //version/check
 			v1SysGroup.POST("/update", v1.SystemUpdate)
+
+			v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) //hardware/info
+
 			v1SysGroup.GET("/wsssh", v1.WsSsh)
-			v1SysGroup.GET("/config", v1.GetSystemConfig)
+			v1SysGroup.POST("/ssh-login", v1.PostSshLogin)
+			//v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
 			//v1SysGroup.POST("/config", v1.PostSetSystemConfig)
-			v1SysGroup.GET("/error/logs", v1.GetCasaOSErrorLogs)
-			v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
-			v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
-			v1SysGroup.GET("/port", v1.GetCasaOSPort)
-			v1SysGroup.PUT("/port", v1.PutCasaOSPort)
+			v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) //error/logs
+			//v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
+			//v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete
+
 			v1SysGroup.POST("/stop", v1.PostKillCasaOS)
+
 			v1SysGroup.GET("/utilization", v1.GetSystemUtilization)
-			v1SysGroup.PUT("/usb/:status", v1.PutSystemUSBAutoMount)
-			v1SysGroup.GET("/usb/status", v1.GetSystemUSBAutoMount)
-			v1SysGroup.GET("/cpu", v1.GetSystemCupInfo)
-			v1SysGroup.GET("/mem", v1.GetSystemMemInfo)
-			v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
-			v1SysGroup.GET("/network", v1.GetSystemNetInfo)
+			// v1SysGroup.GET("/cpu", v1.GetSystemCupInfo)
+			// v1SysGroup.GET("/mem", v1.GetSystemMemInfo)
+			// v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
+			// v1SysGroup.GET("/network", v1.GetSystemNetInfo)
+
+			v1SysGroup.PUT("/usb-auto-mount", v1.PutSystemUSBAutoMount) ///sys/usb/:status
+			v1SysGroup.GET("/usb-auto-mount", v1.GetSystemUSBAutoMount) ///sys/usb/status
+
+			v1SysGroup.GET("/server-info", nil)
+			v1SysGroup.PUT("/server-info", nil)
+			v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus)
+			v1SysGroup.GET("/port", v1.GetCasaOSPort)
+			v1SysGroup.PUT("/port", v1.PutCasaOSPort)
+		}
+		v1PortGroup := v1Group.Group("/port")
+		v1PortGroup.Use()
+		{
+			v1PortGroup.GET("/", v1.GetPort)              //app/port
+			v1PortGroup.GET("/state/:port", v1.PortCheck) //app/check/:port
 		}
+
 		v1FileGroup := v1Group.Group("/file")
 		v1FileGroup.Use()
 		{
-			v1FileGroup.PUT("/rename", v1.RenamePath)
-			v1FileGroup.GET("/read", v1.GetFilerContent)
+			v1FileGroup.GET("", v1.GetDownloadSingleFile) //download/:path
+			v1FileGroup.POST("", v1.PostCreateFile)
+			v1FileGroup.PUT("", v1.PutFileContent)
+			v1FileGroup.PUT("/name", v1.RenamePath)
+			//file/rename
+			v1FileGroup.GET("/content", v1.GetFilerContent) //file/read
+
+			//File uploads need to be handled separately, and will not be modified here
 			v1FileGroup.POST("/upload", v1.PostFileUpload)
 			v1FileGroup.GET("/upload", v1.GetFileUpload)
-			v1FileGroup.GET("/dirpath", v1.DirPath)
-			//create folder
-			v1FileGroup.POST("/mkdir", v1.MkdirAll)
-			v1FileGroup.POST("/create", v1.PostCreateFile)
-
-			v1FileGroup.GET("/download", v1.GetDownloadFile)
-			v1FileGroup.GET("/download/*path", v1.GetDownloadSingleFile)
-			v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
-			v1FileGroup.DELETE("/delete", v1.DeleteFile)
-			v1FileGroup.PUT("/update", v1.PutFileContent)
-			v1FileGroup.GET("/image", v1.GetFileImage)
-			v1FileGroup.DELETE("/operate/:id", v1.DeleteOperateFileOrDir)
 			//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
 		}
-		v1DiskGroup := v1Group.Group("/disk")
-		v1DiskGroup.Use()
+		v1FolderGroup := v1Group.Group("/folder")
+		v1FolderGroup.Use()
+		{
+			v1FolderGroup.PUT("/name", v1.RenamePath)
+			v1FolderGroup.GET("", v1.DirPath)   ///file/dirpath
+			v1FolderGroup.POST("", v1.MkdirAll) ///file/mkdir
+		}
+		v1BatchGroup := v1Group.Group("/batch")
+		v1BatchGroup.Use()
 		{
-			v1DiskGroup.GET("/check", v1.GetDiskCheck)
-
-			v1DiskGroup.GET("/list", v1.GetDiskList)
-
-			//获取磁盘详情
-			v1DiskGroup.GET("/info", v1.GetDiskInfo)
 
-			//format storage
-			v1DiskGroup.POST("/format", v1.PostDiskFormat)
+			v1BatchGroup.DELETE("", v1.DeleteFile) //file/delete
+			v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
+			v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) //file/operate
+			v1BatchGroup.GET("", v1.GetDownloadFile)
+		}
+		v1ImageGroup := v1Group.Group("/image")
+		v1ImageGroup.Use()
+		{
+			v1ImageGroup.GET("", v1.GetFileImage)
+		}
 
-			// add storage
-			v1DiskGroup.POST("/storage", v1.PostDiskAddPartition)
+		v1DisksGroup := v1Group.Group("/disks")
+		v1DisksGroup.Use()
+		{
+			//v1DiskGroup.GET("/check", v1.GetDiskCheck) //delete
+			//v1DisksGroup.GET("", v1.GetDiskInfo)
 
-			//mount SATA disk
-			v1DiskGroup.POST("/mount", v1.PostMountDisk)
+			//v1DisksGroup.POST("", v1.PostMountDisk)
+			v1DisksGroup.GET("", v1.GetDiskList)
+			// //format storage
+			// v1DiskGroup.POST("/format", v1.PostDiskFormat)
 
-			//umount sata disk
-			v1DiskGroup.POST("/umount", v1.PostDiskUmount)
+			// //mount SATA disk
+			// v1DiskGroup.POST("/mount", v1.PostMountDisk)
 
-			//获取可以格式化的内容
-			v1DiskGroup.GET("/type", v1.FormatDiskType)
+			// //umount sata disk
+			// v1DiskGroup.POST("/umount", v1.PostDiskUmount)
 
-			//删除分区
-			v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
-			v1DiskGroup.GET("/usb", v1.GetUSBList)
+			//v1DiskGroup.GET("/type", v1.FormatDiskType)//delete
 
+			v1DisksGroup.DELETE("/part", v1.RemovePartition) //disk/delpart
 		}
-		v1PersonGroup := v1Group.Group("/person")
-		v1PersonGroup.Use()
+
+		v1StorageGroup := v1Group.Group("/storage")
+		v1StorageGroup.Use()
 		{
-			v1PersonGroup.GET("/detection", v1.GetPersonDetection)
-			v1PersonGroup.GET("/users", v1.GetPersonFriend)
-			v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend)
-			v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend)
-			v1PersonGroup.GET("/directory", v1.GetPersonDirectory)
-			v1PersonGroup.GET("/file", v1.GetPersonFile)
-			v1PersonGroup.GET("/refile/:uuid", v1.GetPersonReFile)
-			v1PersonGroup.PUT("/remarks/:shareid", v1.PutPersonRemarks)
-			v1PersonGroup.GET("/list", v1.GetPersonDownloadList)
-			v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile)
-
-			v1PersonGroup.POST("/share", v1.PostPersonShare)
-			v1PersonGroup.POST("/file/:shareid", v1.PostPersonFile)
-			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)
-			v1PersonGroup.PUT("/friend/:shareid", v1.PutPersonAgreeFriend)
-			v1PersonGroup.PUT("/write/:shareid", v1.PutPersonWrite)
-			v1PersonGroup.GET("/image/thumbnail/:shareid", v1.GetPersonImageThumbnail)
+			v1StorageGroup.POST("", v1.PostDiskAddPartition)
+
+			v1StorageGroup.PUT("", v1.PostDiskFormat)
 
+			v1StorageGroup.DELETE("", v1.PostDiskUmount)
 		}
-		v1Group.GET("/sync/config", v1.GetSyncConfig)
 	}
 	return r
 }

+ 27 - 15
route/v1/app.go

@@ -3,7 +3,6 @@ package v1
 import (
 	"encoding/json"
 	"io/ioutil"
-	"net/http"
 	"strconv"
 
 	"github.com/IceWhaleTech/CasaOS/model"
@@ -37,10 +36,14 @@ func AppList(c *gin.Context) {
 	categoryId := c.DefaultQuery("category_id", "0")
 	key := c.DefaultQuery("key", "")
 	if len(index) == 0 || len(size) == 0 || len(t) == 0 || len(categoryId) == 0 {
-		c.JSON(http.StatusOK, &model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		return
+	}
+	collection, err := service.MyService.Casa().GetServerList(index, size, t, categoryId, key)
+	if err != nil {
+		c.JSON(common_err.SERVICE_ERROR, &model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
-	collection := service.MyService.Casa().GetServerList(index, size, t, categoryId, key)
 	// for i := 0; i < len(recommend); i++ {
 	// 	ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
 	// 	if ct != nil {
@@ -64,7 +67,7 @@ func AppList(c *gin.Context) {
 	data["list"] = collection.List
 	data["community"] = collection.Community
 
-	c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 // @Summary 获取一个可用端口
@@ -83,7 +86,8 @@ func GetPort(c *gin.Context) {
 		p, _ = port2.GetAvailablePort(t)
 		ok = !port2.IsPortAvailable(p, t)
 	}
-	c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
+	// @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
 }
 
 // @Summary 检查端口是否可用
@@ -98,7 +102,7 @@ func GetPort(c *gin.Context) {
 func PortCheck(c *gin.Context) {
 	p, _ := strconv.Atoi(c.Param("port"))
 	t := c.DefaultQuery("type", "tcp")
-	c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port2.IsPortAvailable(p, t)})
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port2.IsPortAvailable(p, t)})
 }
 
 // @Summary 我的应用列表
@@ -117,10 +121,10 @@ func MyAppList(c *gin.Context) {
 	position, _ := strconv.ParseBool(c.DefaultQuery("position", "true"))
 	list, unTranslation := service.MyService.App().GetMyList(index, size, position)
 	data := make(map[string]interface{}, 2)
-	data["list"] = list
-	data["local"] = unTranslation
+	data["casaos_apps"] = list
+	data["local_apps"] = unTranslation
 
-	c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 // @Summary my app hardware usage list
@@ -132,7 +136,7 @@ func MyAppList(c *gin.Context) {
 // @Router /app/usage [get]
 func AppUsageList(c *gin.Context) {
 	list := service.MyService.App().GetHardwareUsage()
-	c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
 }
 
 // @Summary 应用详情
@@ -147,7 +151,11 @@ func AppInfo(c *gin.Context) {
 
 	id := c.Param("id")
 	language := c.GetHeader("Language")
-	info := service.MyService.Casa().GetServerAppInfo(id, "", language)
+	info, err := service.MyService.Casa().GetServerAppInfo(id, "", language)
+	if err != nil {
+		c.JSON(common_err.SERVICE_ERROR, &model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
+		return
+	}
 	if info.NetworkModel != "host" {
 		for i := 0; i < len(info.Ports); i++ {
 			if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
@@ -214,7 +222,7 @@ func AppInfo(c *gin.Context) {
 
 	info.MaxMemory = (service.MyService.System().GetMemInfo()["total"]).(uint64) >> 20
 
-	c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
 }
 
 // @Summary 获取远程分类列表
@@ -225,7 +233,11 @@ func AppInfo(c *gin.Context) {
 // @Success 200 {string} string "ok"
 // @Router /app/category [get]
 func CategoryList(c *gin.Context) {
-	list := service.MyService.Casa().GetServerCategoryList()
+	list, err := service.MyService.Casa().GetServerCategoryList()
+	if err != nil {
+		c.JSON(common_err.SERVICE_ERROR, &model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
+		return
+	}
 	var count uint = 0
 	for _, category := range list {
 		count += category.Count
@@ -234,7 +246,7 @@ func CategoryList(c *gin.Context) {
 	rear := append([]model.CategoryList{}, list[0:]...)
 	list = append(list[:0], model.CategoryList{Count: count, Name: "All", Font: "apps"})
 	list = append(list, rear...)
-	c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
 }
 
 // @Summary 分享该应用配置
@@ -247,5 +259,5 @@ func CategoryList(c *gin.Context) {
 func ShareAppFile(c *gin.Context) {
 	str, _ := ioutil.ReadAll(c.Request.Body)
 	content := service.MyService.Casa().ShareAppFile(str)
-	c.JSON(http.StatusOK, json.RawMessage(content))
+	c.JSON(common_err.SUCCESS, json.RawMessage(content))
 }

+ 134 - 135
route/v1/disk.go

@@ -9,8 +9,9 @@ import (
 	"time"
 
 	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
+	"github.com/IceWhaleTech/CasaOS/model/notify"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
+	"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
 	"github.com/IceWhaleTech/CasaOS/service"
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
@@ -28,7 +29,42 @@ var diskMap = make(map[string]string)
 // @Success 200 {string} string "ok"
 // @Router /disk/list [get]
 func GetDiskList(c *gin.Context) {
+	path := c.Query("path")
+	if len(path) > 0 {
+		m := service.MyService.Disk().GetDiskInfo(path)
+		c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
+		return
+	}
+	t := c.DefaultQuery("type", "")
 	list := service.MyService.Disk().LSBLK(false)
+	if t == "usb" {
+		data := []model.DriveUSB{}
+		for _, v := range list {
+			if v.Tran == "usb" {
+				temp := model.DriveUSB{}
+				temp.Model = v.Model
+				temp.Name = v.Name
+				temp.Size = v.Size
+				mountTemp := true
+				if len(v.Children) == 0 {
+					mountTemp = false
+				}
+				for _, child := range v.Children {
+					if len(child.MountPoint) > 0 {
+						avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
+						temp.Avail += avail
+					} else {
+						mountTemp = false
+					}
+				}
+				temp.Mount = mountTemp
+				data = append(data, temp)
+			}
+		}
+		c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+		return
+	}
+
 	dbList := service.MyService.Disk().GetSerialAll()
 	part := make(map[string]int64, len(dbList))
 	for _, v := range dbList {
@@ -154,7 +190,7 @@ func GetDiskList(c *gin.Context) {
 	data["storage"] = storage
 	data["avail"] = avail
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 // @Summary get disk list
@@ -191,49 +227,6 @@ func GetDiskInfo(c *gin.Context) {
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
 }
 
-// @Summary format storage
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags disk
-// @Security ApiKeyAuth
-// @Param  path formData string true "e.g. /dev/sda1"
-// @Param  pwd formData string true "user password"
-// @Param  volume formData string true "mount point"
-// @Success 200 {string} string "ok"
-// @Router /disk/format [post]
-func PostDiskFormat(c *gin.Context) {
-	path := c.PostForm("path")
-	t := "ext4"
-	pwd := c.PostForm("pwd")
-	volume := c.PostForm("volume")
-
-	if pwd != config.UserInfo.PWD {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
-		return
-	}
-
-	if len(path) == 0 || len(t) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	if _, ok := diskMap[path]; ok {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
-		return
-	}
-	diskMap[path] = "busying"
-	service.MyService.Disk().UmountPointAndRemoveDir(path)
-	format := service.MyService.Disk().FormatDisk(path, t)
-	if len(format) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
-		delete(diskMap, path)
-		return
-	}
-	service.MyService.Disk().MountDisk(path, volume)
-	service.MyService.Disk().RemoveLSBLKCache()
-	delete(diskMap, path)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
 // @Summary 获取支持的格式
 // @Produce  application/json
 // @Accept application/json
@@ -256,15 +249,17 @@ func FormatDiskType(c *gin.Context) {
 // @Success 200 {string} string "ok"
 // @Router /disk/delpart [delete]
 func RemovePartition(c *gin.Context) {
-	path := c.PostForm("path")
+	js := make(map[string]string)
+	c.ShouldBind(&js)
+	path := js["path"]
 
 	if len(path) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 	}
 	var p = path[:len(path)-1]
 	var n = path[len(path)-1:]
 	service.MyService.Disk().DelPartition(p, n)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary  add storage
@@ -280,32 +275,40 @@ func RemovePartition(c *gin.Context) {
 // @Router /disk/storage [post]
 func PostDiskAddPartition(c *gin.Context) {
 
-	name := c.PostForm("name")
-	path := c.PostForm("path")
-	format, _ := strconv.ParseBool(c.PostForm("format"))
+	js := make(map[string]interface{})
+	c.ShouldBind(&js)
+	path := js["path"].(string)
+	name := js["name"].(string)
+	format := js["format"].(bool)
 
 	if len(name) == 0 || len(path) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	if _, ok := diskMap[path]; ok {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
 		return
 	}
 	if !file.CheckNotExist("/DATA/" + name) {
 		// /mnt/name exist
-		c.JSON(http.StatusOK, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
 		return
 	}
 	diskMap[path] = "busying"
 	currentDisk := service.MyService.Disk().GetDiskInfo(path)
 	if !format {
 		if len(currentDisk.Children) != 1 || !(len(currentDisk.Children) > 0 && currentDisk.Children[0].FsType == "ext4") {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
 			delete(diskMap, path)
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
 			return
 		}
 	} else {
+		// format := service.MyService.Disk().FormatDisk(path+"1", "ext4")
+		// if len(format) == 0 {
+		// 	delete(diskMap, path)
+		// 	c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
+		// 	return
+		// }
 		service.MyService.Disk().AddPartition(path)
 	}
 
@@ -321,7 +324,7 @@ func PostDiskAddPartition(c *gin.Context) {
 	}
 	currentDisk = service.MyService.Disk().GetDiskInfo(path)
 	if len(currentDisk.Children) != 1 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
 		return
 	}
 
@@ -340,47 +343,61 @@ func PostDiskAddPartition(c *gin.Context) {
 	service.MyService.Disk().RemoveLSBLKCache()
 
 	delete(diskMap, path)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+
+	//send notify to client
+	msg := notify.StorageMessage{}
+	msg.Action = "ADDED"
+	msg.Path = currentDisk.Children[0].Path
+	msg.Volume = mountPath
+	msg.Size = currentDisk.Children[0].Size
+	msg.Type = currentDisk.Children[0].Tran
+	service.MyService.Notify().SendStorageBySocket(msg)
+
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
-// @Summary add mount point
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags disk
-// @Security ApiKeyAuth
-// @Param  path formData string true "for example: /dev/sda1"
-// @Param  serial formData string true "disk id"
+// @Param  pwd formData string true "user password"
+// @Param  volume formData string true "mount point"
 // @Success 200 {string} string "ok"
-// @Router /disk/mount [post]
-func PostMountDisk(c *gin.Context) {
-	// for example: path=/dev/sda1
-	path := c.PostForm("path")
-	serial := c.PostForm("serial")
-
-	mountPath := "/DATA/volume"
-	var list = service.MyService.Disk().GetSerialAll()
-	var pathMapList = make(map[string]string, len(list))
-	for _, v := range list {
-		pathMapList[v.MountPoint] = "1"
+// @Router /disk/format [post]
+func PostDiskFormat(c *gin.Context) {
+	id := c.GetHeader("user_id")
+	js := make(map[string]string)
+	c.ShouldBind(&js)
+	path := js["path"]
+	t := "ext4"
+	pwd := js["password"]
+	volume := js["volume"]
+	user := service.MyService.User().GetUserAllInfoById(id)
+	if user.Id == 0 {
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
+		return
 	}
-
-	for i := 0; i < len(list)+1; i++ {
-		if _, ok := pathMapList[mountPath+strconv.Itoa(i)]; !ok {
-			mountPath = mountPath + strconv.Itoa(i)
-			break
-		}
+	if encryption.GetMD5ByStr(pwd) != user.Password {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
+		return
 	}
 
-	//mount dir
-	service.MyService.Disk().MountDisk(path, mountPath)
-
-	m := model2.SerialDisk{}
-	m.MountPoint = mountPath
-	m.Path = path
-	m.UUID = serial
-	m.State = 0
-	//service.MyService.Disk().SaveMountPoint(m)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	if len(path) == 0 || len(t) == 0 {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		return
+	}
+	if _, ok := diskMap[path]; ok {
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
+		return
+	}
+	diskMap[path] = "busying"
+	service.MyService.Disk().UmountPointAndRemoveDir(path)
+	format := service.MyService.Disk().FormatDisk(path, t)
+	if len(format) == 0 {
+		delete(diskMap, path)
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
+		return
+	}
+	service.MyService.Disk().MountDisk(path, volume)
+	service.MyService.Disk().RemoveLSBLKCache()
+	delete(diskMap, path)
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary remove mount point
@@ -394,22 +411,30 @@ func PostMountDisk(c *gin.Context) {
 // @Success 200 {string} string "ok"
 // @Router /disk/umount [post]
 func PostDiskUmount(c *gin.Context) {
+	id := c.GetHeader("user_id")
+	js := make(map[string]string)
+	c.ShouldBind(&js)
 
-	path := c.PostForm("path")
-	mountPoint := c.PostForm("volume")
-	pwd := c.PostForm("pwd")
+	path := js["path"]
+	mountPoint := js["volume"]
+	pwd := js["password"]
 
 	if len(path) == 0 || len(mountPoint) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
-	if pwd != config.UserInfo.PWD {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
+	user := service.MyService.User().GetUserAllInfoById(id)
+	if user.Id == 0 {
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
+		return
+	}
+	if encryption.GetMD5ByStr(pwd) != user.Password {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
 		return
 	}
 
 	if _, ok := diskMap[path]; ok {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
 		return
 	}
 
@@ -417,7 +442,16 @@ func PostDiskUmount(c *gin.Context) {
 	//delete data
 	service.MyService.Disk().DeleteMountPoint(path, mountPoint)
 	service.MyService.Disk().RemoveLSBLKCache()
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+
+	//send notify to client
+	msg := notify.StorageMessage{}
+	msg.Action = "REMOVED"
+	msg.Path = path
+	msg.Volume = mountPoint
+	msg.Size = 0
+	msg.Type = ""
+	service.MyService.Notify().SendStorageBySocket(msg)
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary confirm delete disk
@@ -455,45 +489,10 @@ func GetDiskCheck(c *gin.Context) {
 	for _, v := range dbList {
 		if _, ok := mapList[v.UUID]; !ok {
 			//disk undefind
-			c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: "disk undefind"})
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "disk undefind"})
 			return
 		}
 	}
 
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
-
-// @Summary check mount point
-// @Produce  application/json
-// @Accept application/json
-// @Tags disk
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /disk/usb [get]
-func GetUSBList(c *gin.Context) {
-	list := service.MyService.Disk().LSBLK(false)
-	data := []model.DriveUSB{}
-	for _, v := range list {
-		if v.Tran == "usb" {
-			temp := model.DriveUSB{}
-			temp.Model = v.Model
-			temp.Name = v.Name
-			temp.Size = v.Size
-			mountTemp := true
-			if len(v.Children) == 0 {
-				mountTemp = false
-			}
-			for _, child := range v.Children {
-				if len(child.MountPoint) > 0 {
-					avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
-					temp.Avail += avail
-				} else {
-					mountTemp = false
-				}
-			}
-			temp.Mount = mountTemp
-			data = append(data, temp)
-		}
-	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
-}

+ 132 - 111
route/v1/docker.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	json2 "encoding/json"
 	"net/http"
+	"os/exec"
 	"path/filepath"
 	"strconv"
 	"strings"
@@ -15,6 +16,7 @@ import (
 	"github.com/IceWhaleTech/CasaOS/pkg/docker"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
+	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
 	port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
 	"github.com/IceWhaleTech/CasaOS/service"
@@ -25,6 +27,7 @@ import (
 	"github.com/gorilla/websocket"
 	"github.com/jinzhu/copier"
 	uuid "github.com/satori/go.uuid"
+	"go.uber.org/zap"
 	"golang.org/x/crypto/ssh"
 )
 
@@ -41,14 +44,14 @@ func DockerTerminal(c *gin.Context) {
 	row := c.DefaultQuery("rows", "30")
 	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 	defer conn.Close()
 	container := c.Param("id")
 	hr, err := service.Exec(container, row, col)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 	// 关闭I/O流
@@ -63,14 +66,41 @@ func DockerTerminal(c *gin.Context) {
 	docker.WsReaderCopy(conn, hr.Conn)
 }
 
-//打开本机的ssh接口
+func PostSshLogin(c *gin.Context) {
+	j := make(map[string]string)
+	c.ShouldBind(&j)
+	userName := j["username"]
+	password := j["password"]
+	port := j["port"]
+	if userName == "" || password == "" || port == "" {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "Username or password or port is empty"})
+		return
+	}
+	_, err := docker.NewSshClient(userName, password, port)
+	if err != nil {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Please check if the username and port are correct, and make sure that ssh server is installed."})
+		loger.Error("connect ssh error", zap.Any("error", err))
+		return
+	}
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+}
+
 func WsSsh(c *gin.Context) {
-	wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
+	_, e := exec.LookPath("ssh")
+	if e != nil {
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "ssh server not found"})
+		return
+	}
 
+	userName := c.Query("username")
+	password := c.Query("password")
+	port := c.Query("port")
+	wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
 	var logBuff = new(bytes.Buffer)
+
 	quitChan := make(chan bool, 3)
-	user := ""
-	password := ""
+	// user := ""
+	// password := ""
 	var login int = 1
 	cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
 	rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
@@ -78,14 +108,16 @@ func WsSsh(c *gin.Context) {
 	for login != 0 {
 
 		var err error
-
-		wsConn.WriteMessage(websocket.TextMessage, []byte("login:"))
-		user = docker.ReceiveWsMsgUser(wsConn, logBuff)
-		wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
-		wsConn.WriteMessage(websocket.TextMessage, []byte("password:"))
-		password = docker.ReceiveWsMsgPassword(wsConn, logBuff)
-		wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
-		client, err = docker.NewSshClient(user, password)
+		if userName == "" || password == "" || port == "" {
+			wsConn.WriteMessage(websocket.TextMessage, []byte("username or password or port is empty"))
+		}
+		// wsConn.WriteMessage(websocket.TextMessage, []byte("login:"))
+		// user = docker.ReceiveWsMsgUser(wsConn, logBuff)
+		// wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
+		// wsConn.WriteMessage(websocket.TextMessage, []byte("password:"))
+		// password = docker.ReceiveWsMsgPassword(wsConn, logBuff)
+		// wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
+		client, err = docker.NewSshClient(userName, password, port)
 
 		if err != nil && client == nil {
 			wsConn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
@@ -110,25 +142,6 @@ func WsSsh(c *gin.Context) {
 
 }
 
-//安装进度推送
-func SpeedPush(c *gin.Context) {
-	//token := c.Query("token")
-	//if len(token) == 0 || token != config.UserInfo.Token {
-	//	c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN)})
-	//	return
-	//}
-
-	//ws, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
-	//defer ws.Close()
-	//
-	//for {
-	//	select {
-	//	case msg := <-WSMSG:
-	//		ws.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintln(msg)))
-	//	}
-	//}
-}
-
 // @Summary 安装app(该接口需要post json数据)
 // @Produce  application/json
 // @Accept application/json
@@ -144,7 +157,7 @@ func SpeedPush(c *gin.Context) {
 func InstallApp(c *gin.Context) {
 	var appInfo model.ServerAppList
 	m := model.CustomizationPostData{}
-	c.BindJSON(&m)
+	c.ShouldBind(&m)
 
 	const CUSTOM = "custom"
 	var dockerImage string
@@ -154,19 +167,22 @@ func InstallApp(c *gin.Context) {
 	if len(m.Protocol) == 0 {
 		m.Protocol = "http"
 	}
-	if m.Origin != "custom" {
-		oldName := m.Label
+	m.ContainerName = strings.Replace(m.Label, " ", "_", -1)
+	if m.Origin != CUSTOM {
+		oldName := m.ContainerName
+		oldLabel := m.Label
 		for i := 0; true; i++ {
 			if i != 0 {
-				m.Label = oldName + "-" + strconv.Itoa(i)
+				m.ContainerName = oldName + "-" + strconv.Itoa(i)
+				m.Label = oldLabel + "-" + strconv.Itoa(i)
 			}
-			if _, err := service.MyService.Docker().DockerListByName(m.Label); err != nil {
+			if _, err := service.MyService.Docker().DockerListByName(m.ContainerName); err != nil {
 				break
 			}
 		}
 	} else {
-		if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
+		if _, err := service.MyService.Docker().DockerListByName(m.ContainerName); err == nil {
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
 			return
 		}
 
@@ -177,7 +193,7 @@ func InstallApp(c *gin.Context) {
 		//c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		portMap, _ := strconv.Atoi(m.PortMap)
 		if !port2.IsPortAvailable(portMap, "tcp") {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + m.PortMap})
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + m.PortMap})
 			return
 		}
 	}
@@ -199,33 +215,33 @@ func InstallApp(c *gin.Context) {
 		if u.Protocol == "udp" {
 			t, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(t, "udp") {
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 		} else if u.Protocol == "tcp" {
 
 			te, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(te, "tcp") {
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 		} else if u.Protocol == "both" {
 			t, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(t, "udp") {
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 			te, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(te, "tcp") {
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 		}
 	}
-	if m.Origin == "custom" {
+	if m.Origin == CUSTOM {
 		for _, device := range m.Devices {
 			if file.CheckNotExist(device.Path) {
-				c.JSON(http.StatusOK, model.Result{Success: common_err.DEVICE_NOT_EXIST, Message: device.Path + "," + common_err.GetMsg(common_err.DEVICE_NOT_EXIST)})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DEVICE_NOT_EXIST, Message: device.Path + "," + common_err.GetMsg(common_err.DEVICE_NOT_EXIST)})
 				return
 			}
 
@@ -263,7 +279,7 @@ func InstallApp(c *gin.Context) {
 		// installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
 		// installLog.Id = uuid.NewV4().String()
 		// service.MyService.Notify().AddLog(installLog)
-		if m.Origin != "custom" {
+		if m.Origin != CUSTOM {
 			for _, plugin := range appInfo.Plugins {
 				if plugin == "mysql" {
 					mid := uuid.NewV4().String()
@@ -349,7 +365,7 @@ func InstallApp(c *gin.Context) {
 		//		echo -e "hellow\nworld" >>
 
 		//step:启动容器
-		err = service.MyService.Docker().DockerContainerStart(m.Label)
+		err = service.MyService.Docker().DockerContainerStart(m.ContainerName)
 		if err != nil {
 			//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
 			notify := notify.Application{}
@@ -372,7 +388,7 @@ func InstallApp(c *gin.Context) {
 		}
 
 		//step: 启动成功     检查容器状态确认启动成功
-		container, err := service.MyService.Docker().DockerContainerInfo(m.Label)
+		container, err := service.MyService.Docker().DockerContainerInfo(m.ContainerName)
 		if err != nil && container.ContainerJSONBase.State.Running {
 			notify := notify.Application{}
 			notify.Icon = m.Icon
@@ -405,7 +421,7 @@ func InstallApp(c *gin.Context) {
 
 	}()
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m.Label})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m.Label})
 
 }
 
@@ -426,7 +442,7 @@ func InstallApp(c *gin.Context) {
 //	//	appInfo := service.MyService.App().GetServerAppInfo(appId)
 //
 //	m := model.CustomizationPostData{}
-//	c.BindJSON(&m)
+//	c.ShouldBind(&m)
 //	//检查端口
 //	if len(m.PortMap) == 0 || m.PortMap == "0" {
 //		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
@@ -603,27 +619,27 @@ func UnInstallApp(c *gin.Context) {
 	appId := c.Param("id")
 
 	if len(appId) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	//info := service.MyService.App().GetUninstallInfo(appId)
 
 	info, err := service.MyService.Docker().DockerContainerInfo(appId)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 
 	//step:停止容器
 	err = service.MyService.Docker().DockerContainerStop(appId)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
 		return
 	}
 
 	err = service.MyService.Docker().DockerContainerRemove(appId, false)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
 		return
 	}
 
@@ -688,7 +704,7 @@ func UnInstallApp(c *gin.Context) {
 	notify.Success = true
 	notify.Finished = true
 	service.MyService.Notify().SendUninstallAppBySocket(notify)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 
 }
 
@@ -703,26 +719,35 @@ func UnInstallApp(c *gin.Context) {
 // @Router /app/state/{id} [put]
 func ChangAppState(c *gin.Context) {
 	appId := c.Param("id")
-	state := c.DefaultPostForm("state", "stop")
+	js := make(map[string]string)
+	c.ShouldBind(&js)
+	state := js["state"]
+	if len(appId) == 0 || len(state) == 0 {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		return
+	}
 	var err error
-	if state == "stop" {
-		err = service.MyService.Docker().DockerContainerStop(appId)
-	} else if state == "start" {
+	if state == "start" {
 		err = service.MyService.Docker().DockerContainerStart(appId)
 	} else if state == "restart" {
 		service.MyService.Docker().DockerContainerStop(appId)
 		err = service.MyService.Docker().DockerContainerStart(appId)
+	} else {
+		err = service.MyService.Docker().DockerContainerStop(appId)
 	}
+
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 	info, err := service.MyService.App().GetContainerInfo(appId)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info.State})
+
+	// @tiger - 用 {'state': ...} 来体现出参上下文
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info.State})
 }
 
 // @Summary 查看容器日志
@@ -736,7 +761,7 @@ func ChangAppState(c *gin.Context) {
 func ContainerLog(c *gin.Context) {
 	appId := c.Param("id")
 	log, _ := service.MyService.Docker().DockerContainerLog(appId)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: log})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: log})
 }
 
 // @Summary 获取容器状态
@@ -750,10 +775,10 @@ func ContainerLog(c *gin.Context) {
 // @Router /app/state/{id} [get]
 func GetContainerState(c *gin.Context) {
 	id := c.Param("id")
-	t := c.DefaultQuery("type", "0")
+	//t := c.DefaultQuery("type", "0")
 	containerInfo, e := service.MyService.App().GetSimpleContainerInfo(id)
 	if e != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: e.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: e.Error()})
 		return
 	}
 
@@ -761,12 +786,12 @@ func GetContainerState(c *gin.Context) {
 
 	data["state"] = containerInfo.State
 
-	if t == "1" {
-		appInfo := service.MyService.App().GetAppDBInfo(id)
-		data["app"] = appInfo
-	}
+	// if t == "1" {
+	// 	appInfo := service.MyService.App().GetAppDBInfo(id)
+	// 	data["app"] = appInfo
+	// }
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 // @Summary 更新设置
@@ -786,10 +811,10 @@ func UpdateSetting(c *gin.Context) {
 	id := c.Param("id")
 	const CUSTOM = "custom"
 	m := model.CustomizationPostData{}
-	c.BindJSON(&m)
+	c.ShouldBind(&m)
 
 	if len(id) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	//var cpd model.CustomizationPostData
@@ -809,7 +834,7 @@ func UpdateSetting(c *gin.Context) {
 	portMap, _ := strconv.Atoi(m.PortMap)
 	if !port2.IsPortAvailable(portMap, "tcp") {
 		service.MyService.Docker().DockerContainerStart(id)
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + m.PortMap})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + m.PortMap})
 		return
 	}
 
@@ -819,28 +844,28 @@ func UpdateSetting(c *gin.Context) {
 			t, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(t, "udp") {
 				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 		} else if u.Protocol == "tcp" {
 			te, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(te, "tcp") {
 				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 		} else if u.Protocol == "both" {
 			t, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(t, "udp") {
 				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 
 			te, _ := strconv.Atoi(u.CommendPort)
 			if !port2.IsPortAvailable(te, "tcp") {
 				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
+				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
 				return
 			}
 		}
@@ -851,9 +876,9 @@ func UpdateSetting(c *gin.Context) {
 
 	containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, m)
 	if err != nil {
-		service.MyService.Docker().DockerContainerUpdateName(m.Label, id)
+		service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
 		service.MyService.Docker().DockerContainerStart(id)
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
 		return
 	}
 	//		echo -e "hellow\nworld" >>
@@ -862,7 +887,7 @@ func UpdateSetting(c *gin.Context) {
 	err = service.MyService.Docker().DockerContainerStart(containerId)
 
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
 		return
 	}
 	service.MyService.Docker().DockerContainerRemove(id, true)
@@ -933,7 +958,7 @@ func UpdateSetting(c *gin.Context) {
 
 	//service.MyService.App().UpdateApp(appInfo)
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary update app version
@@ -948,20 +973,20 @@ func PutAppUpdate(c *gin.Context) {
 	id := c.Param("id")
 
 	if len(id) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 
 	inspect, err := service.MyService.Docker().DockerContainerInfo(id)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 
 	}
 	imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest"
 	err = service.MyService.Docker().DockerPullImage(imageLatest, "", "")
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 
 	}
@@ -974,7 +999,7 @@ func PutAppUpdate(c *gin.Context) {
 	if err != nil {
 		service.MyService.Docker().DockerContainerUpdateName(inspect.Name, id)
 		service.MyService.Docker().DockerContainerStart(id)
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
 		return
 	}
 
@@ -982,13 +1007,13 @@ func PutAppUpdate(c *gin.Context) {
 	err = service.MyService.Docker().DockerContainerStart(containerId)
 
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
 		return
 	}
 	service.MyService.Docker().DockerContainerRemove(id, true)
 	delete(service.NewVersionApp, id)
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary 获取容器详情
@@ -1001,6 +1026,8 @@ func PutAppUpdate(c *gin.Context) {
 // @Router /app/info/{id} [get]
 func ContainerInfo(c *gin.Context) {
 	appId := c.Param("id")
+
+	// @tiger - 作为最佳实践,不应该直接把数据库的信息返回,来避免未来数据库结构上的迭代带来的新字段
 	appInfo := service.MyService.App().GetAppDBInfo(appId)
 	containerInfo, _ := service.MyService.Docker().DockerContainerStats(appId)
 	var cpuModel = "arm"
@@ -1015,44 +1042,34 @@ func ContainerInfo(c *gin.Context) {
 	info, err := service.MyService.Docker().DockerContainerInfo(appId)
 	if err != nil {
 		//todo 需要自定义错误
-		c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 	con := struct {
 		Status    string `json:"status"`
 		StartedAt string `json:"started_at"`
 		CPUShares int64  `json:"cpu_shares"`
-		Memory    int64  `json:"memory"`
-		Restart   string `json:"restart"`
+		Memory    int64  `json:"total_memory"`   // @tiger - 改成 total_memory,方便以后增加 free_memory 之类的字段
+		Restart   string `json:"restart_policy"` // @tiger - 改成 restart_policy?
 	}{Status: info.State.Status, StartedAt: info.State.StartedAt, CPUShares: info.HostConfig.CPUShares, Memory: info.HostConfig.Memory >> 20, Restart: info.HostConfig.RestartPolicy.Name}
 	data := make(map[string]interface{}, 5)
-	data["app"] = appInfo
-	data["cpu"] = cpuModel
-	data["memory"] = service.MyService.System().GetMemInfo()["total"]
+	data["app"] = appInfo                                             // @tiget - 最佳实践是,返回 appid,然后具体的 app 信息由前端另行获取
+	data["cpu"] = cpuModel                                            // @tiger - 改成 arch
+	data["memory"] = service.MyService.System().GetMemInfo()["total"] // @tiger - 改成 total_memory,方便以后增加 free_memory 之类的字段
 	data["container"] = json2.RawMessage(containerInfo)
 	data["info"] = con
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
-// @Summary 获取安装所需要的数据
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/install/config [get]
-func GetDockerInstallConfig(c *gin.Context) {
+func GetDockerNetworks(c *gin.Context) {
 	networks := service.MyService.Docker().DockerNetworkModelList()
-	data := make(map[string]interface{}, 2)
 	list := []map[string]string{}
 	for _, network := range networks {
 		if network.Driver != "null" {
 			list = append(list, map[string]string{"name": network.Name, "driver": network.Driver, "id": network.ID})
 		}
 	}
-	data["networks"] = list
-	data["memory"] = service.MyService.System().GetMemInfo()
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
 }
 
 // @Summary 获取依赖数据
@@ -1069,7 +1086,6 @@ func ContainerRelyInfo(c *gin.Context) {
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: appInfo})
 }
 
-// @Summary 获取可更新数据
 // @Produce  application/json
 // @Accept application/json
 // @Tags app
@@ -1083,7 +1099,7 @@ func ContainerUpdateInfo(c *gin.Context) {
 	info, err := service.MyService.Docker().DockerContainerInfo(appId)
 	if err != nil {
 
-		c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: err.Error()})
 		return
 	}
 	var port model.PortArray
@@ -1161,7 +1177,7 @@ func ContainerUpdateInfo(c *gin.Context) {
 	}
 	m.NetworkModel = string(info.HostConfig.NetworkMode)
 	m.Description = info.Config.Labels["desc"]
-	m.Label = strings.ReplaceAll(info.Name, "/", "")
+	m.ContainerName = strings.ReplaceAll(info.Name, "/", "")
 	m.PortMap = info.Config.Labels["web"]
 	m.Devices = driver
 	m.Envs = envs
@@ -1181,6 +1197,11 @@ func ContainerUpdateInfo(c *gin.Context) {
 	m.Cmd = info.Config.Cmd
 	m.HostName = info.Config.Hostname
 	m.Privileged = info.HostConfig.Privileged
+	name := info.Config.Labels["name"]
+	if len(name) == 0 {
+		name = strings.ReplaceAll(info.Name, "/", "")
+	}
+	m.Label = name
 
 	m.Protocol = info.Config.Labels["protocol"]
 	if m.Protocol == "" {

+ 62 - 78
route/v1/file.go

@@ -1,9 +1,6 @@
 package v1
 
 import (
-	"bufio"
-	"encoding/csv"
-	"fmt"
 	"io"
 	"io/ioutil"
 	"log"
@@ -26,32 +23,6 @@ import (
 	uuid "github.com/satori/go.uuid"
 )
 
-func downloadReadFile(c *gin.Context) {
-	//http下载地址 csv
-	csvFileUrl := c.PostForm("file_name")
-	res, err := http.Get(csvFileUrl)
-	if err != nil {
-		c.String(400, err.Error())
-		return
-	}
-	defer res.Body.Close()
-	//读取csv
-	reader := csv.NewReader(bufio.NewReader(res.Body))
-	for {
-		line, err := reader.Read()
-		if err == io.EOF {
-			break
-		} else if err != nil {
-			c.String(400, err.Error())
-			return
-		}
-		//line 就是每一行的内容
-		fmt.Println(line)
-		//line[0] 就是第几列
-		fmt.Println(line[0])
-	}
-}
-
 // @Summary 读取文件
 // @Produce  application/json
 // @Accept application/json
@@ -63,14 +34,14 @@ func downloadReadFile(c *gin.Context) {
 func GetFilerContent(c *gin.Context) {
 	filePath := c.Query("path")
 	if len(filePath) == 0 {
-		c.JSON(http.StatusOK, model.Result{
+		c.JSON(common_err.CLIENT_ERROR, model.Result{
 			Success: common_err.INVALID_PARAMS,
 			Message: common_err.GetMsg(common_err.INVALID_PARAMS),
 		})
 		return
 	}
 	if !file.Exists(filePath) {
-		c.JSON(http.StatusOK, model.Result{
+		c.JSON(common_err.SERVICE_ERROR, model.Result{
 			Success: common_err.FILE_DOES_NOT_EXIST,
 			Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
 		})
@@ -79,7 +50,7 @@ func GetFilerContent(c *gin.Context) {
 	//文件读取任务是将文件内容读取到内存中。
 	info, err := ioutil.ReadFile(filePath)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{
+		c.JSON(common_err.SERVICE_ERROR, model.Result{
 			Success: common_err.FILE_READ_ERROR,
 			Message: common_err.GetMsg(common_err.FILE_READ_ERROR),
 			Data:    err.Error(),
@@ -88,8 +59,7 @@ func GetFilerContent(c *gin.Context) {
 	}
 	result := string(info)
 
-	//返回结果
-	c.JSON(http.StatusOK, model.Result{
+	c.JSON(common_err.SUCCESS, model.Result{
 		Success: common_err.SUCCESS,
 		Message: common_err.GetMsg(common_err.SUCCESS),
 		Data:    result,
@@ -121,18 +91,18 @@ func GetLocalFile(c *gin.Context) {
 // @Accept application/json
 // @Tags file
 // @Security ApiKeyAuth
-// @Param t query string false "Compression format" Enums(zip,tar,targz)
+// @Param format query string false "Compression format" Enums(zip,tar,targz)
 // @Param files query string true "file list eg: filename1,filename2,filename3 "
 // @Success 200 {string} string "ok"
 // @Router /file/download [get]
 func GetDownloadFile(c *gin.Context) {
 
-	t := c.Query("t")
+	t := c.Query("format")
 
 	files := c.Query("files")
 
 	if len(files) == 0 {
-		c.JSON(http.StatusOK, model.Result{
+		c.JSON(common_err.CLIENT_ERROR, model.Result{
 			Success: common_err.INVALID_PARAMS,
 			Message: common_err.GetMsg(common_err.INVALID_PARAMS),
 		})
@@ -141,7 +111,7 @@ func GetDownloadFile(c *gin.Context) {
 	list := strings.Split(files, ",")
 	for _, v := range list {
 		if !file.Exists(v) {
-			c.JSON(http.StatusOK, model.Result{
+			c.JSON(common_err.SERVICE_ERROR, model.Result{
 				Success: common_err.FILE_DOES_NOT_EXIST,
 				Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
 			})
@@ -179,7 +149,7 @@ func GetDownloadFile(c *gin.Context) {
 
 	extension, ar, err := file.GetCompressionAlgorithm(t)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{
+		c.JSON(common_err.CLIENT_ERROR, model.Result{
 			Success: common_err.INVALID_PARAMS,
 			Message: common_err.GetMsg(common_err.INVALID_PARAMS),
 		})
@@ -188,9 +158,9 @@ func GetDownloadFile(c *gin.Context) {
 
 	err = ar.Create(c.Writer)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{
-			Success: common_err.ERROR,
-			Message: common_err.GetMsg(common_err.ERROR),
+		c.JSON(common_err.SERVICE_ERROR, model.Result{
+			Success: common_err.SERVICE_ERROR,
+			Message: common_err.GetMsg(common_err.SERVICE_ERROR),
 			Data:    err.Error(),
 		})
 		return
@@ -213,8 +183,22 @@ func GetDownloadFile(c *gin.Context) {
 }
 
 func GetDownloadSingleFile(c *gin.Context) {
-	filePath := c.Param("path")
-	fileTmp, _ := os.Open(filePath)
+	filePath := c.Query("path")
+	if len(filePath) == 0 {
+		c.JSON(service.ClientCount, model.Result{
+			Success: common_err.INVALID_PARAMS,
+			Message: common_err.GetMsg(common_err.INVALID_PARAMS),
+		})
+		return
+	}
+	fileTmp, err := os.Open(filePath)
+	if err != nil {
+		c.JSON(common_err.SERVICE_ERROR, model.Result{
+			Success: common_err.FILE_DOES_NOT_EXIST,
+			Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
+		})
+		return
+	}
 	defer fileTmp.Close()
 
 	fileName := path.Base(filePath)
@@ -297,7 +281,7 @@ func DirPath(c *gin.Context) {
 		}
 	}
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: pathList})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: pathList})
 }
 
 // @Summary rename file or dir
@@ -311,15 +295,15 @@ func DirPath(c *gin.Context) {
 // @Router /file/rename [put]
 func RenamePath(c *gin.Context) {
 	json := make(map[string]string)
-	c.BindJSON(&json)
-	op := json["oldpath"]
-	np := json["newpath"]
+	c.ShouldBind(&json)
+	op := json["old_path"]
+	np := json["new_path"]
 	if len(op) == 0 || len(np) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	success, err := service.MyService.System().RenameFile(op, np)
-	c.JSON(http.StatusOK, model.Result{Success: success, Message: common_err.GetMsg(success), Data: err})
+	c.JSON(common_err.SUCCESS, model.Result{Success: success, Message: common_err.GetMsg(success), Data: err})
 }
 
 // @Summary create folder
@@ -332,11 +316,11 @@ func RenamePath(c *gin.Context) {
 // @Router /file/mkdir [post]
 func MkdirAll(c *gin.Context) {
 	json := make(map[string]string)
-	c.BindJSON(&json)
+	c.ShouldBind(&json)
 	path := json["path"]
 	var code int
 	if len(path) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	// decodedPath, err := url.QueryUnescape(path)
@@ -345,7 +329,7 @@ func MkdirAll(c *gin.Context) {
 	// 	return
 	// }
 	code, _ = service.MyService.System().MkdirAll(path)
-	c.JSON(http.StatusOK, model.Result{Success: code, Message: common_err.GetMsg(code)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
 }
 
 // @Summary create file
@@ -358,11 +342,11 @@ func MkdirAll(c *gin.Context) {
 // @Router /file/create [post]
 func PostCreateFile(c *gin.Context) {
 	json := make(map[string]string)
-	c.BindJSON(&json)
+	c.ShouldBind(&json)
 	path := json["path"]
 	var code int
 	if len(path) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	// decodedPath, err := url.QueryUnescape(path)
@@ -371,7 +355,7 @@ func PostCreateFile(c *gin.Context) {
 	// 	return
 	// }
 	code, _ = service.MyService.System().CreateFile(path)
-	c.JSON(http.StatusOK, model.Result{Success: code, Message: common_err.GetMsg(code)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
 }
 
 // @Summary upload file
@@ -452,7 +436,7 @@ func PostFileUpload(c *gin.Context) {
 		defer out.Close()
 		_, err := io.Copy(out, f)
 		if err != nil {
-			c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 			return
 		}
 	} else {
@@ -460,7 +444,7 @@ func PostFileUpload(c *gin.Context) {
 		defer out.Close()
 		_, err := io.Copy(out, f)
 		if err != nil {
-			c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 			return
 		}
 		c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
@@ -468,7 +452,7 @@ func PostFileUpload(c *gin.Context) {
 	}
 	fileNum, err := ioutil.ReadDir(tempDir)
 	if err != nil {
-		c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 	if totalChunks == len(fileNum) {
@@ -476,7 +460,7 @@ func PostFileUpload(c *gin.Context) {
 		file.RMDir(tempDir)
 	}
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary copy or move file
@@ -490,14 +474,14 @@ func PostFileUpload(c *gin.Context) {
 func PostOperateFileOrDir(c *gin.Context) {
 
 	list := model.FileOperate{}
-	c.BindJSON(&list)
+	c.ShouldBind(&list)
 
 	if len(list.Item) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)})
 		return
 	}
 
@@ -526,7 +510,7 @@ func PostOperateFileOrDir(c *gin.Context) {
 
 	}
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary delete file
@@ -540,9 +524,9 @@ func PostOperateFileOrDir(c *gin.Context) {
 func DeleteFile(c *gin.Context) {
 
 	paths := []string{}
-	c.BindJSON(&paths)
+	c.ShouldBind(&paths)
 	if len(paths) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	//	path := c.Query("path")
@@ -552,12 +536,12 @@ func DeleteFile(c *gin.Context) {
 	for _, v := range paths {
 		err := os.RemoveAll(v)
 		if err != nil {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
 			return
 		}
 	}
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary update file
@@ -572,26 +556,26 @@ func DeleteFile(c *gin.Context) {
 func PutFileContent(c *gin.Context) {
 
 	fi := model.FileUpdate{}
-	c.BindJSON(&fi)
+	c.ShouldBind(&fi)
 
 	// path := c.PostForm("path")
 	// content := c.PostForm("content")
 	if !file.Exists(fi.FilePath) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
 		return
 	}
 	//err := os.Remove(path)
 	err := os.RemoveAll(fi.FilePath)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
 		return
 	}
 	err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary image thumbnail/original image
@@ -607,13 +591,13 @@ func GetFileImage(c *gin.Context) {
 	t := c.Query("type")
 	path := c.Query("path")
 	if !file.Exists(path) {
-		c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
 		return
 	}
 	if t == "thumbnail" {
 		f, err := file.GetImage(path, 100, 0)
 		if err != nil {
-			c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 			return
 		}
 		c.Writer.WriteString(string(f))
@@ -621,13 +605,13 @@ func GetFileImage(c *gin.Context) {
 	}
 	f, err := os.Open(path)
 	if err != nil {
-		c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 	defer f.Close()
 	data, err := ioutil.ReadAll(f)
 	if err != nil {
-		c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
 		return
 	}
 	c.Writer.WriteString(string(data))
@@ -652,5 +636,5 @@ func DeleteOperateFileOrDir(c *gin.Context) {
 	}
 
 	go service.MyService.Notify().SendFileOperateNotify(true)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }

+ 0 - 804
route/v1/person.go

@@ -1,804 +0,0 @@
-package v1
-
-import (
-	"bytes"
-	"encoding/base64"
-	"encoding/gob"
-	"encoding/json"
-	"io/ioutil"
-	"net"
-	"net/http"
-	"os"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-
-	natType "github.com/Curtis-Milo/nat-type-identifier-go"
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
-
-	"github.com/IceWhaleTech/CasaOS/service"
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/IceWhaleTech/CasaOS/types"
-	"github.com/gin-gonic/gin"
-	uuid "github.com/satori/go.uuid"
-)
-
-// @Summary Retry the file that failed to download
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Param  uui path string true "download uuid"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/refile/{uuid} [get]
-func GetPersonReFile(c *gin.Context) {
-
-	uid := c.Param("uuid")
-	_, err := uuid.FromString(uid)
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-
-	task := service.MyService.Download().GetDownloadById(uid)
-	if reflect.DeepEqual(task, model2.PersonDownloadDBModel{}) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
-		return
-	}
-	token := task.From
-	if _, ok := service.UDPAddressMap[token]; !ok {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
-		return
-	}
-
-	m := model.MessageModel{}
-	m.Data = task.Path
-	m.From = config.ServerInfo.Token
-	m.To = token
-	m.Type = types.PERSONDOWNLOAD
-	m.UUId = uid
-	go service.Dial(m, false)
-
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary download file
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Param  share_id query string true "opponent share_id"
-// @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
-// @Success 200 {string} string "ok"
-// @Router /person/file [get]
-func GetPersonFile(c *gin.Context) {
-
-	path := c.Query("path")
-	localPath := c.Query("local_path")
-	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: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	if file.CheckNotExist(localPath) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
-		return
-	}
-	if _, ok := service.UDPAddressMap[token]; !ok {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
-		return
-	}
-
-	if _, ok := service.UDPAddressMap[token]; !ok {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
-		return
-	}
-
-	// task id
-	uuid := uuid.NewV4().String()
-
-	task := model2.PersonDownloadDBModel{}
-	task.UUID = uuid
-	task.Name = fileName
-	task.Length = 0
-	task.From = token
-	task.Path = path
-	task.Size = 0
-	task.State = types.DOWNLOADAWAIT
-	task.Created = time.Now().Unix()
-	task.Type = types.PERSONFILEDOWNLOAD
-	task.LocalPath = localPath
-	if service.MyService.Download().GetDownloadListByPath(task) > 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_EXIST_DOWNLOAD, Message: common_err.GetMsg(common_err.PERSON_EXIST_DOWNLOAD)})
-		return
-	}
-	service.MyService.Download().AddDownloadTask(task)
-
-	m := model.MessageModel{}
-	m.Data = path
-	m.From = config.ServerInfo.Token
-	m.To = token
-	m.Type = types.PERSONDOWNLOAD
-	m.UUId = uuid
-	go service.Dial(m, false)
-
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary delete download file records
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Param  uuid path string true "download uuid"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/file/{uuid} [delete]
-func DeletePersonDownloadFile(c *gin.Context) {
-
-	id := c.Param("uuid")
-	_, err := uuid.FromString(id)
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		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)
-
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary Get file download list
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @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
-// @Success 200 {object} []model2.PersonDownloadDBModel
-// @Router /person/list [get]
-func GetPersonDownloadList(c *gin.Context) {
-	state := c.DefaultQuery("state", "")
-	list := service.MyService.Download().GetDownloadListByState(state, types.PERSONFILEDOWNLOAD)
-	//if it is  downloading, it need to add 'already'
-	for i := 0; i < len(list); i++ {
-		if list[i].State == types.DOWNLOADING {
-			tempDir := config.AppInfo.TempPath + "/" + list[i].UUID
-			files, err := ioutil.ReadDir(tempDir)
-			if err == nil {
-				list[i].Already = len(files)
-			}
-		}
-		list[i].Duration = time.Now().Unix() - list[i].Created
-	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
-}
-
-// @Summary edit friend's remarks
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Param remarks formData string true "remarks name"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/remarks/{shareid} [put]
-func PutPersonRemarks(c *gin.Context) {
-	token := c.Param("shareid")
-	_, err := uuid.FromString(token)
-	mark := c.PostForm("remarks")
-	if err != nil || len(mark) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	friend := model2.FriendModel{}
-	friend.Token = token
-	friend.Mark = mark
-	service.MyService.Friend().EditFriendMark(friend)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary edit friend's
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Param write formData bool true "write"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/write/{shareid} [put]
-func PutPersonWrite(c *gin.Context) {
-	token := c.Param("shareid")
-	_, err := uuid.FromString(token)
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	write, _ := strconv.ParseBool(c.PostForm("write"))
-	friend := model2.FriendModel{}
-	friend.Token = token
-	friend.Write = write
-	service.MyService.Friend().EditFriendMark(friend)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary image thumbnail
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Param write formData bool true "write"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/image/thumbnail/{shareid} [get]
-func GetPersonImageThumbnail(c *gin.Context) {
-	token := c.Param("shareid")
-	path := c.Query("path")
-	_, err := uuid.FromString(token)
-	if err != nil || len(path) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	uuid := uuid.NewV4().String()
-	m := model.MessageModel{}
-	m.Data = path
-	m.From = config.ServerInfo.Token
-	m.To = token
-	m.Type = types.PERSONIMAGETHUMBNAIL
-	m.UUId = uuid
-
-	img, err := service.Dial(m, false)
-	if err != nil {
-		c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-		return
-	}
-
-	//	var buf bytes.Buffer
-	//err = gob.NewEncoder(&buf).Encode(img.Data)
-
-	if err != nil {
-		c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-		return
-	}
-	var buf bytes.Buffer
-	err = gob.NewEncoder(&buf).Encode(img.Data)
-	if err != nil {
-		c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-		return
-	}
-
-	imageBuffer, _ := base64.StdEncoding.DecodeString(img.Data.(string))
-	c.Writer.WriteString(string(imageBuffer))
-	//	c.String(http.StatusOK, "data:image/"+filesuffix+";base64,"+img.Data.(string))
-	//c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: img.Data.(string)})
-}
-
-// @Summary get my friend list
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Security ApiKeyAuth
-// @Success 200 {object}  []model2.FriendModel
-// @Router /person/users [get]
-func GetPersonFriend(c *gin.Context) {
-	list := service.MyService.Friend().GetFriendList()
-	for i := 0; i < len(list); i++ {
-		if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 {
-			list[i].OnLine = true
-			if ip_helper.HasLocalIP(net.ParseIP(strings.Split(v, ":")[0])) {
-				list[i].LocalIP = strings.Split(v, ":")[0]
-			}
-		}
-	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
-}
-
-// @Summary network type detection
-// @Produce application/json
-// @Accept application/json
-// @Tags person
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/detection [get]
-func GetPersonDetection(c *gin.Context) {
-	// - Blocked
-	// - Open Internet
-	// - Full Cone
-	// - Symmetric UDP Firewall
-	// - Restric NAT
-	// - Restric Port NAT
-	// - Symmetric NAT
-
-	result, err := natType.GetDeterminedNatType(true, 5, "stun.l.google.com")
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-		return
-	}
-	//result := service.MyService.Person().GetPersionNetWorkTypeDetection()
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result})
-}
-
-// @Summary add friend
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/user/{shareids} [post]
-func PostAddPersonFriend(c *gin.Context) {
-	token := c.Param("shareids")
-	tokenList := strings.Split(token, ",")
-
-	for _, v := range tokenList {
-		_, err := uuid.FromString(v)
-		if err != nil {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-			return
-		}
-
-		if v == config.ServerInfo.Token {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_MYSELF, Message: common_err.GetMsg(common_err.PERSON_MYSELF)})
-			return
-		}
-
-		udb := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: v})
-		if !reflect.DeepEqual(udb, model2.FriendModel{Token: v}) {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_EXIST_FRIEND, Message: common_err.GetMsg(common_err.PERSON_EXIST_FRIEND)})
-			return
-		}
-
-		user := service.MyService.Casa().GetUserInfoByShareId(v)
-		if reflect.DeepEqual(user, model.UserInfo{}) {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_NOT_EXIST_USER, Message: common_err.GetMsg(common_err.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)
-
-		msg := model.MessageModel{}
-		msg.Type = types.PERSONGETIP
-		msg.Data = ""
-		msg.From = config.ServerInfo.Token
-		msg.To = v
-		msg.UUId = uuid.NewV4().String()
-
-		service.Dial(msg, true)
-
-		friend := model2.FriendModel{}
-		friend.Token = v
-		friend.Avatar = user.Avatar
-		friend.Block = false
-		friend.State = types.FRIENDSTATEWAIT
-		friend.NickName = user.NickName
-		friend.Profile = user.Desc
-		friend.Version = user.Version
-		service.MyService.Friend().AddFriend(friend)
-	}
-
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary Get a list of directories
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Param  share_id query string true "Opponent share_id"
-// @Param  path query string true "dir path"
-// @Security ApiKeyAuth
-// @Success 200 {object}  []model.Path
-// @Router /person/directory [get]
-func GetPersonDirectory(c *gin.Context) {
-	path := c.Query("path")
-	token := c.Query("share_id")
-	_, err := uuid.FromString(token)
-	if len(path) == 0 || err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	if _, ok := service.UDPAddressMap[token]; !ok {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
-		return
-	}
-	uuid := uuid.NewV4().String()
-	m := model.MessageModel{}
-	m.Data = path
-	m.From = config.ServerInfo.Token
-	m.To = token
-	m.Type = types.PERSONDIRECTORY
-	m.UUId = uuid
-	result, err := service.Dial(m, false)
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-		return
-	}
-	dataModel := []model.Path{}
-	if uuid == m.UUId {
-		dataModelByte, _ := json.Marshal(result.Data)
-		err := json.Unmarshal(dataModelByte, &dataModel)
-		if err != nil {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-			return
-		}
-	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.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: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	if file.CheckNotExist(downPath) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.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: common_err.SUCCESS, Message: common_err.GetMsg(common_err.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: common_err.SUCCESS, Message: common_err.GetMsg(common_err.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: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-
-	var list []string
-	json.Unmarshal([]byte(share), &list)
-
-	if len(list) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	for _, v := range list {
-		if !file.Exists(v) {
-			c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.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: common_err.SUCCESS, Message: common_err.GetMsg(common_err.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: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: config.FileSettingInfo.ShareDir})
-}
-
-// @Summary Get the shareid
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/shareid [get]
-func GetPersonShareId(c *gin.Context) {
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: config.ServerInfo.Token})
-}
-
-// @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: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	friend := model2.FriendModel{}
-	friend.Token = token
-	friend.Block = block
-	service.MyService.Friend().EditFriendBlock(friend)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.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: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	friend := model2.FriendModel{}
-	friend.Token = token
-
-	service.MyService.Friend().DeleteFriend(friend)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary Get public person
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/public [get]
-func GetPersonPublic(c *gin.Context) {
-	list := service.MyService.Casa().GetPersonPublic()
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
-}
-
-// @Summary upload file to friend
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Security ApiKeyAuth
-// @Param path formData string true "Destination path"
-// @Param local_path formData string true "Full path of the file to be uploaded"
-// @Success 200 {string} string "ok"
-// @Router /person/file/{shareid} [post]
-func PostPersonFile(c *gin.Context) {
-	token := c.Param("shareid")
-	_, err := uuid.FromString(token)
-	path := c.PostForm("path")
-	localPath := c.PostForm("local_path")
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	if !file.Exists(localPath) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
-		return
-	}
-	uuid := uuid.NewV4().String()
-	m := model.MessageModel{}
-	m.Data = path
-	m.From = config.ServerInfo.Token
-	m.To = token
-	m.Type = types.PERSONUPLOAD
-	m.UUId = uuid
-	go service.UDPSendData(m, localPath)
-
-	f, _ := os.Stat(localPath)
-
-	task := model2.PersonDownloadDBModel{}
-	task.UUID = uuid
-	task.Name = f.Name()
-	task.Length = 0
-	task.From = token
-	task.Path = path
-	task.Size = f.Size()
-	task.State = types.DOWNLOADFINISHED
-	task.Created = time.Now().Unix()
-	task.Type = types.PERSONFILEUPLOAD
-	task.LocalPath = localPath
-	if service.MyService.Download().GetDownloadListByPath(task) > 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_EXIST_DOWNLOAD, Message: common_err.GetMsg(common_err.PERSON_EXIST_DOWNLOAD)})
-		return
-	}
-	service.MyService.Download().AddDownloadTask(task)
-
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary agree add friend
-// @Produce  application/json
-// @Accept application/json
-// @Tags person
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /person/friend/{shareid} [put]
-func PutPersonAgreeFriend(c *gin.Context) {
-	token := c.Param("shareid")
-	_, err := uuid.FromString(token)
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-
-	user := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: token})
-
-	if user.State != types.FRIENDSTATEREQUEST {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.COMMAND_ERROR_INVALID_OPERATION, Message: common_err.GetMsg(common_err.COMMAND_ERROR_INVALID_OPERATION)})
-		return
-	}
-	service.MyService.Friend().AgreeFrined(user.Token)
-
-	uuid := uuid.NewV4().String()
-	m := model.MessageModel{}
-	m.Data = ""
-	m.From = config.ServerInfo.Token
-	m.To = token
-	m.Type = types.PERSONAGREEFRIEND
-	m.UUId = uuid
-	go service.Dial(m, true)
-
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// // @Summary upload file
-// // @Produce  application/json
-// // @Accept  multipart/form-data
-// // @Tags person
-// // @Security ApiKeyAuth
-// // @Param path formData string false "file path"
-// // @Param file formData file true "file"
-// // @Success 200 {string} string "ok"
-// // @Router /person/upload/{shareid} [get]
-// func GetPersonFileUpload(c *gin.Context) {
-
-// 	token := c.Param("shareid")
-// 	_, err := uuid.FromString(token)
-// 	path := c.Query("path")
-// 	if err != nil {
-// 		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-// 		return
-// 	}
-
-// 	relative := c.Query("relativePath")
-// 	fileName := c.Query("filename")
-// 	chunkNumber := c.Query("chunkNumber")
-// 	totalChunks, _ := strconv.Atoi(c.DefaultQuery("totalChunks", "0"))
-// 	dirPath := ""
-// 	hash := file.GetHashByContent([]byte(fileName))
-// 	tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
-// 	if fileName != relative {
-// 		dirPath = strings.TrimSuffix(relative, fileName)
-// 		tempDir += dirPath
-// 		file.MkDir(path + "/" + dirPath)
-// 	}
-// 	tempDir += chunkNumber
-// 	if !file.CheckNotExist(tempDir) {
-// 		c.JSON(200, model.Result{Success: 200, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
-// 		return
-// 	}
-
-// 	c.JSON(204, model.Result{Success: 204, Message: common_err.GetMsg(common_err.SUCCESS)})
-// }
-
-// // @Summary upload file
-// // @Produce  application/json
-// // @Accept  multipart/form-data
-// // @Tags person
-// // @Security ApiKeyAuth
-// // @Param path formData string false "file path"
-// // @Param file formData file true "file"
-// // @Success 200 {string} string "ok"
-// // @Router /person/upload [post]
-// func PostPersonFileUpload(c *gin.Context) {
-// 	token := c.Param("shareid")
-// 	_, err := uuid.FromString(token)
-// 	if err != nil {
-// 		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-// 		return
-// 	}
-// 	f, _, _ := c.Request.FormFile("file")
-// 	relative := c.PostForm("relativePath")
-// 	fileName := c.PostForm("filename")
-// 	totalChunks, _ := strconv.Atoi(c.DefaultPostForm("totalChunks", "0"))
-// 	chunkNumber := c.PostForm("chunkNumber")
-// 	dirPath := ""
-// 	path := c.PostForm("path")
-
-// 	hash := file.GetHashByContent([]byte(fileName))
-
-// 	if len(path) == 0 {
-// 		c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-// 		return
-// 	}
-// 	tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
-
-// 	if fileName != relative {
-// 		dirPath = strings.TrimSuffix(relative, fileName)
-// 		tempDir += dirPath
-// 		file.MkDir(path + "/" + dirPath)
-// 	}
-
-// 	path += "/" + relative
-
-// 	if !file.CheckNotExist(tempDir + chunkNumber) {
-// 		file.RMDir(tempDir + chunkNumber)
-// 	}
-
-// 	if totalChunks > 1 {
-// 		file.IsNotExistMkDir(tempDir)
-
-// 		out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
-// 		defer out.Close()
-// 		_, err := io.Copy(out, f)
-// 		if err != nil {
-// 			c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-// 			return
-// 		}
-// 	} else {
-// 		out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
-// 		defer out.Close()
-// 		_, err := io.Copy(out, f)
-// 		if err != nil {
-// 			c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-// 			return
-// 		}
-// 		c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-// 		return
-// 	}
-
-// 	fileNum, err := ioutil.ReadDir(tempDir)
-// 	if err != nil {
-// 		c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-// 		return
-// 	}
-// 	if totalChunks == len(fileNum) {
-// 		file.RMDir(tempDir)
-// 	}
-
-// 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-// }

+ 0 - 107
route/v1/shortcuts.go

@@ -1,107 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2021-09-30 18:18:14
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-15 14:30:05
- * @FilePath: /CasaOS/route/v1/shortcuts.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package v1
-
-import (
-	"net/http"
-	"net/url"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
-	"github.com/IceWhaleTech/CasaOS/service"
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/gin-gonic/gin"
-)
-
-// @Summary 获取短链列表
-// @Produce  application/json
-// @Accept application/json
-// @Tags shortcuts
-// @Param username formData string true "User name"
-// @Param pwd  formData string true "password"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /shortcuts/list [get]
-func GetShortcutsList(c *gin.Context) {
-	list := service.MyService.Shortcuts().GetList()
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
-}
-
-// @Summary 添加shortcuts
-// @Produce  application/json
-// @Accept application/json
-// @Tags shortcuts
-// @Param title formData string true "title"
-// @Param url  formData string true "url"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /shortcuts/add [post]
-func PostShortcutsAdd(c *gin.Context) {
-	var m model2.ShortcutsDBModel
-
-	c.BindJSON(&m)
-	if len(m.Url) == 0 || len(m.Title) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	u, err := url.Parse(m.Url)
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.SHORTCUTS_URL_ERROR, Message: common_err.GetMsg(common_err.SHORTCUTS_URL_ERROR), Data: err.Error()})
-		return
-	}
-	m.Icon = "https://api.faviconkit.com/" + u.Host + "/57"
-	service.MyService.Shortcuts().AddData(m)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-
-}
-
-// @Summary 删除shortcuts
-// @Produce  application/json
-// @Accept application/json
-// @Tags shortcuts
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /shortcuts/del/{id} [post]
-func DeleteShortcutsDelete(c *gin.Context) {
-	id := c.Param("id")
-	service.MyService.Shortcuts().DeleteData(id)
-	c.JSON(http.StatusOK, model.Result{
-		Success: common_err.SUCCESS,
-		Message: common_err.GetMsg(common_err.SUCCESS),
-		Data:    "",
-	})
-}
-
-// @Summary 编辑shortcuts
-// @Produce  application/json
-// @Accept application/json
-// @Tags shortcuts
-// @Param title formData string true "title"
-// @Param url  formData string true "url"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /shortcuts/edit [put]
-func PutShortcutsEdit(c *gin.Context) {
-	var m model2.ShortcutsDBModel
-	c.BindJSON(&m)
-	if len(m.Url) == 0 || len(m.Title) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	u, err := url.Parse(m.Url)
-	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.SHORTCUTS_URL_ERROR, Message: common_err.GetMsg(common_err.SHORTCUTS_URL_ERROR), Data: err.Error()})
-		return
-	}
-	m.Icon = "https://api.faviconkit.com/" + u.Host + "/57"
-	service.MyService.Shortcuts().EditData(m)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: ""})
-}

+ 17 - 0
route/v1/storage.go

@@ -0,0 +1,17 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-07-11 16:02:29
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-07-11 16:02:55
+ * @FilePath: /CasaOS/route/v1/storage.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package v1
+
+import "github.com/gin-gonic/gin"
+
+func GetStorageList(c *gin.Context) {
+
+}

+ 0 - 27
route/v1/sync.go

@@ -1,27 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2021-11-08 18:02:02
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-21 19:13:59
- * @FilePath: /CasaOS/route/v1/sync.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package v1
-
-import (
-	"net/http"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
-	"github.com/gin-gonic/gin"
-)
-
-func GetSyncConfig(c *gin.Context) {
-	data := make(map[string]string)
-	data["key"] = config.SystemConfigInfo.SyncKey
-	data["port"] = config.SystemConfigInfo.SyncPort
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
-}

+ 57 - 135
route/v1/system.go

@@ -1,7 +1,6 @@
 package v1
 
 import (
-	"encoding/json"
 	"fmt"
 	"net/http"
 	"os"
@@ -21,7 +20,6 @@ import (
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
 	"github.com/IceWhaleTech/CasaOS/types"
 	"github.com/gin-gonic/gin"
-	uuid "github.com/satori/go.uuid"
 	"go.uber.org/zap"
 )
 
@@ -45,10 +43,10 @@ func GetSystemCheckVersion(c *gin.Context) {
 		service.MyService.Notify().AddLog(installLog)
 	}
 	data := make(map[string]interface{}, 3)
-	data["is_need"] = need
+	data["need_update"] = need
 	data["version"] = version
 	data["current_version"] = types.CURRENTVERSION
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 // @Summary 系统信息
@@ -63,12 +61,7 @@ func SystemUpdate(c *gin.Context) {
 	if need {
 		service.MyService.System().UpdateSystemVersion(version.Version)
 	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-//Get system config
-func GetSystemConfig(c *gin.Context) {
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: ""})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 // @Summary  get logs
@@ -80,86 +73,29 @@ func GetSystemConfig(c *gin.Context) {
 // @Router /sys/error/logs [get]
 func GetCasaOSErrorLogs(c *gin.Context) {
 	line, _ := strconv.Atoi(c.DefaultQuery("line", "100"))
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
-}
-
-// @Summary 修改配置文件
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags sys
-// @Param config formData string true "config json string"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /sys/changhead [post]
-func PostSetSystemConfig(c *gin.Context) {
-	buf := make([]byte, 1024)
-	n, _ := c.Request.Body.Read(buf)
-
-	service.MyService.System().UpSystemConfig(string(buf[0:n]), "")
-	c.JSON(http.StatusOK,
-		model.Result{
-			Success: common_err.SUCCESS,
-			Message: common_err.GetMsg(common_err.SUCCESS),
-			Data:    json.RawMessage(config.SystemConfigInfo.ConfigStr),
-		})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
 }
 
 //系统配置
 func GetSystemConfigDebug(c *gin.Context) {
-
 	array := service.MyService.System().GetSystemConfigDebug()
 	disk := service.MyService.System().GetDiskInfo()
 	sys := service.MyService.System().GetSysInfo()
-	//todo 准备sync需要显示的数据(镜像,容器)
-	var systemAppStatus string
-	images := service.MyService.Docker().IsExistImage("linuxserver/syncthing")
-	systemAppStatus += "Sync img: " + strconv.FormatBool(images) + "\n\t"
-
-	list := service.MyService.App().GetSystemAppList()
-	for _, v := range list {
-		systemAppStatus += v.Image + ",\n\t"
-	}
-
-	systemAppStatus += "Sync Key length: " + strconv.Itoa(len(config.SystemConfigInfo.SyncKey))
-
+	version := service.MyService.Casa().GetCasaosVersion()
 	var bugContent string = fmt.Sprintf(`
 	 - OS: %s
 	 - CasaOS Version: %s
 	 - Disk Total: %v 
 	 - Disk Used: %v 
-	 - Sync State: %s
 	 - System Info: %s
+	 - Remote Version: %s
 	 - Browser: $Browser$ 
 	 - Version: $Version$
-`, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, systemAppStatus, array)
+`, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, array, version.Version)
 
 	//	array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent})
-}
-
-//widget配置
-func GetWidgetConfig(c *gin.Context) {
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.WidgetList)})
-}
-
-// @Summary 修改组件配置文件
-// @Produce  application/json
-// @Accept application/json
-// @Tags sys
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /sys/widget/config [post]
-func PostSetWidgetConfig(c *gin.Context) {
-	buf := make([]byte, 1024)
-	n, _ := c.Request.Body.Read(buf)
-	service.MyService.System().UpSystemConfig("", string(buf[0:n]))
-	c.JSON(http.StatusOK,
-		model.Result{
-			Success: common_err.SUCCESS,
-			Message: common_err.GetMsg(common_err.SUCCESS),
-			Data:    json.RawMessage(config.SystemConfigInfo.WidgetList),
-		})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent})
 }
 
 // @Summary get casaos server port
@@ -170,7 +106,7 @@ func PostSetWidgetConfig(c *gin.Context) {
 // @Success 200 {string} string "ok"
 // @Router /sys/port [get]
 func GetCasaOSPort(c *gin.Context) {
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
@@ -188,13 +124,13 @@ func GetCasaOSPort(c *gin.Context) {
 // @Router /sys/port [put]
 func PutCasaOSPort(c *gin.Context) {
 	json := make(map[string]string)
-	c.BindJSON(&json)
+	c.ShouldBind(&json)
 	portStr := json["port"]
 	port, err := strconv.Atoi(portStr)
 	if err != nil {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{
-				Success: common_err.ERROR,
+				Success: common_err.SERVICE_ERROR,
 				Message: err.Error(),
 			})
 		return
@@ -202,7 +138,7 @@ func PutCasaOSPort(c *gin.Context) {
 
 	isAvailable := port2.IsPortAvailable(port, "tcp")
 	if !isAvailable {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{
 				Success: common_err.PORT_IS_OCCUPIED,
 				Message: common_err.GetMsg(common_err.PORT_IS_OCCUPIED),
@@ -210,40 +146,13 @@ func PutCasaOSPort(c *gin.Context) {
 		return
 	}
 	service.MyService.System().UpSystemPort(strconv.Itoa(port))
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
 		})
 }
 
-// @Summary 检查是否进入引导状态
-// @Produce  application/json
-// @Accept application/json
-// @Tags sys
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /sys/init/check [get]
-func GetSystemInitCheck(c *gin.Context) {
-	data := make(map[string]interface{}, 2)
-
-	if service.MyService.User().GetUserCount() > 0 {
-		data["initialized"] = true
-		data["key"] = ""
-	} else {
-		key := uuid.NewV4().String()
-		service.UserRegisterHash[key] = key
-		data["key"] = key
-		data["initialized"] = false
-	}
-	c.JSON(http.StatusOK,
-		model.Result{
-			Success: common_err.SUCCESS,
-			Message: common_err.GetMsg(common_err.SUCCESS),
-			Data:    data,
-		})
-}
-
 // @Summary active killing casaos
 // @Produce  application/json
 // @Accept application/json
@@ -263,7 +172,9 @@ func PostKillCasaOS(c *gin.Context) {
 // @Success 200 {string} string "ok"
 // @Router /sys/usb/off [put]
 func PutSystemUSBAutoMount(c *gin.Context) {
-	status := c.Param("status")
+	js := make(map[string]string)
+	c.ShouldBind(&js)
+	status := js["status"]
 	if status == "on" {
 		service.MyService.System().UpdateUSBAutoMount("True")
 		service.MyService.System().ExecUSBAutoMountShell("True")
@@ -272,7 +183,7 @@ func PutSystemUSBAutoMount(c *gin.Context) {
 		service.MyService.System().ExecUSBAutoMountShell("False")
 	}
 
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
@@ -292,7 +203,7 @@ func GetSystemUSBAutoMount(c *gin.Context) {
 		state = "False"
 	}
 
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
@@ -300,6 +211,40 @@ func GetSystemUSBAutoMount(c *gin.Context) {
 		})
 }
 
+func GetSystemAppsStatus(c *gin.Context) {
+	systemAppList := service.MyService.App().GetSystemAppList()
+	appList := []model2.MyAppList{}
+	for _, v := range systemAppList {
+		name := strings.ReplaceAll(v.Names[0], "/", "")
+		if len(v.Labels["name"]) > 0 {
+			name = v.Labels["name"]
+		}
+		appList = append(appList, model2.MyAppList{
+			Name:     name,
+			Icon:     v.Labels["icon"],
+			State:    v.State,
+			CustomId: v.Labels["custom_id"],
+			Id:       v.ID,
+			Port:     v.Labels["web"],
+			Index:    v.Labels["index"],
+			//Order:      m.Labels["order"],
+			Image:  v.Image,
+			Latest: false,
+			//Type:   m.Labels["origin"],
+			//Slogan: m.Slogan,
+			//Rely:     m.Rely,
+			Host:     v.Labels["host"],
+			Protocol: v.Labels["protocol"],
+		})
+	}
+	c.JSON(common_err.SUCCESS,
+		model.Result{
+			Success: common_err.SUCCESS,
+			Message: common_err.GetMsg(common_err.SUCCESS),
+			Data:    appList,
+		})
+}
+
 // @Summary get system hardware info
 // @Produce  application/json
 // @Accept application/json
@@ -311,7 +256,7 @@ func GetSystemHardwareInfo(c *gin.Context) {
 
 	data := make(map[string]string, 1)
 	data["drive_model"] = service.MyService.System().GetDeviceTree()
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
@@ -454,7 +399,7 @@ func GetSystemUtilization(c *gin.Context) {
 
 	data["net"] = newNet
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 // @Summary Get notification port
@@ -466,11 +411,11 @@ func GetSystemUtilization(c *gin.Context) {
 // @Router /sys/socket/port [get]
 func GetSystemSocketPort(c *gin.Context) {
 
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
-			Data:    config.ServerInfo.SocketPort,
+			Data:    config.ServerInfo.SocketPort, // @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
 		})
 }
 
@@ -540,26 +485,3 @@ func GetSystemNetInfo(c *gin.Context) {
 
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
 }
-
-//********************************************* Soon to be removed ***********************************************
-// @Summary 检查是否进入引导状态
-// @Produce  application/json
-// @Accept application/json
-// @Tags sys
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /guide/check [get]
-func GetGuideCheck(c *gin.Context) {
-	initUser := true
-	if service.MyService.User().GetUserCount() > 0 {
-		initUser = false
-	}
-	data := make(map[string]interface{}, 1)
-	data["need_init_user"] = initUser
-	c.JSON(http.StatusOK,
-		model.Result{
-			Success: common_err.SUCCESS,
-			Message: common_err.GetMsg(common_err.SUCCESS),
-			Data:    data,
-		})
-}

+ 216 - 268
route/v1/user.go

@@ -10,15 +10,17 @@ import (
 	"path/filepath"
 	"strconv"
 	"strings"
+	"time"
 
 	"github.com/IceWhaleTech/CasaOS/model"
+	"github.com/IceWhaleTech/CasaOS/model/system_model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/IceWhaleTech/CasaOS/types"
+	uuid "github.com/satori/go.uuid"
 	"github.com/tidwall/gjson"
 
 	"github.com/IceWhaleTech/CasaOS/service"
@@ -29,46 +31,47 @@ import (
 // @Router /user/register/ [post]
 func PostUserRegister(c *gin.Context) {
 	json := make(map[string]string)
-	c.BindJSON(&json)
-	username := json["user_name"]
+	c.ShouldBind(&json)
+
+	username := json["username"]
 	pwd := json["password"]
-	key := c.Param("key")
+	key := json["key"]
 	if _, ok := service.UserRegisterHash[key]; !ok {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.CLIENT_ERROR,
 			model.Result{Success: common_err.KEY_NOT_EXIST, Message: common_err.GetMsg(common_err.KEY_NOT_EXIST)})
 		return
 	}
 
 	if len(username) == 0 || len(pwd) == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.CLIENT_ERROR,
 			model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	if len(pwd) < 6 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.CLIENT_ERROR,
 			model.Result{Success: common_err.PWD_IS_TOO_SIMPLE, Message: common_err.GetMsg(common_err.PWD_IS_TOO_SIMPLE)})
 		return
 	}
 	oldUser := service.MyService.User().GetUserInfoByUserName(username)
 	if oldUser.Id > 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.CLIENT_ERROR,
 			model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
 		return
 	}
 
 	user := model2.UserDBModel{}
-	user.UserName = username
-	user.Password = encryption.GetMD5ByStr(config.UserInfo.PWD)
+	user.Username = username
+	user.Password = encryption.GetMD5ByStr(pwd)
 	user.Role = "admin"
 
 	user = service.MyService.User().CreateUser(user)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
 		return
 	}
 	file.MkDir(config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id))
 	delete(service.UserRegisterHash, key)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 
 }
 
@@ -82,44 +85,43 @@ func PostUserRegister(c *gin.Context) {
 // @Router /user/login [post]
 func PostUserLogin(c *gin.Context) {
 	json := make(map[string]string)
-	c.BindJSON(&json)
+	c.ShouldBind(&json)
 
 	username := json["username"]
-	pwd := json["pwd"]
+
+	password := json["password"]
 	//check params is empty
-	if len(username) == 0 || len(pwd) == 0 {
-		c.JSON(http.StatusOK,
+	if len(username) == 0 || len(password) == 0 {
+		c.JSON(common_err.CLIENT_ERROR,
 			model.Result{
-				Success: common_err.ERROR,
+				Success: common_err.CLIENT_ERROR,
 				Message: common_err.GetMsg(common_err.INVALID_PARAMS),
 			})
 		return
 	}
 	user := service.MyService.User().GetUserAllInfoByName(username)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.CLIENT_ERROR,
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
-	if user.Password != encryption.GetMD5ByStr(pwd) {
-		c.JSON(http.StatusOK,
+	if user.Password != encryption.GetMD5ByStr(password) {
+		c.JSON(common_err.CLIENT_ERROR,
 			model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
 		return
 	}
+	token := system_model.VerifyInformation{}
+	token.AccessToken = jwt.GetAccessToken(user.Username, user.Password, user.Id)
+	token.RefreshToken = jwt.GetRefreshToken(user.Username, user.Password, user.Id)
+	token.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
+	data := make(map[string]interface{}, 2)
 	user.Password = ""
-	// token := system_model.VerifyInformation{}
-	// token.AccessToken = jwt.GetAccessToken(user.UserName, user.Password, user.Id)
-	// token.RefreshToken = jwt.GetRefreshToken(user.UserName, user.Password, user.Id)
-	// token.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
-	// data := make(map[string]interface{}, 2)
-	// data["token"] = token
-	// data["user"] = user
-	data := make(map[string]interface{}, 3)
-	data["token"] = jwt.GetToken(username, pwd)
-	data["version"] = types.CURRENTVERSION
+	data["token"] = token
+
+	// TODO:1 Database fields cannot be external
 	data["user"] = user
 
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
@@ -139,14 +141,14 @@ func PutUserAvatar(c *gin.Context) {
 	id := c.GetHeader("user_id")
 	user := service.MyService.User().GetUserInfoById(id)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
 	f, err := c.FormFile("file")
 	if err != nil {
-		c.JSON(http.StatusOK,
-			model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.CLIENT_ERROR,
+			model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
 		return
 	}
 	if len(user.Avatar) > 0 {
@@ -165,22 +167,6 @@ func PutUserAvatar(c *gin.Context) {
 		})
 }
 
-/**
- * @description: get user avatar by user id
- * @param {query} id string user id
- * @method: GET
- */
-func GetUserAvatar(c *gin.Context) {
-	id := c.Param("id")
-	user := service.MyService.User().GetUserInfoById(id)
-
-	path := "default.png"
-	if user.Id > 0 {
-		path = user.Avatar
-	}
-	c.File(path)
-}
-
 // @Summary edit user name
 // @Produce  application/json
 // @Accept application/json
@@ -189,27 +175,42 @@ func GetUserAvatar(c *gin.Context) {
 // @Security ApiKeyAuth
 // @Success 200 {string} string "ok"
 // @Router /user/name/:id [put]
-func PutUserName(c *gin.Context) {
-	//id := c.GetHeader("user_id")
-	json := make(map[string]string)
-	c.BindJSON(&json)
-	//userName := json["user_name"]
-	username := json["username"]
-	id := json["user_id"]
-	if len(username) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR)})
-		return
-	}
+func PutUserInfo(c *gin.Context) {
+	id := c.GetHeader("user_id")
+	json := model2.UserDBModel{}
+	c.ShouldBind(&json)
 	user := service.MyService.User().GetUserInfoById(id)
-
 	if user.Id == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
-	user.UserName = username
-	service.MyService.User().UpdateUser(user)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
+	if len(json.Username) > 0 {
+		u := service.MyService.User().GetUserInfoByUserName(json.Username)
+		if u.Id > 0 {
+			c.JSON(common_err.CLIENT_ERROR,
+				model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
+			return
+		}
+	}
+
+	if len(json.Email) == 0 {
+		json.Email = user.Email
+	}
+	if len(json.Avatar) == 0 {
+		json.Avatar = user.Avatar
+	}
+	if len(json.Role) == 0 {
+		json.Role = user.Role
+	}
+	if len(json.Description) == 0 {
+		json.Description = user.Description
+	}
+	if len(json.Nickname) == 0 {
+		json.Nickname = user.Nickname
+	}
+	service.MyService.User().UpdateUser(json)
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json})
 }
 
 // @Summary edit user password
@@ -219,31 +220,30 @@ func PutUserName(c *gin.Context) {
 // @Security ApiKeyAuth
 // @Success 200 {string} string "ok"
 // @Router /user/password/:id [put]
-func PutUserPwd(c *gin.Context) {
-	//id := c.GetHeader("user_id")
+func PutUserPassword(c *gin.Context) {
+	id := c.GetHeader("user_id")
 	json := make(map[string]string)
-	c.BindJSON(&json)
-	oldPwd := json["old_pwd"]
-	pwd := json["pwd"]
-	id := json["user_id"]
+	c.ShouldBind(&json)
+	oldPwd := json["old_password"]
+	pwd := json["password"]
 	if len(oldPwd) == 0 || len(pwd) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	user := service.MyService.User().GetUserAllInfoById(id)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
 	if user.Password != encryption.GetMD5ByStr(oldPwd) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.PWD_INVALID_OLD, Message: common_err.GetMsg(common_err.PWD_INVALID_OLD)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID_OLD, Message: common_err.GetMsg(common_err.PWD_INVALID_OLD)})
 		return
 	}
 	user.Password = encryption.GetMD5ByStr(pwd)
 	service.MyService.User().UpdateUserPassword(user)
 	user.Password = ""
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
 }
 
 // @Summary edit user nick
@@ -256,12 +256,11 @@ func PutUserPwd(c *gin.Context) {
 // @Router /user/nick [put]
 func PutUserNick(c *gin.Context) {
 
-	//id := c.GetHeader("user_id")
+	id := c.GetHeader("user_id")
 	json := make(map[string]string)
-	c.BindJSON(&json)
-	nickName := json["nick_name"]
-	id := json["user_id"]
-	if len(nickName) == 0 {
+	c.ShouldBind(&json)
+	Nickname := json["nick_name"]
+	if len(Nickname) == 0 {
 		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
@@ -271,10 +270,8 @@ func PutUserNick(c *gin.Context) {
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
-	user.NickName = nickName
+	user.Nickname = Nickname
 	service.MyService.User().UpdateUser(user)
-	//TODO:person remove together
-	go service.MyService.Casa().PushUserInfo()
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
 }
 
@@ -287,10 +284,9 @@ func PutUserNick(c *gin.Context) {
 // @Success 200 {string} string "ok"
 // @Router /user/desc [put]
 func PutUserDesc(c *gin.Context) {
-	//	id := c.GetHeader("user_id")
+	id := c.GetHeader("user_id")
 	json := make(map[string]string)
-	c.BindJSON(&json)
-	id := json["user_id"]
+	c.ShouldBind(&json)
 	desc := json["description"]
 	if len(desc) == 0 {
 		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
@@ -309,39 +305,6 @@ func PutUserDesc(c *gin.Context) {
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
 }
 
-// @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) {
-	json := make(map[string]string)
-	c.BindJSON(&json)
-	desc := json["description"]
-	nickName := json["nick_name"]
-	id := json["user_id"]
-	if len(desc) == 0 || len(nickName) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	user := service.MyService.User().GetUserInfoById(id)
-	if user.Id == 0 {
-		c.JSON(http.StatusOK,
-			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
-		return
-	}
-	//user_service.SetUser("", "", "", "", desc, nickName)
-	user.NickName = nickName
-	user.Description = desc
-	service.MyService.User().UpdateUser(user)
-	go service.MyService.Casa().PushUserInfo()
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
-}
-
 // @Summary get user info
 // @Produce  application/json
 // @Accept  application/json
@@ -349,51 +312,38 @@ func PostUserPersonInfo(c *gin.Context) {
 // @Success 200 {string} string "ok"
 // @Router /user/info/:id [get]
 func GetUserInfo(c *gin.Context) {
-	//id := c.GetHeader("user_id")
-	id := c.Param("id")
+	id := c.GetHeader("user_id")
 	user := service.MyService.User().GetUserInfoById(id)
 
-	//*****
-	var u = make(map[string]string, 5)
-	u["user_name"] = user.UserName
-	u["head"] = user.Avatar
-	u["email"] = user.Email
-	u["description"] = user.NickName
-	u["nick_name"] = user.NickName
-	u["id"] = strconv.Itoa(user.Id)
-
-	//**
-
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
-			Data:    u,
+			Data:    user,
 		})
 }
 
-// @Summary get user info
-// @Produce  application/json
-// @Accept  application/json
-// @Tags user
-// @Success 200 {string} string "ok"
-// @Router /user/info [get]
-func GetUserInfoByUserName(c *gin.Context) {
-	json := make(map[string]string)
-	c.BindJSON(&json)
-	userName := json["user_name"]
-	if len(userName) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+/**
+ * @description:
+ * @param {*gin.Context} c
+ * @param {string} Username
+ * @return {*}
+ * @method:
+ * @router:
+ */
+func GetUserInfoByUsername(c *gin.Context) {
+	username := c.Param("username")
+	if len(username) == 0 {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
-	user := service.MyService.User().GetUserInfoByUserName(userName)
+	user := service.MyService.User().GetUserInfoByUserName(username)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
-	//**
 
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
@@ -401,29 +351,18 @@ func GetUserInfoByUserName(c *gin.Context) {
 		})
 }
 
-// @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: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: config.ServerInfo.Token})
-}
-
 /**
- * @description: get all user name
+ * @description: get all Usernames
  * @method:GET
  * @router:/user/all/name
  */
-func GetUserAllUserName(c *gin.Context) {
+func GetUserAllUsername(c *gin.Context) {
 	users := service.MyService.User().GetAllUserName()
 	names := []string{}
 	for _, v := range users {
-		names = append(names, v.UserName)
+		names = append(names, v.Username)
 	}
-	c.JSON(http.StatusOK,
+	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
 			Message: common_err.GetMsg(common_err.SUCCESS),
@@ -440,25 +379,26 @@ func GetUserAllUserName(c *gin.Context) {
 func GetUserCustomConf(c *gin.Context) {
 	name := c.Param("key")
 	if len(name) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
-	//id := c.GetHeader("user_id")
-	id := c.Param("id")
+	id := c.GetHeader("user_id")
+
 	user := service.MyService.User().GetUserInfoById(id)
-	//	user := service.MyService.User().GetUserInfoByUserName(userName)
+	//	user := service.MyService.User().GetUserInfoByUsername(Username)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
 	filePath := config.AppInfo.UserDataPath + "/" + id + "/" + name + ".json"
+
 	data := file.ReadFullFile(filePath)
 	if !gjson.ValidBytes(data) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)})
+		c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)})
 		return
 	}
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
 }
 
 /**
@@ -468,16 +408,16 @@ func GetUserCustomConf(c *gin.Context) {
  * @router:/user/custom/:key
  */
 func PostUserCustomConf(c *gin.Context) {
+
 	name := c.Param("key")
 	if len(name) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
-	//id := c.GetHeader("user_id")
-	id := c.Param("id")
+	id := c.GetHeader("user_id")
 	user := service.MyService.User().GetUserInfoById(id)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
@@ -485,7 +425,7 @@ func PostUserCustomConf(c *gin.Context) {
 	filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)
 
 	file.WriteToPath(data, filePath, name+".json")
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
 }
 
 /**
@@ -497,20 +437,23 @@ func PostUserCustomConf(c *gin.Context) {
 func DeleteUserCustomConf(c *gin.Context) {
 	name := c.Param("key")
 	if len(name) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
-	//id := c.GetHeader("user_id")
-	id := c.Param("id")
+	id := c.GetHeader("user_id")
 	user := service.MyService.User().GetUserInfoById(id)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK,
+		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
 	filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + name + ".json"
-	os.Remove(filePath)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	err := os.Remove(filePath)
+	if err != nil {
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
+		return
+	}
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
 /**
@@ -522,19 +465,18 @@ func DeleteUserCustomConf(c *gin.Context) {
 func DeleteUser(c *gin.Context) {
 	id := c.Param("id")
 	service.MyService.User().DeleteUserById(id)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
 }
 
 /**
  * @description:update user image
  * @method:POST
- * @router:/user/file/image/:key
+ * @router:/user/current/image/:key
  */
-func PostUserFileImage(c *gin.Context) {
-	//id := c.GetHeader("user_id")
-	id := c.Param("id")
+func PutUserImage(c *gin.Context) {
+	id := c.GetHeader("user_id")
 	json := make(map[string]string)
-	c.BindJSON(&json)
+	c.ShouldBind(&json)
 
 	path := json["path"]
 	key := c.Param("key")
@@ -571,50 +513,57 @@ func PostUserFileImage(c *gin.Context) {
 	data := make(map[string]string, 3)
 	data["path"] = filePath
 	data["file_name"] = key + ext
-	data["online_path"] = "/v1/user/image?path=" + filePath
+	data["online_path"] = "/v1/users/image?path=" + filePath
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 /**
- * @description:create or update user's custom image
- * @param {formData} file file "a file to be uploaded"
- * @param {path} key string "file name"
- * @method:POST
- * @router:/user/upload/image/:key
+* @description:
+* @param {*gin.Context} c
+* @param {file} file
+* @param {string} key
+* @param {string} type:avatar,background
+* @return {*}
+* @method:
+* @router:
  */
 func PostUserUploadImage(c *gin.Context) {
-	//id := c.GetHeader("user_id")
-	id := c.Param("id")
+	id := c.GetHeader("user_id")
 	f, err := c.FormFile("file")
 	key := c.Param("key")
+	t := c.PostForm("type")
 	if len(key) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
 		return
 	}
 
 	_, err = file.GetImageExtByName(f.Filename)
 	if err != nil {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
 		return
 	}
 	ext := filepath.Ext(f.Filename)
 	user := service.MyService.User().GetUserInfoById(id)
 
 	if user.Id == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
+	if t == "avatar" {
+		key = "avatar"
+	}
 	path := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext
+
 	c.SaveUploadedFile(f, path)
 	data := make(map[string]string, 3)
 	data["path"] = path
 	data["file_name"] = key + ext
-	data["online_path"] = "/v1/user/image?path=" + path
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+	data["online_path"] = "/v1/users/image?path=" + path
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
 }
 
 /**
@@ -641,95 +590,94 @@ func GetUserImage(c *gin.Context) {
 	defer fileTmp.Close()
 
 	fileName := path.Base(filePath)
+
+	// @tiger - RESTful 规范下不应该返回文件本身内容,而是返回文件的静态URL,由前端去解析
 	c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
 	c.File(filePath)
 }
 func DeleteUserImage(c *gin.Context) {
-	//	id := c.GetHeader("user_id")
-	id := c.Param("id")
+	id := c.GetHeader("user_id")
 	path := c.Query("path")
 	if len(path) == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
 		return
 	}
 	user := service.MyService.User().GetUserInfoById(id)
 	if user.Id == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
 		return
 	}
 	if !file.Exists(path) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
 		return
 	}
 	if !strings.Contains(path, config.AppInfo.UserDataPath+"/"+strconv.Itoa(user.Id)) {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
+		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
 		return
 	}
 	os.Remove(path)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
 }
 
-////refresh token
-// func PostUserRefreshToken(c *gin.Context) {
-// 	json := make(map[string]string)
-// 	c.BindJSON(&json)
-// 	refresh := json["refresh_token"]
-// 	claims, err := jwt.ParseToken(refresh)
-// 	if err != nil {
-// 		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE), Data: err.Error()})
-// 		return
-// 	}
-// 	if claims.VerifyExpiresAt(time.Now(), true) || claims.VerifyIssuer("refresh", true) {
-// 		c.JSON(http.StatusOK, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE)})
-// 		return
-// 	}
-// 	newToken := jwt.GetAccessToken(claims.UserName, claims.PassWord, claims.Id)
-// 	if err != nil {
-// 		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
-// 		return
-// 	}
-// 	verifyInfo := system_model.VerifyInformation{}
-// 	verifyInfo.AccessToken = newToken
-// 	verifyInfo.RefreshToken = jwt.GetRefreshToken(claims.UserName, claims.PassWord, claims.Id)
-// 	verifyInfo.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
-
-// 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: verifyInfo})
-
-// }
-
-//******** soon to be removed ********
-
-// @Summary 设置用户名和密码
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags user
-// @Param username formData string true "User name"
-// @Param pwd  formData string true "password"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /user/setusernamepwd [post]
-func Set_Name_Pwd(c *gin.Context) {
-	json := make(map[string]string)
-	c.BindJSON(&json)
-	username := json["username"]
-	pwd := json["pwd"]
-	if service.MyService.User().GetUserCount() > 0 || len(username) == 0 || len(pwd) == 0 {
-		c.JSON(http.StatusOK,
-			model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+/**
+ * @description:
+ * @param {*gin.Context} c
+ * @param {string} refresh_token
+ * @return {*}
+ * @method:
+ * @router:
+ */
+func PostUserRefreshToken(c *gin.Context) {
+	js := make(map[string]string)
+	c.ShouldBind(&js)
+	refresh := js["refresh_token"]
+	claims, err := jwt.ParseToken(refresh, true)
+	if err != nil {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE), Data: err.Error()})
 		return
 	}
-	user := model2.UserDBModel{}
-	user.UserName = username
-	user.Password = encryption.GetMD5ByStr(pwd)
-	user.Role = "admin"
-
-	user = service.MyService.User().CreateUser(user)
-	if user.Id == 0 {
-		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR)})
+	if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("refresh", true) {
+		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE)})
 		return
 	}
-	file.MkDir(config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id))
+	newToken := jwt.GetAccessToken(claims.Username, claims.PassWord, claims.Id)
+	verifyInfo := system_model.VerifyInformation{}
+	verifyInfo.AccessToken = newToken
+	verifyInfo.RefreshToken = jwt.GetRefreshToken(claims.Username, claims.PassWord, claims.Id)
+	verifyInfo.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
 
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: verifyInfo})
+
+}
+
+func DeleteUserAll(c *gin.Context) {
+	service.MyService.User().DeleteAllUser()
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+}
 
+// @Summary 检查是否进入引导状态
+// @Produce  application/json
+// @Accept application/json
+// @Tags sys
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /sys/init/check [get]
+func GetUserStatus(c *gin.Context) {
+	data := make(map[string]interface{}, 2)
+
+	if service.MyService.User().GetUserCount() > 0 {
+		data["initialized"] = true
+		data["key"] = ""
+	} else {
+		key := uuid.NewV4().String()
+		service.UserRegisterHash[key] = key
+		data["key"] = key
+		data["initialized"] = false
+	}
+	c.JSON(common_err.SUCCESS,
+		model.Result{
+			Success: common_err.SUCCESS,
+			Message: common_err.GetMsg(common_err.SUCCESS),
+			Data:    data,
+		})
 }

+ 54 - 36
service/app.go

@@ -30,13 +30,13 @@ type AppService interface {
 	SaveContainer(m model2.AppListDBModel)
 	GetUninstallInfo(id string) model2.AppListDBModel
 	DeleteApp(id string)
-	GetContainerInfo(name string) (types.Container, error)
+	GetContainerInfo(id string) (types.Container, error)
 	GetAppDBInfo(id string) model2.AppListDBModel
 	UpdateApp(m model2.AppListDBModel)
-	GetSimpleContainerInfo(name string) (types.Container, error)
+	GetSimpleContainerInfo(id string) (types.Container, error)
 	DelAppConfigDir(path string)
 	GetSystemAppList() []types.Container
-	GetHardwareUsageSteam()
+	GetHardwareUsageStream()
 	GetHardwareUsage() []model.DockerStatsModel
 	GetAppStats(id string) string
 	GetAllDBApps() []model2.AppListDBModel
@@ -156,22 +156,32 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
 
 	for _, m := range containers {
 		if m.Labels["casaos"] == "casaos" {
+
+			_, newVersion := NewVersionApp[m.ID]
+			name := strings.ReplaceAll(m.Names[0], "/", "")
+			icon := m.Labels["icon"]
+			if len(m.Labels["name"]) > 0 {
+				name = m.Labels["name"]
+			}
 			if m.Labels["origin"] == "system" {
-				continue
+				name = strings.Split(m.Image, ":")[0]
+				if len(strings.Split(name, "/")) > 1 {
+					icon = "https://icon.casaos.io/main/all/" + strings.Split(name, "/")[1] + ".png"
+				}
 			}
-			_, newVersion := NewVersionApp[m.ID]
+
 			list = append(list, model2.MyAppList{
-				Name:     strings.ReplaceAll(m.Names[0], "/", ""),
-				Icon:     m.Labels["icon"],
+				Name:     name,
+				Icon:     icon,
 				State:    m.State,
 				CustomId: m.Labels["custom_id"],
 				Id:       m.ID,
 				Port:     m.Labels["web"],
 				Index:    m.Labels["index"],
 				//Order:      m.Labels["order"],
-				Image:      m.Image,
-				NewVersion: newVersion,
-				Type:       m.Labels["origin"],
+				Image:  m.Image,
+				Latest: newVersion,
+				//Type:   m.Labels["origin"],
 				//Slogan: m.Slogan,
 				//Rely:     m.Rely,
 				Host:     m.Labels["host"],
@@ -179,16 +189,16 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
 			})
 		} else {
 			unTranslation = append(unTranslation, model2.MyAppList{
-				Name:       strings.ReplaceAll(m.Names[0], "/", ""),
-				Icon:       "",
-				State:      m.State,
-				CustomId:   m.ID,
-				Id:         m.ID,
-				Port:       "",
-				NewVersion: false,
-				Host:       "",
-				Protocol:   "",
-				Image:      m.Image,
+				Name:     strings.ReplaceAll(m.Names[0], "/", ""),
+				Icon:     "",
+				State:    m.State,
+				CustomId: m.ID,
+				Id:       m.ID,
+				Port:     "",
+				Latest:   false,
+				Host:     "",
+				Protocol: "",
+				Image:    m.Image,
 			})
 		}
 	}
@@ -274,14 +284,14 @@ func (a *appStruct) GetAllDBApps() []model2.AppListDBModel {
 }
 
 //获取我的应用列表
-func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
+func (a *appStruct) GetContainerInfo(id string) (types.Container, error) {
 	//获取docker应用
 	cli, err := client2.NewClientWithOpts(client2.FromEnv)
 	if err != nil {
 		loger.Error("Failed to init client", zap.Any("err", err))
 	}
 	filters := filters.NewArgs()
-	filters.Add("name", name)
+	filters.Add("id", id)
 	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
 	if err != nil {
 		loger.Error("Failed to get container_list", zap.Any("err", err))
@@ -294,7 +304,7 @@ func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
 
 }
 
-func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error) {
+func (a *appStruct) GetSimpleContainerInfo(id string) (types.Container, error) {
 	//获取docker应用
 	cli, err := client2.NewClientWithOpts(client2.FromEnv)
 	if err != nil {
@@ -302,7 +312,7 @@ func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error)
 	}
 	defer cli.Close()
 	filters := filters.NewArgs()
-	filters.Add("name", name)
+	filters.Add("id", id)
 	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
 	if err != nil {
 		return types.Container{}, err
@@ -366,12 +376,12 @@ func (a *appStruct) GetAppStats(id string) string {
 
 func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
 
-	steam := true
+	stream := true
 	for !isFinish {
-		if steam {
-			steam = false
+		if stream {
+			stream = false
 			go func() {
-				a.GetHardwareUsageSteam()
+				a.GetHardwareUsageStream()
 			}()
 		}
 		runtime.Gosched()
@@ -386,7 +396,7 @@ func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
 
 }
 
-func (a *appStruct) GetHardwareUsageSteam() {
+func (a *appStruct) GetHardwareUsageStream() {
 
 	cli, err := client2.NewClientWithOpts(client2.FromEnv)
 	if err != nil {
@@ -400,20 +410,26 @@ func (a *appStruct) GetHardwareUsageSteam() {
 	fts := filters.NewArgs()
 	fts.Add("label", "casaos=casaos")
 	//fts.Add("status", "running")
-
+	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
+	if err != nil {
+		loger.Error("Failed to get container_list", zap.Any("err", err))
+	}
 	for i := 0; i < 100; i++ {
+		if i%10 == 0 {
+			containers, err = cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
+			if err != nil {
+				loger.Error("Failed to get container_list", zap.Any("err", err))
+				continue
+			}
+		}
 		if config.CasaOSGlobalVariables.AppChange {
 			config.CasaOSGlobalVariables.AppChange = false
-
 			dataStats.Range(func(key, value interface{}) bool {
 				dataStats.Delete(key)
 				return true
 			})
 		}
-		containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
-		if err != nil {
-			loger.Error("Failed to get container_list", zap.Any("err", err))
-		}
+
 		var temp sync.Map
 		var wg sync.WaitGroup
 		for _, v := range containers {
@@ -435,12 +451,14 @@ func (a *appStruct) GetHardwareUsageSteam() {
 				m, _ := dataStats.Load(v.ID)
 				dockerStats := model.DockerStatsModel{}
 				if m != nil {
-					dockerStats.Pre = m.(model.DockerStatsModel).Data
+					dockerStats.Previous = m.(model.DockerStatsModel).Data
 				}
 				dockerStats.Data = data
 				dockerStats.Icon = v.Labels["icon"]
 				dockerStats.Title = strings.ReplaceAll(v.Names[0], "/", "")
 
+				// @tiger - 不建议直接把依赖的数据结构封装返回。
+				//          如果依赖的数据结构有变化,应该在这里适配或者保存,这样更加对客户端负责
 				temp.Store(v.ID, dockerStats)
 				if i == 99 {
 					stats.Body.Close()

+ 33 - 109
service/casa.go

@@ -14,24 +14,19 @@ import (
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
 	httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
+	"github.com/pkg/errors"
 	"github.com/tidwall/gjson"
 	"go.uber.org/zap"
 )
 
 type CasaService interface {
-	GetServerList(index, size, tp, categoryId, key string) model.ServerAppListCollection
-	GetServerCategoryList() []model.CategoryList
-	GetServerAppInfo(id, t string, language string) model.ServerAppList
+	GetServerList(index, size, tp, categoryId, key string) (model.ServerAppListCollection, error)
+	GetServerCategoryList() (list []model.CategoryList, err error)
+	GetServerAppInfo(id, t string, language string) (model.ServerAppList, error)
 	ShareAppFile(body []byte) string
-	PushHeart(id, t string, language string)
-
-	PushConnectionStatus(uuid, err string, from, to, event string)
-	PushUserInfo()
-	GetUserInfoByShareId(shareId string) model.UserInfo
-	GetPersonPublic() (list []model.FriendsModel)
 	GetCasaosVersion() model.Version
-	AsyncGetServerList() (collection model.ServerAppListCollection)
-	AsyncGetServerCategoryList() []model.CategoryList
+	AsyncGetServerList() (collection model.ServerAppListCollection, err error)
+	AsyncGetServerCategoryList() ([]model.CategoryList, error)
 }
 
 type casaService struct {
@@ -46,7 +41,7 @@ func (o *casaService) ShareAppFile(body []byte) string {
 	return content
 }
 
-func (o *casaService) GetServerList(index, size, tp, categoryId, key string) model.ServerAppListCollection {
+func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (model.ServerAppListCollection, error) {
 
 	keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, "en")
 	collection := model.ServerAppListCollection{}
@@ -54,7 +49,7 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key string) mod
 		res, ok := result.(string)
 		if ok {
 			json2.Unmarshal([]byte(res), &collection)
-			return collection
+			return collection, nil
 		}
 	}
 
@@ -63,7 +58,10 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key string) mod
 	err := json2.Unmarshal(collectionStr, &collection)
 	if err != nil {
 		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(collectionStr)))
-		collection = o.AsyncGetServerList()
+		collection, err = o.AsyncGetServerList()
+		if err != nil {
+			return collection, err
+		}
 	}
 
 	go o.AsyncGetServerList()
@@ -122,20 +120,20 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key string) mod
 		Cache.Set(keyName, string(by), time.Minute*10)
 	}
 
-	return collection
+	return collection, nil
 
 }
 
-func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollection) {
+func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollection, err error) {
 
 	results := file.ReadFullFile(config.AppInfo.DBPath + "/app_list.json")
-	err := json2.Unmarshal(results, &collection)
+	err = json2.Unmarshal(results, &collection)
 	if err != nil {
 		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
 	}
 
 	if collection.Version == o.GetCasaosVersion().Version {
-		return collection
+		return collection, err
 	}
 
 	head := make(map[string]string)
@@ -187,33 +185,36 @@ func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollec
 // 	return list
 // }
 
-func (o *casaService) GetServerCategoryList() (list []model.CategoryList) {
+func (o *casaService) GetServerCategoryList() (list []model.CategoryList, err error) {
 	category := model.ServerCategoryList{}
 	results := file.ReadFullFile(config.AppInfo.DBPath + "/app_category.json")
-	err := json2.Unmarshal(results, &category)
+	err = json2.Unmarshal(results, &category)
 	if err != nil {
 		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
 		return o.AsyncGetServerCategoryList()
 	}
 	go o.AsyncGetServerCategoryList()
-	return category.Item
+	return category.Item, err
 }
 
-func (o *casaService) AsyncGetServerCategoryList() []model.CategoryList {
+func (o *casaService) AsyncGetServerCategoryList() ([]model.CategoryList, error) {
 	list := model.ServerCategoryList{}
 	results := file.ReadFullFile(config.AppInfo.DBPath + "/app_category.json")
 	err := json2.Unmarshal(results, &list)
 	if err != nil {
 		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
-	}
-
-	if list.Version == o.GetCasaosVersion().Version {
-		return nil
+	} else {
+		if list.Version == o.GetCasaosVersion().Version {
+			return list.Item, nil
+		}
 	}
 	item := []model.CategoryList{}
 	head := make(map[string]string)
 	head["Authorization"] = GetToken()
 	listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
+	if len(listS) == 0 {
+		return item, errors.New("server error")
+	}
 	json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &item)
 	if len(item) > 0 {
 		list.Version = o.GetCasaosVersion().Version
@@ -224,10 +225,10 @@ func (o *casaService) AsyncGetServerCategoryList() []model.CategoryList {
 		}
 		file.WriteToPath(by, config.AppInfo.DBPath, "app_category.json")
 	}
-	return item
+	return item, nil
 }
 
-func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {
+func (o *casaService) GetServerAppInfo(id, t string, language string) (model.ServerAppList, error) {
 
 	head := make(map[string]string)
 
@@ -235,9 +236,12 @@ func (o *casaService) GetServerAppInfo(id, t string, language string) model.Serv
 	infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t+"&language="+language, head)
 
 	info := model.ServerAppList{}
+	if infoS == "" {
+		return info, errors.New("server error")
+	}
 	json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
 
-	return info
+	return info, nil
 }
 func GetToken() string {
 	t := make(chan string)
@@ -289,86 +293,6 @@ func (o *casaService) GetCasaosVersion() model.Version {
 	return version
 }
 
-func (o *casaService) PushHeart(id, t string, language string) {
-
-	m := model.CasaOSHeart{}
-	m.UuId = id
-	m.Type = t
-	b, _ := json.Marshal(m)
-
-	head := make(map[string]string)
-
-	head["Authorization"] = GetToken()
-
-	infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/heart", b, "application/json", head)
-
-	info := model.ServerAppList{}
-	json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
-
-}
-
-func (o *casaService) PushConnectionStatus(uuid, err string, from, to, event string) {
-
-	m := model.ConnectionStatus{}
-	m.UUId = uuid
-	m.Error = err
-	m.From = from
-	m.To = to
-	m.Event = event
-	b, _ := json.Marshal(m)
-
-	head := make(map[string]string)
-
-	head["Authorization"] = GetToken()
-
-	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{}
-	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 {
 	return &casaService{}
 }

+ 2 - 1
service/docker.go

@@ -540,6 +540,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
 	config.Labels["show_env"] = strings.Join(showENV, ",")
 	config.Labels["protocol"] = m.Protocol
 	config.Labels["host"] = m.Host
+	config.Labels["name"] = m.Label
 	hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(m.NetworkModel), Privileged: m.Privileged, CapAdd: m.CapAdd}
 	//if net != "host" {
 	config.ExposedPorts = ports
@@ -551,7 +552,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
 		hostConfig,
 		&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{m.NetworkModel: {NetworkID: "", Aliases: []string{}}}},
 		nil,
-		m.Label)
+		m.ContainerName)
 	if err != nil {
 		return "", err
 	}

+ 0 - 33
service/down_record.go

@@ -1,33 +0,0 @@
-package service
-
-import (
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"gorm.io/gorm"
-)
-
-type DownRecordService interface {
-	AddDownRecord(m model2.PersonDownRecordDBModel)
-	GetDownloadListByFrom(id string) []model2.PersonDownRecordDBModel
-	GetDownloadListByPath(path string) (list []model2.PersonDownRecordDBModel)
-}
-type downRecordService struct {
-	db *gorm.DB
-}
-
-func (d *downRecordService) AddDownRecord(m model2.PersonDownRecordDBModel) {
-	d.db.Create(&m)
-}
-
-func (d *downRecordService) GetDownloadListByFrom(id string) []model2.PersonDownRecordDBModel {
-	var m []model2.PersonDownRecordDBModel
-	d.db.Model(m).Where("from = ?", id).Find(&m)
-	return m
-}
-func (d *downRecordService) GetDownloadListByPath(path string) (list []model2.PersonDownRecordDBModel) {
-	d.db.Where("path = ?", path).Find(&list)
-	return
-}
-
-func NewDownRecordService(db *gorm.DB) DownRecordService {
-	return &downRecordService{db: db}
-}

+ 0 - 66
service/download.go

@@ -1,66 +0,0 @@
-package service
-
-import (
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"gorm.io/gorm"
-)
-
-type DownloadService interface {
-	AddDownloadTask(m model2.PersonDownloadDBModel)   //添加下载任务
-	EditDownloadState(m model2.PersonDownloadDBModel) //只修改状态
-	SaveDownload(m model2.PersonDownloadDBModel)
-	DelDownload(uuid string)
-	GetDownloadById(uuid string) model2.PersonDownloadDBModel
-	GetDownloadListByState(state string, t int) []model2.PersonDownloadDBModel
-	SetDownloadError(m model2.PersonDownloadDBModel)
-	GetDownloadListByPath(m model2.PersonDownloadDBModel) int
-}
-type downloadService struct {
-	db *gorm.DB
-}
-
-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)
-}
-func (d *downloadService) EditDownloadState(m model2.PersonDownloadDBModel) {
-
-	d.db.Model(&m).Where("uuid = ?", m.UUID).Update("state", m.State)
-}
-
-//failed during download
-func (d *downloadService) SetDownloadError(m model2.PersonDownloadDBModel) {
-	d.db.Model(&m).Updates(m)
-}
-
-func (d *downloadService) DelDownload(uuid string) {
-	var m model2.PersonDownloadDBModel
-	d.db.Where("uuid = ?", uuid).Delete(&m)
-}
-func (d *downloadService) GetDownloadById(uuid string) model2.PersonDownloadDBModel {
-	var m model2.PersonDownloadDBModel
-	d.db.Model(m).Where("uuid = ?", uuid).First(&m)
-	return m
-}
-func (d *downloadService) GetDownloadListByState(state string, t int) (list []model2.PersonDownloadDBModel) {
-	if len(state) == 0 {
-		d.db.Where("type = ?", t).Find(&list)
-	} else {
-		d.db.Where("state = ? AND type= ?", state, t).Find(&list)
-	}
-
-	return
-}
-
-func (d *downloadService) SaveDownload(m model2.PersonDownloadDBModel) {
-	d.db.Save(&m)
-}
-func NewDownloadService(db *gorm.DB) DownloadService {
-	return &downloadService{db: db}
-}

+ 0 - 155
service/friend.go

@@ -1,155 +0,0 @@
-package service
-
-import (
-	"context"
-	"fmt"
-	"net"
-	"reflect"
-	"strconv"
-	"time"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/IceWhaleTech/CasaOS/types"
-	"github.com/lucas-clemente/quic-go"
-	uuid "github.com/satori/go.uuid"
-	"gorm.io/gorm"
-)
-
-type FriendService interface {
-	AddFriend(m model2.FriendModel)
-	DeleteFriend(m model2.FriendModel)
-	EditFriendMark(m model2.FriendModel)
-	EditFriendWrite(m model2.FriendModel)
-	EditFriendBlock(m model2.FriendModel)
-	GetFriendById(m model2.FriendModel) model2.FriendModel
-	GetFriendList() (list []model2.FriendModel)
-	GetFriendListRemote() (list []model2.FriendModel)
-	UpdateAddFriendType(m model2.FriendModel)
-	AgreeFrined(id string)
-	GetFriendByToken(token string) model2.FriendModel
-	UpdateOrCreate(m model2.FriendModel)
-	InternalInspection(ips []string, token string)
-}
-
-type friendService struct {
-	db *gorm.DB
-}
-
-func (p *friendService) AgreeFrined(id string) {
-	var m model2.FriendModel
-	p.db.Model(&m).Where("token = ?", id).Update("state", types.FRIENDSTATEDEFAULT)
-}
-func (p *friendService) AddFriend(m model2.FriendModel) {
-	p.db.Create(&m)
-}
-func (p *friendService) DeleteFriend(m model2.FriendModel) {
-	p.db.Where("token = ?", m.Token).Delete(&m)
-}
-func (p *friendService) EditFriendMark(m model2.FriendModel) {
-	p.db.Model(&m).Where("token = ?", m.Token).Update("mark", m.Mark)
-}
-func (p *friendService) EditFriendWrite(m model2.FriendModel) {
-	p.db.Model(&m).Where("token = ?", m.Token).Update("write", m.Write)
-}
-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 {
-	p.db.Model(m).Where("token = ?", m.Token).First(&m)
-	return m
-}
-
-func (p *friendService) GetFriendList() (list []model2.FriendModel) {
-	p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Find(&list)
-	return list
-}
-func (p *friendService) GetFriendListRemote() (list []model2.FriendModel) {
-	p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Where("internal_ip == '' OR internal_ip is null").Find(&list)
-	return list
-}
-func (p *friendService) GetFriendListInternal() (list []model2.FriendModel) {
-	p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Where("internal_ip != ''").Find(&list)
-	return list
-}
-func (p *friendService) UpdateOrCreate(m model2.FriendModel) {
-	friend := model2.FriendModel{}
-	p.db.Where("token = ?", m.Token).First(&friend)
-	if reflect.DeepEqual(friend, model2.FriendModel{}) {
-		p.db.Create(&m)
-	} else {
-		p.db.Model(&m).Updates(m)
-	}
-
-}
-
-func (p *friendService) UpdateAddFriendType(m model2.FriendModel) {
-	p.db.Model(&m).Updates(m)
-}
-
-func (p *friendService) GetFriendByToken(token string) model2.FriendModel {
-	var m model2.FriendModel
-	p.db.Model(&m).Where("token = ?", token).First(&m)
-	return m
-}
-
-func (p *friendService) InternalInspection(ips []string, token string) {
-	for _, v := range ips {
-		fmt.Println("开始遍历 ip:", v)
-		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-		defer cancel()
-
-		dstAddr, err := net.ResolveUDPAddr("udp", v)
-		if err != nil {
-			fmt.Println("1", err.Error())
-			continue
-		}
-		port, err := strconv.Atoi(config.ServerInfo.UDPPort)
-		if err != nil {
-			fmt.Println("2", err)
-			continue
-		}
-		srcAddr := &net.UDPAddr{
-			IP: net.IPv4zero, Port: port}
-		ticket := token
-		session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
-		if err != nil {
-			fmt.Println("3", err, v)
-			continue
-		}
-
-		stream, err := session.OpenStreamSync(ctx)
-		if err != nil {
-			fmt.Println("4", err)
-			continue
-		}
-		uuid := uuid.NewV4().String()
-		SayHello(stream, token)
-		msg := model.MessageModel{
-			Type: types.PERSONPING,
-			Data: "",
-			From: config.ServerInfo.Token,
-			To:   token,
-			UUId: uuid,
-		}
-
-		SendData(stream, msg)
-
-		go ReadContent(stream)
-		result := <-Message
-		fmt.Println("ping返回结果:", result, msg)
-		stream.Close()
-		if !reflect.DeepEqual(result, model.MessageModel{}) && result.Data.(string) == token && result.From == token {
-			fmt.Println("获取到正确的ip", v)
-			UDPAddressMap[result.From] = v
-			p.db.Model(&model2.FriendModel{}).Where("token = ?", token).Update("internal_ip", v)
-			return
-		}
-	}
-}
-
-func NewFriendService(db *gorm.DB) FriendService {
-	return &friendService{db: db}
-}

+ 6 - 7
service/model/o_container.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-05-13 18:15:46
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-05-30 17:33:21
+ * @LastEditTime: 2022-07-13 10:56:34
  * @FilePath: /CasaOS/service/model/o_container.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -67,13 +67,12 @@ type MyAppList struct {
 	Index    string `json:"index"`
 	//Order    string `json:"order"`
 	Port   string `json:"port"`
-	UpTime string `json:"up_time"`
 	Slogan string `json:"slogan"`
 	Type   string `json:"type"`
 	//Rely       model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
-	Image      string `json:"image"`
-	Volumes    string `json:"volumes"`
-	NewVersion bool   `json:"new_version"`
-	Host       string `json:"host"`
-	Protocol   string `json:"protocol"`
+	Image    string `json:"image"`
+	Volumes  string `json:"volumes"`
+	Latest   bool   `json:"latest"`
+	Host     string `json:"host"`
+	Protocol string `json:"protocol"`
 }

+ 0 - 16
service/model/o_down_record.go

@@ -1,16 +0,0 @@
-package model
-
-type PersonDownRecordDBModel struct {
-	UUID       string `gorm:"column:uuid;primary_key" json:"uuid"`
-	Name       string `json:"name"` //file name
-	Type       int    `json:"type"`
-	Size       int64  `json:"size"`       //file size
-	Downloader string `json:"downloader"` //Error message
-	Path       string `json:"path"`
-	Created    int64  `gorm:"autoCreateTime" json:"created"`
-	Updated    int64  `gorm:"autoCreateTime;autoUpdateTime" json:"updated"`
-}
-
-func (p *PersonDownRecordDBModel) TableName() string {
-	return "o_person_down_record"
-}

+ 0 - 24
service/model/o_download.go

@@ -1,24 +0,0 @@
-package model
-
-type PersonDownloadDBModel struct {
-	UUID      string `gorm:"column:uuid;primary_key" json:"uuid"`
-	State     int    `json:"state"`             //
-	Type      int    `json:"type"`              //defult 0
-	Name      string `json:"name"`              //file name
-	Size      int64  `json:"size"`              //file size
-	BlockSize int    `json:"block_size"`        //Size of each file block
-	Length    int    `json:"length"`            //slice length
-	Hash      string `json:"hash"`              //File hash value
-	Error     string `json:"error"`             //
-	From      string `json:"from"`              //Error message
-	Path      string `json:"path"`              //Full path to the file
-	Already   int    `json:"already" gorm:"-"`  //Folder blocks that have been downloaded
-	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 *PersonDownloadDBModel) TableName() string {
-	return "o_person_download"
-}

+ 0 - 21
service/model/o_friend.go

@@ -1,21 +0,0 @@
-package model
-
-type FriendModel struct {
-	State     int    `json:"state"`
-	CreatedAt int64  `gorm:"autoCreateTime" json:"created_at"`
-	UpdatedAt int64  `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
-	NickName  string `json:"nick_name"`
-	Mark      string `json:"mark"`   //Remarks
-	Block     bool   `json:"block"`  //Disable or not
-	Avatar    string `json:"avatar"` //User avatar
-	Token     string `gorm:"column:token;primary_key" json:"token"`
-	Profile   string `json:"profile"` //Description
-	OnLine    bool   `json:"on_line" gorm:"-"`
-	Version   int    `json:"version"`
-	Write     bool   `json:"write"`
-	LocalIP   string `json:"local_ip"`
-}
-
-func (p *FriendModel) TableName() string {
-	return "o_friend"
-}

+ 0 - 17
service/model/o_shortcuts.go

@@ -1,17 +0,0 @@
-package model
-
-import "time"
-
-type ShortcutsDBModel struct {
-	Id        uint      `gorm:"column:id;primary_key" json:"id"`
-	Title     string    `json:"title"`
-	Url       string    `json:"url"`
-	Icon      string    `json:"icon"`
-	Sort      int       `json:"sort"`
-	CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
-	UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
-}
-
-func (p *ShortcutsDBModel) TableName() string {
-	return "o_shortcuts"
-}

+ 4 - 4
service/model/o_user.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-05-13 18:15:46
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-23 15:43:07
+ * @LastEditTime: 2022-07-11 17:57:00
  * @FilePath: /CasaOS/service/model/o_user.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -15,11 +15,11 @@ import "time"
 //Soon to be removed
 type UserDBModel struct {
 	Id          int       `gorm:"column:id;primary_key" json:"id"`
-	UserName    string    `json:"user_name"`
+	Username    string    `json:"username"`
 	Password    string    `json:"password,omitempty"`
 	Role        string    `json:"role"`
 	Email       string    `json:"email"`
-	NickName    string    `json:"nick_name"`
+	Nickname    string    `json:"nickname"`
 	Avatar      string    `json:"avatar"`
 	Description string    `json:"description"`
 	CreatedAt   time.Time `gorm:"<-:create;autoCreateTime" json:"created_at,omitempty"`
@@ -27,5 +27,5 @@ type UserDBModel struct {
 }
 
 func (p *UserDBModel) TableName() string {
-	return "o_user"
+	return "o_users"
 }

+ 16 - 17
service/notify.go

@@ -33,16 +33,31 @@ type NotifyServer interface {
 	SendMemInfoBySocket(mem map[string]interface{})
 	SendUSBInfoBySocket(list []model2.DriveUSB)
 	SendDiskInfoBySocket(disk model2.Summary)
-	SendPersonStatusBySocket(status notify.Person)
 	SendFileOperateNotify(nowSend bool)
 	SendInstallAppBySocket(app notify.Application)
 	SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
+	SendStorageBySocket(message notify.StorageMessage)
 }
 
 type notifyServer struct {
 	db *gorm.DB
 }
 
+func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
+	body := make(map[string]interface{})
+	body["data"] = message
+
+	msg := gosf.Message{}
+	msg.Body = body
+	msg.Success = true
+	msg.Text = "storage_status"
+
+	notify := notify.Message{}
+	notify.Path = "storage_status"
+	notify.Msg = msg
+
+	NotifyMsg <- notify
+}
 func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
 
 	body := make(map[string]interface{})
@@ -224,22 +239,6 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
 
 }
 
-func (i *notifyServer) SendPersonStatusBySocket(status notify.Person) {
-	body := make(map[string]interface{})
-	body["data"] = status
-
-	msg := gosf.Message{}
-	msg.Body = body
-	msg.Success = true
-	msg.Text = "person_status"
-
-	notify := notify.Message{}
-	notify.Path = "person_status"
-	notify.Msg = msg
-
-	NotifyMsg <- notify
-}
-
 func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) {
 	body := make(map[string]interface{})
 	body["data"] = disk

+ 0 - 482
service/person.go

@@ -1,482 +0,0 @@
-package service
-
-import (
-	"bufio"
-	"context"
-	"encoding/json"
-	"fmt"
-	"io"
-	"net"
-	"os"
-	"reflect"
-	"strconv"
-	"time"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
-	port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/IceWhaleTech/CasaOS/types"
-	"github.com/lucas-clemente/quic-go"
-	"gorm.io/gorm"
-)
-
-type PersonService interface {
-	GetPersionInfo(token string) (m model.PersionModel, err error)
-	GetPersionNetWorkTypeDetection() string
-}
-
-type personService struct {
-	db *gorm.DB
-}
-
-var IpInfo model.PersionModel
-var CancelList map[string]string
-var InternalInspection map[string][]string
-
-func PushIpInfo(token string) {
-
-	m := model.PersionModel{}
-	m.Ips = ip_helper.GetDeviceAllIP("")
-	m.Token = token
-	b, _ := json.Marshal(m)
-
-	if reflect.DeepEqual(IpInfo, m) {
-		return
-	}
-	head := make(map[string]string)
-	infoS := httper2.Post(config.ServerInfo.Handshake+"/v1/update", b, "application/json", head)
-	fmt.Println(infoS)
-}
-func (p *personService) GetPersionInfo(token string) (m model.PersionModel, err error) {
-	infoS := httper2.Get(config.ServerInfo.Handshake+"/v1/ips/"+token, nil)
-	err = json.Unmarshal([]byte(infoS), &m)
-	return
-}
-func (p *personService) GetPersionNetWorkTypeDetection() string {
-	data := make(chan string)
-	list := []string{"stun.l.google.com", "stun1.l.google.com", "stun2.l.google.com", "stun.sipgate.net"}
-	for _, v := range list {
-		go utils.GetNetWorkTypeDetection(data, v)
-	}
-	result := <-data
-	close(data)
-	return result
-}
-
-func NewPersonService(db *gorm.DB) PersonService {
-	return &personService{db: db}
-}
-
-//=======================================================================================================================================================================
-
-var StreamList map[string]quic.Stream
-var ServiceMessage chan model.MessageModel
-
-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{
-		IP: net.IPv4zero, Port: port}
-	var err error
-	UDPConn, err = net.ListenUDP("udp", srcAddr)
-	if err != nil {
-		fmt.Println(err)
-	}
-	listener, err := quic.Listen(UDPConn, quic_helper.GetGenerateTLSConfig(config.ServerInfo.Token), quic_helper.GetQUICConfig())
-	if err != nil {
-		fmt.Println(err)
-	}
-	defer listener.Close()
-	ctx := context.Background()
-	acceptFailures := 0
-	const maxAcceptFailures = 10
-	if err != nil {
-		panic(err)
-	}
-
-	for {
-		select {
-		case <-ctx.Done():
-			fmt.Println(ctx.Err())
-			return
-		default:
-		}
-
-		session, err := listener.Accept(ctx)
-		if err != nil {
-			fmt.Println("Listen (BEP/quic): Accepting connection:", err)
-
-			acceptFailures++
-			if acceptFailures > maxAcceptFailures {
-				// Return to restart the listener, because something
-				// seems permanently damaged.
-				fmt.Println(err)
-				return
-			}
-
-			// Slightly increased delay for each failure.
-			time.Sleep(time.Duration(acceptFailures) * time.Second)
-
-			continue
-		}
-
-		acceptFailures = 0
-
-		streamCtx, cancel := context.WithTimeout(ctx, time.Second*10)
-		stream, err := session.AcceptStream(streamCtx)
-		cancel()
-		if err != nil {
-			fmt.Println("failed to accept stream from %s: %v", session.RemoteAddr(), err)
-			_ = session.CloseWithError(1, err.Error())
-			continue
-		}
-
-		// prefixByte := make([]byte, 4)
-		// c1, err := io.ReadFull(stream, prefixByte)
-		// fmt.Println(c1, err)
-		// prefixLength, err := strconv.Atoi(string(prefixByte))
-		// if err != nil {
-		// 	fmt.Println(err)
-		// }
-		// messageByte := make([]byte, prefixLength)
-		// t, err := io.ReadFull(stream, messageByte)
-		// fmt.Println(t, err)
-		// m := model.MessageModel{}
-		// err = json.Unmarshal(messageByte, &m)
-		// if err != nil {
-		// 	fmt.Println(err)
-		// }
-
-		go ProcessingContent(stream)
-	}
-}
-
-//处理内容
-func ProcessingContent(stream quic.Stream) {
-	for {
-		prefixByte := make([]byte, 6)
-		_, err := io.ReadFull(stream, prefixByte)
-		if err != nil {
-			fmt.Println(err)
-			return
-		}
-		prefixLength, err := strconv.Atoi(string(prefixByte))
-		if err != nil {
-			fmt.Println(err)
-		}
-		messageByte := make([]byte, prefixLength)
-		_, err = io.ReadFull(stream, messageByte)
-		if err != nil {
-			return
-		}
-		m := model.MessageModel{}
-		err = json.Unmarshal(messageByte, &m)
-		if err != nil {
-			fmt.Println(err)
-		}
-		if m.Type == types.PERSONHELLO {
-			//nothing
-			continue
-		} else if m.Type == types.PERSONDIRECTORY {
-			friend := model2.FriendModel{}
-			friend.Token = m.From
-			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) == "/" {
-					for _, v := range config.FileSettingInfo.ShareDir {
-						//tempList := MyService.ZiMa().GetDirPath(v)
-						temp := MyService.System().GetDirPathOne(v)
-						list = append(list, temp)
-					}
-				} else {
-					list = MyService.System().GetDirPath(m.Data.(string))
-				}
-			} else {
-				list = []model.Path{}
-			}
-			if rFriend.Write {
-				for i := 0; i < len(list); i++ {
-					list[i].Write = true
-				}
-			}
-			m.To = m.From
-			m.Data = list
-			m.From = config.ServerInfo.Token
-			SendData(stream, m)
-			break
-		} else if m.Type == types.PERSONDOWNLOAD {
-
-			SendFileData(stream, m.Data.(string), m.From, m.UUId, types.PERSONDOWNLOAD)
-			break
-		} else if m.Type == types.PERSONADDFRIEND {
-			friend := model2.FriendModel{}
-			dataModelByte, _ := json.Marshal(m.Data)
-			err := json.Unmarshal(dataModelByte, &friend)
-			if err != nil {
-				fmt.Println(err)
-				continue
-			}
-			go MyService.Friend().UpdateOrCreate(friend)
-			mi := model2.FriendModel{}
-			mi.Avatar = config.UserInfo.Avatar
-			mi.Profile = config.UserInfo.Description
-			mi.NickName = config.UserInfo.NickName
-			m.To = m.From
-			m.Data = mi
-			m.Type = types.PERSONADDFRIEND
-			m.From = config.ServerInfo.Token
-
-			SendData(stream, m)
-			break
-		} else if m.Type == types.PERSONCONNECTION {
-			if len(m.Data.(string)) > 0 {
-				fmt.Println("设置ip", m.Data.(string))
-				UDPAddressMap[m.From] = m.Data.(string)
-			} else {
-				delete(UDPAddressMap, m.From)
-			}
-			// mi := model2.FriendModel{}
-			// mi.Avatar = config.UserInfo.Avatar
-			// mi.Profile = config.UserInfo.Description
-			// mi.NickName = config.UserInfo.NickName
-			// 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.Write = false
-			friend.Version = user.Version
-			if len(config.UserInfo.Public) > 0 {
-				friend.State = types.FRIENDSTATEREQUEST
-			}
-			MyService.Friend().AddFriend(friend)
-
-			msg := model.MessageModel{}
-			msg.Type = types.PERSONHELLO
-			msg.Data = ""
-			msg.To = m.From
-			msg.From = config.ServerInfo.Token
-			msg.UUId = m.UUId
-			Dial(msg, false)
-
-			//agree user
-			if len(config.UserInfo.Public) == 0 {
-				msg.Type = types.PERSONAGREEFRIEND
-				msg.Data = ""
-				msg.To = m.From
-				msg.From = config.ServerInfo.Token
-				msg.UUId = m.UUId
-				Dial(msg, true)
-			}
-			break
-		} else if m.Type == types.PERSONAGREEFRIEND {
-			MyService.Friend().AgreeFrined(m.From)
-			break
-		} else if m.Type == types.PERSONCANCEL {
-			CancelList[m.UUId] = "cancel"
-			break
-		} else if m.Type == types.PERSONSUMMARY {
-			Summary(m, "upload")
-			continue
-		} else if m.Type == types.PERSONUPLOAD {
-			//TODO:检查是否存在如果存在直接结束
-			task := model2.PersonDownloadDBModel{}
-			task.UUID = m.UUId
-			task.LocalPath = m.Data.(string)
-			MyService.Download().AddDownloadTask(task)
-			friend := MyService.Friend().GetFriendById(model2.FriendModel{Token: m.From})
-			if friend.Write {
-				continue
-			} else {
-				break
-			}
-		} else if m.Type == types.PERSONUPLOADDATA {
-			r := SaveFile(m, stream)
-			if r {
-				break
-			}
-			continue
-		} else if m.Type == types.PERSONINTERNALINSPECTION {
-			fmt.Println("内网测试")
-			var ips []string
-			dataModelByte, _ := json.Marshal(m.Data)
-			err := json.Unmarshal(dataModelByte, &ips)
-			if err != nil {
-				fmt.Println(err)
-				break
-			}
-
-			go MyService.Friend().InternalInspection(ips, m.From)
-
-		} else if m.Type == types.PERSONPING {
-			fmt.Println("来自", m.From, "的ping", m.Data)
-			msg := m
-			m.To = m.From
-			m.Data = config.ServerInfo.Token
-			m.From = config.ServerInfo.Token
-			SendData(stream, m)
-
-			var ips []string
-			dataModelByte, _ := json.Marshal(msg.Data)
-			err := json.Unmarshal(dataModelByte, &ips)
-			if err != nil {
-				fmt.Println(err)
-				break
-			}
-			backIP := false
-			if v, ok := UDPAddressMap[msg.From]; ok {
-				for _, ip := range ips {
-					if ip == v {
-						backIP = true
-						break
-					}
-				}
-			}
-			if !backIP {
-				fmt.Println("检测需要查询ip", msg.From)
-				go MyService.Friend().InternalInspection(ips, msg.From)
-			}
-
-			break
-		} else if m.Type == types.PERSONIMAGETHUMBNAIL {
-			m.To = m.From
-
-			if data, err := file.GetImage(m.Data.(string), 100, 0); err == nil {
-				m.Data = data
-			} else {
-				m.Data = ""
-			}
-			m.From = config.ServerInfo.Token
-			SendData(stream, m)
-			break
-		} else {
-			//不应有不做返回的数据
-			//ServiceMessage <- m
-			break
-		}
-	}
-	stream.Close()
-
-}
-
-//文件分片发送
-func SendFileData(stream quic.Stream, filePath, to, uuid, t string) error {
-	summary := model.FileSummaryModel{}
-
-	msg := model.MessageModel{}
-	msg.Type = types.PERSONSUMMARY
-	msg.From = config.ServerInfo.Token
-	msg.To = to
-	msg.UUId = uuid
-
-	fStat, err := os.Stat(filePath)
-	if err != nil {
-
-		summary.Message = err.Error()
-
-		msg.Data = summary
-
-		summaryByte, _ := json.Marshal(msg)
-		summaryPrefixLength := file.PrefixLength(len(summaryByte))
-		summaryData := append(summaryPrefixLength, summaryByte...)
-		stream.Write(summaryData)
-		return err
-	}
-
-	blockSize, length := file.GetBlockInfo(fStat.Size())
-
-	f, err := os.Open(filePath)
-	if err != nil {
-
-		summary.Message = err.Error()
-		msg.Data = summary
-
-		summaryByte, _ := json.Marshal(msg)
-		summaryPrefixLength := file.PrefixLength(len(summaryByte))
-		summaryData := append(summaryPrefixLength, summaryByte...)
-		stream.Write(summaryData)
-		return err
-	}
-
-	//send file summary first
-	summary.BlockSize = blockSize
-	summary.Hash = file.GetHashByPath(filePath)
-	summary.Length = length
-	summary.Name = fStat.Name()
-	summary.Size = fStat.Size()
-
-	msg.Data = summary
-
-	summaryByte, _ := json.Marshal(msg)
-	summaryPrefixLength := file.PrefixLength(len(summaryByte))
-	summaryData := append(summaryPrefixLength, summaryByte...)
-	stream.Write(summaryData)
-
-	bufferedReader := bufio.NewReader(f)
-	buf := make([]byte, blockSize)
-
-	defer stream.Close()
-
-	for i := 0; i < length; i++ {
-
-		tran := model.TranFileModel{}
-
-		n, err := bufferedReader.Read(buf)
-
-		if err == io.EOF {
-			fmt.Println("读取完毕", err)
-		}
-
-		tran.Hash = file.GetHashByContent(buf[:n])
-		tran.Index = i
-		tran.Length = length
-
-		fileMsg := model.MessageModel{}
-		fileMsg.Type = t
-		fileMsg.Data = tran
-		fileMsg.From = config.ServerInfo.Token
-		fileMsg.To = to
-		fileMsg.UUId = uuid
-		b, _ := json.Marshal(fileMsg)
-		prefixLength := file.PrefixLength(len(b))
-		dataLength := file.DataLength(len(buf[:n]))
-		data := append(append(append(prefixLength, b...), dataLength...), buf[:n]...)
-		if _, ok := CancelList[uuid]; ok {
-			delete(CancelList, uuid)
-			return nil
-		}
-		stream.Write(data)
-	}
-	record := model2.PersonDownRecordDBModel{}
-	record.UUID = uuid
-	record.Name = f.Name()
-	record.Downloader = to
-	record.Path = filePath
-	record.Size = fStat.Size()
-	record.Type = types.PERSONFILEDOWNLOAD
-	if t == types.PERSONUPLOADDATA {
-		record.Type = types.PERSONFILEUPLOAD
-	}
-
-	MyService.DownRecord().AddDownRecord(record)
-
-	return nil
-}

+ 2 - 0
service/rely.go

@@ -35,6 +35,8 @@ func (r *relyService) Create(rely model2.RelyDBModel) {
 func (r *relyService) GetInfo(id string) model2.RelyDBModel {
 	var m model2.RelyDBModel
 	r.db.Where("custom_id = ?", id).First(&m)
+
+	// @tiger - 作为出参不应该直接返回数据库内的格式(见类似问题的注释)
 	return m
 }
 

+ 28 - 49
service/service.go

@@ -1,3 +1,13 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-07-12 09:48:56
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-07-15 10:58:54
+ * @FilePath: /CasaOS/service/service.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
 package service
 
 import (
@@ -23,68 +33,37 @@ type Repository interface {
 	Notify() NotifyServer
 	Rely() RelyService
 	System() SystemService
-	Shortcuts() ShortcutsService
-	Person() PersonService
-	Friend() FriendService
-	Download() DownloadService
-	DownRecord() DownRecordService
 }
 
 func NewService(db *gorm.DB) Repository {
-
 	return &store{
-		app:        NewAppService(db),
-		user:       NewUserService(db),
-		docker:     NewDockerService(),
-		casa:       NewCasaService(),
-		disk:       NewDiskService(db),
-		notify:     NewNotifyService(db),
-		rely:       NewRelyService(db),
-		system:     NewSystemService(),
-		shortcuts:  NewShortcutsService(db),
-		person:     NewPersonService(db),
-		friend:     NewFriendService(db),
-		download:   NewDownloadService(db),
-		downrecord: NewDownRecordService(db),
+		app:    NewAppService(db),
+		user:   NewUserService(db),
+		docker: NewDockerService(),
+		casa:   NewCasaService(),
+		disk:   NewDiskService(db),
+		notify: NewNotifyService(db),
+		rely:   NewRelyService(db),
+		system: NewSystemService(),
 	}
 }
 
 type store struct {
-	db         *gorm.DB
-	app        AppService
-	user       UserService
-	docker     DockerService
-	casa       CasaService
-	disk       DiskService
-	notify     NotifyServer
-	rely       RelyService
-	system     SystemService
-	shortcuts  ShortcutsService
-	person     PersonService
-	friend     FriendService
-	download   DownloadService
-	downrecord DownRecordService
-}
-
-func (c *store) DownRecord() DownRecordService {
-	return c.downrecord
+	db     *gorm.DB
+	app    AppService
+	user   UserService
+	docker DockerService
+	casa   CasaService
+	disk   DiskService
+	notify NotifyServer
+	rely   RelyService
+	system SystemService
 }
 
-func (c *store) Download() DownloadService {
-	return c.download
-}
-func (c *store) Friend() FriendService {
-	return c.friend
-}
 func (c *store) Rely() RelyService {
 	return c.rely
 }
-func (c *store) Shortcuts() ShortcutsService {
-	return c.shortcuts
-}
-func (c *store) Person() PersonService {
-	return c.person
-}
+
 func (c *store) System() SystemService {
 	return c.system
 }

+ 0 - 34
service/shortcuts.go

@@ -1,34 +0,0 @@
-package service
-
-import (
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"gorm.io/gorm"
-)
-
-type ShortcutsService interface {
-	DeleteData(id string)
-	AddData(m model2.ShortcutsDBModel)
-	EditData(m model2.ShortcutsDBModel)
-	GetList() (list []model2.ShortcutsDBModel)
-}
-type shortcutsService struct {
-	db *gorm.DB
-}
-
-func (s *shortcutsService) AddData(m model2.ShortcutsDBModel) {
-	s.db.Create(&m)
-}
-func (s *shortcutsService) EditData(m model2.ShortcutsDBModel) {
-	s.db.Save(&m)
-}
-func (s *shortcutsService) DeleteData(id string) {
-	var m model2.ShortcutsDBModel
-	s.db.Where("id=?", id).Delete(&m)
-}
-func (s *shortcutsService) GetList() (list []model2.ShortcutsDBModel) {
-	s.db.Order("sort desc,id").Find(&list)
-	return list
-}
-func NewShortcutsService(db *gorm.DB) ShortcutsService {
-	return &shortcutsService{db: db}
-}

+ 11 - 21
service/system.go

@@ -24,7 +24,6 @@ import (
 )
 
 type SystemService interface {
-	UpSystemConfig(str string, widget string)
 	UpdateSystemVersion(version string)
 	GetSystemConfigDebug() []string
 	GetCasaOSLogs(lineNumber int) string
@@ -54,6 +53,12 @@ type SystemService interface {
 type systemService struct {
 }
 
+func (s *systemService) UpdateUSBAutoMount(state string) {
+	config.ServerInfo.USBAutoMount = state
+	config.Cfg.Section("server").Key("USBAutoMount").SetValue(state)
+	config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
+}
+
 func (c *systemService) MkdirAll(path string) (int, error) {
 	_, err := os.Stat(path)
 	if err == nil {
@@ -66,7 +71,7 @@ func (c *systemService) MkdirAll(path string) (int, error) {
 			return common_err.FILE_OR_DIR_EXISTS, err
 		}
 	}
-	return common_err.ERROR, err
+	return common_err.SERVICE_ERROR, err
 }
 func (c *systemService) RenameFile(oldF, newF string) (int, error) {
 
@@ -77,12 +82,12 @@ func (c *systemService) RenameFile(oldF, newF string) (int, error) {
 		if os.IsNotExist(err) {
 			err := os.Rename(oldF, newF)
 			if err != nil {
-				return common_err.ERROR, err
+				return common_err.SERVICE_ERROR, err
 			}
 			return common_err.SUCCESS, nil
 		}
 	}
-	return common_err.ERROR, err
+	return common_err.SERVICE_ERROR, err
 }
 func (c *systemService) CreateFile(path string) (int, error) {
 	_, err := os.Stat(path)
@@ -94,7 +99,7 @@ func (c *systemService) CreateFile(path string) (int, error) {
 			return common_err.SUCCESS, nil
 		}
 	}
-	return common_err.ERROR, err
+	return common_err.SERVICE_ERROR, err
 }
 func (c *systemService) GetDeviceTree() string {
 	return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDeviceTree")
@@ -232,28 +237,13 @@ func (s *systemService) ExecUSBAutoMountShell(state string) {
 func (s *systemService) GetSystemConfigDebug() []string {
 	return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetSysInfo")
 }
-func (s *systemService) UpSystemConfig(str string, widget string) {
-	if len(str) > 0 && str != config.SystemConfigInfo.ConfigStr {
-		config.Cfg.Section("system").Key("ConfigStr").SetValue(str)
-		config.SystemConfigInfo.ConfigStr = str
-	}
-	if len(widget) > 0 && widget != config.SystemConfigInfo.WidgetList {
-		config.Cfg.Section("system").Key("WidgetList").SetValue(widget)
-		config.SystemConfigInfo.WidgetList = widget
-	}
-	config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
-}
+
 func (s *systemService) UpAppOrderFile(str, id string) {
 	file.WriteToPath([]byte(str), config.AppInfo.DBPath+"/"+id, "app_order.json")
 }
 func (s *systemService) GetAppOrderFile(id string) []byte {
 	return file.ReadFullFile(config.AppInfo.UserDataPath + "/" + id + "/app_order.json")
 }
-func (s *systemService) UpdateUSBAutoMount(state string) {
-	config.ServerInfo.USBAutoMount = state
-	config.Cfg.Section("server").Key("USBAutoMount").SetValue(state)
-	config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
-}
 func (s *systemService) UpSystemPort(port string) {
 	if len(port) > 0 && port != config.ServerInfo.HttpPort {
 		config.Cfg.Section("server").Key("HttpPort").SetValue(port)

+ 0 - 503
service/udpconn.go

@@ -1,503 +0,0 @@
-package service
-
-import (
-	"context"
-	"crypto/md5"
-	"encoding/hex"
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net"
-	"os"
-	path2 "path"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/model/notify"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/IceWhaleTech/CasaOS/types"
-	"github.com/lucas-clemente/quic-go"
-	uuid "github.com/satori/go.uuid"
-)
-
-var UDPConn *net.UDPConn
-var PeopleMap map[string]quic.Stream
-var Message chan model.MessageModel
-var UDPAddressMap map[string]string
-
-func UDPSendData(msg model.MessageModel, localFilePath string) error {
-	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-	defer cancel()
-	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{
-		IP: net.IPv4zero, Port: p} //注意端口必须固定
-	addr := UDPAddressMap[msg.To]
-	ticket := msg.To
-	dstAddr, err := net.ResolveUDPAddr("udp", addr)
-
-	session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
-	if err != nil {
-		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 err
-	}
-
-	stream, err := session.OpenStreamSync(ctx)
-	if err != nil {
-		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())
-		return err
-	}
-
-	SayHello(stream, msg.To)
-	//TODO:发送
-	SendData(stream, msg)
-	SendFileData(stream, localFilePath, msg.To, msg.UUId, types.PERSONUPLOADDATA)
-
-	stream.Close()
-	if config.SystemConfigInfo.Analyse != "False" {
-		go MyService.Casa().PushConnectionStatus(msg.UUId, "OK", msg.From, msg.To, msg.Type)
-	}
-	return nil
-}
-
-func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error) {
-	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
-	defer cancel()
-	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{
-		IP: net.IPv4zero, Port: p} //注意端口必须固定
-	addr := UDPAddressMap[msg.To]
-	ticket := msg.To
-	if server {
-		addr = config.ServerInfo.Handshake + ":9527"
-		ticket = "bench"
-	}
-	dstAddr, err := net.ResolveUDPAddr("udp", addr)
-
-	//DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6";如果laddr不是nil,将使用它作为本地地址,否则自动选择一个本地地址。
-	//(conn)UDPConn代表一个UDP网络连接,实现了Conn和PacketConn接口
-
-	session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
-	if err != nil {
-		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
-	}
-
-	stream, err := session.OpenStreamSync(ctx)
-	if err != nil {
-		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())
-		return m, err
-	}
-
-	SayHello(stream, msg.To)
-
-	SendData(stream, msg)
-
-	go ReadContent(stream)
-	result := <-Message
-	stream.Close()
-	if config.SystemConfigInfo.Analyse != "False" {
-		go MyService.Casa().PushConnectionStatus(msg.UUId, "OK", msg.From, msg.To, msg.Type)
-	}
-	return result, nil
-}
-
-func SayHello(stream quic.Stream, to string) {
-	msg := model.MessageModel{}
-	msg.Type = types.PERSONHELLO
-	msg.Data = "hello"
-	msg.To = to
-	msg.From = config.ServerInfo.Token
-	msg.UUId = uuid.NewV4().String()
-	SendData(stream, msg)
-}
-
-//发送数据
-func SendData(stream quic.Stream, m model.MessageModel) {
-	b, _ := json.Marshal(m)
-	prefixLength := file.PrefixLength(len(b))
-	data := append(prefixLength, b...)
-	stream.Write(data)
-}
-
-//读取数据
-func ReadContent(stream quic.Stream) {
-	for {
-		prefixByte := make([]byte, 6)
-		_, err := io.ReadFull(stream, prefixByte)
-		if err != nil {
-			fmt.Println(err)
-			time.Sleep(time.Second * 1)
-			for k, v := range CancelList {
-				tempPath := config.AppInfo.TempPath + "/" + v
-				fmt.Println(file.RMDir(tempPath))
-				delete(CancelList, k)
-			}
-			break
-		}
-		prefixLength, err := strconv.Atoi(string(prefixByte))
-		if err != nil {
-			fmt.Println(err)
-			break
-		}
-		messageByte := make([]byte, prefixLength)
-		_, err = io.ReadFull(stream, messageByte)
-		if err != nil {
-			fmt.Println(err)
-			break
-		}
-		m := model.MessageModel{}
-		err = json.Unmarshal(messageByte, &m)
-		if err != nil {
-			fmt.Println(err)
-			break
-		}
-		if m.Type == types.PERSONDOWNLOAD {
-			r := SaveFile(m, stream)
-			if r {
-				break
-			}
-		} else if m.Type == types.PERSONSUMMARY {
-			Summary(m, "download")
-		} else if m.Type == types.PERSONCONNECTION {
-			if len(m.Data.(string)) > 0 {
-				UDPAddressMap[m.From] = m.Data.(string)
-			} else {
-				delete(UDPAddressMap, m.From)
-			}
-			// mi := model2.FriendModel{}
-			// mi.Avatar = config.UserInfo.Avatar
-			// mi.Profile = config.UserInfo.Description
-			// mi.NickName = config.UserInfo.NickName
-			// mi.Token = config.ServerInfo.Token
-			msg := model.MessageModel{}
-			msg.Type = types.PERSONHELLO
-			msg.Data = ""
-			msg.To = m.From
-			msg.From = config.ServerInfo.Token
-			msg.UUId = m.UUId
-			go Dial(msg, false)
-			Message <- m
-			break
-		} else if m.Type == types.PERSONGETIP {
-			notify := notify.Person{}
-			notify.ShareId = m.From
-			if len(m.Data.(string)) == 0 {
-				if _, ok := UDPAddressMap[m.From]; ok {
-					notify.Type = "OFFLINE"
-					go MyService.Notify().SendPersonStatusBySocket(notify)
-				}
-				delete(UDPAddressMap, m.From)
-				Message <- m
-				break
-			}
-			if _, ok := UDPAddressMap[m.From]; !ok {
-				notify.Type = "ONLINE"
-				go MyService.Notify().SendPersonStatusBySocket(notify)
-			}
-			UDPAddressMap[m.From] = m.Data.(string)
-			if config.ServerInfo.Token != m.From && strings.Split(m.Data.(string), ":")[0] == strings.Split(UDPAddressMap[config.ServerInfo.Token], ":")[0] {
-				msg := model.MessageModel{}
-				msg.Type = types.PERSONINTERNALINSPECTION
-				msg.Data = ip_helper.GetDeviceAllIP(config.ServerInfo.UDPPort)
-				msg.To = m.From
-				msg.From = config.ServerInfo.Token
-				msg.UUId = m.UUId
-				go Dial(msg, true)
-			}
-
-			Message <- m
-			break
-		} else if m.Type == types.PERSONINTERNALINSPECTION {
-			fmt.Println("接收到反验证")
-			var ips []string
-			dataModelByte, _ := json.Marshal(m.Data)
-			err := json.Unmarshal(dataModelByte, &ips)
-			if err != nil {
-				fmt.Println(err)
-				break
-			}
-			go MyService.Friend().InternalInspection(ips, m.From)
-			Message <- m
-			break
-		} else {
-
-			Message <- m
-		}
-	}
-	Message <- model.MessageModel{}
-}
-
-func SendIPToServer() {
-	msg := model.MessageModel{}
-	msg.Type = types.PERSONHELLO
-	msg.Data = ""
-	msg.From = config.ServerInfo.Token
-	msg.To = config.ServerInfo.Token
-	msg.UUId = uuid.NewV4().String()
-
-	Dial(msg, true)
-}
-
-func LoopFriend() {
-	list := MyService.Friend().GetFriendList()
-	msg := model.MessageModel{}
-	msg.Type = types.PERSONGETIP
-	msg.Data = ""
-	msg.From = config.ServerInfo.Token
-	msg.To = config.ServerInfo.Token
-	msg.UUId = uuid.NewV4().String()
-	Dial(msg, true)
-
-	for i := 0; i < len(list); i++ {
-		if _, ok := UDPAddressMap[list[i].Token]; !ok {
-			msg := model.MessageModel{}
-			msg.Type = types.PERSONGETIP
-			msg.Data = ""
-			msg.From = config.ServerInfo.Token
-			msg.To = list[i].Token
-			msg.UUId = uuid.NewV4().String()
-			Dial(msg, true)
-		}
-
-		msg.Type = types.PERSONPING
-		msg.Data = ""
-		msg.From = config.ServerInfo.Token
-		msg.To = list[i].Token
-		msg.UUId = uuid.NewV4().String()
-
-		if v, ok := UDPAddressMap[list[i].Token]; ok {
-			if ip_helper.HasLocalIP(net.ParseIP(strings.Split(v, ":")[0])) {
-				msg.Data = ip_helper.GetDeviceAllIP(config.ServerInfo.UDPPort)
-			}
-			oldIP := UDPAddressMap[list[i].Token]
-			data, err := Dial(msg, false)
-			if err != nil || reflect.DeepEqual(data, model.MessageModel{}) || len(data.Data.(string)) == 0 {
-				if oldIP == UDPAddressMap[list[i].Token] {
-					notify := notify.Person{}
-					notify.ShareId = data.From
-					notify.Type = "LEAVE"
-					go MyService.Notify().SendPersonStatusBySocket(notify)
-
-					delete(UDPAddressMap, list[i].Token)
-
-					msg := model.MessageModel{}
-					msg.Type = types.PERSONGETIP
-					msg.Data = ""
-					msg.From = config.ServerInfo.Token
-					msg.To = list[i].Token
-					msg.UUId = uuid.NewV4().String()
-					Dial(msg, true)
-				}
-			}
-		}
-		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)
-
-	}
-}
-
-//file summary
-func Summary(m model.MessageModel, t string) {
-	dataModel := model.FileSummaryModel{}
-	dataModelByte, _ := json.Marshal(m.Data)
-	err := json.Unmarshal(dataModelByte, &dataModel)
-	if err != nil {
-		fmt.Println(err)
-	}
-
-	task := MyService.Download().GetDownloadById(m.UUId)
-
-	task.State = types.DOWNLOADING
-	fullPath := path2.Join(task.LocalPath, task.Name)
-
-	if len(dataModel.Message) > 0 {
-		task.State = types.DOWNLOADERROR
-		task.Error = dataModel.Message
-	}
-	//The file already exists and the file is the same, no need to download
-	if t != "upload" && 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 = types.PERSONFILEDOWNLOAD
-	task.From = m.From
-	if t == "upload" {
-		task.Type = types.PERSONFILERECEIVEUPLOAD
-	}
-	MyService.Download().SaveDownload(task)
-}
-
-//Save file fragment
-func SaveFile(m model.MessageModel, stream quic.Stream) bool {
-	dataModelByte, _ := json.Marshal(m.Data)
-	dataModel := model.TranFileModel{}
-	err := json.Unmarshal(dataModelByte, &dataModel)
-	if err != nil {
-		fmt.Println(err)
-		return false
-	}
-
-	dataLengthByte := make([]byte, 8)
-	_, err = io.ReadFull(stream, dataLengthByte)
-	if err != nil {
-		fmt.Println(err)
-		return false
-	}
-	dataLength, err := strconv.Atoi(string(dataLengthByte))
-	if err != nil {
-		fmt.Println(err)
-		return false
-	}
-	dataByte := make([]byte, dataLength)
-	_, err = io.ReadFull(stream, dataByte)
-	if err != nil {
-		fmt.Println(err)
-		return false
-	}
-	sum := md5.Sum(dataByte)
-	hash := hex.EncodeToString(sum[:])
-	if dataModel.Hash != hash {
-		fmt.Println("hash不匹配", hash, dataModel.Hash)
-		return false
-	}
-	tempPath := config.AppInfo.TempPath + "/" + m.UUId
-	file.IsNotExistMkDir(tempPath)
-	filepath := tempPath + "/" + strconv.Itoa(dataModel.Index)
-	_, err = os.Stat(filepath)
-
-	if os.IsNotExist(err) {
-		err = ioutil.WriteFile(filepath, dataByte, 0644)
-		task := model2.PersonDownloadDBModel{}
-		task.UUID = m.UUId
-		if err != nil {
-			task.Error = err.Error()
-			task.State = types.DOWNLOADERROR
-			MyService.Download().SetDownloadError(task)
-		}
-
-	} else {
-		if file.GetHashByPath(filepath) != dataModel.Hash {
-			os.Remove(filepath)
-			err = ioutil.WriteFile(filepath, dataByte, 0644)
-			task := model2.PersonDownloadDBModel{}
-			task.UUID = m.UUId
-			if err != nil {
-				task.Error = err.Error()
-				task.State = types.DOWNLOADERROR
-				MyService.Download().SetDownloadError(task)
-			}
-		}
-	}
-
-	files, err := ioutil.ReadDir(tempPath)
-	if err != nil {
-		fmt.Println(err)
-		return false
-	}
-	if len(files) >= dataModel.Length {
-		summary := MyService.Download().GetDownloadById(m.UUId)
-		summary.State = types.DOWNLOADFINISH
-		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)
-			summary.State = types.DOWNLOADFINISHED
-			MyService.Download().EditDownloadState(summary)
-		} else {
-			os.Remove(config.FileSettingInfo.DownloadDir + "/" + summary.Name)
-
-			summary.State = types.DOWNLOADERROR
-			summary.Error = "hash mismatch"
-			MyService.Download().SetDownloadError(summary)
-		}
-
-		return true
-	}
-	return false
-}

+ 9 - 35
service/user.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-03-18 11:40:55
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-23 19:45:49
+ * @LastEditTime: 2022-07-12 10:05:37
  * @FilePath: /CasaOS/service/user.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -15,13 +15,11 @@ import (
 	"mime/multipart"
 	"os"
 
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/service/model"
 	"gorm.io/gorm"
 )
 
 type UserService interface {
-	SetUser(username, pwd, token, email, desc, nickName string) error
 	UpLoadFile(file multipart.File, name string) error
 	CreateUser(m model.UserDBModel) model.UserDBModel
 	GetUserCount() (userCount int64)
@@ -31,6 +29,7 @@ type UserService interface {
 	GetUserAllInfoById(id string) (m model.UserDBModel)
 	GetUserAllInfoByName(userName string) (m model.UserDBModel)
 	DeleteUserById(id string)
+	DeleteAllUser()
 	GetUserInfoByUserName(userName string) (m model.UserDBModel)
 	GetAllUserName() (list []model.UserDBModel)
 }
@@ -41,12 +40,15 @@ type userService struct {
 	db *gorm.DB
 }
 
+func (u *userService) DeleteAllUser() {
+	u.db.Where("1=1").Delete(&model.UserDBModel{})
+}
 func (u *userService) DeleteUserById(id string) {
 	u.db.Where("id= ?", id).Delete(&model.UserDBModel{})
 }
 
 func (u *userService) GetAllUserName() (list []model.UserDBModel) {
-	u.db.Select("user_name").Find(&list)
+	u.db.Select("username").Find(&list)
 	return
 }
 func (u *userService) CreateUser(m model.UserDBModel) model.UserDBModel {
@@ -70,47 +72,19 @@ func (u *userService) GetUserAllInfoById(id string) (m model.UserDBModel) {
 	return
 }
 func (u *userService) GetUserAllInfoByName(userName string) (m model.UserDBModel) {
-	u.db.Where("user_name= ?", userName).First(&m)
+	u.db.Where("username= ?", userName).First(&m)
 	return
 }
 func (u *userService) GetUserInfoById(id string) (m model.UserDBModel) {
-	u.db.Select("user_name", "id", "role", "nick_name", "description", "avatar").Where("id= ?", id).First(&m)
+	u.db.Select("username", "id", "role", "nickname", "description", "avatar", "email").Where("id= ?", id).First(&m)
 	return
 }
 
 func (u *userService) GetUserInfoByUserName(userName string) (m model.UserDBModel) {
-	u.db.Select("user_name", "id", "role", "nick_name", "description", "avatar").Where("user_name= ?", userName).First(&m)
+	u.db.Select("username", "id", "role", "nickname", "description", "avatar", "email").Where("username= ?", userName).First(&m)
 	return
 }
 
-//设置用户名密码
-func (u *userService) SetUser(username, pwd, token, email, desc, nickName string) error {
-	if len(username) > 0 {
-		config.Cfg.Section("user").Key("UserName").SetValue(username)
-		config.UserInfo.UserName = username
-		config.Cfg.Section("user").Key("Initialized").SetValue("true")
-		config.UserInfo.Initialized = true
-	}
-	if len(pwd) > 0 {
-		config.Cfg.Section("user").Key("PWD").SetValue(pwd)
-		config.UserInfo.PWD = pwd
-	}
-	if len(email) > 0 {
-		config.Cfg.Section("user").Key("Email").SetValue(email)
-		config.UserInfo.Email = email
-	}
-	if len(desc) > 0 {
-		config.Cfg.Section("user").Key("Description").SetValue(desc)
-		config.UserInfo.Description = desc
-	}
-	if len(nickName) > 0 {
-		config.Cfg.Section("user").Key("NickName").SetValue(nickName)
-		config.UserInfo.NickName = nickName
-	}
-	config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
-	return nil
-}
-
 //上传文件
 func (c *userService) UpLoadFile(file multipart.File, url string) error {
 	out, _ := os.OpenFile(url, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)

+ 2 - 2
types/system.go

@@ -2,7 +2,7 @@
  * @Author: LinkLeong link@icewhale.com
  * @Date: 2022-02-17 18:53:22
  * @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-01 15:15:09
+ * @LastEditTime: 2022-07-18 18:47:15
  * @FilePath: /CasaOS/types/system.go
  * @Description:
  * @Website: https://www.casaos.io
@@ -10,6 +10,6 @@
  */
 package types
 
-const CURRENTVERSION = "0.3.3"
+const CURRENTVERSION = "0.3.4"
 
 const BODY = ""

+ 9 - 9
web/browserconfig.xml

@@ -1,9 +1,9 @@
-<?xml version="1.0" encoding="utf-8"?>
-<browserconfig>
-    <msapplication>
-        <tile>
-            <square150x150logo src="/ui/img/icon/mstile-150x150.png"/>
-            <TileColor>#da532c</TileColor>
-        </tile>
-    </msapplication>
-</browserconfig>
+<?xml version="1.0" encoding="utf-8"?>
+<browserconfig>
+    <msapplication>
+        <tile>
+            <square150x150logo src="/ui/img/icon/mstile-150x150.png"/>
+            <TileColor>#da532c</TileColor>
+        </tile>
+    </msapplication>
+</browserconfig>

+ 14 - 14
web/favicon.svg

@@ -1,14 +1,14 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<style type="text/css">
-	.st0{fill:none;stroke:#363636;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
-	@media ( prefers-color-scheme: dark ) {
-		.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
-	}
-</style>
-<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
-<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
-<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:none;stroke:#363636;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
+	@media ( prefers-color-scheme: dark ) {
+		.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
+	}
+</style>
+<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
+<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
+<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
+</svg>

BIN
web/img/1-small.1b74d2ba.png


BIN
web/img/Android-DeviceID.b57fefc8.png


BIN
web/img/Android-Menu.ed4df0da.png


BIN
web/img/Android-NewDevice.f00af2cb.png


BIN
web/img/Android-NewDeviceAdd.784d2f18.png


BIN
web/img/Android-NewFolder.d71dc444.png


BIN
web/img/Android-NewFolderCreate.b3521b45.png


BIN
web/img/Android-ShowDeviceID.f7e46fb8.png


BIN
web/img/Windows-DeviceID.2e929f75.png


BIN
web/img/Windows-NewDevice.c9f2471d.png


BIN
web/img/Windows-NewDeviceSave.fe1078b1.png


BIN
web/img/Windows-NewFolder.5305cc41.png


BIN
web/img/Windows-NewFolderSave.9ce2312f.png


BIN
web/img/Windows-ShowID.1000f319.png


+ 25 - 25
web/img/icon/safari-pinned-tab.svg

@@ -1,25 +1,25 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
- "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
- width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
- preserveAspectRatio="xMidYMid meet">
-<metadata>
-Created by potrace 1.14, written by Peter Selinger 2001-2017
-</metadata>
-<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
-fill="#000000" stroke="none">
-<path d="M875 1894 c-11 -2 -51 -11 -88 -20 -341 -78 -610 -364 -673 -714 -82
--459 197 -902 647 -1030 94 -27 277 -37 378 -21 303 47 575 261 690 540 55
-133 66 192 65 361 -1 136 -4 165 -27 235 -36 116 -62 170 -123 261 -123 186
--347 336 -566 379 -42 8 -276 15 -303 9z m250 -168 c11 -2 42 -9 70 -16 131
--30 288 -135 387 -260 160 -201 198 -506 93 -745 l-22 -50 2 80 c3 180 -64
-351 -184 476 -209 216 -544 260 -807 105 -201 -117 -326 -347 -319 -587 l2
--74 -19 44 c-63 140 -80 332 -44 476 24 94 87 219 147 292 109 133 290 238
-448 259 25 3 47 7 49 9 5 4 173 -3 197 -9z m8 -501 c33 -8 85 -31 116 -50 227
--137 305 -418 183 -651 l-21 -39 -1 35 c-9 251 -245 439 -490 389 -186 -38
--323 -200 -330 -389 l-1 -35 -23 45 c-101 194 -61 429 99 578 130 122 292 162
-468 117z m-27 -499 c182 -85 183 -345 1 -438 -53 -27 -161 -26 -215 1 -146 75
--180 267 -69 390 63 69 190 90 283 47z"/>
-</g>
-</svg>
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.14, written by Peter Selinger 2001-2017
+</metadata>
+<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M875 1894 c-11 -2 -51 -11 -88 -20 -341 -78 -610 -364 -673 -714 -82
+-459 197 -902 647 -1030 94 -27 277 -37 378 -21 303 47 575 261 690 540 55
+133 66 192 65 361 -1 136 -4 165 -27 235 -36 116 -62 170 -123 261 -123 186
+-347 336 -566 379 -42 8 -276 15 -303 9z m250 -168 c11 -2 42 -9 70 -16 131
+-30 288 -135 387 -260 160 -201 198 -506 93 -745 l-22 -50 2 80 c3 180 -64
+351 -184 476 -209 216 -544 260 -807 105 -201 -117 -326 -347 -319 -587 l2
+-74 -19 44 c-63 140 -80 332 -44 476 24 94 87 219 147 292 109 133 290 238
+448 259 25 3 47 7 49 9 5 4 173 -3 197 -9z m8 -501 c33 -8 85 -31 116 -50 227
+-137 305 -418 183 -651 l-21 -39 -1 35 c-9 251 -245 439 -490 389 -186 -38
+-323 -200 -330 -389 l-1 -35 -23 45 c-101 194 -61 429 99 578 130 122 292 162
+468 117z m-27 -499 c182 -85 183 -345 1 -438 -53 -27 -161 -26 -215 1 -146 75
+-180 267 -69 390 63 69 190 90 283 47z"/>
+</g>
+</svg>

BIN
web/img/macOS-Config.f419628a.png


BIN
web/img/macOS-DeviceID.968cc84d.png


BIN
web/img/macOS-NewFolder.fa9e37d0.png


BIN
web/img/macOS-NewFolderSave.6f3f247d.png


BIN
web/img/macOS-ShowID.c822acc3.png


BIN
web/img/macOS-icon.ae9e0906.png


+ 0 - 1
web/img/syncthing.257e4f51.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 66 65" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round"><style><![CDATA[.B{stroke:none}.C{fill-rule:nonzero}.D{stroke:#fff}.E{stroke-width:3.271}]]></style><use xlink:href="#B" x=".5" y=".5"/><defs><linearGradient id="A" x1="49.97%" y1="99.94%" x2="49.97%" y2="0.00%"><stop offset="0%" stop-color="#0882c8"/><stop offset="100%" stop-color="#26b6db"/></linearGradient></defs><symbol id="B" overflow="visible"><path d="M0 32C0 14.272 14.272 0 32 0s32 14.272 32 32-14.272 32-32 32S0 49.728 0 32z" fill="url(#A)" class="B C"/><path d="M8.177 31.891C8.177 18.693 18.802 8.068 32 8.068s23.823 10.625 23.823 23.823S45.198 55.714 32 55.714 8.177 45.089 8.177 31.891z" fill="none" class="D E"/><path d="M51.625 26.058c2.562.872 5.342-.491 6.215-3.053s-.491-5.342-3.053-6.215-5.342.491-6.215 3.053.491 5.342 3.053 6.215z" class="B C"/><path d="M53.206 21.479L36.797 35.108" fill="none" class="D E"/><path d="M42.304 49.608c-.218 2.671 1.745 5.07 4.47 5.342 2.726.218 5.07-1.744 5.343-4.47.218-2.671-1.745-5.07-4.47-5.343-2.726-.218-5.124 1.745-5.342 4.47z" class="B C"/><path d="M47.155 50.044L36.797 35.107" fill="none" class="D E"/><path d="M32.708 37.779c1.472 2.29 4.525 2.944 6.76 1.472 2.29-1.472 2.944-4.525 1.472-6.76-1.472-2.29-4.525-2.944-6.76-1.472-2.29 1.417-2.944 4.47-1.472 6.76zm-21.152-4.307c-2.344-1.363-5.342-.6-6.705 1.69-1.363 2.344-.6 5.342 1.69 6.705 2.344 1.363 5.342.6 6.705-1.69s.6-5.288-1.69-6.705z" class="B C"/><path d="M9.049 37.669l27.748-2.562" fill="none" class="D E"/></symbol></svg>

+ 0 - 1
web/img/windows.d98029c3.svg

@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="88" width="88">
<path style="fill:#00adef;" d="m0,12.402,35.687-4.8602,0.0156,34.423-35.67,0.20313zm35.67,33.529,0.0277,34.453-35.67-4.9041-0.002-29.78zm4.3261-39.025,47.318-6.906,0,41.527-47.318,0.37565zm47.329,39.349-0.0111,41.34-47.318-6.6784-0.0663-34.739z"/>
</svg>

+ 1 - 1
web/index.html

@@ -20,7 +20,7 @@
   <title>
     CasaOS
   </title>
-<link href="/ui/css/10.f0cf5fc3.css" rel="prefetch"><link href="/ui/css/11.32be8789.css" rel="prefetch"><link href="/ui/css/12.ee780c90.css" rel="prefetch"><link href="/ui/css/13.dc77452d.css" rel="prefetch"><link href="/ui/css/14.daa8e8be.css" rel="prefetch"><link href="/ui/css/18.1f93b660.css" rel="prefetch"><link href="/ui/css/19.046fd3d8.css" rel="prefetch"><link href="/ui/css/3.623fa25f.css" rel="prefetch"><link href="/ui/css/9.f27e442b.css" rel="prefetch"><link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/10.js" rel="prefetch"><link href="/ui/js/11.js" rel="prefetch"><link href="/ui/js/12.js" rel="prefetch"><link href="/ui/js/13.js" rel="prefetch"><link href="/ui/js/14.js" rel="prefetch"><link href="/ui/js/15.js" rel="prefetch"><link href="/ui/js/16.js" rel="prefetch"><link href="/ui/js/17.js" rel="prefetch"><link href="/ui/js/18.js" rel="prefetch"><link href="/ui/js/19.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/20.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/8.js" rel="prefetch"><link href="/ui/js/9.js" rel="prefetch"><link href="/ui/css/app.1fb33240.css" rel="preload" as="style"><link href="/ui/css/vendors~app.6b5df7e4.css" rel="preload" as="style"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/vendors~app.js" rel="preload" as="script"><link href="/ui/css/vendors~app.6b5df7e4.css" rel="stylesheet"><link href="/ui/css/app.1fb33240.css" rel="stylesheet"></head>
+<link href="/ui/css/1.73b4186b.css" rel="prefetch"><link href="/ui/css/10.daa8e8be.css" rel="prefetch"><link href="/ui/css/11.232c3bcb.css" rel="prefetch"><link href="/ui/css/15.1f93b660.css" rel="prefetch"><link href="/ui/css/16.046fd3d8.css" rel="prefetch"><link href="/ui/css/5.ae1e42db.css" rel="prefetch"><link href="/ui/css/6.f02d5b96.css" rel="prefetch"><link href="/ui/css/7.32be8789.css" rel="prefetch"><link href="/ui/css/8.ee780c90.css" rel="prefetch"><link href="/ui/css/9.a00e5221.css" rel="prefetch"><link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/10.js" rel="prefetch"><link href="/ui/js/11.js" rel="prefetch"><link href="/ui/js/12.js" rel="prefetch"><link href="/ui/js/13.js" rel="prefetch"><link href="/ui/js/14.js" rel="prefetch"><link href="/ui/js/15.js" rel="prefetch"><link href="/ui/js/16.js" rel="prefetch"><link href="/ui/js/17.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/8.js" rel="prefetch"><link href="/ui/js/9.js" rel="prefetch"><link href="/ui/css/app.e3d6571d.css" rel="preload" as="style"><link href="/ui/css/vendors~app.6b5df7e4.css" rel="preload" as="style"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/vendors~app.js" rel="preload" as="script"><link href="/ui/css/vendors~app.6b5df7e4.css" rel="stylesheet"><link href="/ui/css/app.e3d6571d.css" rel="stylesheet"></head>
 
 <body>
   <noscript>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
web/js/0.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/1.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 12
web/js/10.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/11.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/12.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/13.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/14.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/15.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/16.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/17.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/18.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 8
web/js/2.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/3.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/4.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/5.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
web/js/6.js


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä