update changelog

This commit is contained in:
LinkLeong 2022-05-05 13:46:55 +08:00
parent d9794851f9
commit 92d085acf9
44 changed files with 2167 additions and 579 deletions

332
CHANGELOG.md Normal file
View File

@ -0,0 +1,332 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Connect and file add image thumbnail function
- Import of docker applications
- Apply manual upgrades
- CasaConnect gives priority to LAN connections
### Changed
- Application data is no longer saved to the database
- Optimize app store speed issues
### Removed
- Historical Application Data
### Security
### Fixed
## [0.3.0] - 2022-04-08
### Added
- Add CasaConnect function, now you can share private files peer-to-peer with your friends.
- Add a widget for network traffic monitoring.
- 12 new popular apps added to App Center
### Changed
- Updated the sidebar of Files.
- Updated the initial directory of Files to the Root directory.
- Armbian 22.02 armhf/arm64/amd64 platform tests passed [@igorpecovnik ](https://github.com/igorpecovnik)
- Elementary OS 6.1 Jólnir amd64 platform tests passed [@alvarosamudio ](https://github.com/alvarosamudio)
### Fixed
- Fix an issue in Files where the backspace button would trigger a return to the previous level of the directory when creating a folder.
- Fix the display problem of application list in CPU widget.
- Fix the problem that the ipv6 of the application cannot be opened
### Removed
- Interfaces related to "zerotier"
## [0.2.10] - 2022-03-10
### Added
- Added CasaOS own file manager, now you can browse, upload, download files from the system, even edit code online, preview photos and videos through it. It will appear in the first position of Apps.
- Added CPU core count display and memory capacity display.
### Changed
- Optimized the rendering performance of the home page.
- Optimized the internationalization display of the time widget.
- Show the icon of the stopped application as gray.
- Unify the animation of the drop-down menu.
- Optimize the display of the application drop-down menu.
- Replaced the default font to optimize the display.
### Fixed
- Fix the problem of failed to create storage space
## [0.2.9] - 2022-02-18
### Added
- Add a simple notification function
### Changed
- Custom installation of new parameters(Capabilities,Hostname,Privileged)
- Update front-end translation [@SemVer](https://github.com/zarevskaya) [@koboldMaki](https://github.com/koboldMaki) [@sgastol](https://github.com/sgastol) [@delki8](https://github.com/delki8)
- Modify the default location and name of the usb mount
### Fixed
- Fix the problem of being indexed by search engines
- Fix some style display issues
- Solve hard drive can't be formatted, can't finish adding storage
## [0.2.8] - 2022-01-30
### Added
- Add USB disk device display
### Changed
- Update translation [@baptiste313](https://github.com/baptiste313) [@thueske](https://github.com/thueske)
- Compatible with more types of drives
### Fixed
- Fix the language initialization bug
- Fix the problem that the login page could not be displayed
- Fix missing translated content
## [0.2.7] - 2022.01.26
### Changed
- Apply multilingual support
### Security
- Fix an injectable execution bug
## [0.2.6] - 2022.01.26
### Added
- Add a bug report panel.
- App Store apps start supporting multiple languages
### Fixed
- Fix a disk that cannot be formatted under certain circumstances
## [0.2.5] - 2022.01.24
### Added
- Storage Manager
### Changed
- Update Disk widget
- Update language files [@ImOstrovskiy](https://github.com/ImOstrovskiy) [@baptiste313](https://github.com/baptiste313)
### Fixed
- File synchronization issues
- Fix the app store classification problem
## [0.2.4] - 2021.12.30
### Changed
- Brand new App Store
- Optimize request method
### Fixed
- Fix Sync panel width display error.
- Fix App panel width display error.
## [0.2.3] - 2021.12.11
### Added
- Add detailed CPU and memory statistics.
- Add the multi-language function and add Chinese translation.
- Add the function to modify the search engine.
- Add the function of modifying the WebUI port
### Changed
- Update update script
- Preprocessing usb automounting
### Fixed
- Volume path problem when customizing the installation of applications
- Fix Cpu and Ram usage display error
- Fix translation errors
- Fixed an error when importing and exporting appfile.
## [0.2.2] - 2021.12.02
### Changed
- UI adjustment
### Fixed
- Fix the problem of data display error when manually installing apps
- Fix some spelling problems
- Fix the bug of synchronization module
## [0.2.1] - 2021.11.25
### Fixed
- Fix Sync display error
- Fix Sync Downoad url error
- Fix Smart Block display error
- Fix widgets settings dispaly error
- Fix application installation path error
## [0.2.0] - 2021.11.25
### Added
- Add sync function
## [0.1.11] - 2021.11.10
### Changed
- Adaptation of cell phone terminals
- Optimize user experience
- Replaced the default background
- Optimized the display performance and fixed some bugs
### Fixed
- Resolve application installation path errors
## [0.1.10] - 2021.11.04
### Added
- Add application terminal
- Add application logs
- Add system logs
- Add App Store for installation
## [0.1.9] - 2021.11.01 [YANKED]
## [0.1.8] - 2021.10.27
### Added
- Add system terminal
- Add the ability to modify the user name and password
### Changed
- Experience optimization
- Improve single user management function
- Fixed Disk widget display error
- Fixed Username display error after change
- Adaptation for mobile access
## [0.1.7] - 2021.10.22
### Added
- Add user authentication module, Login page and initialization page.
### Fixed
- Fix the problem that the application could not start after the system restarted.
- Home storage space data display exception
- Script override causes application loss after installation
- Fix docker network error
## [0.1.6] - 2021.10.19
### Added
- Add app icon auto-fill via docker image name.
- Add a file selector for app install.
### Changed
- Modify import reminder.
- Optimize the application installation process
### Fixed
- Fixed an issue with the app were it would disappear when the app was modified.
- Fixed device selector default dir to /dev
## [0.1.5] - 2021.10.15
### Added
- Add CPU RAM Status with widget
- Add Disk Info with widget
- Realize automatic loading of widgets
### Changed
- Enhance the Docker cli import experience and automatically fill in the folders that need to be mounted
### Removed
- Remove Weather widget.
### Fixed
- AppFile upload does not pass verification
- The setting menu of the app is displayed abnormally when the browser window is too narrow
- The port is occupied and the program cannot start
- Fix display bugs when windows size less than 1024px
## [0.1.4] - 2021.09.30
### Added
- Import and export of application configuration files
- Automatic parsing of docker commands
### Changed
- Improve the program release process
- Application installation process UX/UI optimization
### Fixed
- Authentication failure during the operation, resulting in the need to re-login
## [0.1.3] - 2021.09.29 [YANKED]
## [0.1.2] - 2021.09.28
### Fixed
- Application modification and new creation failure issues
## [0.1.1] - 2021.09.27
## [0.1.0] - 2021.09.26
### Added
- Application Center

View File

@ -16,12 +16,11 @@ RootPath = /casaOS
HttpPort = 8089 HttpPort = 8089
UDPPort = UDPPort =
RunMode = release RunMode = release
ServerApi = https://api.casaos.zimaboard.com ServerApi = https://api.casaos.io
Handshake = socket.casaos.io Handshake = socket.casaos.io
Token = Token =
USBAutoMount = true USBAutoMount = true
[user] [user]
UserName = admin UserName = admin
PWD = zimaboard PWD = zimaboard
@ -30,6 +29,7 @@ Description = description
Initialized = false Initialized = false
Avatar = Avatar =
NickName = NickName =
PublicKey =
[redis] [redis]
Host = 127.0.0.1:6379 Host = 127.0.0.1:6379

5
go.mod
View File

@ -5,14 +5,17 @@ go 1.16
require ( require (
github.com/Microsoft/go-winio v0.5.0 // indirect github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/Microsoft/hcsshim v0.8.22 // indirect github.com/Microsoft/hcsshim v0.8.22 // indirect
github.com/PuerkitoBio/goquery v1.7.0
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
github.com/bits-and-blooms/bitset v1.2.1 // indirect github.com/bits-and-blooms/bitset v1.2.1 // indirect
github.com/containerd/containerd v1.5.7 github.com/containerd/containerd v1.5.7
github.com/containerd/continuity v0.2.0 // indirect github.com/containerd/continuity v0.2.0 // indirect
github.com/disintegration/imaging v1.6.2
github.com/docker/distribution v2.8.0+incompatible // indirect github.com/docker/distribution v2.8.0+incompatible // indirect
github.com/docker/docker v20.10.7+incompatible github.com/docker/docker v20.10.7+incompatible
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0
github.com/dsoprea/go-exif v0.0.0-20210625224831-a6301f85c82b
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
github.com/gin-contrib/gzip v0.0.2 github.com/gin-contrib/gzip v0.0.2
github.com/gin-gonic/gin v1.7.2 github.com/gin-gonic/gin v1.7.2

32
go.sum
View File

@ -82,8 +82,6 @@ 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/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/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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.7.0 h1:O5SP3b9JWqMSVMG69zMfj577zwkSNpxrFf7ybS74eiw=
github.com/PuerkitoBio/goquery v1.7.0/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 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 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@ -99,8 +97,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 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= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@ -269,6 +265,8 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@ -289,6 +287,20 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dsoprea/go-exif v0.0.0-20210625224831-a6301f85c82b h1:hoVHc4m/v8Al8mbWyvKJWr4Z37yM4QUSVh/NY6A5Sbc=
github.com/dsoprea/go-exif v0.0.0-20210625224831-a6301f85c82b/go.mod h1:lOaOt7+UEppOgyvRy749v3do836U/hw0YVJNjoyPaEs=
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b h1:NgNuLvW/gAFKU30ULWW0gtkCt56JfB7FrZ2zyo0wT8I=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg=
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf h1:/w4QxepU4AHh3AuO6/g8y/YIIHH5+aKP3Bj8sg5cqhU=
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e h1:IxIbA7VbCNrwumIYjDoMOdf4KOSkMC6NJE4s8oRbE7E=
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
@ -330,6 +342,9 @@ github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.1.1 h1:ljK/pL5ltg3qoN+OtN6yCv9HWSfMwxSx90GJCZQxYNg=
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -400,6 +415,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc=
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -516,6 +534,7 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w= github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro= github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@ -935,6 +954,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -957,7 +978,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -991,6 +1011,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@ -1342,6 +1363,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

49
main.go
View File

@ -4,7 +4,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"net/http" "net/http"
"runtime"
"time" "time"
"github.com/IceWhaleTech/CasaOS/pkg/cache" "github.com/IceWhaleTech/CasaOS/pkg/cache"
@ -13,6 +12,8 @@ import (
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/robfig/cron" "github.com/robfig/cron"
"gorm.io/gorm" "gorm.io/gorm"
@ -21,7 +22,7 @@ import (
var sqliteDB *gorm.DB var sqliteDB *gorm.DB
var configFlag = flag.String("c", "", "config address") 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 showUserInfo = flag.Bool("show-user-info", false, "show user info")
func init() { func init() {
@ -29,25 +30,10 @@ func init() {
config.InitSetup(*configFlag) config.InitSetup(*configFlag)
config.UpdateSetup() config.UpdateSetup()
loger2.LogSetup() loger2.LogSetup()
sysType := runtime.GOOS if len(*dbFlag) == 0 {
if sysType == "windows" { *dbFlag = config.AppInfo.ProjectPath + "/db"
config.AppInfo.ProjectPath = "C:\\CasaOS\\service"
config.Cfg.Section("app").Key("ProjectPath").SetValue("C:\\CasaOS\\service")
config.AppInfo.RootPath = "C:\\CasaOS"
config.Cfg.Section("app").Key("RootPath").SetValue("C:\\CasaOS")
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
} }
if sysType == "darwin" { sqliteDB = sqlite.GetDb(*dbFlag)
config.AppInfo.ProjectPath = "./CasaOS/service"
config.Cfg.Section("app").Key("ProjectPath").SetValue("./CasaOS/service")
config.AppInfo.RootPath = "./CasaOS"
config.Cfg.Section("app").Key("RootPath").SetValue("./CasaOS")
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
//gredis.GetRedisConn(config.RedisInfo), //gredis.GetRedisConn(config.RedisInfo),
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger()) service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
service.Cache = cache.Init() service.Cache = cache.Init()
@ -58,10 +44,13 @@ func init() {
service.UDPAddressMap = make(map[string]string) service.UDPAddressMap = make(map[string]string)
//go service.SocketConnect() //go service.SocketConnect()
service.CancelList = make(map[string]string) service.CancelList = make(map[string]string)
service.InternalInspection = make(map[string][]string)
service.NewVersionApp = make(map[string]string)
route.InitFunction() route.InitFunction()
go service.SendIPToServer() go service.SendIPToServer()
go service.LoopFriend() go service.LoopFriend()
go service.MyService.App().CheckNewImage()
} }
@ -97,20 +86,22 @@ func main() {
service.SendIPToServer() service.SendIPToServer()
service.LoopFriend() service.LoopFriend()
service.MyService.App().CheckNewImage()
})
if err != nil {
fmt.Println(err)
}
err = cron2.AddFunc("0/1 * * * * *", func() {
notify := model2.AppNotify{}
notify.CustomId = ""
notify.Type = types.NOTIFY_TYPE_HEALTH_CHECK
go service.MyService.Notify().SendText(notify)
}) })
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
// err = cron2.AddFunc("0/1 * * * * *", func() {
// //service.SendIPToServer()
// //service.LoopNet()
// })
// if err != nil {
// fmt.Println(err)
// }
cron2.Start() cron2.Start()
defer cron2.Stop() defer cron2.Stop()
s := &http.Server{ s := &http.Server{

View File

@ -18,6 +18,7 @@ type UserModel struct {
Initialized bool Initialized bool
Avatar string Avatar string
NickName string NickName string
Public string
} }
//服务配置 //服务配置

View File

@ -4,7 +4,7 @@ import "time"
type Version struct { type Version struct {
Id uint `gorm:"column:id;primary_key" json:"id"` Id uint `gorm:"column:id;primary_key" json:"id"`
ChangLog string `json:"chang_log"` ChangeLog string `json:"change_log"`
Version string `json:"version"` Version string `json:"version"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`

View File

@ -1,9 +0,0 @@
package model
type ZeroTierUpData struct {
Config ZeroTierConfig `json:"config"`
}
type ZeroTierConfig struct {
Private bool `json:"private"`
}

View File

@ -10,4 +10,5 @@ type Path struct {
Size int64 `json:"size"` //File Size Size int64 `json:"size"` //File Size
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
Label string `json:"label,omitempty"` Label string `json:"label,omitempty"`
Write bool `json:"write"`
} }

View File

@ -12,15 +12,15 @@ import (
var gdb *gorm.DB var gdb *gorm.DB
func GetDb(projectPath string) *gorm.DB { func GetDb(dbPath string) *gorm.DB {
if gdb != nil { if gdb != nil {
return gdb return gdb
} }
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情 // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
//dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName) //dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
//db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{}) //db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
file.IsNotExistMkDir(projectPath + "/db/") file.IsNotExistMkDir(dbPath)
db, err := gorm.Open(sqlite.Open(projectPath+"/db/casaOS.db"), &gorm.Config{}) db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
c, _ := db.DB() c, _ := db.DB()
c.SetMaxIdleConns(10) c.SetMaxIdleConns(10)
c.SetMaxOpenConns(100) c.SetMaxOpenConns(100)
@ -31,7 +31,7 @@ func GetDb(projectPath string) *gorm.DB {
return nil return nil
} }
gdb = db gdb = db
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{}) err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{}, model2.PersonDownRecordDBModel{}, model2.ApplicationModel{})
if err != nil { if err != nil {
fmt.Println("检查和创建数据库出错", err) fmt.Println("检查和创建数据库出错", err)
} }

82
pkg/utils/file/image.go Normal file
View File

@ -0,0 +1,82 @@
package file
import (
"bytes"
"fmt"
"io"
"os"
"github.com/disintegration/imaging"
"github.com/dsoprea/go-exif/v3"
exifcommon "github.com/dsoprea/go-exif/v3/common"
)
func GetImage(path string, width, height int) ([]byte, error) {
if thumbnail, err := GetThumbnailByOwnerPhotos(path); err == nil {
return thumbnail, nil
} else {
return GetThumbnailByWebPhoto(path, width, height)
}
}
func GetThumbnailByOwnerPhotos(path string) ([]byte, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
buff := &bytes.Buffer{}
defer file.Close()
offset := 0
offsets := []int{12, 30}
head := make([]byte, 0xffff)
r := io.TeeReader(file, buff)
_, err = r.Read(head)
if err != nil {
return nil, err
}
for _, offset = range offsets {
if _, err = exif.ParseExifHeader(head[offset:]); err == nil {
break
}
}
im, err := exifcommon.NewIfdMappingWithStandard()
if err != nil {
return nil, err
}
_, index, err := exif.Collect(im, exif.NewTagIndex(), head[offset:])
if err != nil {
return nil, err
}
ifd := index.RootIfd.NextIfd()
if err != nil {
return nil, err
}
thumbnail, err := ifd.Thumbnail()
if err != nil {
return nil, err
}
return thumbnail, nil
}
func GetThumbnailByWebPhoto(path string, width, height int) ([]byte, error) {
src, err := imaging.Open(path)
if err != nil {
fmt.Println(err)
return nil, err
}
img := imaging.Resize(src, width, 0, imaging.Lanczos)
f, err := imaging.FormatFromFilename(path)
if err != nil {
return nil, err
}
buf := bytes.Buffer{}
imaging.Encode(&buf, img, f)
return buf.Bytes(), nil
}

View File

@ -2,7 +2,6 @@ package httper
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -51,6 +50,41 @@ func Get(url string, head map[string]string) (response string) {
return return
} }
//发送GET请求
//url:请求地址
//response:请求返回的内容
func PersonGet(url string) (response string) {
client := &http.Client{Timeout: 5 * time.Second}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return ""
}
resp, err := client.Do(req)
if err != nil {
//需要错误日志的处理
//loger.Error(error)
return ""
//panic(error)
}
defer resp.Body.Close()
var buffer [512]byte
result := bytes.NewBuffer(nil)
for {
n, err := resp.Body.Read(buffer[0:])
result.Write(buffer[0:n])
if err != nil && err == io.EOF {
break
} else if err != nil {
//loger.Error(err)
return ""
// panic(err)
}
}
response = result.String()
return
}
//发送POST请求 //发送POST请求
//url:请求地址data:POST请求提交的数据,contentType:请求体格式application/json //url:请求地址data:POST请求提交的数据,contentType:请求体格式application/json
//content:请求放回的内容 //content:请求放回的内容
@ -78,88 +112,6 @@ func Post(url string, data []byte, contentType string, head map[string]string) (
return return
} }
//发送POST请求
//url:请求地址data:POST请求提交的数据,contentType:请求体格式application/json
//content:请求放回的内容
func ZeroTierPost(url string, data map[string]string, head map[string]string, cookies []*http.Cookie) (content string, code int) {
b, _ := json.Marshal(data)
req, err := http.NewRequest("POST", url, bytes.NewReader(b))
for _, cookie := range cookies {
req.AddCookie(cookie)
}
for k, v := range head {
req.Header.Add(k, v)
}
if err != nil {
panic(err)
}
client := &http.Client{Timeout: 20 * time.Second}
resp, error := client.Do(req)
if error != nil {
panic(error)
}
defer resp.Body.Close()
code = resp.StatusCode
result, _ := ioutil.ReadAll(resp.Body)
content = string(result)
return
}
//发送POST请求
//url:请求地址data:POST请求提交的数据,contentType:请求体格式application/json
//content:请求放回的内容
func ZeroTierPostJson(url string, data string, head map[string]string) (content string, code int) {
var postData *bytes.Buffer
jsonStr := []byte(data)
postData = bytes.NewBuffer(jsonStr)
req, err := http.NewRequest("POST", url, postData)
for k, v := range head {
req.Header.Add(k, v)
}
if err != nil {
panic(err)
}
client := &http.Client{Timeout: 20 * time.Second}
resp, error := client.Do(req)
if error != nil {
panic(error)
}
defer resp.Body.Close()
result, _ := ioutil.ReadAll(resp.Body)
content = string(result)
code = resp.StatusCode
return
}
func ZeroTierDelete(url string, head map[string]string) (content string, code int) {
req, err := http.NewRequest("DELETE", url, nil)
for k, v := range head {
req.Header.Add(k, v)
}
if err != nil {
panic(err)
}
client := &http.Client{Timeout: 20 * time.Second}
resp, error := client.Do(req)
if error != nil {
panic(error)
}
defer resp.Body.Close()
result, _ := ioutil.ReadAll(resp.Body)
content = string(result)
code = resp.StatusCode
return
}
//发送POST请求 //发送POST请求
//url:请求地址data:POST请求提交的数据,contentType:请求体格式application/json //url:请求地址data:POST请求提交的数据,contentType:请求体格式application/json
//content:请求放回的内容 //content:请求放回的内容

View File

@ -1,9 +1,10 @@
package ip_helper package ip_helper
import ( import (
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"net" "net"
"strings" "strings"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
) )
func IsIPv4(address string) bool { func IsIPv4(address string) bool {
@ -39,3 +40,35 @@ func GetLoclIp() string {
} }
return "127.0.0.1" return "127.0.0.1"
} }
func GetDeviceAllIP(port string) []string {
var address []string
addrs, err := net.InterfaceAddrs()
if err != nil {
return address
}
for _, a := range addrs {
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To16() != nil {
address = append(address, ipNet.IP.String()+":"+port)
}
}
}
return address
}
func HasLocalIP(ip net.IP) bool {
if ip.IsLoopback() {
return true
}
ip.String()
ip4 := ip.To4()
if ip4 == nil {
return false
}
return ip4[0] == 10 || // 10.0.0.0/8
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) || // 172.16.0.0/12
(ip4[0] == 169 && ip4[1] == 254) || // 169.254.0.0/16
(ip4[0] == 192 && ip4[1] == 168) // 192.168.0.0/16
}

View File

@ -2,6 +2,7 @@ package ip_helper
import ( import (
"fmt" "fmt"
"net"
"testing" "testing"
) )
@ -20,3 +21,7 @@ func TestGetExternalIPV6(t *testing.T) {
func TestGetLoclIp(t *testing.T) { func TestGetLoclIp(t *testing.T) {
fmt.Println(GetLoclIp()) fmt.Println(GetLoclIp())
} }
func TestHasLocalIP(t *testing.T) {
fmt.Println("dddd")
fmt.Println(HasLocalIP(net.ParseIP("192.168.2.10")))
}

View File

@ -17,6 +17,7 @@ const (
FILE_ALREADY_EXISTS = 20002 FILE_ALREADY_EXISTS = 20002
FILE_OR_DIR_EXISTS = 20003 FILE_OR_DIR_EXISTS = 20003
PORT_IS_OCCUPIED = 20004 PORT_IS_OCCUPIED = 20004
COMMAND_ERROR_INVALID_OPERATION = 20005
//zerotier //zerotier
GET_TOKEN_ERROR = 30001 GET_TOKEN_ERROR = 30001
@ -32,6 +33,7 @@ const (
UNINSTALL_APP_ERROR = 50001 UNINSTALL_APP_ERROR = 50001
PULL_IMAGE_ERROR = 50002 PULL_IMAGE_ERROR = 50002
DEVICE_NOT_EXIST = 50003 DEVICE_NOT_EXIST = 50003
ERROR_APP_NAME_EXIST = 50004
//file //file
FILE_DOES_NOT_EXIST = 60001 FILE_DOES_NOT_EXIST = 60001
@ -76,6 +78,7 @@ var MsgFlags = map[int]string{
UNINSTALL_APP_ERROR: "Error uninstalling app", UNINSTALL_APP_ERROR: "Error uninstalling app",
PULL_IMAGE_ERROR: "Error pulling image", PULL_IMAGE_ERROR: "Error pulling image",
DEVICE_NOT_EXIST: "Device does not exist", DEVICE_NOT_EXIST: "Device does not exist",
ERROR_APP_NAME_EXIST: "App name already exists",
//disk //disk
NAME_NOT_AVAILABLE: "Name not available", NAME_NOT_AVAILABLE: "Name not available",
@ -99,6 +102,7 @@ var MsgFlags = map[int]string{
PERSON_EXIST_FRIEND: "Friend already exist", PERSON_EXIST_FRIEND: "Friend already exist",
PERSON_NOT_EXIST_USER: "User does not exist", PERSON_NOT_EXIST_USER: "User does not exist",
PERSON_MYSELF: "You can not add yourself", PERSON_MYSELF: "You can not add yourself",
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
} }
//获取错误信息 //获取错误信息

View File

@ -37,6 +37,31 @@ func IsNeedUpdate() (bool, model.Version) {
return false, version return false, version
} }
func IsClientNeedUpdate() (bool, model.Version) {
var version model.Version
v := httper.OasisGet(config.ServerInfo.ServerApi + "/v1/sys/client/version")
data := gjson.Get(v, "data")
json2.Unmarshal([]byte(data.String()), &version)
v1 := strings.Split(version.Version, ".")
v2 := strings.Split(types.CURRENTVERSION, ".")
for len(v1) < len(v2) {
v1 = append(v1, "0")
}
for len(v2) < len(v1) {
v2 = append(v2, "0")
}
for i := 0; i < len(v1); i++ {
a, _ := strconv.Atoi(v1[i])
b, _ := strconv.Atoi(v2[i])
if a > b {
return true, version
}
}
return false, version
}
//a版本大于b版本 //a版本大于b版本
func VersionCompared(a string, b string) bool { func VersionCompared(a string, b string) bool {
v1 := strings.Split(a, ".") v1 := strings.Split(a, ".")

View File

@ -27,6 +27,9 @@ func InitFunction() {
CheckSerialDiskMount() CheckSerialDiskMount()
CheckToken2_11() CheckToken2_11()
ImportApplications()
ChangeAPIUrl()
InitSystemApplication()
} }
@ -103,7 +106,7 @@ func installSyncthing(appId string) {
m.Restart = "always" m.Restart = "always"
m.Volumes = appInfo.Volumes m.Volumes = appInfo.Volumes
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel) containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
if err != nil { if err != nil {
fmt.Println("container create error", err) fmt.Println("container create error", err)
// create container error // create container error
@ -261,7 +264,7 @@ func CheckToken2_11() {
downloadPath = "C:\\CasaOS\\DATA\\Downloads" downloadPath = "C:\\CasaOS\\DATA\\Downloads"
} }
if sysType == "darwin" { if sysType == "darwin" {
downloadPath = "~/CasaOS/DATA/Downloads" downloadPath = "./CasaOS/DATA/Downloads"
} }
config.Cfg.Section("file").Key("DownloadDir").SetValue(downloadPath) config.Cfg.Section("file").Key("DownloadDir").SetValue(downloadPath)
config.FileSettingInfo.DownloadDir = downloadPath config.FileSettingInfo.DownloadDir = downloadPath
@ -291,3 +294,35 @@ func CheckToken2_11() {
// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) // config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
} }
func ImportApplications() {
service.MyService.App().ImportApplications(true)
}
// 0.3.1
func ChangeAPIUrl() {
newAPIUrl := "https://api.casaos.io"
config.ServerInfo.ServerApi = newAPIUrl
config.Cfg.Section("server").Key("ServerApi").SetValue(newAPIUrl)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
// 0.3.1
func InitSystemApplication() {
list := service.MyService.App().GetApplicationList()
if len(list) != 2 {
application := model2.ApplicationModel{}
application.Name = "Files"
application.Icon = "http://demo.casaos.io/ui/img/folder-open.d382f130.svg"
application.Type = "system"
application.Index = 0
service.MyService.App().CreateApplication(application)
application.Name = "CasaConnect"
application.Icon = "http://demo.casaos.io/ui/img/folder-publicshare.0219e0d4.svg"
application.Type = "system"
application.Index = 0
service.MyService.App().CreateApplication(application)
}
}

View File

@ -41,7 +41,8 @@ func InitRouter() *gin.Engine {
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd) r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
//get user info //get user info
r.GET("/v1/user/info", v1.GetUserInfo) r.GET("/v1/user/info", v1.GetUserInfo)
//get user info
r.GET("/v1/person/shareid", v1.GetPersonShareId)
v1Group := r.Group("/v1") v1Group := r.Group("/v1")
v1Group.Use(jwt2.JWT(swagHandler)) v1Group.Use(jwt2.JWT(swagHandler))
@ -102,7 +103,7 @@ func InitRouter() *gin.Engine {
v1AppGroup.Use() v1AppGroup.Use()
{ {
//获取我的已安装的列表 //获取我的已安装的列表
v1AppGroup.GET("/mylist", v1.MyAppList) v1AppGroup.GET("/my/list", v1.MyAppList)
// //
v1AppGroup.GET("/usage", v1.AppUsageList) v1AppGroup.GET("/usage", v1.AppUsageList)
//app详情 //app详情
@ -117,8 +118,7 @@ func InitRouter() *gin.Engine {
v1AppGroup.GET("/category", v1.CategoryList) v1AppGroup.GET("/category", v1.CategoryList)
//容器相关 //容器相关
v1AppGroup.GET("/terminal/:id", v1.DockerTerminal) v1AppGroup.GET("/terminal/:id", v1.DockerTerminal)
//准备安装 v1AppGroup.PUT("/index/:id", v1.PutAppIndex)
//v1AppGroup.GET("/ready/:id", v1.ReadyInstall)
//app容器详情 //app容器详情
v1AppGroup.GET("/info/:id", v1.ContainerInfo) v1AppGroup.GET("/info/:id", v1.ContainerInfo)
//app容器日志 //app容器日志
@ -139,7 +139,7 @@ func InitRouter() *gin.Engine {
v1AppGroup.GET("/update/:id/info", v1.ContainerUpdateInfo) v1AppGroup.GET("/update/:id/info", v1.ContainerUpdateInfo)
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo) v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig) v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp) v1AppGroup.PUT("/update/:id", v1.PutAppUpdate)
v1AppGroup.POST("/share", v1.ShareAppFile) v1AppGroup.POST("/share", v1.ShareAppFile)
} }
@ -148,6 +148,7 @@ func InitRouter() *gin.Engine {
{ {
//获取检查版本是否需要升级 //获取检查版本是否需要升级
v1SysGroup.GET("/check", v1.CheckVersion) v1SysGroup.GET("/check", v1.CheckVersion)
v1SysGroup.GET("/client/version", v1.GetClientVersion)
v1SysGroup.POST("/update", v1.SystemUpdate) v1SysGroup.POST("/update", v1.SystemUpdate)
v1SysGroup.GET("/sys", v1.Sys) v1SysGroup.GET("/sys", v1.Sys)
v1SysGroup.GET("/wsssh", v1.WsSsh) v1SysGroup.GET("/wsssh", v1.WsSsh)
@ -182,6 +183,7 @@ func InitRouter() *gin.Engine {
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir) v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
v1FileGroup.DELETE("/delete", v1.DeleteFile) v1FileGroup.DELETE("/delete", v1.DeleteFile)
v1FileGroup.PUT("/update", v1.PutFileContent) v1FileGroup.PUT("/update", v1.PutFileContent)
v1FileGroup.GET("/image", v1.GetFileImage)
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) //v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
} }
@ -233,29 +235,17 @@ func InitRouter() *gin.Engine {
v1TaskGroup.PUT("/completion/:id", v1.PutTaskMarkerCompletion) v1TaskGroup.PUT("/completion/:id", v1.PutTaskMarkerCompletion)
} }
v1ShortcutsGroup := v1Group.Group("/shortcuts")
v1ShortcutsGroup.Use()
{
v1ShortcutsGroup.GET("/list", v1.GetShortcutsList)
v1ShortcutsGroup.POST("/add", v1.PostShortcutsAdd)
v1ShortcutsGroup.PUT("/edit", v1.PutShortcutsEdit)
v1ShortcutsGroup.DELETE("/del/:id", v1.DeleteShortcutsDelete)
}
v1NotifyGroup := v1Group.Group("/notify") v1NotifyGroup := v1Group.Group("/notify")
v1NotifyGroup.Use() v1NotifyGroup.Use()
{ {
v1NotifyGroup.GET("/ws", v1.NotifyWS) v1NotifyGroup.GET("/ws", v1.NotifyWS)
v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead) v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
} }
v1SearchGroup := v1Group.Group("/search")
v1SearchGroup.Use()
{
v1SearchGroup.GET("/search", v1.GetSearchList)
}
v1PersonGroup := v1Group.Group("/person") v1PersonGroup := v1Group.Group("/person")
v1PersonGroup.Use() v1PersonGroup.Use()
{ {
v1PersonGroup.GET("/test", v1.PersonTest)
v1PersonGroup.GET("/users", v1.GetPersonFriend) v1PersonGroup.GET("/users", v1.GetPersonFriend)
v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend) v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend)
v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend) v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend)
@ -267,11 +257,15 @@ func InitRouter() *gin.Engine {
v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile) v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile)
v1PersonGroup.POST("/share", v1.PostPersonShare) v1PersonGroup.POST("/share", v1.PostPersonShare)
v1PersonGroup.POST("/file/:shareid", v1.PostPersonFile)
v1PersonGroup.GET("/share", v1.GetPersonShare) v1PersonGroup.GET("/share", v1.GetPersonShare)
v1PersonGroup.POST("/down/dir", v1.PostPersonDownDir) v1PersonGroup.POST("/down/dir", v1.PostPersonDownDir)
v1PersonGroup.GET("/down/dir", v1.GetPersonDownDir) v1PersonGroup.GET("/down/dir", v1.GetPersonDownDir)
v1PersonGroup.PUT("/block/:shareid", v1.PutPersonBlock) v1PersonGroup.PUT("/block/:shareid", v1.PutPersonBlock)
v1PersonGroup.GET("/public", v1.GetPersonPublic) v1PersonGroup.GET("/public", v1.GetPersonPublic)
v1PersonGroup.PUT("/friend/:shareid", v1.PutPersonAgreeFriend)
v1PersonGroup.PUT("/write/:shareid", v1.PutPersonWrite)
v1PersonGroup.GET("/image/thumbnail/:shareid", v1.GetPersonImageThumbnail)
} }
v1AnalyseGroup := v1Group.Group("/analyse") v1AnalyseGroup := v1Group.Group("/analyse")

View File

@ -106,13 +106,18 @@ func PortCheck(c *gin.Context) {
// @Param size query int false "size" // @Param size query int false "size"
// @Param position query bool false "是否是首页应用" // @Param position query bool false "是否是首页应用"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /app/mylist [get] // @Router /app/my/list [get]
func MyAppList(c *gin.Context) { func MyAppList(c *gin.Context) {
index, _ := strconv.Atoi(c.DefaultQuery("index", "1")) index, _ := strconv.Atoi(c.DefaultQuery("index", "1"))
size, _ := strconv.Atoi(c.DefaultQuery("size", "0")) size, _ := strconv.Atoi(c.DefaultQuery("size", "0"))
position, _ := strconv.ParseBool(c.DefaultQuery("position", "true")) position, _ := strconv.ParseBool(c.DefaultQuery("position", "true"))
list := service.MyService.App().GetMyList(index, size, position) list, unTranslation := service.MyService.App().GetMyList(index, size, position)
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
data := make(map[string]interface{}, 2)
data["list"] = list
data["local"] = unTranslation
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
} }
// @Summary my app hardware usage list // @Summary my app hardware usage list

View File

@ -4,8 +4,8 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
json2 "encoding/json" json2 "encoding/json"
"fmt"
"net/http" "net/http"
"reflect"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -27,7 +27,6 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"github.com/tidwall/gjson"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
) )
@ -154,6 +153,17 @@ func InstallApp(c *gin.Context) {
const CUSTOM = "custom" const CUSTOM = "custom"
var dockerImage string var dockerImage string
var dockerImageVersion string var dockerImageVersion string
//check app name is exist
if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil {
if m.Origin != "custom" {
m.Label = m.Label + "_" + time.Now().Local().Format("02150405")
} else {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_APP_NAME_EXIST, Message: oasis_err2.GetMsg(oasis_err2.ERROR_APP_NAME_EXIST)})
return
}
}
//检查端口 //检查端口
if len(m.PortMap) > 0 && m.PortMap != "0" { if len(m.PortMap) > 0 && m.PortMap != "0" {
//c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) //c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
@ -247,13 +257,13 @@ func InstallApp(c *gin.Context) {
//if len(privileged) > 0 { //if len(privileged) > 0 {
// //
//} //}
id := uuid.NewV4().String() //id := uuid.NewV4().String()
var relyMap = make(map[string]string) var relyMap = make(map[string]string)
go func() { go func() {
installLog := model2.AppNotify{} installLog := model2.AppNotify{}
installLog.State = 0 installLog.State = 0
installLog.CustomId = id installLog.CustomId = m.Label
installLog.Message = "installing rely" installLog.Message = "installing rely"
installLog.Class = types.NOTIFY_APP installLog.Class = types.NOTIFY_APP
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
@ -281,7 +291,7 @@ func InstallApp(c *gin.Context) {
rely.Type = types.RELY_TYPE_MYSQL rely.Type = types.RELY_TYPE_MYSQL
rely.ContainerId = mysqlContainerId rely.ContainerId = mysqlContainerId
rely.CustomId = mid rely.CustomId = mid
rely.ContainerCustomId = id rely.ContainerCustomId = m.Label
var mysqlConfig model2.MysqlConfigs var mysqlConfig model2.MysqlConfigs
//结构体转换 //结构体转换
@ -333,7 +343,7 @@ func InstallApp(c *gin.Context) {
// service.MyService.Notify().UpdateLog(installLog) // service.MyService.Notify().UpdateLog(installLog)
// return // return
// } // }
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel) containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
installLog.Name = appInfo.Title installLog.Name = appInfo.Title
installLog.Icon = appInfo.Icon installLog.Icon = appInfo.Icon
if err != nil { if err != nil {
@ -352,7 +362,7 @@ func InstallApp(c *gin.Context) {
// echo -e "hellow\nworld" >> // echo -e "hellow\nworld" >>
//step启动容器 //step启动容器
err = service.MyService.Docker().DockerContainerStart(id) err = service.MyService.Docker().DockerContainerStart(m.Label)
if err != nil { if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
installLog.State = 0 installLog.State = 0
@ -418,7 +428,7 @@ func InstallApp(c *gin.Context) {
} }
//step: 启动成功 检查容器状态确认启动成功 //step: 启动成功 检查容器状态确认启动成功
container, err := service.MyService.Docker().DockerContainerInfo(id) container, err := service.MyService.Docker().DockerContainerInfo(m.Label)
if err != nil && container.ContainerJSONBase.State.Running { if err != nil && container.ContainerJSONBase.State.Running {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
installLog.State = 0 installLog.State = 0
@ -449,7 +459,7 @@ func InstallApp(c *gin.Context) {
capAdd, _ := json.Marshal(m.CapAdd) capAdd, _ := json.Marshal(m.CapAdd)
//step: 保存数据到数据库 //step: 保存数据到数据库
md := model2.AppListDBModel{ md := model2.AppListDBModel{
CustomId: id, CustomId: "",
Title: appInfo.Title, Title: appInfo.Title,
//ScreenshotLink: appInfo.ScreenshotLink, //ScreenshotLink: appInfo.ScreenshotLink,
Slogan: appInfo.Tagline, Slogan: appInfo.Tagline,
@ -485,12 +495,13 @@ func InstallApp(c *gin.Context) {
//if appInfo.NetworkModel == "host" { //if appInfo.NetworkModel == "host" {
// m.PortMap = m.Port // m.PortMap = m.Port
//} //}
service.MyService.App().SaveContainer(md) fmt.Println(md)
//service.MyService.App().SaveContainer(md)
config.CasaOSGlobalVariables.AppChange = true config.CasaOSGlobalVariables.AppChange = true
}() }()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: id}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m.Label})
} }
@ -691,10 +702,16 @@ func UnInstallApp(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
info := service.MyService.App().GetUninstallInfo(appId) //info := service.MyService.App().GetUninstallInfo(appId)
info, err := service.MyService.Docker().DockerContainerInfo(appId)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
//step停止容器 //step停止容器
err := service.MyService.Docker().DockerContainerStop(appId) err = service.MyService.Docker().DockerContainerStop(appId)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
return return
@ -709,17 +726,16 @@ func UnInstallApp(c *gin.Context) {
//存在镜像正在使用的情况 //存在镜像正在使用的情况
// step删除镜像 // step删除镜像
service.MyService.Docker().DockerImageRemove(info.Image + ":" + info.Version) service.MyService.Docker().DockerImageRemove(info.Image)
//step: 删除本地数据 //step: 删除本地数据
service.MyService.App().RemoveContainerById(appId) //service.MyService.App().RemoveContainerById(appId)
if info.Origin != "custom" { if info.Config.Labels["origin"] != "custom" {
fmt.Println(info.HostConfig.Mounts)
//step: 删除文件夹 //step: 删除文件夹
vol := gjson.Get(info.Volumes, "#.host") for _, v := range info.HostConfig.Mounts {
for _, v := range vol.Array() { if strings.Contains(v.Source, info.Name) {
if strings.Contains(v.String(), appId) { service.MyService.App().DelAppConfigDir(v.Source)
service.MyService.App().DelAppConfigDir(v.String())
} }
} }
@ -793,7 +809,7 @@ func ChangAppState(c *gin.Context) {
} else if state == "start" { } else if state == "start" {
err = service.MyService.Docker().DockerContainerStart(appId) err = service.MyService.Docker().DockerContainerStart(appId)
} else if state == "restart" { } else if state == "restart" {
err = service.MyService.Docker().DockerContainerStop(appId) service.MyService.Docker().DockerContainerStop(appId)
err = service.MyService.Docker().DockerContainerStart(appId) err = service.MyService.Docker().DockerContainerStart(appId)
} }
if err != nil { if err != nil {
@ -889,16 +905,18 @@ func UpdateSetting(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
var cpd model.CustomizationPostData //var cpd model.CustomizationPostData
copier.Copy(&cpd, &m) //copier.Copy(&cpd, &m)
appInfo := service.MyService.App().GetAppDBInfo(id) //appInfo := service.MyService.App().GetAppDBInfo(id)
//info, err := service.MyService.Docker().DockerContainerInfo(id)
var containerId string // //check app name is exist
containerId = appInfo.ContainerId // if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_APP_NAME_EXIST, Message: oasis_err2.GetMsg(oasis_err2.ERROR_APP_NAME_EXIST)})
service.MyService.Docker().DockerContainerStop(id) // return
// }
portMap, _ := strconv.Atoi(m.PortMap) portMap, _ := strconv.Atoi(m.PortMap)
if !port2.IsPortAvailable(portMap, "tcp") { if !port2.IsPortAvailable(portMap, "tcp") {
@ -936,52 +954,27 @@ func UpdateSetting(c *gin.Context) {
} }
//如果容器端口均未修改,这不进行处理 service.MyService.Docker().DockerContainerStop(id)
portsStr, _ := json2.Marshal(m.Ports) service.MyService.Docker().DockerContainerUpdateName(id, id)
//service.MyService.Docker().DockerContainerRemove(id, true)
envsStr, _ := json2.Marshal(m.Envs) containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, m, m.NetworkModel)
volumesStr, _ := json2.Marshal(m.Volumes) if err != nil {
devicesStr, _ := json2.Marshal(m.Devices) service.MyService.Docker().DockerContainerUpdateName(m.Label, id)
capAddStr, _ := json2.Marshal(m.CapAdd) service.MyService.Docker().DockerContainerStart(id)
cmdStr, _ := json.Marshal(m.Cmd) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(string(volumesStr), appInfo.Volumes) || m.PortMap != appInfo.PortMap || m.NetworkModel != appInfo.NetModel || m.HostName != appInfo.HostName || !reflect.DeepEqual(string(cmdStr), appInfo.Cmd) || !reflect.DeepEqual(string(capAddStr), appInfo.CapAdd) || m.Privileged != appInfo.Privileged { return
}
// echo -e "hellow\nworld" >>
var newUUid = uuid.NewV4().String() //step启动容器
var err error err = service.MyService.Docker().DockerContainerStart(containerId)
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetModel)
// if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
// return
// }
containerId, err = service.MyService.Docker().DockerContainerCreate(appInfo.Image+":"+appInfo.Version, newUUid, cpd, m.NetworkModel)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return return
} }
service.MyService.Docker().DockerContainerRemove(id, true)
err = service.MyService.Docker().DockerContainerRemove(id, true)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return
}
service.MyService.Docker().DockerContainerUpdateName(appInfo.CustomId, newUUid)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return
}
} else if !reflect.DeepEqual(string(devicesStr), appInfo.Devices) || m.CpuShares != appInfo.CpuShares || m.Memory != appInfo.Memory || m.Restart != appInfo.Restart {
service.MyService.Docker().DockerContainerUpdate(cpd, id)
}
err := service.MyService.Docker().DockerContainerStart(id)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return
}
//更新upnp //更新upnp
if m.Origin != CUSTOM { if m.Origin != CUSTOM {
//if appInfo.EnableUPNP != appInfo.EnableUPNP { //if appInfo.EnableUPNP != appInfo.EnableUPNP {
@ -1047,27 +1040,117 @@ func UpdateSetting(c *gin.Context) {
//} //}
} }
appInfo.ContainerId = containerId //service.MyService.App().UpdateApp(appInfo)
appInfo.PortMap = m.PortMap
appInfo.Label = m.Label c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
appInfo.Index = m.Index }
appInfo.Ports = string(portsStr)
appInfo.Envs = string(envsStr) // @Summary update app version
appInfo.Icon = m.Icon // @Produce application/json
appInfo.Volumes = string(volumesStr) // @Accept multipart/form-data
appInfo.Devices = string(devicesStr) // @Tags app
appInfo.NetModel = m.NetworkModel // @Param id path string true "容器id"
appInfo.Position = m.Position // @Security ApiKeyAuth
appInfo.EnableUPNP = m.EnableUPNP // @Success 200 {string} string "ok"
appInfo.Restart = m.Restart // @Router /app/update/{id} [put]
appInfo.Memory = m.Memory func PutAppUpdate(c *gin.Context) {
appInfo.CpuShares = m.CpuShares id := c.Param("id")
appInfo.Cmd = string(cmdStr)
appInfo.Privileged = m.Privileged if len(id) == 0 {
appInfo.CapAdd = string(capAddStr) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
appInfo.HostName = m.HostName return
appInfo.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10) }
service.MyService.App().UpdateApp(appInfo)
inspect, err := service.MyService.Docker().DockerContainerInfo(id)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest"
err = service.MyService.Docker().DockerPullImage(imageLatest, model2.AppNotify{})
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
service.MyService.Docker().DockerContainerStop(id)
service.MyService.Docker().DockerContainerUpdateName(id, id)
//service.MyService.Docker().DockerContainerRemove(id, true)
inspect.Image = imageLatest
inspect.Config.Image = imageLatest
containerId, err := service.MyService.Docker().DockerContainerCopyCreate(inspect)
if err != nil {
service.MyService.Docker().DockerContainerUpdateName(inspect.Name, id)
service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return
}
//step启动容器
err = service.MyService.Docker().DockerContainerStart(containerId)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return
}
service.MyService.Docker().DockerContainerRemove(id, true)
delete(service.NewVersionApp, id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary update app index
// @Produce application/json
// @Accept multipart/form-data
// @Tags app
// @Param id path string true "app id"
// @Param index query int true "app index"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/index/{id} [put]
func PutAppIndex(c *gin.Context) {
id := c.Param("id")
index, _ := strconv.Atoi(c.Query("index"))
if len(id) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
inspect, err := service.MyService.Docker().DockerContainerInfo(id)
if err != nil {
if len(service.MyService.App().GetApplicationById(id).Name) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
} else {
service.MyService.App().UpdateApplicationIndexById(id, index)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
return
}
}
service.MyService.Docker().DockerContainerStop(id)
service.MyService.Docker().DockerContainerUpdateName(id, id)
inspect.Config.Labels["index"] = strconv.Itoa(index)
containerId, err := service.MyService.Docker().DockerContainerCopyCreate(inspect)
if err != nil {
service.MyService.Docker().DockerContainerUpdateName(inspect.Name, id)
service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return
}
//step启动容器
err = service.MyService.Docker().DockerContainerStart(containerId)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return
}
service.MyService.Docker().DockerContainerRemove(id, true)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} }
@ -1160,7 +1243,7 @@ func ContainerRelyInfo(c *gin.Context) {
// @Router /app/update/{id}/info [get] // @Router /app/update/{id}/info [get]
func ContainerUpdateInfo(c *gin.Context) { func ContainerUpdateInfo(c *gin.Context) {
appId := c.Param("id") appId := c.Param("id")
appInfo := service.MyService.App().GetAppDBInfo(appId) //appInfo := service.MyService.App().GetAppDBInfo(appId)
info, err := service.MyService.Docker().DockerContainerInfo(appId) info, err := service.MyService.Docker().DockerContainerInfo(appId)
if err != nil { if err != nil {
//todo 需要自定义错误 //todo 需要自定义错误
@ -1168,50 +1251,75 @@ func ContainerUpdateInfo(c *gin.Context) {
return return
} }
var port model.PortArray var port model.PortArray
json2.Unmarshal([]byte(appInfo.Ports), &port) // json2.Unmarshal([]byte(appInfo.Ports), &port)
var envs model.EnvArray for k, v := range info.HostConfig.PortBindings {
json2.Unmarshal([]byte(appInfo.Envs), &envs) temp := model.PortMap{
CommendPort: v[0].HostPort,
ContainerPort: k.Port(),
var vol model.PathArray Protocol: k.Proto(),
json2.Unmarshal([]byte(appInfo.Volumes), &vol) }
port = append(port, temp)
for i := 0; i < len(vol); i++ {
vol[i].Path = strings.ReplaceAll(vol[i].Path, "$AppID", appId)
} }
var dir model.PathArray var envs model.EnvArray
json2.Unmarshal([]byte(appInfo.Devices), &dir) // json2.Unmarshal([]byte(appInfo.Envs), &envs)
for _, v := range info.Config.Env {
temp := model.Env{
Name: strings.Split(v, "=")[0],
Value: strings.Split(v, "=")[1],
}
envs = append(envs, temp)
}
var vol model.PathArray
// json2.Unmarshal([]byte(appInfo.Volumes), &vol)
for i := 0; i < len(info.HostConfig.Mounts); i++ {
temp := model.PathMap{
Path: strings.ReplaceAll(info.HostConfig.Mounts[i].Source, "$AppID", info.Name),
ContainerPath: info.HostConfig.Mounts[i].Target,
}
vol = append(vol, temp)
}
var driver model.PathArray
var cmd []string
json2.Unmarshal([]byte(appInfo.Cmd), &cmd)
var capAdd []string
json2.Unmarshal([]byte(appInfo.CapAdd), &capAdd)
//volumesStr, _ := json2.Marshal(m.Volumes) //volumesStr, _ := json2.Marshal(m.Volumes)
//devicesStr, _ := json2.Marshal(m.Devices) //devicesStr, _ := json2.Marshal(m.Devices)
for _, v := range info.HostConfig.Resources.Devices {
temp := model.PathMap{
Path: v.PathOnHost,
ContainerPath: v.PathInContainer,
}
driver = append(driver, temp)
}
m := model.CustomizationPostData{} m := model.CustomizationPostData{}
m.Index = appInfo.Index m.Index = ""
m.Icon = appInfo.Icon m.Icon = info.Config.Labels["icon"]
m.Ports = port m.Ports = port
m.Image = appInfo.Image + ":" + appInfo.Version m.Image = info.Image
m.Origin = appInfo.Origin m.Origin = info.Config.Labels["origin"]
m.NetworkModel = appInfo.NetModel m.NetworkModel = string(info.HostConfig.NetworkMode)
m.Description = appInfo.Description m.Description = info.Config.Labels["desc"]
m.Label = appInfo.Label m.Label = info.Name
m.PortMap = appInfo.PortMap m.PortMap = info.Config.Labels["web"]
m.Devices = dir //appInfo.Devices m.Devices = driver
m.Envs = envs m.Envs = envs
m.Memory = info.HostConfig.Memory >> 20 m.Memory = info.HostConfig.Memory >> 20
m.CpuShares = info.HostConfig.CPUShares m.CpuShares = info.HostConfig.CPUShares
m.Volumes = vol //appInfo.Volumes m.Volumes = vol //appInfo.Volumes
m.Restart = info.HostConfig.RestartPolicy.Name m.Restart = info.HostConfig.RestartPolicy.Name
m.EnableUPNP = appInfo.EnableUPNP m.EnableUPNP = false
m.Position = appInfo.Position m.Position = false
m.CapAdd = capAdd m.CapAdd = info.HostConfig.CapAdd
m.Cmd = cmd m.Cmd = info.Config.Cmd
m.HostName = appInfo.HostName m.HostName = info.Config.Hostname
m.Privileged = appInfo.Privileged m.Privileged = info.HostConfig.Privileged
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
} }

View File

@ -14,6 +14,7 @@ import (
"strings" "strings"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
@ -342,7 +343,7 @@ func GetFileUpload(c *gin.Context) {
path := c.Query("path") path := c.Query("path")
dirPath := "" dirPath := ""
hash := file.GetHashByContent([]byte(fileName)) hash := file.GetHashByContent([]byte(fileName))
tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/" tempDir := config.AppInfo.RootPath + "/temp/" + hash + strconv.Itoa(totalChunks) + "/"
if fileName != relative { if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName) dirPath = strings.TrimSuffix(relative, fileName)
tempDir += dirPath tempDir += dirPath
@ -381,7 +382,7 @@ func PostFileUpload(c *gin.Context) {
c.JSON(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/" tempDir := config.AppInfo.RootPath + "/temp/" + hash + strconv.Itoa(totalChunks) + "/"
if fileName != relative { if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName) dirPath = strings.TrimSuffix(relative, fileName)
@ -504,7 +505,7 @@ func PutFileContent(c *gin.Context) {
path := c.PostForm("path") path := c.PostForm("path")
content := c.PostForm("content") content := c.PostForm("content")
if !file.Exists(path) { if !file.Exists(path) {
c.JSON(oasis_err2.FILE_ALREADY_EXISTS, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return return
} }
//err := os.Remove(path) //err := os.Remove(path)
@ -522,3 +523,42 @@ func PutFileContent(c *gin.Context) {
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} }
// @Summary image thumbnail/original image
// @Produce application/json
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path query string true "path"
// @Param type query string false "original,thumbnail" Enums(original,thumbnail)
// @Success 200 {string} string "ok"
// @Router /file/image [get]
func GetFileImage(c *gin.Context) {
t := c.Query("type")
path := c.Query("path")
if !file.Exists(path) {
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
if t == "thumbnail" {
f, err := file.GetImage(path, 100, 0)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
c.Writer.WriteString(string(f))
return
}
f, err := os.Open(path)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
c.Writer.WriteString(string(data))
}

View File

@ -1,18 +1,26 @@
package v1 package v1
import ( import (
"bytes"
"encoding/base64"
"encoding/gob"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net"
"net/http" "net/http"
"os"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"time" "time"
path2 "path"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
@ -21,33 +29,6 @@ import (
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
) )
func PersonTest(c *gin.Context) {
token := c.Query("token")
_, err := uuid.FromString(token)
fmt.Println(err)
//service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9")
msg := model.MessageModel{}
msg.Type = types.PERSONHELLO
msg.Data = ""
msg.From = config.ServerInfo.Token
msg.To = token
msg.UUId = uuid.NewV4().String()
dd, err := service.Dial(msg, true)
if err == nil {
fmt.Println(err)
}
fmt.Println(dd)
user := service.MyService.Casa().GetUserInfoByShareId(token)
if reflect.DeepEqual(user, model.UserInfo{}) {
fmt.Println("空数据")
}
fmt.Println(user)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Retry the file that failed to download // @Summary Retry the file that failed to download
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@ -135,7 +116,7 @@ func GetPersonFile(c *gin.Context) {
task.Size = 0 task.Size = 0
task.State = types.DOWNLOADAWAIT task.State = types.DOWNLOADAWAIT
task.Created = time.Now().Unix() task.Created = time.Now().Unix()
task.Type = 0 task.Type = types.PERSONFILEDOWNLOAD
task.LocalPath = localPath task.LocalPath = localPath
if service.MyService.Download().GetDownloadListByPath(task) > 0 { if service.MyService.Download().GetDownloadListByPath(task) > 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
@ -197,7 +178,7 @@ func DeletePersonDownloadFile(c *gin.Context) {
// @Router /person/list [get] // @Router /person/list [get]
func GetPersonDownloadList(c *gin.Context) { func GetPersonDownloadList(c *gin.Context) {
state := c.DefaultQuery("state", "") state := c.DefaultQuery("state", "")
list := service.MyService.Download().GetDownloadListByState(state) list := service.MyService.Download().GetDownloadListByState(state, types.PERSONFILEDOWNLOAD)
//if it is downloading, it need to add 'already' //if it is downloading, it need to add 'already'
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
if list[i].State == types.DOWNLOADING { if list[i].State == types.DOWNLOADING {
@ -235,6 +216,82 @@ func PutPersonRemarks(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
} }
// @Summary 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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
filesuffix := strings.Split(path2.Ext(path), ".")[1]
fmt.Println("data:image/" + filesuffix + ";base64," + img.Data.(string))
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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: img.Data.(string)})
}
// @Summary get my friend list // @Summary get my friend list
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@ -247,6 +304,10 @@ func GetPersonFriend(c *gin.Context) {
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 { if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 {
list[i].OnLine = true list[i].OnLine = true
list[i].Avatar = v
if ip_helper.HasLocalIP(net.ParseIP(strings.Split(v, ":")[0])) {
list[i].LocalIP = strings.Split(v, ":")[0]
}
} }
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
@ -296,10 +357,20 @@ func PostAddPersonFriend(c *gin.Context) {
go service.Dial(message, true) 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 := model2.FriendModel{}
friend.Token = v friend.Token = v
friend.Avatar = user.Avatar friend.Avatar = user.Avatar
friend.Block = false friend.Block = false
friend.State = types.FRIENDSTATEWAIT
friend.NickName = user.NickName friend.NickName = user.NickName
friend.Profile = user.Desc friend.Profile = user.Desc
friend.Version = user.Version friend.Version = user.Version
@ -439,6 +510,17 @@ func GetPersonShare(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.ShareDir}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.ServerInfo.Token})
}
// @Summary Modify disabled status // @Summary Modify disabled status
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@ -494,3 +576,209 @@ func GetPersonPublic(c *gin.Context) {
list := service.MyService.Casa().GetPersonPublic() list := service.MyService.Casa().GetPersonPublic()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
} }
// @Summary 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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if !file.Exists(localPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DOES_NOT_EXIST, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
return
}
service.MyService.Download().AddDownloadTask(task)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
user := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: token})
if user.State != types.FRIENDSTATEREQUEST {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.COMMAND_ERROR_INVALID_OPERATION, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
// return
// }
// c.JSON(204, model.Result{Success: 204, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
// return
// }
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
// return
// }
// fileNum, err := ioutil.ReadDir(tempDir)
// if err != nil {
// c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
// return
// }
// if totalChunks == len(fileNum) {
// file.RMDir(tempDir)
// }
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
// }

View File

@ -23,7 +23,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// @Summary 系统信息 // @Summary check version
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags sys // @Tags sys
@ -50,6 +50,32 @@ func CheckVersion(c *gin.Context) {
return return
} }
// @Summary check client version
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/client/version [get]
func GetClientVersion(c *gin.Context) {
need, version := version.IsClientNeedUpdate()
if need {
installLog := model2.AppNotify{}
installLog.State = 0
installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.Name = "CasaOS System"
service.MyService.Notify().AddLog(installLog)
}
data := make(map[string]interface{}, 1)
data["is_need"] = need
data["version"] = version
data["current_version"] = types.CURRENTVERSION
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
}
// @Summary 系统信息 // @Summary 系统信息
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json

View File

@ -3,9 +3,11 @@ package service
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"runtime" "runtime"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -23,10 +25,14 @@ import (
) )
type AppService interface { type AppService interface {
GetMyList(index, size int, position bool) *[]model2.MyAppList CreateApplication(m model2.ApplicationModel)
GetApplicationList() (m []model2.ApplicationModel)
GetApplicationById(id string) (m model2.ApplicationModel)
UpdateApplicationIndexById(id string, index int)
GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList)
SaveContainer(m model2.AppListDBModel) SaveContainer(m model2.AppListDBModel)
GetUninstallInfo(id string) model2.AppListDBModel GetUninstallInfo(id string) model2.AppListDBModel
RemoveContainerById(id string) DeleteApp(id string)
GetContainerInfo(name string) (types.Container, error) GetContainerInfo(name string) (types.Container, error)
GetAppDBInfo(id string) model2.AppListDBModel GetAppDBInfo(id string) model2.AppListDBModel
UpdateApp(m model2.AppListDBModel) UpdateApp(m model2.AppListDBModel)
@ -37,6 +43,8 @@ type AppService interface {
GetHardwareUsage() []model.DockerStatsModel GetHardwareUsage() []model.DockerStatsModel
GetAppStats(id string) string GetAppStats(id string) string
GetAllDBApps() []model2.AppListDBModel GetAllDBApps() []model2.AppListDBModel
ImportApplications(casaApp bool)
CheckNewImage()
} }
type appStruct struct { type appStruct struct {
@ -44,68 +52,195 @@ type appStruct struct {
log loger2.OLog log loger2.OLog
} }
func (a *appStruct) GetApplicationById(id string) (m model2.ApplicationModel) {
a.db.Where("id = ?", id).First(&m)
return
}
func (a *appStruct) UpdateApplicationIndexById(id string, index int) {
a.db.Model(&model2.ApplicationModel{}).Where("id = ?", id).Update("index", index)
}
func (a *appStruct) CreateApplication(m model2.ApplicationModel) {
a.db.Create(&m)
}
func (a *appStruct) GetApplicationList() (m []model2.ApplicationModel) {
a.db.Find(&m)
return
}
func (a *appStruct) CheckNewImage() {
list := MyService.Docker().DockerContainerList()
for _, v := range list {
inspect, err := MyService.Docker().DockerImageInfo(strings.Split(v.Image, ":")[0])
if err != nil {
NewVersionApp[v.ID] = inspect.ID
continue
}
if inspect.ID == v.ImageID {
delete(NewVersionApp, v.ID)
continue
}
NewVersionApp[v.ID] = inspect.ID
}
}
func (a *appStruct) ImportApplications(casaApp bool) {
if casaApp {
list := MyService.App().GetAllDBApps()
for _, app := range list {
info, err := MyService.Docker().DockerContainerInfo(app.CustomId)
if err != nil {
MyService.App().DeleteApp(app.CustomId)
continue
}
//info.NetworkSettings
info.Config.Labels["casaos"] = "casaos"
info.Config.Labels["web"] = app.PortMap
info.Config.Labels["icon"] = app.Icon
info.Config.Labels["desc"] = app.Description
info.Name = app.Title
container_id, err := MyService.Docker().DockerContainerCopyCreate(info)
if err != nil {
fmt.Println(err)
continue
}
MyService.App().DeleteApp(app.CustomId)
MyService.Docker().DockerContainerStop(app.CustomId)
MyService.Docker().DockerContainerRemove(app.CustomId, false)
MyService.Docker().DockerContainerStart(container_id)
}
} else {
list := MyService.Docker().DockerContainerList()
for _, app := range list {
info, err := MyService.Docker().DockerContainerInfo(app.ID)
if err != nil || info.Config.Labels["casaos"] == "casaos" {
continue
}
info.Config.Labels["casaos"] = "casaos"
info.Config.Labels["web"] = ""
info.Config.Labels["icon"] = ""
info.Config.Labels["desc"] = ""
_, err = MyService.Docker().DockerContainerCopyCreate(info)
if err != nil {
continue
}
}
}
}
//获取我的应用列表 //获取我的应用列表
func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList { func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList) {
//获取docker应用 //获取docker应用
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5)) cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
if err != nil { if err != nil {
a.log.Error("初始化client失败", "app.getmylist", "line:36", err) a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
} }
defer cli.Close() defer cli.Close()
fts := filters.NewArgs() // fts := filters.NewArgs()
fts.Add("label", "origin") // fts.Add("label", "casaos=casaos")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts}) //fts.Add("label", "casaos")
//fts.Add("casaos", "casaos")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
if err != nil { if err != nil {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err) a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
} }
//获取本地数据库应用 //获取本地数据库应用
var lm []model2.AppListDBModel unTranslation := []model2.MyAppList{}
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image").Find(&lm)
list := []model2.MyAppList{} list := []model2.MyAppList{}
lMap := make(map[string]interface{}) for _, m := range containers {
for _, dbModel := range lm { _, newVersion := NewVersionApp[m.ID]
if position {
if dbModel.Position {
lMap[dbModel.ContainerId] = dbModel
}
} else {
lMap[dbModel.ContainerId] = dbModel
}
}
for _, container := range containers {
if lMap[container.ID] != nil && container.Labels["origin"] != "system" { if m.Labels["casaos"] == "casaos" {
m := lMap[container.ID].(model2.AppListDBModel)
if len(m.Label) == 0 {
m.Label = m.Title
}
// info, err := cli.ContainerInspect(context.Background(), container.ID)
// var tm string
// if err != nil {
// tm = time.Now().String()
// } else {
// tm = info.State.StartedAt
//}
list = append(list, model2.MyAppList{ list = append(list, model2.MyAppList{
Name: m.Label, Name: m.Names[0],
Icon: m.Icon, Icon: m.Labels["icon"],
State: container.State, State: m.State,
CustomId: strings.ReplaceAll(container.Names[0], "/", ""), CustomId: m.ID,
Port: m.PortMap, Port: m.Labels["web"],
Index: m.Index, Index: m.Labels["index"],
//UpTime: tm, //UpTime: tm,
Image: m.Image, Image: m.Image,
Slogan: m.Slogan, NewVersion: newVersion,
//Slogan: m.Slogan,
//Rely: m.Rely, //Rely: m.Rely,
}) })
} else {
unTranslation = append(unTranslation, model2.MyAppList{
Name: m.Names[0],
Icon: "",
State: m.State,
CustomId: m.ID,
Port: "",
NewVersion: newVersion,
Image: m.Image,
})
}
}
systemApp := MyService.App().GetApplicationList()
for _, v := range systemApp {
list = append(list, model2.MyAppList{
Name: "/" + v.Name,
Icon: v.Icon,
State: strconv.Itoa(v.State),
CustomId: strconv.Itoa(v.Id),
Port: "",
Index: strconv.Itoa(v.Index),
Image: "",
Type: v.Type,
NewVersion: false,
})
} }
} //lMap := make(map[string]interface{})
// for _, dbModel := range lm {
// if position {
// if dbModel.Position {
// lMap[dbModel.ContainerId] = dbModel
// }
// } else {
// lMap[dbModel.ContainerId] = dbModel
// }
// }
// for _, container := range containers {
return &list // if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
// m := lMap[container.ID].(model2.AppListDBModel)
// if len(m.Label) == 0 {
// m.Label = m.Title
// }
// // info, err := cli.ContainerInspect(context.Background(), container.ID)
// // var tm string
// // if err != nil {
// // tm = time.Now().String()
// // } else {
// // tm = info.State.StartedAt
// //}
// list = append(list, model2.MyAppList{
// Name: m.Label,
// Icon: m.Icon,
// State: container.State,
// CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
// Port: m.PortMap,
// Index: m.Index,
// //UpTime: tm,
// Image: m.Image,
// Slogan: m.Slogan,
// //Rely: m.Rely,
// })
// }
// }
return &list, &unTranslation
} }
@ -159,7 +294,7 @@ func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
UpTime: tm, UpTime: tm,
Image: m.Image, Image: m.Image,
Slogan: m.Slogan, Slogan: m.Slogan,
Volumes: m.Volumes, //Volumes: m.Volumes,
//Rely: m.Rely, //Rely: m.Rely,
}) })
} }
@ -170,7 +305,7 @@ func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
} }
func (a *appStruct) GetAllDBApps() []model2.AppListDBModel { func (a *appStruct) GetAllDBApps() []model2.AppListDBModel {
var lm []model2.AppListDBModel var lm []model2.AppListDBModel
a.db.Table(model2.CONTAINERTABLENAME).Select("custom_id,title,icon,container_id,label,slogan,image").Find(&lm) a.db.Table(model2.CONTAINERTABLENAME).Select("custom_id,title,icon,container_id,label,slogan,image,port_map").Find(&lm)
return lm return lm
} }
@ -242,7 +377,7 @@ func (a *appStruct) DelAppConfigDir(path string) {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + path) command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + path)
} }
func (a *appStruct) RemoveContainerById(id string) { func (a *appStruct) DeleteApp(id string) {
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{}) a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
} }
@ -298,31 +433,29 @@ func (a *appStruct) GetHardwareUsageSteam() {
ctx := context.Background() ctx := context.Background()
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
var lm []model2.AppListDBModel fts := filters.NewArgs()
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm) fts.Add("label", "casaos=casaos")
//fts.Add("label", "casaos")
//fts.Add("casaos", "casaos")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
if err != nil {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
}
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
if config.CasaOSGlobalVariables.AppChange { if config.CasaOSGlobalVariables.AppChange {
lm = []model2.AppListDBModel{}
config.CasaOSGlobalVariables.AppChange = false config.CasaOSGlobalVariables.AppChange = false
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm)
dataApps := dataStats
dataStats.Range(func(key, value interface{}) bool { dataStats.Range(func(key, value interface{}) bool {
dataStats.Delete(key) dataStats.Delete(key)
return true return true
}) })
for _, v := range lm {
m, _ := dataApps.Load(v.ContainerId)
if m != nil {
dataStats.Store(v.ContainerId, m)
}
}
} }
var wg sync.WaitGroup var wg sync.WaitGroup
for _, v := range lm { for _, v := range containers {
wg.Add(1) wg.Add(1)
go func(v model2.AppListDBModel, i int) { go func(v types.Container, i int) {
defer wg.Done() defer wg.Done()
stats, err := cli.ContainerStats(ctx, v.ContainerId, true) stats, err := cli.ContainerStats(ctx, v.ID, true)
if err != nil { if err != nil {
return return
} }
@ -331,19 +464,15 @@ func (a *appStruct) GetHardwareUsageSteam() {
if err := decode.Decode(&data); err == io.EOF { if err := decode.Decode(&data); err == io.EOF {
return return
} }
m, _ := dataStats.Load(v.ContainerId) m, _ := dataStats.Load(v.ID)
dockerStats := model.DockerStatsModel{} dockerStats := model.DockerStatsModel{}
if m != nil { if m != nil {
dockerStats.Pre = m.(model.DockerStatsModel).Data dockerStats.Pre = m.(model.DockerStatsModel).Data
} }
dockerStats.Data = data dockerStats.Data = data
dockerStats.Icon = v.Icon dockerStats.Icon = v.Labels["icon"]
if len(v.Label) > 0 { dockerStats.Title = v.Names[0]
dockerStats.Title = v.Label dataStats.Store(v.ID, dockerStats)
} else {
dockerStats.Title = v.Title
}
dataStats.Store(v.ContainerId, dockerStats)
if i == 99 { if i == 99 {
stats.Body.Close() stats.Body.Close()
} }

View File

@ -137,8 +137,42 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
return nil return nil
} }
var m []model.LSBLKModel var m []model.LSBLKModel
// strStr := `{
// "blockdevices": [
// {"name":"loop0", "kname":"loop0", "path":"/dev/loop0", "maj:min":"7:0", "fsavail":"0", "fssize":"62M", "fstype":"squashfs", "fsused":"62M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/core20/1405", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":619, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop1", "kname":"loop1", "path":"/dev/loop1", "maj:min":"7:1", "fsavail":"0", "fssize":"55.6M", "fstype":"squashfs", "fsused":"55.6M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/core18/2344", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":55, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop2", "kname":"loop2", "path":"/dev/loop2", "maj:min":"7:2", "fsavail":"0", "fssize":"44.8M", "fstype":"squashfs", "fsused":"44.8M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/snapd/15314", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":446, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop3", "kname":"loop3", "path":"/dev/loop3", "maj:min":"7:3", "fsavail":"0", "fssize":"78.9M", "fstype":"squashfs", "fsused":"78.9M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/lxd/22754", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":788, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop4", "kname":"loop4", "path":"/dev/loop4", "maj:min":"7:4", "fsavail":"0", "fssize":"43.8M", "fstype":"squashfs", "fsused":"43.8M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/snapd/15177", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":436, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop5", "kname":"loop5", "path":"/dev/loop5", "maj:min":"7:5", "fsavail":"0", "fssize":"55.5M", "fstype":"squashfs", "fsused":"55.5M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/core18/1997", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":554, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop6", "kname":"loop6", "path":"/dev/loop6", "maj:min":"7:6", "fsavail":"0", "fssize":"80M", "fstype":"squashfs", "fsused":"80M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/lxd/22826", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":799, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"sda", "kname":"sda", "path":"/dev/sda", "maj:min":"8:0", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"1596101a-e20d-4296-96e2-0870efce554a", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":"ST1000DM003-1ER1", "serial":"Z4YCS1B6", "size":9315, "state":"running", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"disk", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c50090db103a", "rand":true, "pkname":null, "hctl":"0:0:0:0", "tran":"sata", "subsystems":"block:scsi:pci", "rev":"CC61", "vendor":"ATA ", "zoned":"none", "dax":false,
// "children": [
// {"name":"sda1", "kname":"sda1", "path":"/dev/sda1", "maj:min":"8:1", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"1596101a-e20d-4296-96e2-0870efce554a", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":9315, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":3072, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"part", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c50090db103a", "rand":true, "pkname":"sda", "hctl":null, "tran":null, "subsystems":"block:scsi:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false}
// ]
// },
// {"name":"sdb", "kname":"sdb", "path":"/dev/sdb", "maj:min":"8:16", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"baed02d0-e92d-4a00-9609-f94f31271a0e", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":"ST1000DM003-1ER1", "serial":"W4Y51MFH", "size":9315, "state":"running", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"disk", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c5008acd2f00", "rand":true, "pkname":null, "hctl":"1:0:0:0", "tran":"sata", "subsystems":"block:scsi:pci", "rev":"CC46", "vendor":"ATA ", "zoned":"none", "dax":false,
// "children": [
// {"name":"sdb1", "kname":"sdb1", "path":"/dev/sdb1", "maj:min":"8:17", "fsavail":null, "fssize":null, "fstype":"zfs_member", "fsused":null, "fsuse%":null, "fsver":"5000", "mountpoint":null, "label":null, "uuid":null, "ptuuid":"baed02d0-e92d-4a00-9609-f94f31271a0e", "pttype":"gpt", "parttype":"0fc63daf-8483-4772-8e79-3d69d8477de4", "parttypename":"Linux filesystem", "partlabel":"primary", "partuuid":"57880cc0-2695-41c3-bf14-7161693e5bff", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":9315, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":3072, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"part", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c5008acd2f00", "rand":true, "pkname":"sdb", "hctl":null, "tran":null, "subsystems":"block:scsi:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false}
// ]
// },
// {"name":"nvme0n1", "kname":"nvme0n1", "path":"/dev/nvme0n1", "maj:min":"259:0", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":"LITEON CL1-8D128-HP", "serial":"UJDJA01PJDH3UI", "size":1192, "state":"live", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"disk", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":null, "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false,
// "children": [
// {"name":"nvme0n1p1", "kname":"nvme0n1p1", "path":"/dev/nvme0n1p1", "maj:min":"259:1", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":"21686148-6449-6e6f-744e-656564454649", "parttypename":"BIOS boot", "partlabel":null, "partuuid":"b2bac638-9468-449f-9669-79be44e3c80d", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":1, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"part", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":"nvme0n1", "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"nvme0n1p2", "kname":"nvme0n1p2", "path":"/dev/nvme0n1p2", "maj:min":"259:2", "fsavail":"1.2G", "fssize":"1.4G", "fstype":"ext4", "fsused":"131.5M", "fsuse%":"9%", "fsver":"1.0", "mountpoint":"/boot", "label":null, "uuid":"cd8164e9-bf7a-4684-8a3b-1d9f209b4930", "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":"0fc63daf-8483-4772-8e79-3d69d8477de4", "parttypename":"Linux filesystem", "partlabel":null, "partuuid":"42ed9ed6-1221-4bea-901a-bc2f7b7cb9e1", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":15, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"part", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":"nvme0n1", "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"nvme0n1p3", "kname":"nvme0n1p3", "path":"/dev/nvme0n1p3", "maj:min":"259:3", "fsavail":null, "fssize":null, "fstype":"LVM2_member", "fsused":null, "fsuse%":null, "fsver":"LVM2 001", "mountpoint":null, "label":null, "uuid":"0G7ryL-p2Ks-i9HS-wvEO-lXHs-oyZX-1KIlZO", "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":"0fc63daf-8483-4772-8e79-3d69d8477de4", "parttypename":"Linux filesystem", "partlabel":null, "partuuid":"f6ae2e8c-14ae-4d94-89f1-2c154e909843", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":1177, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"part", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":"nvme0n1", "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false,
// "children": [
// {"name":"ubuntu--vg-ubuntu--lv", "kname":"dm-0", "path":"/dev/mapper/ubuntu--vg-ubuntu--lv", "maj:min":"253:0", "fsavail":"78.6G", "fssize":"115.4G", "fstype":"ext4", "fsused":"30.9G", "fsuse%":"27%", "fsver":"1.0", "mountpoint":"/", "label":null, "uuid":"e8a9082f-3643-4820-a5e5-05817d7738c6", "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":1177, "state":"running", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":null, "rq-size":128, "type":"lvm", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":"nvme0n1p3", "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false}
// ]
// }
// ]
// }
// ]
// }`
// fmt.Println(gjson.Get(strStr, "blockdevices").String())
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m) err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m)
if err != nil { if err != nil {
fmt.Println(err)
d.log.Error("json ummarshal error", err) d.log.Error("json ummarshal error", err)
} }

View File

@ -16,6 +16,7 @@ import (
"github.com/containerd/containerd/cio" "github.com/containerd/containerd/cio"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci" "github.com/containerd/containerd/oci"
"github.com/pkg/errors"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/docker" "github.com/IceWhaleTech/CasaOS/pkg/docker"
@ -45,7 +46,8 @@ import (
type DockerService interface { type DockerService interface {
DockerPullImage(imageName string, m model2.AppNotify) error DockerPullImage(imageName string, m model2.AppNotify) error
IsExistImage(imageName string) bool IsExistImage(imageName string) bool
DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error)
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
DockerContainerStart(name string) error DockerContainerStart(name string) error
DockerContainerStats(name string) (string, error) DockerContainerStats(name string) (string, error)
DockerListByName(name string) (*types.Container, error) DockerListByName(name string) (*types.Container, error)
@ -58,8 +60,9 @@ type DockerService interface {
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
DockerContainerLog(name string) (string, error) DockerContainerLog(name string) (string, error)
DockerContainerCommit(name string) DockerContainerCommit(name string)
DockerContainerList() []types.Container
DockerNetworkModelList() []types.NetworkResource DockerNetworkModelList() []types.NetworkResource
DockerImageInfo(image string) DockerImageInfo(image string) (types.ImageInspect, error)
GetNetWorkNameByNetWorkID(id string) (string, error) GetNetWorkNameByNetWorkID(id string) (string, error)
ContainerExecShell(container_id string) string ContainerExecShell(container_id string) string
} }
@ -69,6 +72,19 @@ type dockerService struct {
log loger2.OLog log loger2.OLog
} }
func (ds *dockerService) DockerContainerList() []types.Container {
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
if err != nil {
return nil
}
defer cli.Close()
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
if err != nil {
return containers
}
return containers
}
func (ds *dockerService) ContainerExecShell(container_id string) string { func (ds *dockerService) ContainerExecShell(container_id string) string {
cli, _ := client2.NewClientWithOpts(client2.FromEnv) cli, _ := client2.NewClientWithOpts(client2.FromEnv)
exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{ exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
@ -174,18 +190,16 @@ func DockerEx() {
// //
//} //}
func (ds *dockerService) DockerImageInfo(image string) { func (ds *dockerService) DockerImageInfo(image string) (types.ImageInspect, error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
//but := bytes.Buffer{}
d, b, err := cli.ImageInspectWithRaw(context.Background(), image)
st, _ := json2.Marshal(d.Config)
fmt.Println(string(st))
fmt.Println("换行")
fmt.Println(string(b))
if err != nil { if err != nil {
fmt.Print(err) return types.ImageInspect{}, err
} }
inspect, _, err := cli.ImageInspectWithRaw(context.Background(), image)
if err != nil {
return inspect, err
}
return inspect, nil
} }
func MsqlExec(container string) error { func MsqlExec(container string) error {
@ -342,6 +356,18 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
} }
return err return err
} }
func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return "", err
}
defer cli.Close()
container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name)
if err != nil {
return "", err
}
return container.ID, err
}
//param imageName 镜像名称 //param imageName 镜像名称
//param containerDbId 数据库的id //param containerDbId 数据库的id
@ -349,7 +375,7 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
//param mapPort 容器主端口映射到外部的端口 //param mapPort 容器主端口映射到外部的端口
//param tcp 容器其他tcp端口 //param tcp 容器其他tcp端口
//param udp 容器其他udp端口 //param udp 容器其他udp端口
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) { func (ds *dockerService) DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error) {
if len(net) == 0 { if len(net) == 0 {
net = "bridge" net = "bridge"
} }
@ -442,12 +468,12 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
for _, v := range m.Volumes { for _, v := range m.Volumes {
path := v.Path path := v.Path
if len(path) == 0 { if len(path) == 0 {
path = docker.GetDir(containerDbId, v.Path) path = docker.GetDir(m.Label, v.Path)
if len(path) == 0 { if len(path) == 0 {
continue continue
} }
} }
path = strings.ReplaceAll(path, "$AppID", containerDbId) path = strings.ReplaceAll(path, "$AppID", m.Label)
//reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`) //reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
//result1 := reg1.FindAllStringSubmatch(path, -1) //result1 := reg1.FindAllStringSubmatch(path, -1)
//if len(result1) == 0 { //if len(result1) == 0 {
@ -495,12 +521,16 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
} }
config := &container.Config{ config := &container.Config{
Image: imageName, Image: imageName,
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin}, Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin, "casaos": "casaos"},
Env: envArr, Env: envArr,
// Healthcheck: health, // Healthcheck: health,
Hostname: m.HostName, Hostname: m.HostName,
Cmd: m.Cmd, Cmd: m.Cmd,
} }
config.Labels["web"] = m.PortMap
config.Labels["icon"] = m.Icon
config.Labels["desc"] = m.Description
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net), Privileged: m.Privileged, CapAdd: m.CapAdd} hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net), Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" { //if net != "host" {
config.ExposedPorts = ports config.ExposedPorts = ports
@ -512,7 +542,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
hostConfig, hostConfig,
&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{net: {NetworkID: "", Aliases: []string{}}}}, &network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{net: {NetworkID: "", Aliases: []string{}}}},
nil, nil,
containerDbId) m.Label)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -695,6 +725,9 @@ func (ds *dockerService) DockerListByName(name string) (*types.Container, error)
if err != nil { if err != nil {
return &types.Container{}, err return &types.Container{}, err
} }
if len(containers) == 0 {
return &types.Container{}, errors.New("not found")
}
return &containers[0], nil return &containers[0], nil
} }

33
service/down_record.go Normal file
View File

@ -0,0 +1,33 @@
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}
}

View File

@ -11,7 +11,7 @@ type DownloadService interface {
SaveDownload(m model2.PersonDownloadDBModel) SaveDownload(m model2.PersonDownloadDBModel)
DelDownload(uuid string) DelDownload(uuid string)
GetDownloadById(uuid string) model2.PersonDownloadDBModel GetDownloadById(uuid string) model2.PersonDownloadDBModel
GetDownloadListByState(state string) []model2.PersonDownloadDBModel GetDownloadListByState(state string, t int) []model2.PersonDownloadDBModel
SetDownloadError(m model2.PersonDownloadDBModel) SetDownloadError(m model2.PersonDownloadDBModel)
GetDownloadListByPath(m model2.PersonDownloadDBModel) int GetDownloadListByPath(m model2.PersonDownloadDBModel) int
} }
@ -48,11 +48,11 @@ func (d *downloadService) GetDownloadById(uuid string) model2.PersonDownloadDBMo
d.db.Model(m).Where("uuid = ?", uuid).First(&m) d.db.Model(m).Where("uuid = ?", uuid).First(&m)
return m return m
} }
func (d *downloadService) GetDownloadListByState(state string) (list []model2.PersonDownloadDBModel) { func (d *downloadService) GetDownloadListByState(state string, t int) (list []model2.PersonDownloadDBModel) {
if len(state) == 0 { if len(state) == 0 {
d.db.Find(&list) d.db.Where("type = ?", t).Find(&list)
} else { } else {
d.db.Where("state = ?", state).Find(&list) d.db.Where("state = ? AND type= ?", state, t).Find(&list)
} }
return return

View File

@ -1,9 +1,20 @@
package service package service
import ( import (
"context"
"fmt"
"net"
"reflect" "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" 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" "gorm.io/gorm"
) )
@ -11,17 +22,26 @@ type FriendService interface {
AddFriend(m model2.FriendModel) AddFriend(m model2.FriendModel)
DeleteFriend(m model2.FriendModel) DeleteFriend(m model2.FriendModel)
EditFriendMark(m model2.FriendModel) EditFriendMark(m model2.FriendModel)
EditFriendWrite(m model2.FriendModel)
EditFriendBlock(m model2.FriendModel) EditFriendBlock(m model2.FriendModel)
GetFriendById(m model2.FriendModel) model2.FriendModel GetFriendById(m model2.FriendModel) model2.FriendModel
GetFriendList() (list []model2.FriendModel) GetFriendList() (list []model2.FriendModel)
GetFriendListRemote() (list []model2.FriendModel)
UpdateAddFriendType(m model2.FriendModel) UpdateAddFriendType(m model2.FriendModel)
AgreeFrined(id string)
GetFriendByToken(token string) model2.FriendModel
UpdateOrCreate(m model2.FriendModel) UpdateOrCreate(m model2.FriendModel)
InternalInspection(ips []string, token string)
} }
type friendService struct { type friendService struct {
db *gorm.DB 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) { func (p *friendService) AddFriend(m model2.FriendModel) {
p.db.Create(&m) p.db.Create(&m)
} }
@ -31,6 +51,9 @@ func (p *friendService) DeleteFriend(m model2.FriendModel) {
func (p *friendService) EditFriendMark(m model2.FriendModel) { func (p *friendService) EditFriendMark(m model2.FriendModel) {
p.db.Model(&m).Where("token = ?", m.Token).Update("mark", m.Mark) 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) { func (p *friendService) EditFriendBlock(m model2.FriendModel) {
p.db.Model(&m).Where("token = ?", m.Token).Update("block", m.Block) p.db.Model(&m).Where("token = ?", m.Token).Update("block", m.Block)
} }
@ -43,7 +66,14 @@ func (p *friendService) GetFriendList() (list []model2.FriendModel) {
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Find(&list) p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Find(&list)
return 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) { func (p *friendService) UpdateOrCreate(m model2.FriendModel) {
friend := model2.FriendModel{} friend := model2.FriendModel{}
p.db.Where("token = ?", m.Token).First(&friend) p.db.Where("token = ?", m.Token).First(&friend)
@ -59,6 +89,67 @@ func (p *friendService) UpdateAddFriendType(m model2.FriendModel) {
p.db.Model(&m).Updates(m) 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 { func NewFriendService(db *gorm.DB) FriendService {
return &friendService{db: db} return &friendService{db: db}
} }

View File

@ -0,0 +1,20 @@
package model
import (
"time"
)
type ApplicationModel struct {
Id int `gorm:"column:id;primary_key" json:"id"`
Name string `json:"name"`
Icon string `json:"icon"`
State int `json:"state"`
Type string `json:"type"`
Index int `json:"index"`
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
}
func (p *ApplicationModel) TableName() string {
return "o_application"
}

View File

@ -1,11 +1,8 @@
package model package model
import (
"github.com/IceWhaleTech/CasaOS/model"
)
const CONTAINERTABLENAME = "o_container" const CONTAINERTABLENAME = "o_container"
//Soon to be removed
type AppListDBModel struct { type AppListDBModel struct {
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"` CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
Title string `json:"title"` Title string `json:"title"`
@ -60,7 +57,9 @@ type MyAppList struct {
Port string `json:"port"` Port string `json:"port"`
UpTime string `json:"up_time"` UpTime string `json:"up_time"`
Slogan string `json:"slogan"` Slogan string `json:"slogan"`
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}] Type string `json:"type"`
//Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
Image string `json:"image"` Image string `json:"image"`
Volumes string `json:"volumes"` Volumes string `json:"volumes"`
NewVersion bool `json:"new_version"`
} }

View File

@ -0,0 +1,16 @@
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"
}

View File

@ -3,7 +3,7 @@ package model
type PersonDownloadDBModel struct { type PersonDownloadDBModel struct {
UUID string `gorm:"column:uuid;primary_key" json:"uuid"` UUID string `gorm:"column:uuid;primary_key" json:"uuid"`
State int `json:"state"` // State int `json:"state"` //
Type int `json:"type"` //defult 1 Type int `json:"type"` //defult 0
Name string `json:"name"` //file name Name string `json:"name"` //file name
Size int64 `json:"size"` //file size Size int64 `json:"size"` //file size
BlockSize int `json:"block_size"` //Size of each file block BlockSize int `json:"block_size"` //Size of each file block

View File

@ -1,7 +1,7 @@
package model package model
type FriendModel struct { type FriendModel struct {
State int `json:"state"` //Reserved State int `json:"state"`
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"` CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"` UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
NickName string `json:"nick_name"` NickName string `json:"nick_name"`
@ -12,6 +12,8 @@ type FriendModel struct {
Profile string `json:"profile"` //Description Profile string `json:"profile"` //Description
OnLine bool `json:"on_line" gorm:"-"` OnLine bool `json:"on_line" gorm:"-"`
Version int `json:"version"` Version int `json:"version"`
Write bool `json:"write"`
LocalIP string `json:"local_ip"`
} }
func (p *FriendModel) TableName() string { func (p *FriendModel) TableName() string {

View File

@ -17,6 +17,7 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper" "github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper" httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port" port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
@ -34,11 +35,12 @@ type personService struct {
var IpInfo model.PersionModel var IpInfo model.PersionModel
var CancelList map[string]string var CancelList map[string]string
var InternalInspection map[string][]string
func PushIpInfo(token string) { func PushIpInfo(token string) {
m := model.PersionModel{} m := model.PersionModel{}
m.Ips = GetDeviceAllIP() m.Ips = ip_helper.GetDeviceAllIP("")
m.Token = token m.Token = token
b, _ := json.Marshal(m) b, _ := json.Marshal(m)
@ -193,6 +195,11 @@ func ProcessingContent(stream quic.Stream) {
} else { } else {
list = []model.Path{} list = []model.Path{}
} }
if rFriend.Write {
for i := 0; i < len(list); i++ {
list[i].Write = true
}
}
m.To = m.From m.To = m.From
m.Data = list m.Data = list
m.From = config.ServerInfo.Token m.From = config.ServerInfo.Token
@ -200,10 +207,9 @@ func ProcessingContent(stream quic.Stream) {
break break
} else if m.Type == types.PERSONDOWNLOAD { } else if m.Type == types.PERSONDOWNLOAD {
SendFileData(stream, m.Data.(string), m.From, m.UUId) SendFileData(stream, m.Data.(string), m.From, m.UUId, types.PERSONDOWNLOAD)
break break
} else if m.Type == types.PERSONADDFRIEND { } else if m.Type == types.PERSONADDFRIEND {
fmt.Println("有用户来请求加好友", m)
friend := model2.FriendModel{} friend := model2.FriendModel{}
dataModelByte, _ := json.Marshal(m.Data) dataModelByte, _ := json.Marshal(m.Data)
err := json.Unmarshal(dataModelByte, &friend) err := json.Unmarshal(dataModelByte, &friend)
@ -225,6 +231,7 @@ func ProcessingContent(stream quic.Stream) {
break break
} else if m.Type == types.PERSONCONNECTION { } else if m.Type == types.PERSONCONNECTION {
if len(m.Data.(string)) > 0 { if len(m.Data.(string)) > 0 {
fmt.Println("设置ip", m.Data.(string))
UDPAddressMap[m.From] = m.Data.(string) UDPAddressMap[m.From] = m.Data.(string)
} else { } else {
delete(UDPAddressMap, m.From) delete(UDPAddressMap, m.From)
@ -236,14 +243,18 @@ func ProcessingContent(stream quic.Stream) {
// mi.Token = config.ServerInfo.Token // mi.Token = config.ServerInfo.Token
user := MyService.Casa().GetUserInfoByShareId(m.From) user := MyService.Casa().GetUserInfoByShareId(m.From)
//好友申请 //不是好友
friend := model2.FriendModel{} friend := model2.FriendModel{}
friend.Token = m.From friend.Token = m.From
friend.Avatar = user.Avatar friend.Avatar = user.Avatar
friend.Block = false friend.Block = false
friend.NickName = user.NickName friend.NickName = user.NickName
friend.Profile = user.Avatar friend.Profile = user.Avatar
friend.Write = false
friend.Version = user.Version friend.Version = user.Version
if len(config.UserInfo.Public) > 0 {
friend.State = types.FRIENDSTATEREQUEST
}
MyService.Friend().AddFriend(friend) MyService.Friend().AddFriend(friend)
msg := model.MessageModel{} msg := model.MessageModel{}
@ -254,10 +265,96 @@ func ProcessingContent(stream quic.Stream) {
msg.UUId = m.UUId msg.UUId = m.UUId
Dial(msg, false) 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 break
} else if m.Type == types.PERSONCANCEL { } else if m.Type == types.PERSONCANCEL {
CancelList[m.UUId] = "cancel" CancelList[m.UUId] = "cancel"
break 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 { } else {
//不应有不做返回的数据 //不应有不做返回的数据
//ServiceMessage <- m //ServiceMessage <- m
@ -269,7 +366,7 @@ func ProcessingContent(stream quic.Stream) {
} }
//文件分片发送 //文件分片发送
func SendFileData(stream quic.Stream, filePath, to, uuid string) error { func SendFileData(stream quic.Stream, filePath, to, uuid, t string) error {
summary := model.FileSummaryModel{} summary := model.FileSummaryModel{}
msg := model.MessageModel{} msg := model.MessageModel{}
@ -341,7 +438,7 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
tran.Length = length tran.Length = length
fileMsg := model.MessageModel{} fileMsg := model.MessageModel{}
fileMsg.Type = types.PERSONDOWNLOAD fileMsg.Type = t
fileMsg.Data = tran fileMsg.Data = tran
fileMsg.From = config.ServerInfo.Token fileMsg.From = config.ServerInfo.Token
fileMsg.To = to fileMsg.To = to
@ -356,5 +453,18 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
} }
stream.Write(data) 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 return nil
} }

View File

@ -12,7 +12,7 @@ var Cache *cache.Cache
var MyService Repository var MyService Repository
var WebSocketConns []*websocket.Conn var WebSocketConns []*websocket.Conn
var NewVersionApp map[string]string
var SocketRun bool var SocketRun bool
type Repository interface { type Repository interface {
@ -34,6 +34,7 @@ type Repository interface {
Person() PersonService Person() PersonService
Friend() FriendService Friend() FriendService
Download() DownloadService Download() DownloadService
DownRecord() DownRecordService
} }
func NewService(db *gorm.DB, log loger2.OLog) Repository { func NewService(db *gorm.DB, log loger2.OLog) Repository {
@ -57,6 +58,7 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
person: NewPersonService(db), person: NewPersonService(db),
friend: NewFriendService(db), friend: NewFriendService(db),
download: NewDownloadService(db), download: NewDownloadService(db),
downrecord: NewDownRecordService(db),
} }
} }
@ -79,6 +81,11 @@ type store struct {
person PersonService person PersonService
friend FriendService friend FriendService
download DownloadService download DownloadService
downrecord DownRecordService
}
func (c *store) DownRecord() DownRecordService {
return c.downrecord
} }
func (c *store) Download() DownloadService { func (c *store) Download() DownloadService {

View File

@ -11,13 +11,16 @@ import (
"net" "net"
"os" "os"
path2 "path" path2 "path"
"reflect"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper" "github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
"github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go"
@ -29,6 +32,65 @@ var PeopleMap map[string]quic.Stream
var Message chan model.MessageModel var Message chan model.MessageModel
var UDPAddressMap map[string]string 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) { func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
@ -142,44 +204,257 @@ func ReadContent(stream quic.Stream) {
} }
m := model.MessageModel{} m := model.MessageModel{}
err = json.Unmarshal(messageByte, &m) err = json.Unmarshal(messageByte, &m)
fmt.Println("客户端", m)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
break break
} }
fmt.Println(m)
if m.Type == types.PERSONDOWNLOAD { 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 {
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
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 := model2.AppNotify{}
notify.CustomId = m.From
if len(m.Data.(string)) == 0 {
if _, ok := UDPAddressMap[m.From]; ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
go MyService.Notify().SendText(notify)
}
delete(UDPAddressMap, m.From)
Message <- m
break
}
if _, ok := UDPAddressMap[m.From]; !ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LIVE
go MyService.Notify().SendText(notify)
}
fmt.Println("设置ip", m.Data.(string))
UDPAddressMap[m.From] = m.Data.(string)
fmt.Println(config.ServerInfo.Token != m.From)
fmt.Println(strings.Split(m.Data.(string), ":")[0] == strings.Split(UDPAddressMap[config.ServerInfo.Token], ":")[0])
fmt.Println(strings.Split(m.Data.(string), ":")[0])
fmt.Println(strings.Split(UDPAddressMap[config.ServerInfo.Token], ":")[0])
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()
//list := MyService.Friend().GetFriendListRemote()
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)
fmt.Println("判断为内网ip,设置自己的ip地址", msg.Data)
}
fmt.Println("ping的数据", UDPAddressMap[list[i].Token])
oldIP := UDPAddressMap[list[i].Token]
fmt.Println("old ip", oldIP)
data, err := Dial(msg, false)
if err != nil || reflect.DeepEqual(data, model.MessageModel{}) || len(data.Data.(string)) == 0 {
fmt.Println("ping失败", list[i].Token, err, data, UDPAddressMap[list[i].Token])
if oldIP == UDPAddressMap[list[i].Token] {
notify := model2.AppNotify{}
notify.CustomId = data.From
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
go MyService.Notify().SendText(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) dataModelByte, _ := json.Marshal(m.Data)
dataModel := model.TranFileModel{} dataModel := model.TranFileModel{}
err := json.Unmarshal(dataModelByte, &dataModel) err := json.Unmarshal(dataModelByte, &dataModel)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
continue return false
} }
dataLengthByte := make([]byte, 8) dataLengthByte := make([]byte, 8)
_, err = io.ReadFull(stream, dataLengthByte) _, err = io.ReadFull(stream, dataLengthByte)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
continue return false
} }
dataLength, err := strconv.Atoi(string(dataLengthByte)) dataLength, err := strconv.Atoi(string(dataLengthByte))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
continue return false
} }
dataByte := make([]byte, dataLength) dataByte := make([]byte, dataLength)
_, err = io.ReadFull(stream, dataByte) _, err = io.ReadFull(stream, dataByte)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
continue return false
} }
sum := md5.Sum(dataByte) sum := md5.Sum(dataByte)
hash := hex.EncodeToString(sum[:]) hash := hex.EncodeToString(sum[:])
if dataModel.Hash != hash { if dataModel.Hash != hash {
fmt.Println("hash不匹配", hash, dataModel.Hash) fmt.Println("hash不匹配", hash, dataModel.Hash)
continue return false
} }
tempPath := config.AppInfo.RootPath + "/temp" + "/" + m.UUId tempPath := config.AppInfo.RootPath + "/temp" + "/" + m.UUId
file.IsNotExistMkDir(tempPath) file.IsNotExistMkDir(tempPath)
@ -213,7 +488,7 @@ func ReadContent(stream quic.Stream) {
files, err := ioutil.ReadDir(tempPath) files, err := ioutil.ReadDir(tempPath)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
continue return false
} }
if len(files) >= dataModel.Length { if len(files) >= dataModel.Length {
summary := MyService.Download().GetDownloadById(m.UUId) summary := MyService.Download().GetDownloadById(m.UUId)
@ -233,138 +508,7 @@ func ReadContent(stream quic.Stream) {
MyService.Download().SetDownloadError(summary) MyService.Download().SetDownloadError(summary)
} }
break return true
}
} else if m.Type == types.PERSONSUMMARY {
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)
fullPath := path2.Join(task.LocalPath, task.Name)
task.State = types.DOWNLOADING
if len(dataModel.Message) > 0 {
task.State = types.DOWNLOADERROR
task.Error = dataModel.Message
}
if file.Exists(fullPath) && file.GetHashByPath(fullPath) == dataModel.Hash {
task.State = types.DOWNLOADFINISHED
go func(from, uuid string) {
m := model.MessageModel{}
m.Data = ""
m.From = config.ServerInfo.Token
m.To = from
m.Type = types.PERSONCANCEL
m.UUId = uuid
CancelList[uuid] = uuid
Dial(m, false)
}(task.From, task.UUID)
}
task.UUID = m.UUId
task.Name = dataModel.Name
task.Length = dataModel.Length
task.Size = dataModel.Size
task.BlockSize = dataModel.BlockSize
task.Hash = dataModel.Hash
task.Type = 0
task.From = m.From
MyService.Download().SaveDownload(task)
} 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 == "get_ip" {
notify := model2.AppNotify{}
notify.CustomId = m.From
if len(m.Data.(string)) == 0 {
if _, ok := UDPAddressMap[m.From]; ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
go MyService.Notify().SendText(notify)
}
delete(UDPAddressMap, m.From)
Message <- m
break
}
if _, ok := UDPAddressMap[m.From]; !ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LIVE
go MyService.Notify().SendText(notify)
}
UDPAddressMap[m.From] = m.Data.(string)
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()
for i := 0; i < len(list); i++ {
msg := model.MessageModel{}
msg.Type = "get_ip"
msg.Data = ""
msg.From = config.ServerInfo.Token
msg.To = list[i].Token
msg.UUId = uuid.NewV4().String()
Dial(msg, true)
msg.Type = types.PERSONHELLO
msg.Data = ""
msg.From = config.ServerInfo.Token
msg.To = list[i].Token
msg.UUId = uuid.NewV4().String()
if _, ok := UDPAddressMap[list[i].Token]; ok {
go Dial(msg, false)
}
go func(shareId string) {
user := MyService.Casa().GetUserInfoByShareId(shareId)
m := model2.FriendModel{}
m.Token = shareId
friend := MyService.Friend().GetFriendById(m)
if friend.Version != user.Version {
friend.Avatar = user.Avatar
friend.NickName = user.NickName
friend.Profile = user.Desc
friend.Version = user.Version
MyService.Friend().UpdateOrCreate(friend)
}
}(list[i].Token)
} }
return false
} }

View File

@ -86,6 +86,16 @@ func (c *zima) GetDiskInfo() *disk.UsageStat {
//获取硬盘目录 //获取硬盘目录
func (c *zima) GetDirPath(path string) []model.Path { func (c *zima) GetDirPath(path string) []model.Path {
if path == "/DATA" {
sysType := runtime.GOOS
if sysType == "windows" {
path = "C:\\CasaOS\\DATA"
}
if sysType == "darwin" {
path = "./CasaOS/DATA"
}
}
ls, _ := ioutil.ReadDir(path) ls, _ := ioutil.ReadDir(path)
dirs := []model.Path{} dirs := []model.Path{}

View File

@ -1 +0,0 @@
package types

7
types/friend.go Normal file
View File

@ -0,0 +1,7 @@
package types
const (
FRIENDSTATEDEFAULT = iota
FRIENDSTATEWAIT
FRIENDSTATEREQUEST
)

View File

@ -12,6 +12,7 @@ const (
NOTIFY_TYPE_INSTALL_LOG NOTIFY_TYPE_INSTALL_LOG
NOTIFY_TYPE_PERSION_FIRNED_LEAVE NOTIFY_TYPE_PERSION_FIRNED_LEAVE
NOTIFY_TYPE_PERSION_FIRNED_LIVE NOTIFY_TYPE_PERSION_FIRNED_LIVE
NOTIFY_TYPE_HEALTH_CHECK
) )
const ( const (

View File

@ -1,9 +1,24 @@
package types package types
const PERSONADDFRIEND = "add_user" const PERSONADDFRIEND = "add_user"
const PERSONAGREEFRIEND = "agree_user"
const PERSONDOWNLOAD = "file_data" const PERSONDOWNLOAD = "file_data"
const PERSONSUMMARY = "summary" const PERSONSUMMARY = "summary"
const PERSONGETIP = "get_ip"
const PERSONCONNECTION = "connection" const PERSONCONNECTION = "connection"
const PERSONDIRECTORY = "directory" const PERSONDIRECTORY = "directory"
const PERSONHELLO = "hello" const PERSONHELLO = "hello"
const PERSONSHAREID = "share_id"
const PERSONUPLOAD = "upload"
const PERSONUPLOADDATA = "upload_data"
const PERSONINTERNALINSPECTION = "internal_inspection"
const PERSONPING = "ping"
const PERSONIMAGETHUMBNAIL = "image_thumbnail"
const PERSONCANCEL = "cancel" // Cancel Download const PERSONCANCEL = "cancel" // Cancel Download
const (
PERSONFILEDOWNLOAD = iota //default state
PERSONFILEUPLOAD
PERSONFILERECEIVEUPLOAD //receive upload file
)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long