Преглед изворни кода

filter list managment mvp

tags/v0.5.0
Jonathan Cobb пре 5 година
родитељ
комит
d7c281f20c
10 измењених фајлова са 97 додато и 17 уклоњено
  1. +60
    -4
      bubble-server/src/main/java/bubble/app/bblock/BubbleBlockAppConfigDriver.java
  2. +1
    -0
      bubble-server/src/main/java/bubble/model/app/config/AppConfigAction.java
  3. +3
    -0
      bubble-server/src/main/java/bubble/rule/bblock/BubbleBlockList.java
  4. +8
    -3
      bubble-server/src/main/java/bubble/rule/bblock/BubbleBlockRuleDriver.java
  5. +1
    -1
      bubble-server/src/main/java/bubble/service/stream/RuleEngineService.java
  6. +0
    -0
      bubble-server/src/main/resources/bubble/rule/bblock/BubbleBlockRuleDriver.js.hbs
  7. +4
    -0
      bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties
  8. +18
    -7
      bubble-server/src/main/resources/models/apps/bubble_block/bubbleApp_bubbleBlock.json
  9. +1
    -1
      bubble-web
  10. +1
    -1
      utils/abp-parser

+ 60
- 4
bubble-server/src/main/java/bubble/app/bblock/BubbleBlockAppConfigDriver.java Прегледај датотеку

@@ -1,19 +1,24 @@
package bubble.app.bblock;

import bubble.abp.BlockDecision;
import bubble.abp.BlockListSource;
import bubble.abp.BlockSpec;
import bubble.dao.app.AppRuleDAO;
import bubble.dao.app.RuleDriverDAO;
import bubble.model.account.Account;
import bubble.model.app.AppMatcher;
import bubble.model.app.AppRule;
import bubble.model.app.BubbleApp;
import bubble.model.app.RuleDriver;
import bubble.model.app.config.AppConfigDriver;
import bubble.model.device.Device;
import bubble.rule.bblock.BubbleBlockConfig;
import bubble.rule.bblock.BubbleBlockList;
import bubble.rule.bblock.BubbleBlockRuleDriver;
import bubble.server.BubbleConfiguration;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.string.ValidationRegexes;
import org.cobbzilla.wizard.validation.ValidationResult;
import org.springframework.beans.factory.annotation.Autowired;

@@ -25,6 +30,10 @@ import java.util.stream.Collectors;

import static java.util.Collections.emptyList;
import static org.cobbzilla.util.daemon.ZillaRuntime.*;
import static org.cobbzilla.util.http.HttpSchemes.SCHEME_HTTPS;
import static org.cobbzilla.util.http.HttpSchemes.isHttpOrHttps;
import static org.cobbzilla.util.http.URIUtil.getHost;
import static org.cobbzilla.util.http.URIUtil.getPath;
import static org.cobbzilla.util.json.JsonUtil.json;
import static org.cobbzilla.util.string.ValidationRegexes.HTTPS_PATTERN;
import static org.cobbzilla.util.string.ValidationRegexes.HTTP_PATTERN;
@@ -38,9 +47,12 @@ public class BubbleBlockAppConfigDriver implements AppConfigDriver {
public static final String VIEW_manageLists = "manageLists";
public static final String VIEW_manageList = "manageList";
public static final String VIEW_manageRules = "manageRules";
public static final AppMatcher TEST_MATCHER = new AppMatcher();
public static final Device TEST_DEVICE = new Device();

@Autowired private RuleDriverDAO driverDAO;
@Autowired private AppRuleDAO ruleDAO;
@Autowired private BubbleConfiguration configuration;

@Override public Object getView(Account account, BubbleApp app, String view, Map<String, String> params) {
final String id = params.get(PARAM_ID);
@@ -114,10 +126,12 @@ public class BubbleBlockAppConfigDriver implements AppConfigDriver {
public static final String ACTION_updateList = "updateList";
public static final String ACTION_createRule = "createRule";
public static final String ACTION_removeRule = "removeRule";
public static final String ACTION_test_url = "test_url";
public static final String ACTION_testUrl = "testUrl";

public static final String PARAM_URL = "url";
public static final String PARAM_RULE = "rule";
public static final String PARAM_TEST_URL = "testUrl";
public static final String PARAM_TEST_URL_PRIMARY = "testUrlPrimary";

@Override public Object takeAppAction(Account account,
BubbleApp app,
@@ -130,10 +144,47 @@ public class BubbleBlockAppConfigDriver implements AppConfigDriver {
return addList(account, app, data);
case ACTION_createRule:
return addRule(account, app, params, data);
case ACTION_testUrl:
return testUrl(account, app, data);
}
throw notFoundEx(action);
}

private BubbleBlockList testUrl(Account account, BubbleApp app, JsonNode data) {
final JsonNode testUrlNode = data.get(PARAM_TEST_URL);
if (testUrlNode == null || empty(testUrlNode.textValue())) throw invalidEx("err.testUrl.required");
String testUrl = testUrlNode.textValue();

final JsonNode testUrlPrimaryNode = data.get(PARAM_TEST_URL_PRIMARY);
final boolean primary = testUrlPrimaryNode == null || testUrlPrimaryNode.booleanValue();

if (!isHttpOrHttps(testUrl)) testUrl = SCHEME_HTTPS + testUrl;

final String host;
final String path;
try {
host = getHost(testUrl);
path = getPath(testUrl);
} catch (Exception e) {
throw invalidEx("err.testUrl.invalid", "Test URL was not valid", shortError(e));
}
if (empty(host) || !ValidationRegexes.HOST_PATTERN.matcher(host).matches()) {
throw invalidEx("err.testUrl.invalidHostname", "Test URL was not valid");
}

try {
final AppRule rule = loadRule(account, app);
final RuleDriver ruleDriver = loadDriver(account, rule);
final BubbleBlockRuleDriver unwiredDriver = (BubbleBlockRuleDriver) rule.initDriver(ruleDriver, TEST_MATCHER, account, TEST_DEVICE);
final BubbleBlockRuleDriver driver = configuration.autowire(unwiredDriver);
final BlockDecision decision = driver.getDecision(host, path, primary);
return getBuiltinList(account, app).setResponse(decision);

} catch (Exception e) {
throw invalidEx("err.testRule.loadingTestDriver", "Error loading test driver", shortError(e));
}
}

private BubbleBlockList addRule(Account account, BubbleApp app, Map<String, String> params, JsonNode data) {

final String id = params.get(PARAM_ID);
@@ -151,7 +202,8 @@ public class BubbleBlockAppConfigDriver implements AppConfigDriver {
}
}
try {
BlockSpec.parse(line);
final List<BlockSpec> specs = BlockSpec.parse(line);
if (log.isDebugEnabled()) log.debug("addRule: parsed line ("+line+"): "+json(specs));
} catch (Exception e) {
log.warn("addRule: invalid line ("+line+"): "+shortError(e));
throw invalidEx("err.rule.invalid", "Error parsing rule", e.getMessage());
@@ -233,11 +285,15 @@ public class BubbleBlockAppConfigDriver implements AppConfigDriver {
}

private BubbleBlockList removeRule(Account account, BubbleApp app, String id) {
final BubbleBlockList builtin = getBuiltinList(account, app);
return updateList(builtin.removeRule(id));
}

private BubbleBlockList getBuiltinList(Account account, BubbleApp app) {
final List<BubbleBlockList> customLists = loadAllLists(account, app).stream().filter(list -> !list.hasUrl()).collect(Collectors.toList());
if (customLists.isEmpty()) throw invalidEx("err.removeRule.noCustomList");
if (customLists.size() > 1) throw invalidEx("err.removeRule.multipleCustomLists");
final BubbleBlockList builtin = customLists.get(0);
return updateList(builtin.removeRule(id));
return customLists.get(0);
}

private ValidationResult validate(BubbleBlockList list, BubbleBlockList request, List<BubbleBlockList> allLists) {


+ 1
- 0
bubble-server/src/main/java/bubble/model/app/config/AppConfigAction.java Прегледај датотеку

@@ -12,6 +12,7 @@ public class AppConfigAction {
@Getter @Setter private String when;
@Getter @Setter private String view;
@Getter @Setter private String successView;
@Getter @Setter private String successMessage;
@Getter @Setter private Integer index = 0;

@Getter @Setter private String[] params;


+ 3
- 0
bubble-server/src/main/java/bubble/rule/bblock/BubbleBlockList.java Прегледај датотеку

@@ -11,6 +11,7 @@ import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.ArrayUtil;

import javax.persistence.Transient;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -66,6 +67,8 @@ public class BubbleBlockList {

@JsonIgnore @Getter @Setter private AppRule rule;

@Transient @Getter @Setter private Object response; // non-standard config response (test URL) uses this

public boolean hasEntry(String line) {
return hasAdditionalEntries() && Arrays.asList(getAdditionalEntries()).contains(line);
}


+ 8
- 3
bubble-server/src/main/java/bubble/rule/bblock/BubbleBlockRuleDriver.java Прегледај датотеку

@@ -75,13 +75,14 @@ public class BubbleBlockRuleDriver extends TrafficAnalyticsRuleDriver {
}
}
if (list.hasAdditionalEntries()) {
if (blockListSource == null) blockListSource = new BlockListSource(); // might be built-in source
try {
blockListSource.addEntries(list.getAdditionalEntries());
} catch (IOException e) {
log.error("init: error adding additional entries: "+shortError(e));
}
}
blockList.merge(blockListSource.getBlockList());
if (blockListSource != null) blockList.merge(blockListSource.getBlockList());
}
}

@@ -95,7 +96,7 @@ public class BubbleBlockRuleDriver extends TrafficAnalyticsRuleDriver {
final String site = ruleHarness.getMatcher().getSite();
final String fqdn = filter.getFqdn();

final BlockDecision decision = blockList.getDecision(filter.getFqdn(), filter.getUri());
final BlockDecision decision = getDecision(filter.getFqdn(), filter.getUri());
switch (decision.getDecisionType()) {
case block:
incrementCounters(account, device, app, site, fqdn);
@@ -107,6 +108,10 @@ public class BubbleBlockRuleDriver extends TrafficAnalyticsRuleDriver {
}
}

public BlockDecision getDecision(String fqdn, String uri) { return blockList.getDecision(fqdn, uri, false); }

public BlockDecision getDecision(String fqdn, String uri, boolean primary) { return blockList.getDecision(fqdn, uri, primary); }

public FilterMatchResponse getFilterMatchResponse(FilterMatchersRequest filter, BlockDecision decision) {
switch (decision.getDecisionType()) {
case block: return FilterMatchResponse.ABORT_NOT_FOUND;
@@ -144,7 +149,7 @@ public class BubbleBlockRuleDriver extends TrafficAnalyticsRuleDriver {
}

// Now that we know the content type, re-check the BlockList
final BlockDecision decision = blockList.getDecision(request.getFqdn(), request.getUri(), contentType);
final BlockDecision decision = blockList.getDecision(request.getFqdn(), request.getUri(), contentType, true);
switch (decision.getDecisionType()) {
case block:
log.warn("doFilterRequest: preprocessed request was filtered, but ultimate decision was block, returning EMPTY_STREAM");


+ 1
- 1
bubble-server/src/main/java/bubble/service/stream/RuleEngineService.java Прегледај датотеку

@@ -212,7 +212,7 @@ public class RuleEngineService {
for (AppRuleHarness h : rules) {
final RuleDriver ruleDriver = driverDAO.findByUuid(h.getRule().getDriver());
if (ruleDriver == null) {
log.warn("get: driver not found: "+h.getRule().getDriver());
log.warn("initRules: driver not found: "+h.getRule().getDriver());
continue;
}
final AppRuleDriver unwiredDriver = h.getRule().initDriver(ruleDriver, h.getMatcher(), account, device);


bubble-server/src/main/resources/bubble/rule/bblock/BubbleBlock.js.hbs → bubble-server/src/main/resources/bubble/rule/bblock/BubbleBlockRuleDriver.js.hbs Прегледај датотеку


+ 4
- 0
bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties Прегледај датотеку

@@ -614,6 +614,10 @@ err.suspended.cannotSuspendSelf=You cannot suspend yourself
err.tag.invalid=Tag is invalid
err.tagsJson.length=Too many tags
err.tagString.length=Too many tags
err.testUrl.required=URL is required
err.testUrl.loadingTestDriver=Error loading test driver
err.testUrl.invalid=URL is invalid
err.testUrl.invalidHostname=URL did not have a valid hostname
err.tgzB64.invalid.noRolesDir=No roles directory found in tgz
err.tgzB64.invalid.wrongNumberOfFiles=Wrong number of files in tgz base directory
err.tgzB64.invalid.missingTasksMainYml=No tasks/main.yml file found for role in tgz


+ 18
- 7
bubble-server/src/main/resources/models/apps/bubble_block/bubbleApp_bubbleBlock.json Прегледај датотеку

@@ -28,12 +28,13 @@
{"name": "name"},
{"name": "description", "control": "textarea"},
{"name": "url", "type": "http_url"},
{"name": "testUrl", "type": "http_url"},
{"name": "tags"},
{"name": "tagString"},
{"name": "enabled", "type": "flag", "mode": "readOnly"},
{"name": "rule"},
{"name": "ruleType", "mode": "readOnly"}
{"name": "ruleType", "mode": "readOnly"},
{"name": "testUrl", "type": "http_url"},
{"name": "testUrlPrimary", "type": "flag"}
],
"configViews": [{
"name": "manageLists",
@@ -53,8 +54,9 @@
},
{
"name": "testUrl", "scope": "app", "index": 20,
"params": ["testUrl"],
"button": "testUrl"
"params": ["testUrl", "testUrlPrimary"],
"button": "testUrl",
"successMessage": "response.decisionType"
}
]
}, {
@@ -81,8 +83,9 @@
},
{
"name": "testUrl", "scope": "app", "index": 20,
"params": ["testUrl"],
"button": "testUrl"
"params": ["testUrl", "testUrlPrimary"],
"button": "testUrl",
"successMessage": "decisionType"
}
]
}]
@@ -159,6 +162,8 @@
{"name": "config.field.ruleType", "value": "Rule Type"},
{"name": "config.field.testUrl", "value": "Test URL"},
{"name": "config.field.testUrl.description", "value": "URL to check against filters"},
{"name": "config.field.testUrlPrimary", "value": "Primary"},
{"name": "config.field.testUrlPrimary.description", "value": "A primary request will receive either an ALLOW or BLOCK decision from your Bubble. A non-primary request (for example a request for a webpage) may additionally receive a FILTER decision. This means the request will be permitted, but the response will be instrumented with Bubble filters to remove ads, malware and blocked elements."},

{"name": "config.action.enableList", "value": "Enable"},
{"name": "config.action.disableList", "value": "Disable"},
@@ -172,7 +177,13 @@
{"name": "config.action.createRule", "value": "Add New Rule"},
{"name": "config.button.createRule", "value": "Add"},
{"name": "config.action.testUrl", "value": "Test URL"},
{"name": "config.button.testUrl", "value": "Test"}
{"name": "config.button.testUrl", "value": "Test"},
{"name": "config.response.block", "value": "Block"},
{"name": "config.response.block.description", "value": "Requests to this URL would be blocked by your Bubble"},
{"name": "config.response.allow", "value": "Allow"},
{"name": "config.response.allow.description", "value": "Requests to this URL would be allowed by your Bubble, and would not be filtered"},
{"name": "config.response.filter", "value": "Filter"},
{"name": "config.response.filter.description", "value": "Requests to this URL would be allowed by your Bubble, but would be filtered"}
]
}]
}

+ 1
- 1
bubble-web

@@ -1 +1 @@
Subproject commit 66eab3f6c7013af92ab0aa8e0bd24855edaf986a
Subproject commit e25dbdfc8a4d6e617b17a4e5347d0cd143425576

+ 1
- 1
utils/abp-parser

@@ -1 +1 @@
Subproject commit 3922106b4227b8fa2e77eeea113e5cba2308c08b
Subproject commit 5f96e9be2a720925347ba65c866a1cee2cdb4cd5

Loading…
Откажи
Сачувај