From 5d60bb05ab98c4ed31a9e5a189c4a6dfeb62d817 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 25 Jun 2019 15:55:09 +0300 Subject: [PATCH 1/3] * /control/version.json: add "recheck_now" parameter --- AGHTechDoc.md | 6 +++++- home/control_update.go | 34 ++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index e4462ad9..cfe0304f 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -257,7 +257,11 @@ Server can only auto-update if the current version is equal or higher than `self Request: - GET /control/version.json + POST /control/version.json + + { + "recheck_now": true | false // if false, server will check for a new version data only once in several hours + } Response: diff --git a/home/control_update.go b/home/control_update.go index f910b055..763a0b48 100644 --- a/home/control_update.go +++ b/home/control_update.go @@ -51,6 +51,10 @@ func getVersionResp(data []byte) []byte { return d } +type getVersionJSONRequest struct { + RecheckNow bool `json:"recheck_now"` +} + // Get the latest available version from the Internet func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) { log.Tracef("%s %v", r.Method, r.URL) @@ -60,19 +64,29 @@ func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) { return } - now := time.Now() - controlLock.Lock() - cached := now.Sub(versionCheckLastTime) <= versionCheckPeriod && len(versionCheckJSON) != 0 - data := versionCheckJSON - controlLock.Unlock() - - if cached { - // return cached copy - w.Header().Set("Content-Type", "application/json") - w.Write(getVersionResp(data)) + req := getVersionJSONRequest{} + err := json.NewDecoder(r.Body).Decode(&req) + if err != nil { + httpError(w, http.StatusBadRequest, "JSON parse: %s", err) return } + now := time.Now() + if !req.RecheckNow { + controlLock.Lock() + cached := now.Sub(versionCheckLastTime) <= versionCheckPeriod && len(versionCheckJSON) != 0 + data := versionCheckJSON + controlLock.Unlock() + + if cached { + log.Tracef("Returning cached data") + w.Header().Set("Content-Type", "application/json") + w.Write(getVersionResp(data)) + return + } + } + + log.Tracef("Downloading data from %s", versionCheckURL) resp, err := client.Get(versionCheckURL) if err != nil { httpError(w, http.StatusBadGateway, "Couldn't get version check json from %s: %T %s\n", versionCheckURL, err, err) From 0e9df33a409dbffeb2d5d45b7f31f30587a2e4f7 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Tue, 25 Jun 2019 17:56:50 +0300 Subject: [PATCH 2/3] + client: add button for check updates --- client/src/__locales/en.json | 4 ++- client/src/actions/index.js | 7 +++-- client/src/api/Api.js | 10 +++++-- client/src/components/App/index.js | 3 +- client/src/components/Dashboard/index.js | 22 +++++++++++++-- client/src/components/Header/Header.css | 9 ++++++ client/src/components/Header/Version.js | 31 ++++++++++++++++----- client/src/components/Header/index.js | 12 ++++---- client/src/components/Settings/Settings.css | 7 +++++ client/src/components/ui/Card.css | 15 ---------- client/src/components/ui/Icons.js | 4 +++ client/src/reducers/index.js | 1 + 12 files changed, 88 insertions(+), 37 deletions(-) diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 63301db5..1e66a0e8 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -312,5 +312,7 @@ "access_disallowed_desc": "A list of CIDR or IP addresses. If configured, AdGuard Home will drop requests from these IP addresses.", "access_blocked_title": "Blocked domains", "access_blocked_desc": "Don't confuse this with filters. AdGuard Home will drop DNS queries with these domains in query's question.", - "access_settings_saved": "Access settings successfully saved" + "access_settings_saved": "Access settings successfully saved", + "updates_checked": "Updates successfully checked", + "check_updates_now": "Check updates now" } \ No newline at end of file diff --git a/client/src/actions/index.js b/client/src/actions/index.js index 3ceed2c4..aca824c6 100644 --- a/client/src/actions/index.js +++ b/client/src/actions/index.js @@ -145,11 +145,14 @@ export const getVersionRequest = createAction('GET_VERSION_REQUEST'); export const getVersionFailure = createAction('GET_VERSION_FAILURE'); export const getVersionSuccess = createAction('GET_VERSION_SUCCESS'); -export const getVersion = () => async (dispatch) => { +export const getVersion = (recheck = false) => async (dispatch) => { dispatch(getVersionRequest()); try { - const newVersion = await apiClient.getGlobalVersion(); + const newVersion = await apiClient.getGlobalVersion({ recheck_now: recheck }); dispatch(getVersionSuccess(newVersion)); + if (recheck) { + dispatch(addSuccessToast('updates_checked')); + } } catch (error) { dispatch(addErrorToast({ error })); dispatch(getVersionFailure()); diff --git a/client/src/api/Api.js b/client/src/api/Api.js index ad4e03fb..76b17888 100644 --- a/client/src/api/Api.js +++ b/client/src/api/Api.js @@ -36,7 +36,7 @@ export default class Api { GLOBAL_QUERY_LOG_DISABLE = { path: 'querylog_disable', method: 'POST' }; GLOBAL_SET_UPSTREAM_DNS = { path: 'set_upstreams_config', method: 'POST' }; GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' }; - GLOBAL_VERSION = { path: 'version.json', method: 'GET' }; + GLOBAL_VERSION = { path: 'version.json', method: 'POST' }; GLOBAL_ENABLE_PROTECTION = { path: 'enable_protection', method: 'POST' }; GLOBAL_DISABLE_PROTECTION = { path: 'disable_protection', method: 'POST' }; GLOBAL_UPDATE = { path: 'update', method: 'POST' }; @@ -125,9 +125,13 @@ export default class Api { return this.makeRequest(path, method, config); } - getGlobalVersion() { + getGlobalVersion(data) { const { path, method } = this.GLOBAL_VERSION; - return this.makeRequest(path, method); + const config = { + data, + headers: { 'Content-Type': 'application/json' }, + }; + return this.makeRequest(path, method, config); } enableGlobalProtection() { diff --git a/client/src/components/App/index.js b/client/src/components/App/index.js index f77097a0..6489649c 100644 --- a/client/src/components/App/index.js +++ b/client/src/components/App/index.js @@ -65,8 +65,7 @@ class App extends Component { render() { const { dashboard, encryption } = this.props; - const updateAvailable = - !dashboard.processingVersions && dashboard.isCoreRunning && dashboard.isUpdateAvailable; + const updateAvailable = dashboard.isCoreRunning && dashboard.isUpdateAvailable; return ( diff --git a/client/src/components/Dashboard/index.js b/client/src/components/Dashboard/index.js index 2509b7c7..ad207ba0 100644 --- a/client/src/components/Dashboard/index.js +++ b/client/src/components/Dashboard/index.js @@ -50,8 +50,26 @@ class Dashboard extends Component { dashboard.processingClients || dashboard.processingTopStats; - const refreshFullButton = ; - const refreshButton = + ); + const refreshButton = ( + + ); return ( diff --git a/client/src/components/Header/Header.css b/client/src/components/Header/Header.css index 35e8a3cc..759594ac 100644 --- a/client/src/components/Header/Header.css +++ b/client/src/components/Header/Header.css @@ -75,7 +75,11 @@ } .nav-version__value { + max-width: 110px; font-weight: 600; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } .nav-version__link { @@ -85,6 +89,11 @@ cursor: pointer; } +.nav-version__text { + display: flex; + justify-content: flex-end; +} + .header-brand-img { height: 32px; } diff --git a/client/src/components/Header/Version.js b/client/src/components/Header/Version.js index be2158e9..6ac4f1ab 100644 --- a/client/src/components/Header/Version.js +++ b/client/src/components/Header/Version.js @@ -4,12 +4,26 @@ import { Trans, withNamespaces } from 'react-i18next'; import { getDnsAddress } from '../../helpers/helpers'; -function Version(props) { - const { dnsVersion, dnsAddresses, dnsPort } = props; +const Version = (props) => { + const { + dnsVersion, dnsAddresses, dnsPort, processingVersion, t, + } = props; + return (
- version: {dnsVersion} + version{dnsVersion} +
@@ -17,20 +31,23 @@ function Version(props) {
- {dnsAddresses - .map(ip =>
  • {getDnsAddress(ip, dnsPort)}
  • ) - } + {dnsAddresses.map(ip => ( +
  • {getDnsAddress(ip, dnsPort)}
  • + ))}
    ); -} +}; Version.propTypes = { dnsVersion: PropTypes.string.isRequired, dnsAddresses: PropTypes.array.isRequired, dnsPort: PropTypes.number.isRequired, + getVersion: PropTypes.func.isRequired, + processingVersion: PropTypes.bool.isRequired, + t: PropTypes.func.isRequired, }; export default withNamespaces()(Version); diff --git a/client/src/components/Header/index.js b/client/src/components/Header/index.js index e2d47fe6..07e64241 100644 --- a/client/src/components/Header/index.js +++ b/client/src/components/Header/index.js @@ -23,7 +23,7 @@ class Header extends Component { }; render() { - const { dashboard } = this.props; + const { dashboard, getVersion, location } = this.props; const { isMenuOpen } = this.state; const badgeClass = classnames({ 'badge dns-status': true, @@ -51,7 +51,7 @@ class Header extends Component { } @@ -71,8 +72,9 @@ class Header extends Component { } Header.propTypes = { - dashboard: PropTypes.object, - location: PropTypes.object, + dashboard: PropTypes.object.isRequired, + location: PropTypes.object.isRequired, + getVersion: PropTypes.func.isRequired, }; export default withNamespaces()(Header); diff --git a/client/src/components/Settings/Settings.css b/client/src/components/Settings/Settings.css index 7e410a0c..48acf4eb 100644 --- a/client/src/components/Settings/Settings.css +++ b/client/src/components/Settings/Settings.css @@ -88,3 +88,10 @@ width: 30px; height: 30px; } + +.btn-icon-sm { + width: 23px; + height: 23px; + min-width: 23px; + padding: 5px; +} diff --git a/client/src/components/ui/Card.css b/client/src/components/ui/Card.css index 33b69c2d..6794a791 100644 --- a/client/src/components/ui/Card.css +++ b/client/src/components/ui/Card.css @@ -33,21 +33,6 @@ text-align: center; } -.card-refresh { - height: 26px; - width: 26px; - background-size: 14px; - background-position: center; - background-repeat: no-repeat; - background-image: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiM0NjdmY2YiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMjMgNHY2aC02Ii8+PHBhdGggZD0ibTEgMjB2LTZoNiIvPjxwYXRoIGQ9Im0zLjUxIDlhOSA5IDAgMCAxIDE0Ljg1LTMuMzZsNC42NCA0LjM2bS0yMiA0IDQuNjQgNC4zNmE5IDkgMCAwIDAgMTQuODUtMy4zNiIvPjwvc3ZnPg=="); -} - -.card-refresh:hover, -.card-refresh:not(:disabled):not(.disabled):active, -.card-refresh:focus:active { - background-image: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMjMgNHY2aC02Ii8+PHBhdGggZD0ibTEgMjB2LTZoNiIvPjxwYXRoIGQ9Im0zLjUxIDlhOSA5IDAgMCAxIDE0Ljg1LTMuMzZsNC42NCA0LjM2bS0yMiA0IDQuNjQgNC4zNmE5IDkgMCAwIDAgMTQuODUtMy4zNiIvPjwvc3ZnPg=="); -} - .card-title-stats { font-size: 13px; color: #9aa0ac; diff --git a/client/src/components/ui/Icons.js b/client/src/components/ui/Icons.js index 58a5af9f..92a9efa4 100644 --- a/client/src/components/ui/Icons.js +++ b/client/src/components/ui/Icons.js @@ -55,6 +55,10 @@ const Icons = () => ( + + + + ); diff --git a/client/src/reducers/index.js b/client/src/reducers/index.js index 17d82608..94301e25 100644 --- a/client/src/reducers/index.js +++ b/client/src/reducers/index.js @@ -137,6 +137,7 @@ const dashboard = handleActions({ newVersion, canAutoUpdate, isUpdateAvailable: true, + processingVersion: false, }; return newState; } From d2258cb66de32092f145f2803a7be3d7869970f2 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 27 Jun 2019 10:52:45 +0300 Subject: [PATCH 3/3] * openapi.yaml: update /version.json --- openapi/openapi.yaml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 385ac057..063b85c7 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -135,11 +135,19 @@ paths: "192.168.1.104:53535": "Couldn't communicate with DNS server" /version.json: - get: + post: tags: - global operationId: getVersionJson summary: 'Gets information about the latest available version of AdGuard' + consumes: + - application/json + parameters: + - in: "body" + name: "body" + required: true + schema: + $ref: "#/definitions/GetVersionRequest" produces: - 'application/json' responses: @@ -994,6 +1002,13 @@ definitions: example: - '||example.org^' - '||example.com^' + GetVersionRequest: + type: "object" + description: "/version.json request data" + properties: + recheck_now: + description: "If false, server will check for a new version data only once in several hours" + type: "boolean" VersionInfo: type: "object" description: "Information about the latest available version of AdGuard Home"