diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 36bd3501..25053476 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -223,13 +223,14 @@ "encryption_dot": "DNS-over-TLS port", "encryption_dot_desc": "If this port is configured, AdGuard Home will run a DNS-over-TLS server on this port.", "encryption_certificates": "Certificates", - "encryption_certificates_desc": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on letsencrypt.org or you can buy it from one of the trusted Certificate Authorities.", + "encryption_certificates_desc": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on <0>{{link}} or you can buy it from one of the trusted Certificate Authorities.", "encryption_certificates_input": "Copy/paste your PEM-encoded cerificates here.", "encryption_status": "Status", "encryption_certificates_for": "Certificates for {{domains}}", "encryption_expire": "Expire on {{date}}", "encryption_key": "Private key", "encryption_key_input": "Copy/paste your PEM-encoded private key for your cerficate here.", + "topline_expiring_certificate": "Your SSL certificate is about to expire. Update <0>Encryption settings.", "form_error_port_range": "Enter port value in the range of 80-65535", "form_error_equal": "Shouldn't be equal", "form_error_password": "Password mismatched" diff --git a/client/src/actions/index.js b/client/src/actions/index.js index da33f0fe..30527245 100644 --- a/client/src/actions/index.js +++ b/client/src/actions/index.js @@ -659,6 +659,9 @@ export const getTlsStatus = () => async (dispatch) => { dispatch(getTlsStatusRequest()); try { const status = await apiClient.getTlsStatus(); + status.certificate_chain = decodeURIComponent(status.certificate_chain); + status.private_key = decodeURIComponent(status.private_key); + dispatch(getTlsStatusSuccess(status)); } catch (error) { dispatch(addErrorToast({ error })); @@ -673,7 +676,11 @@ export const setTlsConfigSuccess = createAction('SET_TLS_CONFIG_SUCCESS'); export const setTlsConfig = config => async (dispatch) => { dispatch(setTlsConfigRequest()); try { - await apiClient.setTlsConfig(config); + const values = { ...config }; + values.certificate_chain = encodeURIComponent(values.certificate_chain); + values.private_key = encodeURIComponent(values.private_key); + + await apiClient.setTlsConfig(values); dispatch(setTlsConfigSuccess(config)); dispatch(addSuccessToast('encryption_config_saved')); } catch (error) { diff --git a/client/src/components/App/index.js b/client/src/components/App/index.js index 74bc6960..5bf0f925 100644 --- a/client/src/components/App/index.js +++ b/client/src/components/App/index.js @@ -1,6 +1,7 @@ import React, { Component, Fragment } from 'react'; import { HashRouter, Route } from 'react-router-dom'; import PropTypes from 'prop-types'; +import { Trans, withNamespaces } from 'react-i18next'; import LoadingBar from 'react-redux-loading-bar'; import 'react-table/react-table.css'; @@ -16,7 +17,7 @@ import Logs from '../../containers/Logs'; import Footer from '../ui/Footer'; import Toasts from '../Toasts'; import Status from '../ui/Status'; -import Update from '../ui/Update'; +import Topline from '../ui/Topline'; import i18n from '../../i18n'; class App extends Component { @@ -55,15 +56,22 @@ class App extends Component { !dashboard.processingVersions && dashboard.isCoreRunning && dashboard.isUpdateAvailable; + const isExpiringCertificate = false; return ( {updateAvailable && - + + {dashboard.announcement} Click here for more info. + + } + {isExpiringCertificate && + + link]}> + topline_expiring_certificate + + } @@ -100,6 +108,7 @@ App.propTypes = { error: PropTypes.string, getVersion: PropTypes.func, changeLanguage: PropTypes.func, + encryption: PropTypes.object, }; -export default App; +export default withNamespaces()(App); diff --git a/client/src/components/Settings/Encryption/Form.js b/client/src/components/Settings/Encryption/Form.js index 3c814fad..e58aa8f4 100644 --- a/client/src/components/Settings/Encryption/Form.js +++ b/client/src/components/Settings/Encryption/Form.js @@ -114,7 +114,12 @@ const Form = (props) => { encryption_certificates
- encryption_certificates_desc + link]} + > + encryption_certificates_desc +
{ encryption_status:
- encryption_certificates_for - *.example.org, example.org + + encryption_certificates_for +
- encryption_expire - 2022-01-01 + + encryption_expire +
diff --git a/client/src/components/ui/Update.css b/client/src/components/ui/Topline.css similarity index 89% rename from client/src/components/ui/Update.css rename to client/src/components/ui/Topline.css index ec7ec532..33c4e8fd 100644 --- a/client/src/components/ui/Update.css +++ b/client/src/components/ui/Topline.css @@ -1,4 +1,4 @@ -.update { +.topline { position: relative; z-index: 102; margin-bottom: 0; diff --git a/client/src/components/ui/Topline.js b/client/src/components/ui/Topline.js new file mode 100644 index 00000000..13bfd827 --- /dev/null +++ b/client/src/components/ui/Topline.js @@ -0,0 +1,19 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import './Topline.css'; + +const Topline = props => ( +
+
+ {props.children} +
+
+); + +Topline.propTypes = { + children: PropTypes.node.isRequired, + type: PropTypes.string.isRequired, +}; + +export default Topline; diff --git a/client/src/components/ui/Update.js b/client/src/components/ui/Update.js deleted file mode 100644 index 5df9df65..00000000 --- a/client/src/components/ui/Update.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import './Update.css'; - -const Update = props => ( -
-
- {props.announcement} Click here for more info. -
-
-); - -Update.propTypes = { - announcement: PropTypes.string.isRequired, - announcementUrl: PropTypes.string.isRequired, -}; - -export default Update; diff --git a/client/src/containers/App.js b/client/src/containers/App.js index 905596c5..b6ce2cde 100644 --- a/client/src/containers/App.js +++ b/client/src/containers/App.js @@ -3,8 +3,8 @@ import * as actionCreators from '../actions'; import App from '../components/App'; const mapStateToProps = (state) => { - const { dashboard } = state; - const props = { dashboard }; + const { dashboard, encryption } = state; + const props = { dashboard, encryption }; return props; };