@@ -55,6 +55,8 @@ class Rerouter: | |||||
if re.match(m['urlRegex'], flow.request.path): | if re.match(m['urlRegex'], flow.request.path): | ||||
bubble_log('get_matchers: rule matched, adding rule: '+m['rule']) | bubble_log('get_matchers: rule matched, adding rule: '+m['rule']) | ||||
matcher_ids.append(m['uuid']) | matcher_ids.append(m['uuid']) | ||||
else: | |||||
bubble_log('get_matchers: rule (regex='+m['urlRegex']+') did NOT match, skipping rule: '+m['rule']) | |||||
matcher_response = { 'matchers': matcher_ids, 'request_id': req_id } | matcher_response = { 'matchers': matcher_ids, 'request_id': req_id } | ||||
bubble_log("get_matchers: returning "+repr(matcher_response)) | bubble_log("get_matchers: returning "+repr(matcher_response)) | ||||
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; | |||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||
import lombok.Setter; | import lombok.Setter; | ||||
import lombok.ToString; | |||||
import lombok.experimental.Accessors; | import lombok.experimental.Accessors; | ||||
import org.cobbzilla.util.collection.ArrayUtil; | import org.cobbzilla.util.collection.ArrayUtil; | ||||
import org.cobbzilla.util.collection.HasPriority; | import org.cobbzilla.util.collection.HasPriority; | ||||
@@ -28,7 +29,7 @@ import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_PAD; | |||||
@ECType(root=true) | @ECType(root=true) | ||||
@ECTypeURIs(baseURI=EP_MATCHERS, listFields={"name", "app", "fqdn", "urlRegex", "rule"}) | @ECTypeURIs(baseURI=EP_MATCHERS, listFields={"name", "app", "fqdn", "urlRegex", "rule"}) | ||||
@Entity @NoArgsConstructor @Accessors(chain=true) | |||||
@Entity @NoArgsConstructor @Accessors(chain=true) @ToString | |||||
@ECIndexes({ | @ECIndexes({ | ||||
@ECIndex(unique=true, of={"account", "app", "name"}), | @ECIndex(unique=true, of={"account", "app", "name"}), | ||||
@ECIndex(of={"account", "name"}), | @ECIndex(of={"account", "name"}), | ||||
@@ -7,6 +7,7 @@ import bubble.model.account.HasAccount; | |||||
import bubble.model.account.HasAccountNoName; | import bubble.model.account.HasAccountNoName; | ||||
import bubble.server.BubbleConfiguration; | import bubble.server.BubbleConfiguration; | ||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.glassfish.grizzly.http.server.Request; | import org.glassfish.grizzly.http.server.Request; | ||||
import org.glassfish.jersey.server.ContainerRequest; | import org.glassfish.jersey.server.ContainerRequest; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -23,6 +24,7 @@ import static org.cobbzilla.wizard.resources.ResourceUtil.*; | |||||
@Consumes(APPLICATION_JSON) | @Consumes(APPLICATION_JSON) | ||||
@Produces(APPLICATION_JSON) | @Produces(APPLICATION_JSON) | ||||
@Slf4j | |||||
public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwnedEntityDAO<E>> { | public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwnedEntityDAO<E>> { | ||||
@Autowired protected AccountDAO accountDAO; | @Autowired protected AccountDAO accountDAO; | ||||
@@ -123,6 +125,7 @@ public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwned | |||||
public Response create(@Context Request req, | public Response create(@Context Request req, | ||||
@Context ContainerRequest ctx, | @Context ContainerRequest ctx, | ||||
E request) { | E request) { | ||||
if (request == null) return invalid("err.request.invalid"); | |||||
final Account caller = checkEditable(ctx); | final Account caller = checkEditable(ctx); | ||||
E found = find(ctx, request.getName()); | E found = find(ctx, request.getName()); | ||||
if (found == null) { | if (found == null) { | ||||
@@ -149,13 +152,14 @@ public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwned | |||||
public Response update(@Context ContainerRequest ctx, | public Response update(@Context ContainerRequest ctx, | ||||
@PathParam("id") String id, | @PathParam("id") String id, | ||||
E request) { | E request) { | ||||
if (request == null) return invalid("err.request.invalid"); | |||||
final Account caller = checkEditable(ctx); | final Account caller = checkEditable(ctx); | ||||
E found = find(ctx, id); | E found = find(ctx, id); | ||||
if (found == null) { | if (found == null) { | ||||
found = findAlternateForUpdate(ctx, id); | found = findAlternateForUpdate(ctx, id); | ||||
if (found == null) return notFound(id); | if (found == null) return notFound(id); | ||||
} | } | ||||
if (!(found instanceof HasAccountNoName) && !canChangeName() && request.hasName() && !found.getName().equals(request.getName())) { | |||||
if (!(found instanceof HasAccountNoName) && !canChangeName() && request.hasName() && !request.getName().equals(found.getName())) { | |||||
return notFound(id+"/"+request.getName()); | return notFound(id+"/"+request.getName()); | ||||
} | } | ||||
@@ -144,8 +144,8 @@ public class FilterHttpResource { | |||||
if (device == null) { | if (device == null) { | ||||
if (log.isDebugEnabled()) log.debug(prefix+"device not found for IP "+vpnAddr+", returning no matchers"); | if (log.isDebugEnabled()) log.debug(prefix+"device not found for IP "+vpnAddr+", returning no matchers"); | ||||
return ok(NO_MATCHERS); | return ok(NO_MATCHERS); | ||||
} else if (log.isDebugEnabled()) { | |||||
log.debug(prefix+"found device "+device.id()+" for IP "+vpnAddr); | |||||
} else if (log.isTraceEnabled()) { | |||||
log.trace(prefix+"found device "+device.id()+" for IP "+vpnAddr); | |||||
} | } | ||||
filterRequest.setDevice(device.getUuid()); | filterRequest.setDevice(device.getUuid()); | ||||
final FilterMatchersResponse response = getMatchersResponse(filterRequest, req, request); | final FilterMatchersResponse response = getMatchersResponse(filterRequest, req, request); | ||||
@@ -188,6 +188,8 @@ public class FilterHttpResource { | |||||
case no_match: break; | case no_match: break; | ||||
case match: retainMatchers.put(matcher.getUuid(), matcher); break; | case match: retainMatchers.put(matcher.getUuid(), matcher); break; | ||||
} | } | ||||
} else { | |||||
if (log.isDebugEnabled()) log.debug(prefix+"matcher "+matcher.getName()+" with pattern "+matcher.getUrlRegex()+" did NOT match uri: '"+uri+"'"); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -208,6 +210,7 @@ public class FilterHttpResource { | |||||
if (log.isTraceEnabled()) log.trace(prefix+"checking all enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER)); | if (log.isTraceEnabled()) log.trace(prefix+"checking all enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER)); | ||||
matchers = matchers.stream() | matchers = matchers.stream() | ||||
.filter(m -> appDAO.findByAccountAndId(accountUuid, m.getApp()).enabled()).collect(Collectors.toList()); | .filter(m -> appDAO.findByAccountAndId(accountUuid, m.getApp()).enabled()).collect(Collectors.toList()); | ||||
if (log.isTraceEnabled()) log.trace(prefix+"after removing disabled apps, enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER)); | |||||
matchers = matchers.stream() | matchers = matchers.stream() | ||||
.filter(m -> { | .filter(m -> { | ||||
final AppSite site = siteDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getSite()); | final AppSite site = siteDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getSite()); | ||||
@@ -217,6 +220,7 @@ public class FilterHttpResource { | |||||
} | } | ||||
return site.enabled(); | return site.enabled(); | ||||
}).collect(Collectors.toList()); | }).collect(Collectors.toList()); | ||||
if (log.isTraceEnabled()) log.trace(prefix+"after removing disabled sites, enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER)); | |||||
matchers = matchers.stream() | matchers = matchers.stream() | ||||
.filter(m -> { | .filter(m -> { | ||||
final AppRule rule = ruleDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getRule()); | final AppRule rule = ruleDAO.findByAccountAndAppAndId(accountUuid, m.getApp(), m.getRule()); | ||||
@@ -226,7 +230,8 @@ public class FilterHttpResource { | |||||
} | } | ||||
return rule.enabled(); | return rule.enabled(); | ||||
}).collect(Collectors.toList()); | }).collect(Collectors.toList()); | ||||
if (log.isDebugEnabled()) log.debug(prefix+"found "+matchers.size()+" candidate matchers: "+names(matchers)); | |||||
if (log.isTraceEnabled()) log.trace(prefix+"after removing disabled rules, enabled matchers for fqdn: "+json(matchers, COMPACT_MAPPER)); | |||||
else if (log.isDebugEnabled()) log.debug(prefix+"found "+matchers.size()+" candidate matchers: "+names(matchers)); | |||||
return matchers; | return matchers; | ||||
} | } | ||||
@@ -170,7 +170,7 @@ public class BubbleBlockRuleDriver extends TrafficAnalyticsRuleDriver { | |||||
return in; | return in; | ||||
} | } | ||||
final String replacement = "<head><meta charset=\"UTF-8\"><script>" + getBubbleJs(filterRequest.getId(), decision) + "</script>"; | |||||
final String replacement = "<head><script>" + getBubbleJs(filterRequest.getId(), decision) + "</script>"; | |||||
final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement); | final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement); | ||||
final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in, UTF8cs), filter).setMaxMatches(1); | final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in, UTF8cs), filter).setMaxMatches(1); | ||||
if (log.isDebugEnabled()) { | if (log.isDebugEnabled()) { | ||||
@@ -32,7 +32,7 @@ public class JsUserBlockerRuleDriver extends AbstractAppRuleDriver { | |||||
@Override public InputStream doFilterResponse(FilterHttpRequest filterRequest, InputStream in) { | @Override public InputStream doFilterResponse(FilterHttpRequest filterRequest, InputStream in) { | ||||
if (!isHtml(filterRequest.getContentType())) return in; | if (!isHtml(filterRequest.getContentType())) return in; | ||||
final String replacement = "<head><script>" + getBubbleJs(filterRequest.getId()) + "</script>"; | |||||
final String replacement = "<head><meta charset=\"UTF-8\"><script>" + getBubbleJs(filterRequest.getId()) + "</script>"; | |||||
final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement); | final RegexReplacementFilter filter = new RegexReplacementFilter("<head>", replacement); | ||||
final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in), filter).setMaxMatches(1); | final RegexFilterReader reader = new RegexFilterReader(new InputStreamReader(in), filter).setMaxMatches(1); | ||||
return new ReaderInputStream(reader, UTF8cs); | return new ReaderInputStream(reader, UTF8cs); | ||||
@@ -1,7 +1,7 @@ | |||||
let {{JS_PREFIX}}_doc_ready = false; | let {{JS_PREFIX}}_doc_ready = false; | ||||
const {{JS_PREFIX}}_request_id = '{{BUBBLE_REQUEST_ID}}'; | const {{JS_PREFIX}}_request_id = '{{BUBBLE_REQUEST_ID}}'; | ||||
const {{JS_PREFIX}}_interval = 50; | const {{JS_PREFIX}}_interval = 50; | ||||
const {{JS_PREFIX}}_idle_interval = 1000; | |||||
const {{JS_PREFIX}}_idle_interval = 5000; | |||||
const {{JS_PREFIX}}_blacklist = {{{BUBBLE_BLACKLIST_JSON}}}; | const {{JS_PREFIX}}_blacklist = {{{BUBBLE_BLACKLIST_JSON}}}; | ||||
const {{JS_PREFIX}}_whitelist = {{{BUBBLE_WHITELIST_JSON}}}; | const {{JS_PREFIX}}_whitelist = {{{BUBBLE_WHITELIST_JSON}}}; | ||||
@@ -22,7 +22,7 @@ function {{JS_PREFIX}}_consider_block(comments, blocked_users) { | |||||
if (userElement.parentNode.querySelector('.bubble_block') === null) { | if (userElement.parentNode.querySelector('.bubble_block') === null) { | ||||
const blockNode = document.createElement('span'); | const blockNode = document.createElement('span'); | ||||
blockNode.className = "bubble_block"; | blockNode.className = "bubble_block"; | ||||
blockNode.innerHTML = ' [<b><a href="#" onclick="_bubble_block_user(\'' + author.replace("'", "\\\'") + '\'); return false;">X</a></b>] '; | |||||
blockNode.innerHTML = ' [<b><a href="#" onclick="{{JS_PREFIX}}_bubble_block_user(\'' + author.replace("'", "\\\'") + '\'); return false;">X</a></b>] '; | |||||
console.log('inserting block control...'); | console.log('inserting block control...'); | ||||
userElement.parentNode.insertBefore(blockNode, userElement); | userElement.parentNode.insertBefore(blockNode, userElement); | ||||
} | } | ||||
@@ -6,7 +6,7 @@ | |||||
"site": "MarginalRevolution", | "site": "MarginalRevolution", | ||||
"template": true, | "template": true, | ||||
"fqdn": "marginalrevolution.com", | "fqdn": "marginalrevolution.com", | ||||
"urlRegex": "marginalrevolution/20\\d{2}/\\d{2}/\\w+", | |||||
"urlRegex": "(/marginalrevolution)?/20\\d{2}/\\d{2}/\\w+", | |||||
"rule": "mr_user_blocker" | "rule": "mr_user_blocker" | ||||
}, { | }, { | ||||
"name": "MRTestMatcher", | "name": "MRTestMatcher", | ||||