Merge pull request #68 in DNS/adguard-dns from feature/357 to master

* commit '8d13770b0d4b6d8fde0a61bbfdaa7bf9817142f6':
  Remove unneeded debug prints
  API filtering/add_url -- accept JSON instead of name=value lines
  Remove unused module
  Send json for addFilter request
  Fix params
  Add name field to the filter subscription dialog
This commit is contained in:
Eugene Bujak 2018-10-11 18:35:30 +03:00
commit fb2d90832c
8 changed files with 63 additions and 102 deletions

View File

@ -1559,6 +1559,7 @@
"version": "6.26.0", "version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"dev": true,
"requires": { "requires": {
"core-js": "^2.4.0", "core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0" "regenerator-runtime": "^0.11.0"
@ -1567,7 +1568,8 @@
"core-js": { "core-js": {
"version": "2.5.7", "version": "2.5.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==",
"dev": true
} }
} }
}, },
@ -3074,15 +3076,6 @@
"sha.js": "^2.4.8" "sha.js": "^2.4.8"
} }
}, },
"create-react-context": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz",
"integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==",
"requires": {
"fbjs": "^0.8.0",
"gud": "^1.0.0"
}
},
"cross-spawn": { "cross-spawn": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@ -6203,11 +6196,6 @@
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
"dev": true "dev": true
}, },
"gud": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
"integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
},
"handle-thing": { "handle-thing": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
@ -9752,11 +9740,6 @@
"integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
"dev": true "dev": true
}, },
"popper.js": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz",
"integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY="
},
"portfinder": { "portfinder": {
"version": "1.0.17", "version": "1.0.17",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz",
@ -12869,19 +12852,6 @@
"raf": "^3.1.0" "raf": "^3.1.0"
} }
}, },
"react-popper": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.0.2.tgz",
"integrity": "sha512-vjZ94ki8sfCAg45MMi4uqnUUWdzbnYkb95sR2+HgiMaAPzQcy4DfDKYtYUOhhE+sdtkufWcUHLv09DmH2Js57w==",
"requires": {
"babel-runtime": "6.x.x",
"create-react-context": "^0.2.1",
"popper.js": "^1.14.1",
"prop-types": "^15.6.1",
"typed-styles": "^0.0.5",
"warning": "^3.0.0"
}
},
"react-redux": { "react-redux": {
"version": "5.0.7", "version": "5.0.7",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
@ -12959,14 +12929,6 @@
"classnames": "^2.2.5" "classnames": "^2.2.5"
} }
}, },
"react-text-mask": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.4.3.tgz",
"integrity": "sha1-mR77QpnjDC5sLEbRP2FxaUY+DS0=",
"requires": {
"prop-types": "^15.5.6"
}
},
"react-transition-group": { "react-transition-group": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz",
@ -13147,7 +13109,8 @@
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.11.1", "version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
"dev": true
}, },
"regenerator-transform": { "regenerator-transform": {
"version": "0.10.1", "version": "0.10.1",
@ -14901,16 +14864,6 @@
} }
} }
}, },
"tabler-react": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/tabler-react/-/tabler-react-1.19.1.tgz",
"integrity": "sha512-dwfG64aCG5QEJ6zINpzDi75iNVTwgFFnOhUDTcvpe2Eqn2ZCpBkVcmG9KlcJqq0xI7/t8GJcvc9osjDqXbbLPg==",
"requires": {
"classnames": "^2.2.5",
"react-popper": "^1.0.0-beta.6",
"react-text-mask": "^5.4.1"
}
},
"tapable": { "tapable": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz",
@ -15153,11 +15106,6 @@
"mime-types": "~2.1.18" "mime-types": "~2.1.18"
} }
}, },
"typed-styles": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.5.tgz",
"integrity": "sha512-ht+rEe5UsdEBAa3gr64+QjUOqjOLJfWLvl5HZR5Ev9uo/OnD3p43wPeFSB1hNFc13GXQF/JU1Bn0YHLUqBRIlw=="
},
"typedarray": { "typedarray": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",

View File

@ -30,7 +30,6 @@
"redux-actions": "^2.4.0", "redux-actions": "^2.4.0",
"redux-thunk": "^2.3.0", "redux-thunk": "^2.3.0",
"svg-url-loader": "^2.3.2", "svg-url-loader": "^2.3.2",
"tabler-react": "^1.10.0",
"tiny-version-compare": "^0.9.1", "tiny-version-compare": "^0.9.1",
"whatwg-fetch": "2.0.3" "whatwg-fetch": "2.0.3"
}, },

View File

@ -398,10 +398,10 @@ export const addFilterRequest = createAction('ADD_FILTER_REQUEST');
export const addFilterFailure = createAction('ADD_FILTER_FAILURE'); export const addFilterFailure = createAction('ADD_FILTER_FAILURE');
export const addFilterSuccess = createAction('ADD_FILTER_SUCCESS'); export const addFilterSuccess = createAction('ADD_FILTER_SUCCESS');
export const addFilter = url => async (dispatch) => { export const addFilter = (url, name) => async (dispatch) => {
dispatch(addFilterRequest()); dispatch(addFilterRequest());
try { try {
await apiClient.addFilter(url); await apiClient.addFilter(url, name);
dispatch(addFilterSuccess(url)); dispatch(addFilterSuccess(url));
dispatch(getFilteringStatus()); dispatch(getFilteringStatus());
} catch (error) { } catch (error) {

View File

@ -167,13 +167,13 @@ export default class Api {
return this.makeRequest(path, method); return this.makeRequest(path, method);
} }
addFilter(url) { addFilter(url, name) {
const { path, method } = this.FILTERING_ADD_FILTER; const { path, method } = this.FILTERING_ADD_FILTER;
const parameter = 'url';
const requestBody = `${parameter}=${url}`;
const config = { const config = {
data: requestBody, data: {
header: { 'Content-Type': 'text/plain' }, name,
url,
},
}; };
return this.makeRequest(path, method, config); return this.makeRequest(path, method, config);
} }

View File

@ -7,12 +7,15 @@ import './Modal.css';
ReactModal.setAppElement('#root'); ReactModal.setAppElement('#root');
export default class Modal extends Component { const initialState = {
state = {
url: '', url: '',
name: '',
isUrlValid: false, isUrlValid: false,
}; };
export default class Modal extends Component {
state = initialState;
// eslint-disable-next-line // eslint-disable-next-line
isUrlValid = url => { isUrlValid = url => {
return R_URL_REQUIRES_PROTOCOL.test(url); return R_URL_REQUIRES_PROTOCOL.test(url);
@ -27,33 +30,48 @@ export default class Modal extends Component {
} }
}; };
handleNameChange = (e) => {
const { value: name } = e.currentTarget;
this.setState({ ...this.state, name });
};
handleNext = () => { handleNext = () => {
this.props.addFilter(this.state.url); this.props.addFilter(this.state.url, this.state.name);
setTimeout(() => { setTimeout(() => {
if (this.props.isFilterAdded) { if (this.props.isFilterAdded) {
this.props.toggleModal(); this.closeModal();
} }
}, 2000); }, 2000);
}; };
closeModal = () => {
this.props.toggleModal();
this.setState({ ...this.state, ...initialState });
}
render() { render() {
const { const {
isOpen, isOpen,
toggleModal,
title, title,
inputDescription, inputDescription,
} = this.props; } = this.props;
const { isUrlValid, url } = this.state; const { isUrlValid, url, name } = this.state;
const inputClass = classnames({ const inputUrlClass = classnames({
'form-control mb-2': true, 'form-control mb-2': true,
'is-invalid': url.length > 0 && !isUrlValid, 'is-invalid': url.length > 0 && !isUrlValid,
'is-valid': url.length > 0 && isUrlValid, 'is-valid': url.length > 0 && isUrlValid,
}); });
const inputNameClass = classnames({
'form-control mb-2': true,
'is-valid': name.length > 0,
});
const renderBody = () => { const renderBody = () => {
if (!this.props.isFilterAdded) { if (!this.props.isFilterAdded) {
return ( return (
<React.Fragment> <React.Fragment>
<input type="text" className={inputClass} placeholder="Enter URL or path" onChange={this.handleUrlChange}/> <input type="text" className={inputNameClass} placeholder="Enter name" onChange={this.handleNameChange} />
<input type="text" className={inputUrlClass} placeholder="Enter URL" onChange={this.handleUrlChange} />
{inputDescription && {inputDescription &&
<div className="description"> <div className="description">
{inputDescription} {inputDescription}
@ -68,21 +86,21 @@ export default class Modal extends Component {
); );
}; };
const isValidForSubmit = !(url.length > 0 && isUrlValid); const isValidForSubmit = !(url.length > 0 && isUrlValid && name.length > 0);
return ( return (
<ReactModal <ReactModal
className="Modal__Bootstrap modal-dialog modal-dialog-centered" className="Modal__Bootstrap modal-dialog modal-dialog-centered"
closeTimeoutMS={0} closeTimeoutMS={0}
isOpen={ isOpen } isOpen={ isOpen }
onRequestClose={toggleModal} onRequestClose={this.closeModal}
> >
<div className="modal-content"> <div className="modal-content">
<div className="modal-header"> <div className="modal-header">
<h4 className="modal-title"> <h4 className="modal-title">
{title} {title}
</h4> </h4>
<button type="button" className="close" onClick={toggleModal}> <button type="button" className="close" onClick={this.closeModal}>
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</button> </button>
</div> </div>
@ -92,7 +110,7 @@ export default class Modal extends Component {
{ {
!this.props.isFilterAdded && !this.props.isFilterAdded &&
<div className="modal-footer"> <div className="modal-footer">
<button type="button" className="btn btn-secondary" onClick={toggleModal}>Cancel</button> <button type="button" className="btn btn-secondary" onClick={this.closeModal}>Cancel</button>
<button type="button" className="btn btn-success" onClick={this.handleNext} disabled={isValidForSubmit}>Add filter</button> <button type="button" className="btn btn-success" onClick={this.handleNext} disabled={isValidForSubmit}>Add filter</button>
</div> </div>
} }

View File

@ -437,6 +437,7 @@ func handleStatsTop(w http.ResponseWriter, r *http.Request) {
func httpError(w http.ResponseWriter, code int, format string, args ...interface{}) { func httpError(w http.ResponseWriter, code int, format string, args ...interface{}) {
text := fmt.Sprintf(format, args...) text := fmt.Sprintf(format, args...)
log.Println(text)
http.Error(w, text, code) http.Error(w, text, code)
} }
@ -705,55 +706,49 @@ func handleFilteringStatus(w http.ResponseWriter, r *http.Request) {
} }
func handleFilteringAddURL(w http.ResponseWriter, r *http.Request) { func handleFilteringAddURL(w http.ResponseWriter, r *http.Request) {
parameters, err := parseParametersFromBody(r.Body) filter := filter{}
err := json.NewDecoder(r.Body).Decode(&filter)
if err != nil { if err != nil {
errortext := fmt.Sprintf("failed to parse parameters from body: %s", err) httpError(w, http.StatusBadRequest, "Failed to parse request body json: %s", err)
log.Println(errortext)
http.Error(w, errortext, 400)
return return
} }
url, ok := parameters["url"] filter.Enabled = true
if !ok { if len(filter.URL) == 0 {
http.Error(w, "URL parameter was not specified", 400) http.Error(w, "URL parameter was not specified", 400)
return return
} }
if valid := govalidator.IsRequestURL(url); !valid { if valid := govalidator.IsRequestURL(filter.URL); !valid {
http.Error(w, "URL parameter is not valid request URL", 400) http.Error(w, "URL parameter is not valid request URL", 400)
return return
} }
// check for duplicates // check for duplicates
for i := range config.Filters { for i := range config.Filters {
filter := &config.Filters[i] if config.Filters[i].URL == filter.URL {
if filter.URL == url { errortext := fmt.Sprintf("Filter URL already added -- %s", filter.URL)
errortext := fmt.Sprintf("Filter URL already added -- %s", url)
log.Println(errortext) log.Println(errortext)
http.Error(w, errortext, http.StatusBadRequest) http.Error(w, errortext, http.StatusBadRequest)
return return
} }
} }
var filter = filter{ ok, err := filter.update(time.Now())
Enabled: true,
URL: url,
}
ok, err = filter.update(time.Now())
if err != nil { if err != nil {
errortext := fmt.Sprintf("Couldn't fetch filter from url %s: %s", url, err) errortext := fmt.Sprintf("Couldn't fetch filter from url %s: %s", filter.URL, err)
log.Println(errortext) log.Println(errortext)
http.Error(w, errortext, http.StatusBadRequest) http.Error(w, errortext, http.StatusBadRequest)
return return
} }
if filter.RulesCount == 0 { if filter.RulesCount == 0 {
errortext := fmt.Sprintf("Filter at url %s has no rules (maybe it points to blank page?)", url) errortext := fmt.Sprintf("Filter at url %s has no rules (maybe it points to blank page?)", filter.URL)
log.Println(errortext) log.Println(errortext)
http.Error(w, errortext, http.StatusBadRequest) http.Error(w, errortext, http.StatusBadRequest)
return return
} }
if !ok { if !ok {
errortext := fmt.Sprintf("Filter at url %s is invalid (maybe it points to blank page?)", url) errortext := fmt.Sprintf("Filter at url %s is invalid (maybe it points to blank page?)", filter.URL)
log.Println(errortext) log.Println(errortext)
http.Error(w, errortext, http.StatusBadRequest) http.Error(w, errortext, http.StatusBadRequest)
return return

View File

@ -242,9 +242,10 @@ func (p *plug) parseEtcHosts(text string) bool {
return false return false
} }
for _, host := range fields[1:] { for _, host := range fields[1:] {
if val, ok := p.hosts[host]; ok { // debug logging for duplicate values, pretty common if you subscribe to many hosts files
log.Printf("warning: host %s already has value %s, will overwrite it with %s", host, val, addr) // if val, ok := p.hosts[host]; ok {
} // log.Printf("warning: host %s already has value %s, will overwrite it with %s", host, val, addr)
// }
p.hosts[host] = addr p.hosts[host] = addr
} }
return true return true
@ -323,7 +324,7 @@ func (p *plug) replaceHostWithValAndReply(ctx context.Context, w dns.ResponseWri
// check if it's a domain name or IP address // check if it's a domain name or IP address
addr := net.ParseIP(val) addr := net.ParseIP(val)
var records []dns.RR var records []dns.RR
log.Println("Will give", val, "instead of", host) // log.Println("Will give", val, "instead of", host) // debug logging
if addr != nil { if addr != nil {
// this is an IP address, return it // this is an IP address, return it
result, err := dns.NewRR(fmt.Sprintf("%s %d A %s", host, p.settings.BlockedTTL, val)) result, err := dns.NewRR(fmt.Sprintf("%s %d A %s", host, p.settings.BlockedTTL, val))

View File

@ -221,7 +221,7 @@ func genericLoader(onEntry func(entry *logEntry) error, needMore func() bool, ti
} }
if now.Sub(entry.Time) > timeWindow { if now.Sub(entry.Time) > timeWindow {
trace("skipping entry") // trace("skipping entry") // debug logging
continue continue
} }