client: 1383 Support device identifier - DOT and DOH

This commit is contained in:
Artem Baskal 2020-12-11 17:49:50 +03:00
parent e2738fdf3f
commit 503974c210
7 changed files with 37 additions and 17 deletions

12
client/package-lock.json generated vendored
View File

@ -3066,12 +3066,6 @@
"pkg-up": "^2.0.0"
}
},
"caniuse-lite": {
"version": "1.0.30001062",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001062.tgz",
"integrity": "sha512-ei9ZqeOnN7edDrb24QfJ0OZicpEbsWxv7WusOiQGz/f2SfvBgHHbOEwBJ8HKGVSyx8Z6ndPjxzR6m0NQq+0bfw==",
"dev": true
},
"postcss": {
"version": "7.0.30",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.30.tgz",
@ -3928,9 +3922,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001059",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001059.tgz",
"integrity": "sha512-oOrc+jPJWooKIA0IrNZ5sYlsXc7NP7KLhNWrSGEJhnfSzDvDJ0zd3i6HXsslExY9bbu+x0FQ5C61LcqmPt7bOQ==",
"version": "1.0.30001165",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz",
"integrity": "sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==",
"dev": true
},
"capture-exit": {

View File

@ -32,6 +32,7 @@
"form_error_ip_format": "Invalid IP format",
"form_error_mac_format": "Invalid MAC format",
"form_error_client_id_format": "Invalid client ID format",
"form_error_server_name": "Invalid server name or wildcard certificate",
"form_error_positive": "Must be greater than 0",
"form_error_negative": "Must be equal to 0 or greater",
"range_end_error": "Must be greater than range start",
@ -331,7 +332,7 @@
"encryption_config_saved": "Encryption config saved",
"encryption_server": "Server name",
"encryption_server_enter": "Enter your domain name",
"encryption_server_desc": "In order to use HTTPS, you need to enter the server name that matches your SSL certificate.",
"encryption_server_desc": "In order to use HTTPS, you need to enter the server name that matches your SSL certificate or wildcard certificate. If the field is not set, it will accept TLS connections for any domain.",
"encryption_redirect": "Redirect to HTTPS automatically",
"encryption_redirect_desc": "If checked, AdGuard Home will automatically redirect you from HTTP to HTTPS addresses.",
"encryption_https": "HTTPS port",
@ -387,7 +388,7 @@
"client_edit": "Edit Client",
"client_identifier": "Identifier",
"ip_address": "IP address",
"client_identifier_desc": "Clients can be identified by the IP address, CIDR, MAC address. Please note that using MAC as identifier is possible only if AdGuard Home is also a <0>DHCP server</0>",
"client_identifier_desc": "Clients can be identified by the IP address, CIDR, MAC address or domain. Please note that using MAC as identifier is possible only if AdGuard Home is also a <0>DHCP server</0>",
"form_enter_ip": "Enter IP",
"form_enter_mac": "Enter MAC",
"form_enter_id": "Enter identifier",

View File

@ -50,7 +50,7 @@ const CertificateStatus = ({
{dnsNames && (
<li>
<Trans>encryption_hostnames</Trans>:&nbsp;
{dnsNames}
{dnsNames.join(', ')}
</li>
)}
</Fragment>
@ -65,7 +65,7 @@ CertificateStatus.propTypes = {
subject: PropTypes.string,
issuer: PropTypes.string,
notAfter: PropTypes.string,
dnsNames: PropTypes.string,
dnsNames: PropTypes.arrayOf(PropTypes.string),
};
export default withTranslation()(CertificateStatus);

View File

@ -12,7 +12,7 @@ import {
toNumber,
} from '../../../helpers/form';
import {
validateIsSafePort, validatePort, validatePortQuic, validatePortTLS,
validateServerName, validateIsSafePort, validatePort, validatePortQuic, validatePortTLS,
} from '../../../helpers/validators';
import i18n from '../../../i18n';
import KeyStatus from './KeyStatus';
@ -127,6 +127,7 @@ let Form = (props) => {
placeholder={t('encryption_server_enter')}
onChange={handleChange}
disabled={!isEnabled}
validate={validateServerName}
/>
<div className="form__desc">
<Trans>encryption_server_desc</Trans>
@ -413,7 +414,7 @@ Form.propTypes = {
valid_key: PropTypes.bool,
valid_cert: PropTypes.bool,
valid_pair: PropTypes.bool,
dns_names: PropTypes.string,
dns_names: PropTypes.arrayOf(PropTypes.string),
key_type: PropTypes.string,
issuer: PropTypes.string,
subject: PropTypes.string,

View File

@ -11,15 +11,17 @@ const MOBILE_CONFIG_LINKS = {
DOT: '/apple/dot.mobileconfig',
DOH: '/apple/doh.mobileconfig',
};
/* FIXME: find out `client_id` */
const renderMobileconfigInfo = ({ label, components, server_name }) => <li key={label}>
<Trans components={components}>{label}</Trans>
<ul>
<li>
<a href={getPathWithQueryString(MOBILE_CONFIG_LINKS.DOT, { host: server_name })}
<a href={getPathWithQueryString(MOBILE_CONFIG_LINKS.DOT, { host: server_name, client_id: 'client_id' })}
download>{i18next.t('download_mobileconfig_dot')}</a>
</li>
<li>
<a href={getPathWithQueryString(MOBILE_CONFIG_LINKS.DOH, { host: server_name })}
<a href={getPathWithQueryString(MOBILE_CONFIG_LINKS.DOH, { host: server_name, client_id: 'client_id' })}
download>{i18next.t('download_mobileconfig_doh')}</a>
</li>
</ul>

View File

@ -13,6 +13,10 @@ export const R_MAC = /^((([a-fA-F0-9][a-fA-F0-9]+[-]){5}|([a-fA-F0-9][a-fA-F0-9]
export const R_CIDR_IPV6 = /^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/(12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))$/;
export const R_DOMAIN = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/;
export const R_SERVER_NAME = /^(\*\.)?[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/;
export const R_PATH_LAST_PART = /\/[^/]*$/;
// eslint-disable-next-line no-control-regex

View File

@ -9,6 +9,8 @@ import {
R_URL_REQUIRES_PROTOCOL,
STANDARD_WEB_PORT,
UNSAFE_PORTS,
R_DOMAIN,
R_SERVER_NAME,
} from './constants';
import { getLastIpv4Octet, isValidAbsolutePath } from './form';
@ -71,12 +73,28 @@ export const validateClientId = (value) => {
|| R_MAC.test(formattedValue)
|| R_CIDR.test(formattedValue)
|| R_CIDR_IPV6.test(formattedValue)
|| R_DOMAIN.test(formattedValue)
)) {
return 'form_error_client_id_format';
}
return undefined;
};
/**
* @param value {string}
* @returns {undefined|string}
*/
export const validateServerName = (value) => {
if (!value) {
return undefined;
}
const formattedValue = value ? value.trim() : value;
if (formattedValue && !R_SERVER_NAME.test(formattedValue)) {
return 'form_error_server_name';
}
return undefined;
};
/**
* @param value {string}
* @returns {undefined|string}