* initial completion of the sharing function

* Adjusting multi-partition disk mounts

* Add file sharing function

* update usb auto mount shell

* update samba config

* add umount disk function

* update change log

* update usb auto mount \

* update usb auto mount

* Update periodical.go
This commit is contained in:
link 2022-08-15 11:37:21 +08:00 committed by GitHub
parent 848ee63386
commit cee34ec1c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 2167 additions and 592 deletions

1
.gitignore vendored
View file

@ -37,3 +37,4 @@ __debug_bin
main
CasaOS
github.com
.all-contributorsrc

View file

@ -18,6 +18,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
## [0.3.5-alpha] - 2022-08-08
### Added
- [File] Mount the shared samba
- [File] File sharing via Samba
- [System] You can share casaos on Twitter, facebook, reddit
### Changed
- [Disk] Support for mounting existing data disks
### Fixed
- [App] fixed uninstalling imported docker container apps results in wiping ALL your config data from them ([#360](https://github.com/IceWhaleTech/CasaOS/issues/360))
## [0.3.4] - 2022-07-29(UTC)
### Added

11
go.mod
View file

@ -6,7 +6,6 @@ require (
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/Microsoft/hcsshim v0.8.22 // indirect
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
github.com/ambelovsky/go-structs v1.1.0 // indirect
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
@ -22,17 +21,18 @@ require (
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-playground/validator/v10 v10.6.1 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0
github.com/gomodule/redigo v1.8.5
github.com/google/go-github/v36 v36.0.0
github.com/google/uuid v1.3.0 // indirect
github.com/googollee/go-socket.io v1.6.2
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.4.2
github.com/hirochachacha/go-smb2 v1.1.0
github.com/jinzhu/copier v0.3.2
github.com/json-iterator/go v1.1.11 // indirect
github.com/klauspost/compress v1.13.6 // indirect
@ -47,16 +47,17 @@ require (
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/selinux v1.8.5 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pilebones/go-udev v0.9.0
github.com/pkg/errors v0.9.1
github.com/prometheus/procfs v0.7.3 // indirect
github.com/robfig/cron v1.2.0
github.com/satori/go.uuid v1.2.0
github.com/shirou/gopsutil/v3 v3.21.5
github.com/shirou/gopsutil/v3 v3.22.7
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/stretchr/testify v1.8.0
github.com/tidwall/gjson v1.10.2
github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/ugorji/go v1.2.6 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/zap v1.10.0
@ -64,7 +65,6 @@ require (
golang.org/x/mod v0.5.0 // indirect
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
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
@ -75,7 +75,6 @@ require (
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gorm.io/driver/sqlite v1.2.6
gorm.io/gorm v1.22.5
)

54
go.sum
View file

@ -86,9 +86,6 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
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/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -330,6 +327,8 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
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.2 h1:VMBkd4ZB1Hl7e1lOA5gEZ/qdD3d9vLIq57xKWgPCCV8=
@ -356,9 +355,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
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-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
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/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@ -455,8 +453,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
@ -513,6 +512,8 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI=
github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
@ -577,6 +578,8 @@ github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
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-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@ -702,6 +705,8 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q=
github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -709,6 +714,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
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=
@ -756,8 +763,8 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
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/shirou/gopsutil/v3 v3.22.7 h1:flKnuCMfUUrO+oAvwAd6GKZgnPzr098VA/UJ14nhJd4=
github.com/shirou/gopsutil/v3 v3.22.7/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI=
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=
@ -818,14 +825,17 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
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=
@ -837,12 +847,10 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
@ -883,6 +891,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
@ -1103,10 +1113,9 @@ golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1116,8 +1125,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo=
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1340,8 +1350,8 @@ 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-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=

16
main.go
View file

@ -15,6 +15,7 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
"github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/robfig/cron"
"gorm.io/gorm"
@ -26,21 +27,31 @@ var configFlag = flag.String("c", "", "config address")
var dbFlag = flag.String("db", "", "db path")
var resetUser = flag.Bool("ru", false, "reset user")
var user = flag.String("user", "", "user name")
var version = flag.Bool("v", false, "show version")
func init() {
flag.Parse()
if *version {
fmt.Println("v" + types.CURRENTVERSION)
return
}
config.InitSetup(*configFlag)
config.UpdateSetup()
loger.LogInit()
if len(*dbFlag) == 0 {
*dbFlag = config.AppInfo.DBPath + "/db"
}
sqliteDB = sqlite.GetDb(*dbFlag)
//gredis.GetRedisConn(config.RedisInfo),
service.MyService = service.NewService(sqliteDB)
service.Cache = cache.Init()
service.GetToken()
service.NewVersionApp = make(map[string]string)
route.InitFunction()
@ -62,6 +73,9 @@ func init() {
// @BasePath /v1
func main() {
service.NotifyMsg = make(chan notify.Message, 10)
if *version {
return
}
if *resetUser {
if user == nil || len(*user) == 0 {
fmt.Println("user is empty")
@ -81,7 +95,7 @@ func main() {
return
}
go route.SocketInit(service.NotifyMsg)
go route.MonitoryUSB()
//model.Setup()
//gredis.Setup()
r := route.InitRouter()

20
model/connections.go Normal file
View file

@ -0,0 +1,20 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-27 10:30:43
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-04 20:06:04
* @FilePath: /CasaOS/model/connections.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
type Connections struct {
ID uint `json:"id"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
Host string `json:"host"`
Port string `json:"port"`
MountPoint string `json:"mount_point"`
}

View file

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-13 10:43:45
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-13 11:00:04
* @LastEditTime: 2022-08-03 14:45:35
* @FilePath: /CasaOS/model/disk.go
* @Description:
* @Website: https://www.casaos.io
@ -39,6 +39,7 @@ type LSBLKModel struct {
Serial string `json:"serial"`
Children []LSBLKModel `json:"children"`
SubSystems string `json:"subsystems"`
Label string `json:"label"`
//详情特有
StartSector uint64 `json:"start_sector,omitempty"`
Rota bool `json:"rota"` //true(hhd) false(ssd)
@ -47,35 +48,46 @@ type LSBLKModel struct {
}
type Drive struct {
Name string `json:"name"`
Size uint64 `json:"size"`
Model string `json:"model"`
Health string `json:"health"`
Temperature int `json:"temperature"`
DiskType string `json:"disk_type"`
NeedFormat bool `json:"need_format"`
Serial string `json:"serial"`
Path string `json:"path"`
Name string `json:"name"`
Size uint64 `json:"size"`
Model string `json:"model"`
Health string `json:"health"`
Temperature int `json:"temperature"`
DiskType string `json:"disk_type"`
NeedFormat bool `json:"need_format"`
Serial string `json:"serial"`
Path string `json:"path"`
ChildrenNumber int `json:"children_number"`
}
type DriveUSB struct {
Name string `json:"name"`
Size uint64 `json:"size"`
Used uint64 `json:"use"`
Model string `json:"model"`
Mount bool `json:"mount"`
Avail uint64 `json:"avail"`
Name string `json:"name"`
Size uint64 `json:"size"`
Model string `json:"model"`
Avail uint64 `json:"avail"`
Children []USBChildren `json:"children"`
}
type USBChildren struct {
Name string `json:"name"`
Size uint64 `json:"size"`
Avail uint64 `json:"avail"`
MountPoint string `json:"mount_point"`
}
type Storage struct {
Name string `json:"name"`
MountPoint string `json:"mountpoint"`
MountPoint string `json:"mount_point"`
Size string `json:"size"`
Avail string `json:"avail"` //可用空间
Type string `json:"type"`
CreatedAt int64 `json:"create_at"`
Path string `json:"path"`
DriveName string `json:"drive_name"`
Label string `json:"label"`
}
type Storages struct {
DiskName string `json:"disk_name"`
Size uint64 `json:"size"`
Path string `json:"path"`
Children []Storage `json:"children"`
}
type Summary struct {

17
model/share.go Normal file
View file

@ -0,0 +1,17 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-26 11:12:12
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-27 14:58:55
* @FilePath: /CasaOS/model/share.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
type Shares struct {
ID uint `json:"id"`
Anonymous bool `json:"anonymous"`
Path string `json:"path"`
}

View file

@ -1,14 +1,25 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-01 18:32:57
* @FilePath: /CasaOS/model/zima.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
import "time"
type Path struct {
Name string `json:"name"` //File name or document name
Path string `json:"path"` //Full path to file or folder
IsDir bool `json:"is_dir"` //Is it a folder
Date time.Time `json:"date"`
Size int64 `json:"size"` //File Size
Type string `json:"type,omitempty"`
Label string `json:"label,omitempty"`
Write bool `json:"write"`
Name string `json:"name"` //File name or document name
Path string `json:"path"` //Full path to file or folder
IsDir bool `json:"is_dir"` //Is it a folder
Date time.Time `json:"date"`
Size int64 `json:"size"` //File Size
Type string `json:"type,omitempty"`
Label string `json:"label,omitempty"`
Write bool `json:"write"`
Extensions map[string]interface{} `json:"extensions"`
}

75
pkg/samba/smaba.go Normal file
View file

@ -0,0 +1,75 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-27 10:35:29
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-01 13:56:44
* @FilePath: /CasaOS/pkg/samba/smaba.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package samba
import (
"errors"
"net"
"github.com/hirochachacha/go-smb2"
)
func ConnectSambaService(host, port, username, password, directory string) error {
conn, err := net.Dial("tcp", host+":"+port)
if err != nil {
return err
}
defer conn.Close()
d := &smb2.Dialer{
Initiator: &smb2.NTLMInitiator{
User: username,
Password: password,
},
}
s, err := d.Dial(conn)
if err != nil {
return err
}
defer s.Logoff()
names, err := s.ListSharenames()
if err != nil {
return err
}
for _, name := range names {
if name == directory {
return nil
}
}
return errors.New("directory not found")
}
//get share name list
func GetSambaSharesList(host, port, username, password string) ([]string, error) {
conn, err := net.Dial("tcp", host+":"+port)
if err != nil {
return nil, err
}
defer conn.Close()
d := &smb2.Dialer{
Initiator: &smb2.NTLMInitiator{
User: username,
Password: password,
},
}
s, err := d.Dial(conn)
if err != nil {
return nil, err
}
defer s.Logoff()
names, err := s.ListSharenames()
if err != nil {
return nil, err
}
return names, err
}

View file

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-11 18:10:53
* @LastEditTime: 2022-07-27 11:25:26
* @FilePath: /CasaOS/pkg/sqlite/db.go
* @Description:
* @Website: https://www.casaos.io
@ -53,7 +53,7 @@ func GetDb(dbPath string) *gorm.DB {
drop table o_user;
`)
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.UserDBModel{})
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.UserDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
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")

View file

@ -27,6 +27,9 @@ const (
PORT_IS_OCCUPIED = 20004
COMMAND_ERROR_INVALID_OPERATION = 20005
VERIFICATION_FAILURE = 20006
Record_NOT_EXIST = 20007
Record_ALREADY_EXIST = 20008
SERVICE_NOT_RUNNING = 20009
//disk
NAME_NOT_AVAILABLE = 40001
@ -48,8 +51,9 @@ const (
DIR_NOT_EXISTS = 60004
SOURCE_DES_SAME = 60005
//shortcuts
SHORTCUTS_URL_ERROR = 70001
//share
SHARE_ALREADY_EXISTS = 70001
SHARE_NAME_ALREADY_EXISTS = 70002
)
var MsgFlags = map[int]string{
@ -78,6 +82,9 @@ var MsgFlags = map[int]string{
FILE_OR_DIR_EXISTS: "File or folder already exists",
PORT_IS_OCCUPIED: "Port is occupied",
VERIFICATION_FAILURE: "Verification failure",
Record_ALREADY_EXIST: "Record already exists",
Record_NOT_EXIST: "Record does not exist",
SERVICE_NOT_RUNNING: "Service is not running",
//app
UNINSTALL_APP_ERROR: "Error uninstalling app",
@ -91,16 +98,17 @@ var MsgFlags = map[int]string{
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
DISK_BUSYING: "Drive is busy",
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
//share
SHARE_ALREADY_EXISTS: "Share already exists",
SHARE_NAME_ALREADY_EXISTS: "Share name already exists",
//
SOURCE_DES_SAME: "Source and destination cannot be the same.",
FILE_DOES_NOT_EXIST: "File does not exist",
DIR_NOT_EXISTS: "Directory does not exist",
FILE_READ_ERROR: "File read error",
FILE_DELETE_ERROR: "Delete error",
SHORTCUTS_URL_ERROR: "URL error",
FILE_READ_ERROR: "File read error",
FILE_DELETE_ERROR: "Delete error",
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
}

View file

@ -547,3 +547,20 @@ func MoveFile(sourcePath, destPath string) error {
}
return nil
}
func ReadLine(lineNumber int, path string) string {
file, err := os.Open(path)
if err != nil {
return ""
}
fileScanner := bufio.NewScanner(file)
lineCount := 1
for fileScanner.Scan() {
if lineCount == lineNumber {
return fileScanner.Text()
}
lineCount++
}
defer file.Close()
return ""
}

33
pkg/utils/udev_helper.go Normal file
View file

@ -0,0 +1,33 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-08-10 16:06:12
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-10 16:11:37
* @FilePath: /CasaOS/pkg/utils/udev_helper.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package utils
// func getOptionnalMatcher() (matcher netlink.Matcher, err error) {
// if filePath == nil || *filePath == "" {
// return nil, nil
// }
// stream, err := ioutil.ReadFile(*filePath)
// if err != nil {
// return nil, err
// }
// if stream == nil {
// return nil, fmt.Errorf("Empty, no rules provided in \"%s\", err: %w", *filePath, err)
// }
// var rules netlink.RuleDefinitions
// if err := json.Unmarshal(stream, &rules); err != nil {
// return nil, fmt.Errorf("Wrong rule syntax, err: %w", err)
// }
// return &rules, nil
// }

25
route/darwin.go Normal file
View file

@ -0,0 +1,25 @@
//go:build darwin
// +build darwin
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-08-12 14:22:28
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-12 18:41:14
* @FilePath: /CasaOS/route/darwin.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package route
func MonitoryUSB() {
}
func SendAllHardwareStatusBySocket() {
}
func SendUSBBySocket() {
}

View file

@ -1,11 +1,13 @@
package route
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/samba"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@ -15,15 +17,14 @@ import (
)
func InitFunction() {
ShellInit()
CheckSerialDiskMount()
CheckToken2_11()
ImportApplications()
// Soon to be removed
ChangeAPIUrl()
MoveUserToDB()
InitNetworkMount()
}
func CheckSerialDiskMount() {
@ -40,25 +41,25 @@ func CheckSerialDiskMount() {
command.ExecEnabledSMART(v.Path)
if v.Children != nil {
for _, h := range v.Children {
if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
if m, ok := mountPoint[h.UUID]; ok {
//mount point check
volume := m
if !file.CheckNotExist(m) {
for i := 0; file.CheckNotExist(volume); i++ {
volume = m + strconv.Itoa(i+1)
}
//if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
if m, ok := mountPoint[h.UUID]; ok {
//mount point check
volume := m
if !file.CheckNotExist(m) {
for i := 0; file.CheckNotExist(volume); i++ {
volume = m + strconv.Itoa(i+1)
}
service.MyService.Disk().MountDisk(h.Path, volume)
if volume != m {
ms := model2.SerialDisk{}
ms.UUID = v.UUID
ms.MountPoint = volume
service.MyService.Disk().UpdateMountPoint(ms)
}
}
service.MyService.Disk().MountDisk(h.Path, volume)
if volume != m {
ms := model2.SerialDisk{}
ms.UUID = v.UUID
ms.MountPoint = volume
service.MyService.Disk().UpdateMountPoint(ms)
}
}
//}
}
}
}
@ -138,3 +139,32 @@ func MoveUserToDB() {
}
}
func InitNetworkMount() {
connections := service.MyService.Connections().GetConnectionsList()
for _, v := range connections {
connection := service.MyService.Connections().GetConnectionByID(fmt.Sprint(v.ID))
directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
if err != nil {
service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
continue
}
baseHostPath := "/mnt/" + connection.Host
mountPointList := service.MyService.System().GetDirPath(baseHostPath)
for _, v := range mountPointList {
service.MyService.Connections().UnmountSmaba(v.Path)
}
os.RemoveAll(baseHostPath)
file.IsNotExistMkDir(baseHostPath)
for _, v := range directories {
mountPoint := baseHostPath + "/" + v
file.IsNotExistMkDir(mountPoint)
service.MyService.Connections().MountSmaba(connection.Username, connection.Host, v, connection.Port, mountPoint, connection.Password)
}
connection.Directories = strings.Join(directories, ",")
service.MyService.Connections().UpdateConnection(&connection)
}
}

View file

@ -1,8 +1,11 @@
//go:build !darwin
// +build !darwin
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-01 15:11:36
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-21 15:25:07
* @LastEditTime: 2022-08-12 18:58:00
* @FilePath: /CasaOS/route/periodical.go
* @Description:
* @Website: https://www.casaos.io
@ -11,14 +14,20 @@
package route
import (
"os"
"os/signal"
"reflect"
"strconv"
"strings"
"syscall"
"time"
"unsafe"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/pilebones/go-udev/netlink"
"go.uber.org/zap"
)
func SendNetINfoBySocket() {
@ -129,26 +138,22 @@ func SendUSBBySocket() {
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
isMount := false
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 {
isMount = true
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
temp.Used += used
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
usb = append(usb, temp)
if isMount {
usb = append(usb, temp)
}
}
}
service.MyService.Notify().SendUSBInfoBySocket(usb)
@ -246,26 +251,22 @@ func SendAllHardwareStatusBySocket() {
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
isMount = false
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 {
isMount = true
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
temp.Used += used
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
usb = append(usb, temp)
if isMount {
usb = append(usb, temp)
}
}
}
memInfo := service.MyService.System().GetMemInfo()
@ -273,3 +274,38 @@ func SendAllHardwareStatusBySocket() {
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet)
}
func MonitoryUSB() {
var matcher netlink.Matcher
conn := new(netlink.UEventConn)
if err := conn.Connect(netlink.UdevEvent); err != nil {
loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err))
}
defer conn.Close()
queue := make(chan netlink.UEvent)
errors := make(chan error)
quit := conn.Monitor(queue, errors, matcher)
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
<-signals
close(quit)
os.Exit(0)
}()
for {
select {
case uevent := <-queue:
if uevent.Env["DEVTYPE"] == "disk" {
time.Sleep(time.Microsecond * 500)
SendUSBBySocket()
continue
}
case err := <-errors:
loger.Error("udev err", zap.Any("err", err))
}
}
}

View file

@ -196,6 +196,9 @@ func InitRouter() *gin.Engine {
//v1DisksGroup.POST("", v1.PostMountDisk)
v1DisksGroup.GET("", v1.GetDiskList)
v1DisksGroup.GET("/usb", v1.GetDisksUSBList)
v1DisksGroup.DELETE("/usb", v1.DeleteDiskUSB)
v1DisksGroup.DELETE("", v1.DeleteDisksUmount)
// //format storage
// v1DiskGroup.POST("/format", v1.PostDiskFormat)
@ -218,6 +221,26 @@ func InitRouter() *gin.Engine {
v1StorageGroup.PUT("", v1.PostDiskFormat)
v1StorageGroup.DELETE("", v1.PostDiskUmount)
v1StorageGroup.GET("", v1.GetStorageList)
}
v1SambaGroup := v1Group.Group("/samba")
v1SambaGroup.Use()
{
v1ConnectionsGroup := v1SambaGroup.Group("/connections")
v1ConnectionsGroup.Use()
{
v1ConnectionsGroup.GET("", v1.GetSambaConnectionsList)
v1ConnectionsGroup.POST("", v1.PostSambaConnectionsCreate)
v1ConnectionsGroup.DELETE("/:id", v1.DeleteSambaConnections)
}
v1SharesGroup := v1SambaGroup.Group("/shares")
v1SharesGroup.Use()
{
v1SharesGroup.GET("", v1.GetSambaSharesList)
v1SharesGroup.POST("", v1.PostSambaSharesCreate)
v1SharesGroup.DELETE("/:id", v1.DeleteSambaShares)
v1SharesGroup.GET("/status", v1.GetSambaStatus)
}
}
}
return r

View file

@ -1,7 +1,6 @@
package v1
import (
"fmt"
"net/http"
"reflect"
"strconv"
@ -45,19 +44,12 @@ func GetDiskList(c *gin.Context) {
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)
}
}
@ -87,14 +79,13 @@ func GetDiskList(c *gin.Context) {
disk.Size = list[i].Size
disk.Path = list[i].Path
disk.Model = list[i].Model
disk.ChildrenNumber = len(list[i].Children)
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
stor := model.Storage{}
stor.Name = "System"
stor.MountPoint = v.MountPoint
stor.Size = v.FSSize
stor.Avail = v.FSAvail
@ -118,7 +109,6 @@ func GetDiskList(c *gin.Context) {
} else {
if list[i].Children[j].MountPoint == "/" {
stor := model.Storage{}
stor.Name = "System"
stor.MountPoint = list[i].Children[j].MountPoint
stor.Size = list[i].Children[j].FSSize
stor.Avail = list[i].Children[j].FSAvail
@ -152,33 +142,31 @@ func GetDiskList(c *gin.Context) {
if reflect.DeepEqual(temp, model.SmartctlA{}) {
temp.SmartStatus.Passed = true
}
if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
stor := model.Storage{}
stor.MountPoint = list[i].Children[0].MountPoint
stor.Size = list[i].Children[0].FSSize
stor.Avail = list[i].Children[0].FSAvail
stor.Path = list[i].Children[0].Path
stor.Type = list[i].Children[0].FsType
stor.DriveName = list[i].Name
pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
if len(pathArr) == 3 {
stor.Name = pathArr[2]
}
if t, ok := part[list[i].Children[0].MountPoint]; ok {
stor.CreatedAt = t
}
storage = append(storage, stor)
} else {
//todo 长度有问题
if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
disk.NeedFormat = false
avail = append(avail, disk)
} else {
disk.NeedFormat = true
avail = append(avail, disk)
isAvail := true
for _, v := range list[i].Children {
if v.MountPoint != "" {
stor := model.Storage{}
stor.MountPoint = v.MountPoint
stor.Size = v.FSSize
stor.Avail = v.FSAvail
stor.Path = v.Path
stor.Type = v.FsType
stor.DriveName = list[i].Name
storage = append(storage, stor)
isAvail = false
}
}
if isAvail {
//if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
disk.NeedFormat = false
avail = append(avail, disk)
// } else {
// disk.NeedFormat = true
// avail = append(avail, disk)
// }
}
disk.Temperature = temp.Temperature.Current
disk.Health = strconv.FormatBool(temp.SmartStatus.Passed)
@ -193,6 +181,107 @@ func GetDiskList(c *gin.Context) {
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
// @Summary disk list
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /disk/list [get]
func GetDisksUSBList(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.Label
if temp.Name == "" {
temp.Name = v.Name
}
temp.Size = v.Size
children := []model.USBChildren{}
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
tempChildren := model.USBChildren{}
tempChildren.MountPoint = child.MountPoint
tempChildren.Size, _ = strconv.ParseUint(child.FSSize, 10, 64)
tempChildren.Avail, _ = strconv.ParseUint(child.FSAvail, 10, 64)
tempChildren.Name = child.Label
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
children = append(children, tempChildren)
temp.Avail += avail
}
}
temp.Children = children
data = append(data, temp)
}
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
func DeleteDisksUmount(c *gin.Context) {
id := c.GetHeader("user_id")
js := make(map[string]string)
c.ShouldBind(&js)
path := js["path"]
pwd := js["password"]
if len(path) == 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().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(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
return
}
diskInfo := service.MyService.Disk().GetDiskInfo(path)
for _, v := range diskInfo.Children {
service.MyService.Disk().UmountPointAndRemoveDir(v.Path)
//delete data
service.MyService.Disk().DeleteMountPoint(v.Path, v.MountPoint)
}
service.MyService.Disk().RemoveLSBLKCache()
//send notify to client
msg := notify.StorageMessage{}
msg.Action = "REMOVED"
msg.Path = path
msg.Volume = ""
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), Data: path})
}
func DeleteDiskUSB(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
mountPoint := js["mount_point"]
if file.CheckNotExist(mountPoint) {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
return
}
service.MyService.Disk().UmountUSB(mountPoint)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mountPoint})
}
// @Summary get disk list
// @Produce application/json
// @Accept application/json
@ -278,10 +367,10 @@ func PostDiskAddPartition(c *gin.Context) {
js := make(map[string]interface{})
c.ShouldBind(&js)
path := js["path"].(string)
name := js["name"].(string)
//name := js["name"].(string)
format := js["format"].(bool)
if len(name) == 0 || len(path) == 0 {
if len(path) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
@ -289,20 +378,17 @@ func PostDiskAddPartition(c *gin.Context) {
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(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
return
}
//diskInfo := service.MyService.Disk().GetDiskInfo(path)
// if !file.CheckNotExist("/DATA/" + name) {
// // /mnt/name exist
// 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") {
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 {
if format {
// format := service.MyService.Disk().FormatDisk(path+"1", "ext4")
// if len(format) == 0 {
// delete(diskMap, path)
@ -312,34 +398,45 @@ func PostDiskAddPartition(c *gin.Context) {
service.MyService.Disk().AddPartition(path)
}
formatBool := true
for formatBool {
currentDisk = service.MyService.Disk().GetDiskInfo(path)
fmt.Println(currentDisk.Children)
if len(currentDisk.Children) > 0 {
formatBool = false
break
}
time.Sleep(time.Second)
}
// formatBool := true
// for formatBool {
// currentDisk = service.MyService.Disk().GetDiskInfo(path)
// if len(currentDisk.Children) > 0 {
// formatBool = false
// break
// }
// time.Sleep(time.Second)
// }
currentDisk = service.MyService.Disk().GetDiskInfo(path)
if len(currentDisk.Children) != 1 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
return
// if len(currentDisk.Children) != 1 {
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
// return
// }
for i := 0; i < len(currentDisk.Children); i++ {
childrenName := currentDisk.Children[i].Label
if len(childrenName) == 0 {
childrenName = "Storage_" + currentDisk.Children[i].Name
}
mountPath := "/DATA/" + childrenName
if !file.CheckNotExist(mountPath) {
ls := service.MyService.System().GetDirPath(mountPath)
if len(ls) > 0 {
// exist
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
return
}
}
m := model2.SerialDisk{}
m.MountPoint = mountPath
m.Path = currentDisk.Children[i].Path
m.UUID = currentDisk.Children[i].UUID
m.State = 0
m.CreatedAt = time.Now().Unix()
service.MyService.Disk().SaveMountPoint(m)
//mount dir
service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath)
}
mountPath := "/DATA/" + name
m := model2.SerialDisk{}
m.MountPoint = mountPath
m.Path = currentDisk.Children[0].Path
m.UUID = currentDisk.Children[0].UUID
m.State = 0
m.CreatedAt = time.Now().Unix()
service.MyService.Disk().SaveMountPoint(m)
//mount dir
service.MyService.Disk().MountDisk(currentDisk.Children[0].Path, mountPath)
service.MyService.Disk().RemoveLSBLKCache()
delete(diskMap, path)
@ -348,7 +445,7 @@ func PostDiskAddPartition(c *gin.Context) {
msg := notify.StorageMessage{}
msg.Action = "ADDED"
msg.Path = currentDisk.Children[0].Path
msg.Volume = mountPath
msg.Volume = "/DATA/"
msg.Size = currentDisk.Children[0].Size
msg.Type = currentDisk.Children[0].Tran
service.MyService.Notify().SendStorageBySocket(msg)

View file

@ -209,7 +209,7 @@ func InstallApp(c *gin.Context) {
dockerImage = m.Image
dockerImageVersion = "latest"
}
m.Image = dockerImage + ":" + dockerImageVersion
for _, u := range m.Ports {
if u.Protocol == "udp" {
@ -334,11 +334,11 @@ func InstallApp(c *gin.Context) {
return
}
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
for !service.MyService.Docker().IsExistImage(m.Image) {
time.Sleep(time.Second)
}
_, err = service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m)
_, err = service.MyService.Docker().DockerContainerCreate(m, "")
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
notify := notify.Application{}
@ -829,7 +829,6 @@ func UpdateSetting(c *gin.Context) {
// c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
// return
// }
service.MyService.Docker().DockerContainerStop(id)
portMap, _ := strconv.Atoi(m.PortMap)
if !port2.IsPortAvailable(portMap, "tcp") {
@ -874,7 +873,7 @@ func UpdateSetting(c *gin.Context) {
service.MyService.Docker().DockerContainerUpdateName(id, id)
//service.MyService.Docker().DockerContainerRemove(id, true)
containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, m)
containerId, err := service.MyService.Docker().DockerContainerCreate(m, id)
if err != nil {
service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
service.MyService.Docker().DockerContainerStart(id)

View file

@ -1,6 +1,7 @@
package v1
import (
"fmt"
"io"
"io/ioutil"
"log"
@ -218,6 +219,11 @@ func GetDownloadSingleFile(c *gin.Context) {
func DirPath(c *gin.Context) {
path := c.DefaultQuery("path", "")
info := service.MyService.System().GetDirPath(path)
shares := service.MyService.Shares().GetSharesList()
sharesMap := make(map[string]string)
for _, v := range shares {
sharesMap[v.Path] = fmt.Sprint(v.ID)
}
if path == "/DATA/AppData" {
list := service.MyService.Docker().DockerContainerList()
apps := make(map[string]string, len(list))
@ -257,7 +263,17 @@ func DirPath(c *gin.Context) {
}
}
}
for i := 0; i < len(info); i++ {
if v, ok := sharesMap[info[i].Path]; ok {
ex := make(map[string]interface{})
shareEx := make(map[string]string)
shareEx["shared"] = "true"
shareEx["id"] = v
ex["share"] = shareEx
info[i].Extensions = ex
}
}
//Hide the files or folders in operation
fileQueue := make(map[string]string)
if len(service.OpStrArr) > 0 {

180
route/v1/samba.go Normal file
View file

@ -0,0 +1,180 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-26 11:08:48
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-05 12:16:39
* @FilePath: /CasaOS/route/v1/samba.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package v1
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/samba"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/gin-gonic/gin"
)
// service
func GetSambaStatus(c *gin.Context) {
status := service.MyService.System().IsServiceRunning("smbd")
if !status {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_NOT_RUNNING, Message: common_err.GetMsg(common_err.SERVICE_NOT_RUNNING)})
return
}
needInit := true
if file.Exists("/etc/samba/smb.conf") {
str := file.ReadLine(1, "/etc/samba/smb.conf")
if strings.Contains(str, "# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.") {
needInit = false
}
}
data := make(map[string]string, 1)
data["need_init"] = fmt.Sprintf("%v", needInit)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
func GetSambaSharesList(c *gin.Context) {
shares := service.MyService.Shares().GetSharesList()
shareList := []model.Shares{}
for _, v := range shares {
shareList = append(shareList, model.Shares{
Anonymous: v.Anonymous,
Path: v.Path,
ID: v.ID,
})
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shareList})
}
func PostSambaSharesCreate(c *gin.Context) {
shares := []model.Shares{}
c.ShouldBindJSON(&shares)
for _, v := range shares {
if v.Path == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
if !file.Exists(v.Path) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
return
}
if len(service.MyService.Shares().GetSharesByPath(v.Path)) > 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_ALREADY_EXISTS)})
return
}
if len(service.MyService.Shares().GetSharesByPath(filepath.Base(v.Path))) > 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_NAME_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_NAME_ALREADY_EXISTS)})
return
}
}
for _, v := range shares {
shareDBModel := model2.SharesDBModel{}
shareDBModel.Anonymous = true
shareDBModel.Path = v.Path
shareDBModel.Name = filepath.Base(v.Path)
service.MyService.Shares().CreateShare(shareDBModel)
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shares})
}
func DeleteSambaShares(c *gin.Context) {
id := c.Param("id")
if id == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
service.MyService.Shares().DeleteShare(id)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
}
//client
func GetSambaConnectionsList(c *gin.Context) {
connections := service.MyService.Connections().GetConnectionsList()
connectionList := []model.Connections{}
for _, v := range connections {
connectionList = append(connectionList, model.Connections{
ID: v.ID,
Username: v.Username,
Port: v.Port,
Host: v.Host,
MountPoint: v.MountPoint,
})
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connectionList})
}
func PostSambaConnectionsCreate(c *gin.Context) {
connection := model.Connections{}
c.ShouldBindJSON(&connection)
if connection.Port == "" {
connection.Port = "445"
}
if connection.Username == "" || connection.Host == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
// check is exists
connections := service.MyService.Connections().GetConnectionByHost(connection.Host)
if len(connections) > 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.Record_ALREADY_EXIST, Message: common_err.GetMsg(common_err.Record_ALREADY_EXIST), Data: common_err.GetMsg(common_err.Record_ALREADY_EXIST)})
return
}
// check connect is ok
directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
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
}
connectionDBModel := model2.ConnectionsDBModel{}
connectionDBModel.Username = connection.Username
connectionDBModel.Password = connection.Password
connectionDBModel.Host = connection.Host
connectionDBModel.Port = connection.Port
connectionDBModel.Directories = strings.Join(directories, ",")
baseHostPath := "/mnt/" + connection.Host
connectionDBModel.MountPoint = baseHostPath
connection.MountPoint = baseHostPath
file.IsNotExistMkDir(baseHostPath)
for _, v := range directories {
mountPoint := baseHostPath + "/" + v
file.IsNotExistMkDir(mountPoint)
service.MyService.Connections().MountSmaba(connectionDBModel.Username, connectionDBModel.Host, v, connectionDBModel.Port, mountPoint, connectionDBModel.Password)
}
service.MyService.Connections().CreateConnection(&connectionDBModel)
connection.ID = connectionDBModel.ID
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connection})
}
func DeleteSambaConnections(c *gin.Context) {
id := c.Param("id")
connection := service.MyService.Connections().GetConnectionByID(id)
if connection.Username == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.Record_NOT_EXIST, Message: common_err.GetMsg(common_err.Record_NOT_EXIST)})
return
}
mountPointList := service.MyService.System().GetDirPath(connection.MountPoint)
for _, v := range mountPointList {
service.MyService.Connections().UnmountSmaba(v.Path)
}
os.RemoveAll(connection.MountPoint)
service.MyService.Connections().DeleteConnection(id)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
}

73
route/v1/samba_test.go Normal file
View file

@ -0,0 +1,73 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-08-02 15:10:56
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-02 16:58:42
* @FilePath: /CasaOS/route/v1/samba_test.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package v1
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
req, _ := http.NewRequest(method, path, nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
// func TestHelloWorld(t *testing.T) {
// // Build our expected body
// body := gin.H{
// "hello": "world",
// }
// // Grab our router
// router := "SetupRouter()"
// // Perform a GET request with that handler.
// w := performRequest(router, "GET", "/")
// // Assert we encoded correctly,
// // the request gives a 200
// assert.Equal(t, http.StatusOK, w.Code)
// // Convert the JSON response to a map
// var response map[string]string
// err := json.Unmarshal([]byte(w.Body.String()), &response)
// // Grab the value & whether or not it exists
// value, exists := response["hello"]
// // Make some assertions on the correctness of the response.
// assert.Nil(t, err)
// assert.True(t, exists)
// assert.Equal(t, body["hello"], value)
// }
func TestGetSambaSharesList(t *testing.T) {
gin.SetMode(gin.TestMode)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
executeWithContext := func() *httptest.ResponseRecorder {
response := httptest.NewRecorder()
con, ginEngine := gin.CreateTestContext(response)
requestUrl := "/v1/samba/shares"
httpRequest, _ := http.NewRequest("GET", requestUrl, nil)
GetSambaSharesList(con)
ginEngine.ServeHTTP(response, httpRequest)
return response
}
t.Run("Happy", func(t *testing.T) {
res := executeWithContext()
assert.Equal(t, http.StatusOK, res.Code)
})
}

View file

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-11 16:02:29
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-11 16:02:55
* @LastEditTime: 2022-08-11 14:20:02
* @FilePath: /CasaOS/route/v1/storage.go
* @Description:
* @Website: https://www.casaos.io
@ -10,8 +10,95 @@
*/
package v1
import "github.com/gin-gonic/gin"
import (
"reflect"
"strconv"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
)
func GetStorageList(c *gin.Context) {
system := c.Query("system")
storages := []model.Storages{}
disks := service.MyService.Disk().LSBLK(false)
diskNumber := 1
children := 1
findSystem := 0
for _, d := range disks {
if d.Tran != "usb" {
tempSystemDisk := false
children = 1
tempDisk := model.Storages{
DiskName: d.Model,
Path: d.Path,
Size: d.Size,
}
storageArr := []model.Storage{}
temp := service.MyService.Disk().SmartCTL(d.Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
temp.SmartStatus.Passed = true
}
for _, v := range d.Children {
if v.MountPoint != "" {
if findSystem == 0 {
if v.MountPoint == "/" {
tempDisk.DiskName = "System"
findSystem = 1
tempSystemDisk = true
}
if len(v.Children) > 0 {
for _, c := range v.Children {
if c.MountPoint == "/" {
tempDisk.DiskName = "System"
findSystem = 1
tempSystemDisk = true
break
}
}
}
}
stor := model.Storage{}
stor.MountPoint = v.MountPoint
stor.Size = v.FSSize
stor.Avail = v.FSAvail
stor.Path = v.Path
stor.Type = v.FsType
stor.DriveName = v.Name
if len(v.Label) == 0 {
stor.Label = "Storage" + strconv.Itoa(diskNumber) + "_" + strconv.Itoa(children)
children += 1
} else {
stor.Label = v.Label
}
storageArr = append(storageArr, stor)
}
}
if len(storageArr) > 0 {
if tempSystemDisk && len(system) > 0 {
tempStorageArr := []model.Storage{}
for i := 0; i < len(storageArr); i++ {
if storageArr[i].MountPoint != "/boot/efi" && storageArr[i].Type != "swap" {
tempStorageArr = append(tempStorageArr, storageArr[i])
}
}
tempDisk.Children = tempStorageArr
storages = append(storages, tempDisk)
diskNumber += 1
} else if !tempSystemDisk {
tempDisk.Children = storageArr
storages = append(storages, tempDisk)
diskNumber += 1
}
}
}
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: storages})
}

View file

@ -174,7 +174,7 @@ func PostKillCasaOS(c *gin.Context) {
func PutSystemUSBAutoMount(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
status := js["status"]
status := js["state"]
if status == "on" {
service.MyService.System().UpdateUSBAutoMount("True")
service.MyService.System().ExecUSBAutoMountShell("True")
@ -182,7 +182,31 @@ func PutSystemUSBAutoMount(c *gin.Context) {
service.MyService.System().UpdateUSBAutoMount("False")
service.MyService.System().ExecUSBAutoMountShell("False")
}
go func() {
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
isMount := false
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
isMount = true
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
}
}
if isMount {
usb = append(usb, temp)
}
}
}
service.MyService.Notify().SendUSBInfoBySocket(usb)
}()
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
@ -202,7 +226,31 @@ func GetSystemUSBAutoMount(c *gin.Context) {
if config.ServerInfo.USBAutoMount == "False" {
state = "False"
}
go func() {
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
isMount := false
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
isMount = true
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
}
}
if isMount {
usb = append(usb, temp)
}
}
}
service.MyService.Notify().SendUSBInfoBySocket(usb)
}()
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
@ -354,21 +402,13 @@ func GetSystemUtilization(c *gin.Context) {
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
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
temp.Used += used
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
usb = append(usb, temp)
}
}

69
service/connections.go Normal file
View file

@ -0,0 +1,69 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-26 18:13:22
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-04 20:10:31
* @FilePath: /CasaOS/service/connections.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package service
import (
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/service/model"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/gorm"
)
type ConnectionsService interface {
GetConnectionsList() (connections []model2.ConnectionsDBModel)
GetConnectionByHost(host string) (connections []model2.ConnectionsDBModel)
GetConnectionByID(id string) (connections model2.ConnectionsDBModel)
CreateConnection(connection *model2.ConnectionsDBModel)
DeleteConnection(id string)
UpdateConnection(connection *model2.ConnectionsDBModel)
MountSmaba(username, host, directory, port, mountPoint, password string) string
UnmountSmaba(mountPoint string) string
}
type connectionsStruct struct {
db *gorm.DB
}
func (s *connectionsStruct) GetConnectionByHost(host string) (connections []model2.ConnectionsDBModel) {
s.db.Select("username,host,status,id").Where("host = ?", host).Find(&connections)
return
}
func (s *connectionsStruct) GetConnectionByID(id string) (connections model2.ConnectionsDBModel) {
s.db.Select("username,password,host,status,id,directories,mount_point,port").Where("id = ?", id).First(&connections)
return
}
func (s *connectionsStruct) GetConnectionsList() (connections []model2.ConnectionsDBModel) {
s.db.Select("username,host,port,status,id,mount_point").Find(&connections)
return
}
func (s *connectionsStruct) CreateConnection(connection *model2.ConnectionsDBModel) {
s.db.Create(connection)
}
func (s *connectionsStruct) UpdateConnection(connection *model2.ConnectionsDBModel) {
s.db.Save(connection)
}
func (s *connectionsStruct) DeleteConnection(id string) {
s.db.Where("id= ?", id).Delete(&model.ConnectionsDBModel{})
}
func (s *connectionsStruct) MountSmaba(username, host, directory, port, mountPoint, password string) string {
str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + username + " " + host + " " + directory + " " + port + " " + mountPoint + " " + password)
return str
}
func (s *connectionsStruct) UnmountSmaba(mountPoint string) string {
str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + mountPoint)
return str
}
func NewConnectionsService(db *gorm.DB) ConnectionsService {
return &connectionsStruct{db: db}
}

View file

@ -36,6 +36,7 @@ type DiskService interface {
DeleteMount(id string)
UpdateMountPoint(m model2.SerialDisk)
RemoveLSBLKCache()
UmountUSB(path string)
}
type diskService struct {
db *gorm.DB
@ -45,6 +46,10 @@ func (d *diskService) RemoveLSBLKCache() {
key := "system_lsblk"
Cache.Delete(key)
}
func (d *diskService) UmountUSB(path string) {
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UDEVILUmount " + path)
fmt.Println(r)
}
func (d *diskService) SmartCTL(path string) model.SmartctlA {
key := "system_smart_" + path
@ -243,8 +248,9 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
}
func (d *diskService) MountDisk(path, volume string) {
//fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
fmt.Print(r)
fmt.Println(r)
}
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {

View file

@ -45,7 +45,7 @@ import (
type DockerService interface {
DockerPullImage(imageName string, icon, name string) error
IsExistImage(imageName string) bool
DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error)
DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error)
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
DockerContainerStart(name string) error
DockerContainerStats(name string) (string, error)
@ -376,7 +376,7 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c
//param mapPort 容器主端口映射到外部的端口
//param tcp 容器其他tcp端口
//param udp 容器其他udp端口
func (ds *dockerService) DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error) {
func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) {
if len(m.NetworkModel) == 0 {
m.NetworkModel = "bridge"
}
@ -385,6 +385,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
if err != nil {
return "", err
}
defer cli.Close()
ports := make(nat.PortSet)
portMaps := make(nat.PortMap)
@ -523,15 +524,26 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
if len(m.HostName) == 0 {
m.HostName = m.Label
}
config := &container.Config{
Image: imageName,
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin, "casaos": "casaos"},
Env: envArr,
// Healthcheck: health,
Hostname: m.HostName,
Cmd: m.Cmd,
info, err := cli.ContainerInspect(context.Background(), id)
hostConfig := &container.HostConfig{}
config := &container.Config{}
config.Labels = map[string]string{}
if err == nil {
// info.HostConfig = &container.HostConfig{}
// info.Config = &container.Config{}
// info.NetworkSettings = &types.NetworkSettings{}
hostConfig = info.HostConfig
config = info.Config
}
config.Cmd = m.Cmd
config.Image = m.Image
config.Env = envArr
config.Hostname = m.HostName
config.ExposedPorts = ports
config.Labels["origin"] = m.Origin
config.Labels["casaos"] = "casaos"
config.Labels["web"] = m.PortMap
config.Labels["icon"] = m.Icon
config.Labels["desc"] = m.Description
@ -541,12 +553,19 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
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}
//container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name)
hostConfig.Mounts = volumes
hostConfig.Privileged = m.Privileged
hostConfig.CapAdd = m.CapAdd
hostConfig.NetworkMode = container.NetworkMode(m.NetworkModel)
hostConfig.RestartPolicy = rp
hostConfig.Resources = res
//hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: , Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" {
config.ExposedPorts = ports
hostConfig.PortBindings = portMaps
//}
containerDb, err := cli.ContainerCreate(context.Background(),
config,
hostConfig,

View file

@ -0,0 +1,28 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-26 17:17:57
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-01 17:08:08
* @FilePath: /CasaOS/service/model/o_connections.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
type ConnectionsDBModel struct {
ID uint `gorm:"column:id;primary_key" json:"id"`
Updated int64 `gorm:"autoUpdateTime"`
Created int64 `gorm:"autoCreateTime"`
Username string `json:"username"`
Password string `json:"password"`
Host string `json:"host"`
Port string `json:"port"`
Status string `json:"status"`
Directories string `json:"directories"` // string array
MountPoint string `json:"mount_point"` //parent directory of mount point
}
func (p *ConnectionsDBModel) TableName() string {
return "o_connections"
}

24
service/model/o_shares.go Normal file
View file

@ -0,0 +1,24 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-26 11:17:17
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-27 15:25:07
* @FilePath: /CasaOS/service/model/o_shares.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
type SharesDBModel struct {
ID uint `gorm:"column:id;primary_key" json:"id"`
Anonymous bool `json:"anonymous"`
Path string `json:"path"`
Name string `json:"name"`
Updated int64 `gorm:"autoUpdateTime"`
Created int64 `gorm:"autoCreateTime"`
}
func (p *SharesDBModel) TableName() string {
return "o_shares"
}

View file

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-12 09:48:56
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-15 10:58:54
* @LastEditTime: 2022-07-27 10:28:48
* @FilePath: /CasaOS/service/service.go
* @Description:
* @Website: https://www.casaos.io
@ -33,31 +33,44 @@ type Repository interface {
Notify() NotifyServer
Rely() RelyService
System() SystemService
Shares() SharesService
Connections() ConnectionsService
}
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(),
app: NewAppService(db),
user: NewUserService(db),
docker: NewDockerService(),
casa: NewCasaService(),
disk: NewDiskService(db),
notify: NewNotifyService(db),
rely: NewRelyService(db),
system: NewSystemService(),
shares: NewSharesService(db),
connections: NewConnectionsService(db),
}
}
type store struct {
db *gorm.DB
app AppService
user UserService
docker DockerService
casa CasaService
disk DiskService
notify NotifyServer
rely RelyService
system SystemService
db *gorm.DB
app AppService
user UserService
docker DockerService
casa CasaService
disk DiskService
notify NotifyServer
rely RelyService
system SystemService
shares SharesService
connections ConnectionsService
}
func (s *store) Connections() ConnectionsService {
return s.connections
}
func (s *store) Shares() SharesService {
return s.shares
}
func (c *store) Rely() RelyService {

151
service/shares.go Normal file
View file

@ -0,0 +1,151 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-26 11:21:14
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-11 14:04:00
* @FilePath: /CasaOS/service/shares.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package service
import (
"path/filepath"
"strings"
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/service/model"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/gorm"
)
type SharesService interface {
GetSharesList() (shares []model2.SharesDBModel)
GetSharesByPath(path string) (shares []model2.SharesDBModel)
GetSharesByName(name string) (shares []model2.SharesDBModel)
CreateShare(share model2.SharesDBModel)
DeleteShare(id string)
UpdateConfigFile()
InitSambaConfig()
}
type sharesStruct struct {
db *gorm.DB
}
func (s *sharesStruct) GetSharesByName(name string) (shares []model2.SharesDBModel) {
s.db.Select("anonymous,path,id").Where("name = ?", name).Find(&shares)
return
}
func (s *sharesStruct) GetSharesByPath(path string) (shares []model2.SharesDBModel) {
s.db.Select("anonymous,path,id").Where("path = ?", path).Find(&shares)
return
}
func (s *sharesStruct) GetSharesList() (shares []model2.SharesDBModel) {
s.db.Select("anonymous,path,id").Find(&shares)
return
}
func (s *sharesStruct) CreateShare(share model2.SharesDBModel) {
s.db.Create(&share)
s.InitSambaConfig()
s.UpdateConfigFile()
}
func (s *sharesStruct) DeleteShare(id string) {
s.db.Where("id= ?", id).Delete(&model.SharesDBModel{})
s.UpdateConfigFile()
}
func (s *sharesStruct) UpdateConfigFile() {
shares := []model2.SharesDBModel{}
s.db.Select("anonymous,path").Find(&shares)
//generated config file
var configStr = ""
for _, share := range shares {
dirName := filepath.Base(share.Path)
configStr += `
[` + dirName + `]
comment = CasaOS share ` + dirName + `
public = Yes
path = ` + share.Path + `
browseable = Yes
read only = No
guest ok = Yes
create mask = 0777
directory mask = 0777
`
}
//write config file
file.WriteToPath([]byte(configStr), "/etc/samba", "smb.casa.conf")
//restart samba
command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;RestartSMBD")
}
func (s *sharesStruct) InitSambaConfig() {
if file.Exists("/etc/samba/smb.conf") {
str := file.ReadLine(1, "/etc/samba/smb.conf")
if strings.Contains(str, "# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.") {
return
}
file.MoveFile("/etc/samba/smb.conf", "/etc/samba/smb.conf.bak")
var smbConf = ""
smbConf += `# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.
#
#
# ______ _______
# ( __ \ ( ___ )
# | ( \ ) | ( ) |
# | | ) | | | | |
# | | | | | | | |
# | | ) | | | | |
# | (__/ ) | (___) |
# (______/ (_______)
#
# _ _______ _________
# ( ( /| ( ___ ) \__ __/
# | \ ( | | ( ) | ) (
# | \ | | | | | | | |
# | (\ \) | | | | | | |
# | | \ | | | | | | |
# | ) \ | | (___) | | |
# |/ )_) (_______) )_(
#
# _______ _______ ______ _________ _______
# ( ) ( ___ ) ( __ \ \__ __/ ( ____ \ |\ /|
# | () () | | ( ) | | ( \ ) ) ( | ( \/ ( \ / )
# | || || | | | | | | | ) | | | | (__ \ (_) /
# | |(_)| | | | | | | | | | | | | __) \ /
# | | | | | | | | | | ) | | | | ( ) (
# | ) ( | | (___) | | (__/ ) ___) (___ | ) | |
# |/ \| (_______) (______/ \_______/ |/ \_/
#
#
# IMPORTANT: CasaOS will not provide technical support for any issues
# caused by unauthorized modification to the configuration.
[global]
## fruit settings
min protocol = SMB2
ea support = yes
## vfs objects = fruit streams_xattr
fruit:metadata = stream
fruit:model = Macmini
fruit:veto_appledouble = no
fruit:posix_rename = yes
fruit:zero_file_id = yes
fruit:wipe_intentionally_left_blank_rfork = yes
fruit:delete_empty_adfiles = yes
map to guest = bad user
include=/etc/samba/smb.casa.conf`
file.WriteToPath([]byte(smbConf), "/etc/samba", "smb.conf")
}
}
func NewSharesService(db *gorm.DB) SharesService {
return &sharesStruct{db: db}
}

View file

@ -49,6 +49,7 @@ type SystemService interface {
CreateFile(path string) (int, error)
RenameFile(oldF, newF string) (int, error)
MkdirAll(path string) (int, error)
IsServiceRunning(name string) bool
}
type systemService struct {
}
@ -232,9 +233,9 @@ func (s *systemService) GetTimeZone() string {
func (s *systemService) ExecUSBAutoMountShell(state string) {
if state == "False" {
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Remove_File")
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Stop_Auto")
} else {
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Move_File")
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Start_Auto")
}
}
@ -287,6 +288,12 @@ func GetDeviceAllIP() []string {
}
return address
}
func (s *systemService) IsServiceRunning(name string) bool {
status := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;CheckServiceStatus smbd")
return strings.TrimSpace(status) == "running"
}
func NewSystemService() SystemService {
return &systemService{}
}

View file

@ -330,17 +330,17 @@ TarFolder() {
du -sh /DATA
}
USB_Move_File() {
USB_Start_Auto() {
((EUID)) && sudo_cmd="sudo"
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
$sudo_cmd systemctl enable devmon@devmon
$sudo_cmd systemctl start devmon@devmon
}
USB_Remove_File() {
USB_Stop_Auto() {
((EUID)) && sudo_cmd="sudo"
$sudo_cmd rm -fr /etc/udev/rules.d/11-usb-mount.rules
$sudo_cmd rm -fr /etc/systemd/system/usb-mount@.service
$sudo_cmd systemctl stop devmon@devmon
$sudo_cmd systemctl disable devmon@devmon
$sudo_cmd udevil clean
}
GetDeviceTree(){
@ -363,4 +363,27 @@ AddSmabaUser(){
$2
$2
EOF
}
}
# $1:username $2:host $3:share $4:port $5:mountpoint $6:password
MountCIFS(){
$sudo_cmd mount -t cifs -o username=$1,password=$6,port=$4 //$2/$3 $5
}
# $1:service name
CheckServiceStatus(){
rs="`systemctl status $1 |grep -E 'Active|PID'`"
#echo "$rs"
run="`echo "$rs" |grep -B 2 'running'`"
fai="`echo "$rs" |grep -E -B 2 'failed|inactive|dead'`"
if [ "$run" == "" ]
then
echo "failed"
else
echo "running"
fi
}
UDEVILUmount(){
$sudo_cmd udevil umount -f $1
}

View file

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

View file

@ -20,7 +20,7 @@
<title>
CasaOS
</title>
<link href="/ui/css/13.a16d5119.css" rel="prefetch"><link href="/ui/css/14.cf8c898a.css" rel="prefetch"><link href="/ui/css/4.f7a3b3b4.css" rel="prefetch"><link href="/ui/css/5.e8438f80.css" rel="prefetch"><link href="/ui/css/6.d72d6157.css" rel="prefetch"><link href="/ui/css/7.805596b0.css" rel="prefetch"><link href="/ui/css/8.92188e4d.css" rel="prefetch"><link href="/ui/css/9.dccf29b4.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/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.344b6034.css" rel="preload" as="style"><link href="/ui/css/vendors~app.c42f9a2b.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.c42f9a2b.css" rel="stylesheet"><link href="/ui/css/app.344b6034.css" rel="stylesheet"></head>
<link href="/ui/css/13.a16d5119.css" rel="prefetch"><link href="/ui/css/14.cf8c898a.css" rel="prefetch"><link href="/ui/css/4.f17f9b01.css" rel="prefetch"><link href="/ui/css/5.e8438f80.css" rel="prefetch"><link href="/ui/css/6.d72d6157.css" rel="prefetch"><link href="/ui/css/7.805596b0.css" rel="prefetch"><link href="/ui/css/8.92188e4d.css" rel="prefetch"><link href="/ui/css/9.dccf29b4.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/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.c78d232d.css" rel="preload" as="style"><link href="/ui/css/vendors~app.c42f9a2b.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.c42f9a2b.css" rel="stylesheet"><link href="/ui/css/app.c78d232d.css" rel="stylesheet"></head>
<body>
<noscript>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long