@@ -1,11 +0,0 @@ | |||||
package bubble.abp; | |||||
import com.fasterxml.jackson.annotation.JsonCreator; | |||||
public enum BlockListType { | |||||
ads, malware, privacy, clickbait, gambling, phishing, nsfw, crypto, annoyances, custom; | |||||
@JsonCreator public BlockListType fromString (String v) { return valueOf(v.toLowerCase()); } | |||||
} |
@@ -2,6 +2,7 @@ package bubble.app.analytics; | |||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.app.*; | import bubble.model.app.*; | ||||
import bubble.model.app.config.AppDataView; | |||||
import bubble.model.device.Device; | import bubble.model.device.Device; | ||||
import bubble.rule.analytics.TrafficAnalytics; | import bubble.rule.analytics.TrafficAnalytics; | ||||
import bubble.rule.analytics.TrafficRecord; | import bubble.rule.analytics.TrafficRecord; | ||||
@@ -1,6 +1,7 @@ | |||||
package bubble.model.app; | package bubble.model.app; | ||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.app.config.AppDataView; | |||||
import bubble.model.device.Device; | import bubble.model.device.Device; | ||||
import org.cobbzilla.wizard.dao.SearchResults; | import org.cobbzilla.wizard.dao.SearchResults; | ||||
import org.cobbzilla.wizard.model.search.SearchQuery; | import org.cobbzilla.wizard.model.search.SearchQuery; | ||||
@@ -2,6 +2,7 @@ package bubble.model.app; | |||||
import bubble.dao.app.AppDataDAO; | import bubble.dao.app.AppDataDAO; | ||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.app.config.AppDataView; | |||||
import bubble.model.device.Device; | import bubble.model.device.Device; | ||||
import bubble.service.SearchService; | import bubble.service.SearchService; | ||||
import org.cobbzilla.wizard.cache.redis.RedisService; | import org.cobbzilla.wizard.cache.redis.RedisService; | ||||
@@ -2,6 +2,7 @@ package bubble.model.app; | |||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.account.AccountTemplate; | import bubble.model.account.AccountTemplate; | ||||
import bubble.model.app.config.AppDataConfig; | |||||
import com.fasterxml.jackson.annotation.JsonIgnore; | import com.fasterxml.jackson.annotation.JsonIgnore; | ||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||
@@ -0,0 +1,13 @@ | |||||
package bubble.model.app.config; | |||||
import lombok.Getter; | |||||
import lombok.Setter; | |||||
public class AppConfigAction { | |||||
@Getter @Setter private String name; | |||||
@Getter @Setter private AppConfigActionType type; | |||||
@Getter @Setter private String when; | |||||
@Getter @Setter private String view; | |||||
} |
@@ -0,0 +1,13 @@ | |||||
package bubble.model.app.config; | |||||
import com.fasterxml.jackson.annotation.JsonCreator; | |||||
import static bubble.ApiConstants.enumFromString; | |||||
public enum AppConfigActionType { | |||||
create, update; | |||||
@JsonCreator public static AppConfigActionType fromString(String v) { return enumFromString(AppConfigActionType.class, v); } | |||||
} |
@@ -0,0 +1,14 @@ | |||||
package bubble.model.app.config; | |||||
import lombok.Getter; | |||||
import lombok.Setter; | |||||
public class AppConfigView { | |||||
@Getter @Setter private String name; | |||||
@Getter @Setter private AppConfigViewType type; | |||||
@Getter @Setter private String[] columns; | |||||
@Getter @Setter private AppConfigAction[] actions; | |||||
@Getter @Setter private AppDataField[] fields; | |||||
} |
@@ -0,0 +1,13 @@ | |||||
package bubble.model.app.config; | |||||
import com.fasterxml.jackson.annotation.JsonCreator; | |||||
import static bubble.ApiConstants.enumFromString; | |||||
public enum AppConfigViewType { | |||||
list, item; | |||||
@JsonCreator public static AppConfigViewType fromString (String v) { return enumFromString(AppConfigViewType.class, v); } | |||||
} |
@@ -1,4 +1,4 @@ | |||||
package bubble.model.app; | |||||
package bubble.model.app.config; | |||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.Setter; | import lombok.Setter; |
@@ -1,5 +1,6 @@ | |||||
package bubble.model.app; | |||||
package bubble.model.app.config; | |||||
import bubble.model.app.*; | |||||
import bubble.server.BubbleConfiguration; | import bubble.server.BubbleConfiguration; | ||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.Setter; | import lombok.Setter; | ||||
@@ -7,7 +8,7 @@ import lombok.Setter; | |||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.concurrent.ConcurrentHashMap; | import java.util.concurrent.ConcurrentHashMap; | ||||
import static bubble.model.app.AppDataPresentation.none; | |||||
import static bubble.model.app.config.AppDataPresentation.none; | |||||
import static org.cobbzilla.util.daemon.ZillaRuntime.empty; | import static org.cobbzilla.util.daemon.ZillaRuntime.empty; | ||||
import static org.cobbzilla.util.reflect.ReflectionUtil.instantiate; | import static org.cobbzilla.util.reflect.ReflectionUtil.instantiate; | ||||
@@ -42,6 +43,15 @@ public class AppDataConfig { | |||||
return null; | return null; | ||||
} | } | ||||
@Getter @Setter private AppConfigView[] configViews; | |||||
public boolean hasConfigViews () { return !empty(configViews); } | |||||
public AppConfigView getConfigView(String viewName) { | |||||
if (!hasConfigViews()) return null; | |||||
for (AppConfigView v : getConfigViews()) if (v.getName().equalsIgnoreCase(viewName)) return v; | |||||
return null; | |||||
} | |||||
private final Map<String, AppDataDriver> DRIVER_CACHE = new ConcurrentHashMap<>(); | private final Map<String, AppDataDriver> DRIVER_CACHE = new ConcurrentHashMap<>(); | ||||
public AppDataDriver getDriver(BubbleConfiguration configuration) { | public AppDataDriver getDriver(BubbleConfiguration configuration) { | ||||
return DRIVER_CACHE.computeIfAbsent(getDriverClass(), c -> configuration.autowire(instantiate(c))); | return DRIVER_CACHE.computeIfAbsent(getDriverClass(), c -> configuration.autowire(instantiate(c))); |
@@ -1,4 +1,4 @@ | |||||
package bubble.model.app; | |||||
package bubble.model.app.config; | |||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.Setter; | import lombok.Setter; |
@@ -1,4 +1,4 @@ | |||||
package bubble.model.app; | |||||
package bubble.model.app.config; | |||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.Setter; | import lombok.Setter; |
@@ -1,4 +1,4 @@ | |||||
package bubble.model.app; | |||||
package bubble.model.app.config; | |||||
import com.fasterxml.jackson.annotation.JsonCreator; | import com.fasterxml.jackson.annotation.JsonCreator; | ||||
@@ -1,4 +1,4 @@ | |||||
package bubble.model.app; | |||||
package bubble.model.app.config; | |||||
import lombok.Getter; | import lombok.Getter; | ||||
import lombok.Setter; | import lombok.Setter; |
@@ -3,7 +3,7 @@ package bubble.resources.app; | |||||
import bubble.dao.app.AppSiteDAO; | import bubble.dao.app.AppSiteDAO; | ||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.app.AppDataDriver; | import bubble.model.app.AppDataDriver; | ||||
import bubble.model.app.AppDataView; | |||||
import bubble.model.app.config.AppDataView; | |||||
import bubble.model.app.AppSite; | import bubble.model.app.AppSite; | ||||
import bubble.model.app.BubbleApp; | import bubble.model.app.BubbleApp; | ||||
import bubble.model.device.Device; | import bubble.model.device.Device; | ||||
@@ -2,7 +2,7 @@ package bubble.resources.app; | |||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.app.AppDataDriver; | import bubble.model.app.AppDataDriver; | ||||
import bubble.model.app.AppDataView; | |||||
import bubble.model.app.config.AppDataView; | |||||
import bubble.model.app.BubbleApp; | import bubble.model.app.BubbleApp; | ||||
import bubble.model.device.Device; | import bubble.model.device.Device; | ||||
import bubble.service.cloud.DeviceIdService; | import bubble.service.cloud.DeviceIdService; | ||||
@@ -4,9 +4,9 @@ import bubble.dao.app.AppMatcherDAO; | |||||
import bubble.dao.app.AppRuleDAO; | import bubble.dao.app.AppRuleDAO; | ||||
import bubble.dao.app.BubbleAppDAO; | import bubble.dao.app.BubbleAppDAO; | ||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.app.AppDataConfig; | |||||
import bubble.model.app.config.AppDataConfig; | |||||
import bubble.model.app.AppDataDriver; | import bubble.model.app.AppDataDriver; | ||||
import bubble.model.app.AppDataPresentation; | |||||
import bubble.model.app.config.AppDataPresentation; | |||||
import bubble.model.app.BubbleApp; | import bubble.model.app.BubbleApp; | ||||
import bubble.resources.account.AccountOwnedTemplateResource; | import bubble.resources.account.AccountOwnedTemplateResource; | ||||
import bubble.server.BubbleConfiguration; | import bubble.server.BubbleConfiguration; | ||||
@@ -4,6 +4,9 @@ import bubble.dao.app.AppMessageDAO; | |||||
import bubble.dao.app.BubbleAppDAO; | import bubble.dao.app.BubbleAppDAO; | ||||
import bubble.model.account.Account; | import bubble.model.account.Account; | ||||
import bubble.model.app.*; | import bubble.model.app.*; | ||||
import bubble.model.app.config.AppDataAction; | |||||
import bubble.model.app.config.AppDataConfig; | |||||
import bubble.model.app.config.AppDataView; | |||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.cobbzilla.util.collection.NameAndValue; | import org.cobbzilla.util.collection.NameAndValue; | ||||
import org.cobbzilla.wizard.model.entityconfig.EntityFieldConfig; | import org.cobbzilla.wizard.model.entityconfig.EntityFieldConfig; | ||||
@@ -426,6 +426,7 @@ err.accountPlan.noVerifiedContacts=Cannot proceed, no account contact informatio | |||||
err.admin.cannotRemoveAdminStatusFromSelf=You cannot remove admin status from your own account | err.admin.cannotRemoveAdminStatusFromSelf=You cannot remove admin status from your own account | ||||
err.allowedCountriesJson.length=Allowed countries list is too long | err.allowedCountriesJson.length=Allowed countries list is too long | ||||
err.approval.invalid=Approval cannot proceed | err.approval.invalid=Approval cannot proceed | ||||
err.appMessages.length=App messages maximum length exceeded | |||||
err.authenticator.cannotCreate=Cannot create authenticator | err.authenticator.cannotCreate=Cannot create authenticator | ||||
err.authenticator.configured=Only one authenticator can be configured | err.authenticator.configured=Only one authenticator can be configured | ||||
err.authenticator.invalid=Authenticator data is invalid | err.authenticator.invalid=Authenticator data is invalid | ||||
@@ -28,11 +28,11 @@ | |||||
"type": "list", | "type": "list", | ||||
"columns": ["name", "description", "url", "enabled", "tags"], | "columns": ["name", "description", "url", "enabled", "tags"], | ||||
"actions": [ | "actions": [ | ||||
{"name": "enable", "when": "!item.enabled"}, | |||||
{"name": "disable", "when": "item.enabled"}, | |||||
{"name": "enable_blocklist", "when": "!item.enabled"}, | |||||
{"name": "disable_blocklist", "when": "item.enabled"}, | |||||
{"name": "manage_blocklist", "view": "manage_blocklist"}, | {"name": "manage_blocklist", "view": "manage_blocklist"}, | ||||
{"name": "remove"}, | |||||
{"name": "add", "type": "new", "view": "manage_blocklist"} | |||||
{"name": "remove_blocklist"}, | |||||
{"name": "add_blocklist", "type": "create", "view": "manage_blocklist"} | |||||
] | ] | ||||
}, { | }, { | ||||
"name": "manage_blocklist", | "name": "manage_blocklist", | ||||
@@ -45,26 +45,26 @@ | |||||
{"name": "enabled", "type": "flag"} | {"name": "enabled", "type": "flag"} | ||||
], | ], | ||||
"actions": [ | "actions": [ | ||||
{"name": "enable", "when": "!item.enabled"}, | |||||
{"name": "disable", "when": "item.enabled"}, | |||||
{"name": "remove", "when": "item.id !== null"}, | |||||
{"name": "create", "when": "item.id === null"}, | |||||
{"name": "update", "when": "item.id !== null"}, | |||||
{"name": "manage_entries", "when": "item.id !== null"} | |||||
{"name": "enable_blocklist", "when": "!item.enabled"}, | |||||
{"name": "disable_blocklist", "when": "item.enabled"}, | |||||
{"name": "remove_blocklist", "when": "item.id !== null"}, | |||||
{"name": "create_blocklist", "when": "item.id === null"}, | |||||
{"name": "update_blocklist", "when": "item.id !== null"}, | |||||
{"name": "manage_blocklist_entries", "when": "item.id !== null"} | |||||
] | ] | ||||
}, { | }, { | ||||
"name": "manage_entries", | "name": "manage_entries", | ||||
"type": "list", | "type": "list", | ||||
"columns": ["block_rule"], | "columns": ["block_rule"], | ||||
"actions": [ | "actions": [ | ||||
{"name": "remove"}, | |||||
{"name": "add", "type": "new", "view": "add_entry"} | |||||
{"name": "remove_rule"}, | |||||
{"name": "add_rule", "type": "create", "view": "add_entry"} | |||||
] | ] | ||||
}, { | }, { | ||||
"name": "add_entry", | "name": "add_entry", | ||||
"type": "item", | "type": "item", | ||||
"fields": [ {"name": "block_rule"} ], | "fields": [ {"name": "block_rule"} ], | ||||
"actions": ["create"] | |||||
"actions": ["create_rule"] | |||||
}] | }] | ||||
}, | }, | ||||
"children": { | "children": { | ||||
@@ -122,12 +122,32 @@ | |||||
{"name": "view.last_30_days", "value": "Last 30 Days"}, | {"name": "view.last_30_days", "value": "Last 30 Days"}, | ||||
{"name": "view.last_30_days.ctime.format", "value": "{{MM}} {{d}}, {{YYYY}}"}, | {"name": "view.last_30_days.ctime.format", "value": "{{MM}} {{d}}, {{YYYY}}"}, | ||||
{"name": "list.easylist.name", "value": "EasyList"}, | |||||
{"name": "list.easylist.description", "value": "EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists."}, | |||||
{"name": "list.local.name", "value": "Bubble Custom List"}, | |||||
{"name": "list.local.description", "value": "A place to maintain your own block rules for this Bubble."}, | |||||
{"name": "list.dandelion_sprouts_anti_malware_list.name", "value": "Dandelion Sprout's Anti-Malware List"}, | |||||
{"name": "list.dandelion_sprouts_anti_malware_list.description", "value": "Most anti-malware lists are pretty big and can cover a 5- or 6-digit amount of specific domains. But my list hereby claims to remove more than 25% of all known malware sites with just a 2-digit amount of entries. This is mostly done by blocking top-level domains that have become devastatingly abused by spammers, usually because they allowed for free and uncontrolled domain registrations. There's also additional categories that cover unusual malware and phishing domains that very few other lists seem to cover."} | |||||
{"name": "config.field.name", "value": "Name"}, | |||||
{"name": "config.field.description", "value": "Description"}, | |||||
{"name": "config.field.url", "value": "URL"}, | |||||
{"name": "config.field.tags", "value": "Tags"}, | |||||
{"name": "config.field.tags.description", "value": "A comma-separated list of tags: "}, | |||||
{"name": "config.field.enabled", "value": "Enabled"}, | |||||
{"name": "config.field.block_rule", "value": "Rule"}, | |||||
{"name": "config.action.enable_blocklist", "value": "Enable"}, | |||||
{"name": "config.action.disable_blocklist", "value": "Disable"}, | |||||
{"name": "config.action.manage_blocklist", "value": "Manage List"}, | |||||
{"name": "config.action.remove_blocklist", "value": "Remove List"}, | |||||
{"name": "config.action.add_blocklist", "value": "Add New List"}, | |||||
{"name": "config.action.create_blocklist", "value": "Create List"}, | |||||
{"name": "config.action.update_blocklist", "value": "Update List"}, | |||||
{"name": "config.action.manage_blocklist_entries", "value": "Manage Entries"}, | |||||
{"name": "config.action.remove_rule", "value": "Remove Rule"}, | |||||
{"name": "config.action.add_rule", "value": "Add New Rule"}, | |||||
{"name": "config.action.create_rule", "value": "Create Rule"}, | |||||
{"name": "config.item.easylist.name", "value": "EasyList"}, | |||||
{"name": "config.item.easylist.description", "value": "EasyList is the primary filter list that removes most adverts from international web pages, including unwanted frames, images, and objects. It is the most popular list used by many ad blockers and forms the basis of over a dozen combination and supplementary filter lists."}, | |||||
{"name": "config.item.local.name", "value": "Bubble Custom List"}, | |||||
{"name": "config.item.local.description", "value": "A place to maintain your own block rules for this Bubble."}, | |||||
{"name": "config.item.dandelion_sprouts_anti_malware_list.name", "value": "Dandelion Sprout's Anti-Malware List"}, | |||||
{"name": "config.item.dandelion_sprouts_anti_malware_list.description", "value": "Most anti-malware lists are pretty big and can cover a 5- or 6-digit amount of specific domains. But my list hereby claims to remove more than 25% of all known malware sites with just a 2-digit amount of entries. This is mostly done by blocking top-level domains that have become devastatingly abused by spammers, usually because they allowed for free and uncontrolled domain registrations. There's also additional categories that cover unusual malware and phishing domains that very few other lists seem to cover."} | |||||
] | ] | ||||
}] | }] | ||||
} | } |