diff --git a/event-management/.gitignore b/event-management/.gitignore index 55c4463ac75a74d2c00337071f348e302204b7ce..f12b562cb4e16a96dcfd6c418613d56089aaa0bc 100644 --- a/event-management/.gitignore +++ b/event-management/.gitignore @@ -1,6 +1,9 @@ .idea broker-client/*.js -config-files/broker*.p12 -config-files/broker*.crt +config-files/*.p12 +config-files/*.crt public_resources/** -tcnative* \ No newline at end of file +tcnative* +ems.log +server.pem +.dev-* \ No newline at end of file diff --git a/event-management/README-for-TESTING.md b/event-management/README-for-TESTING.md index ac63e6ecec8082652ef29542aaf5fa5081c84c4e..af72125b6043893b03deeabb7d84c7bf9d696944 100644 --- a/event-management/README-for-TESTING.md +++ b/event-management/README-for-TESTING.md @@ -52,7 +52,7 @@ We also distinguish between ***Monitoring Topologies***: ## A) Support for Resource-Limited nodes > Feature Quick Notes: > - EMS server will NOT install EMS client and JRE8 in RL nodes. -> - EMS server will install Netda in RL nodes. +> - EMS server will install Netdata in RL nodes. > - EMS server or an Aggregator will periodically query Netdata agents of RL nodes for metrics. > - Normal nodes will periodically query their Local Netdata agent for metrics. @@ -723,7 +723,8 @@ We distinguish between monitoring topologies: ``` *

EMS server log: Aggregator give up message

* ``` - ......................... BUG: No Give up message + e.m.e.b.server.ClientShellCommand : #00000--> Client notification: CMD=RECOVERY, ARGS=GIVE_UP node_3866738cb0f4_2002 @ 192.168.16.4 + e.m.e.b.server.ClientShellCommand : #00000--> Client Recovery Notification: GIVE_UP: node_3866738cb0f4_2002 @ 192.168.16.4 ``` Note: EMS client disconnection from EMS server will also be logged in EMS server logs, but no recovery action will be taken by EMS server. @@ -740,7 +741,7 @@ We distinguish between monitoring topologies: SelfHealingPlugin: Retry #0: Recovering node: id=node_3866738cb0f4_2002, address=192.168.16.4 VmNodeRecoveryTask: connectToNode(): Connecting to node using SSH: address=192.168.16.4, port=22, username=ubuntu Connecting to server... - SelfHealingPlugin: EXCEPTION while recovering node: node-info={random=cecab3d4-4c09-43b1-b6fa-3534d37bbc8f, zone-id=IMU-ZONE, address=192.168.16.4,......................... + SelfHealingPlugin: EXCEPTION while recovering node: node-address=192.168.16.4 -- Exception: java.net.NoRouteToHostException: No route to host at sun.nio.ch.UnixAsynchronousSocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:252) @@ -748,11 +749,12 @@ We distinguish between monitoring topologies: at sun.nio.ch.UnixAsynchronousSocketChannelImpl.onEvent(UnixAsynchronousSocketChannelImpl.java:213) at sun.nio.ch.EPollPort$EventHandlerTask.run(EPollPort.java:293) at java.lang.Thread.run(Thread.java:748) - - SelfHealingPlugin: Retry #0: Recovering node: id=node_3866738cb0f4_2002, address=192.168.16.4 + ......................... + ......................... + SelfHealingPlugin: Retry #3: Recovering node: id=node_3866738cb0f4_2002, address=192.168.16.4 VmNodeRecoveryTask: connectToNode(): Connecting to node using SSH: address=192.168.16.4, port=22, username=ubuntu Connecting to server... - SelfHealingPlugin: EXCEPTION while recovering node: node-info={random=cecab3d4-4c09-43b1-b6fa-3534d37bbc8f, zone-id=IMU-ZONE, address=192.168.16.4,......................... + SelfHealingPlugin: EXCEPTION while recovering node: node-address=192.168.16.4 -- Exception: java.net.NoRouteToHostException: No route to host at sun.nio.ch.UnixAsynchronousSocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:252) @@ -762,7 +764,9 @@ We distinguish between monitoring topologies: at java.lang.Thread.run(Thread.java:748) ``` ``` - ......................... BUG: No Give up message + SelfHealingPlugin: Max retries reached. No more recovery retries for node: id=node_3866738cb0f4_2002, address=192.168.16.4 + SelfHealingPlugin: cancelRecoveryTask(): Cancelled recovery task for Node: id=node_3866738cb0f4_2002, address=192.168.16.4 + NOTIFY-X: RECOVERY GIVE_UP node_3866738cb0f4_2002 @ 192.168.16.4 ``` * ***Normal nodes that operate***, for logs about EMS client leaving cluster, and NO logs about recovery actions or EMS client joining back. @@ -920,7 +924,7 @@ We distinguish between monitoring topologies: **After Application deployment...** - * Terminate the VM of the Aggregator's + * Terminate the VM of the Aggregator **Next, check the logs of:** @@ -934,11 +938,12 @@ We distinguish between monitoring topologies: ``` *

EMS server log: New Aggregator queries for node's credentials

* ``` - e.m.e.b.server.ClientShellCommand : #00004==> PUSH : {"random":"4abf9ae2-b7fc-4e8c-b6d9-464623d1b05f","zone-id":"IMU-ZONE","address":"192.168.16.4","provider":"AWS","name":"vm2","ssh.port":"22","ssh.username":"ubuntu","ssh.password":"ubuntu",......................... + e.m.e.b.server.ClientShellCommand : #00004==> PUSH : {"random":"4abf9ae2-b7fc-4e8c-b6d9-464623d1b05f","zone-id":"IMU-ZONE","address":"192.168.16.4",......................... ``` *

EMS server log: New Aggregator give up message

* ``` - ......................... BUG: No give up message + e.m.e.b.server.ClientShellCommand : #00004--> Client notification: CMD=RECOVERY, ARGS=GIVE_UP node_3866738cb0f4_2002 @ 192.168.16.4 + e.m.e.b.server.ClientShellCommand : #00004--> Client Recovery Notification: GIVE_UP: node_3866738cb0f4_2002 @ 192.168.16.4 ``` Note: Aggregator disconnection from EMS server will also be logged in EMS server logs, but no recovery action will be taken by EMS server. @@ -981,12 +986,12 @@ We distinguish between monitoring topologies: SEND: SERVER-GET-NODE-SSH-CREDENTIALS 192.168.16.4 SelfHealingPlugin: createRecoveryTask(): Created recovery task for Node: id=node_3866738cb0f4_2002, address=192.168.16.4 ``` - *

New Aggregator log: Failing recovery actions of old Aggregator and give up message

* + *

New Aggregator log: Failing recovery actions of old Aggregator

* ``` SelfHealingPlugin: Retry #0: Recovering node: id=node_3866738cb0f4_2002, address=192.168.16.4 VmNodeRecoveryTask: connectToNode(): Connecting to node using SSH: address=192.168.16.4, port=22, username=ubuntu Connecting to server... - SelfHealingPlugin: EXCEPTION while recovering node: node-info={random=4abf9ae2-b7fc-4e8c-b6d9-464623d1b05f, zone-id=IMU-ZONE, address=192.168.16.4,......................... + SelfHealingPlugin: EXCEPTION while recovering node: node-address=192.168.16.4 -- Exception: java.net.NoRouteToHostException: No route to host at sun.nio.ch.UnixAsynchronousSocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:252) @@ -994,11 +999,12 @@ We distinguish between monitoring topologies: at sun.nio.ch.UnixAsynchronousSocketChannelImpl.onEvent(UnixAsynchronousSocketChannelImpl.java:213) at sun.nio.ch.EPollPort$EventHandlerTask.run(EPollPort.java:293) at java.lang.Thread.run(Thread.java:748) - - SelfHealingPlugin: Retry #0: Recovering node: id=node_3866738cb0f4_2002, address=192.168.16.4 + ......................... + ......................... + SelfHealingPlugin: Retry #3: Recovering node: id=node_3866738cb0f4_2002, address=192.168.16.4 VmNodeRecoveryTask: connectToNode(): Connecting to node using SSH: address=192.168.16.4, port=22, username=ubuntu Connecting to server... - SelfHealingPlugin: EXCEPTION while recovering node: node-info={random=4abf9ae2-b7fc-4e8c-b6d9-464623d1b05f, zone-id=IMU-ZONE, address=192.168.16.4,......................... + SelfHealingPlugin: EXCEPTION while recovering node: node-address=192.168.16.4 -- Exception: java.net.NoRouteToHostException: No route to host at sun.nio.ch.UnixAsynchronousSocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:252) @@ -1007,8 +1013,11 @@ We distinguish between monitoring topologies: at sun.nio.ch.EPollPort$EventHandlerTask.run(EPollPort.java:293) at java.lang.Thread.run(Thread.java:748) ``` + *

New Aggregator log: Recovery actions Give Up message

* ``` - ......................... BUG: No give up message + SelfHealingPlugin: Max retries reached. No more recovery retries for node: id=node_3866738cb0f4_2002, address=192.168.16.4 + SelfHealingPlugin: cancelRecoveryTask(): Cancelled recovery task for Node: id=node_3866738cb0f4_2002, address=192.168.16.4 + NOTIFY-X: RECOVERY GIVE_UP node_3866738cb0f4_2002 @ 192.168.16.4 ``` * ***Normal nodes that operate***, for log messages about, (i) EMS client leaving cluster, (ii) Aggregator election, but NO logs about recovery actions, or EMS client joining back to cluster. @@ -1056,7 +1065,7 @@ We distinguish between monitoring topologies: Collectors::Netdata: Collecting data from url: http://192.168.96.2:19999/api/v1/allmetrics?format=json Collectors::Netdata: Exception while collecting metrics from node: 192.168.96.2, #errors=3, exception: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://192.168.96.2:19999/api/v1/allmetrics": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) -> java.net.ConnectException: Connection refused (Connection refused) Collectors::Netdata: Too many consecutive errors occurred while attempting to collect metrics from node: 192.168.96.2, num-of-errors=3 - Collectors::Netdata: Will pause metrics collection from node for 60 seconds: 192.168.96.2 + Collectors::Netdata: Pausing collection from Node: 192.168.96.2 ``` *

Aggregator log: Requesting RL node's credentials

* ``` @@ -1080,11 +1089,14 @@ We distinguish between monitoring topologies: VmNodeRecoveryTask: disconnectFromNode(): Disconnecting from node: address=192.168.96.2, port=22, username=ubuntu Stopping SSH client... SSH client stopped + Collectors::Netdata: Resuming collection from Node: 192.168.96.2 Collectors::Netdata: Collecting metrics from local node... Collectors::Netdata: Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json Collectors::Netdata: Metrics: extracted=0, published=0, failed=0 Collectors::Netdata: Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Collectors::Netdata: Node is in ignore list: 192.168.96.2 + Collectors::Netdata: Collecting data from url: http://192.168.96.2:19999/api/v1/allmetrics?format=json + Collectors::Netdata: Metrics: extracted=0, published=0, failed=0 + SelfHealingPlugin: cancelRecoveryTask(): Cancelled recovery task for Node: id=null, address=192.168.96.2 OUT> Last login: Sat Feb 12 10:40:09 2022 from 172.29.0.4 OUT> OUT> pwd @@ -1113,27 +1125,6 @@ We distinguish between monitoring topologies: ``` *

Aggregator log: Successful metrics collection from RL node's Netdata agent

* ``` - Collectors::Netdata: Collecting metrics from local node... - Collectors::Netdata: Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json - Collectors::Netdata: Metrics: extracted=0, published=0, failed=0 - Collectors::Netdata: Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Collectors::Netdata: Node is in ignore list: 192.168.96.2 - - Collectors::Netdata: Collecting metrics from local node... - Collectors::Netdata: Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json - Collectors::Netdata: Metrics: extracted=0, published=0, failed=0 - Collectors::Netdata: Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Collectors::Netdata: Node is in ignore list: 192.168.96.2 - - Collectors::Netdata: Collecting metrics from local node... - Collectors::Netdata: Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json - Collectors::Netdata: Metrics: extracted=0, published=0, failed=0 - Collectors::Netdata: Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Collectors::Netdata: Node is in ignore list: 192.168.96.2 - - Collectors::Netdata: Resumed metrics collection from node: 192.168.96.2 - SelfHealingPlugin: cancelRecoveryTask(): Cancelled recovery task for Node: id=null, address=192.168.96.2 - Collectors::Netdata: Collecting metrics from local node... Collectors::Netdata: Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json Collectors::Netdata: Metrics: extracted=0, published=0, failed=0 @@ -1179,7 +1170,9 @@ We distinguish between monitoring topologies: ``` *

EMS server log: Aggregator give up message

* ``` - ......................... BUG: No Give up message + e.m.e.b.server.ClientShellCommand : #00000--> Client notification: CMD=RECOVERY, ARGS=GIVE_UP null @ 192.168.96.2 + e.m.e.b.server.ClientShellCommand : #00000--> Client Recovery Notification: GIVE_UP: null @ 192.168.96.2 + e.m.e.baguette.server.BaguetteServer : BaguetteServer.onMessage: Marked Node as Failed: 192.168.96.2 ``` * ***Aggregator***, for logs reporting (i) connection failures to a Netdata agent, (ii) a number of failed attempts to connect to VM, and (iii) a recovery give up message. *

Aggregator log: Failed metric collection attempts from a RL node's Netdata agent

* @@ -1205,20 +1198,19 @@ We distinguish between monitoring topologies: Collectors::Netdata: Collecting data from url: http://192.168.96.2:19999/api/v1/allmetrics?format=json Collectors::Netdata: Exception while collecting metrics from node: 192.168.96.2, #errors=3, exception: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://192.168.96.2:19999/api/v1/allmetrics": connect timed out; nested exception is java.net.SocketTimeoutException: connect timed out -> java.net.SocketTimeoutException: connect timed out Collectors::Netdata: Too many consecutive errors occurred while attempting to collect metrics from node: 192.168.96.2, num-of-errors=3 - Collectors::Netdata: Will pause metrics collection from node for 60 seconds: 192.168.96.2 + Collectors::Netdata: Pausing collection from Node: 192.168.96.2 ``` *

Aggregator log: Requesting RL node's credentials

* ``` SEND: SERVER-GET-NODE-SSH-CREDENTIALS 192.168.96.2 SelfHealingPlugin: createRecoveryTask(): Created recovery task for Node: id=null, address=192.168.96.2 ``` - *

Aggregator log: Netdata agent recovery actions

* + *

Aggregator log: Netdata agent (failing) recovery actions

* ``` SelfHealingPlugin: Retry #0: Recovering node: id=null, address=192.168.96.2 VmNodeRecoveryTask: connectToNode(): Connecting to node using SSH: address=192.168.96.2, port=22, username=ubuntu Connecting to server... - Heartbeat 1645015873205 - SelfHealingPlugin: EXCEPTION while recovering node: node-info={random=4b676a58-e00e-4ddf-a21e-b1c0d1382cd6, zone-id=IMU-ZONE, address=192.168.96.2, provider=AWS,......................... + SelfHealingPlugin: EXCEPTION while recovering node: node-address=192.168.96.2 -- Exception: java.net.NoRouteToHostException: No route to host at sun.nio.ch.UnixAsynchronousSocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:252) @@ -1233,47 +1225,31 @@ We distinguish between monitoring topologies: Collecting metrics from remote nodes (without EMS client): [192.168.96.2] Node is in ignore list: 192.168.96.2 ......................... - Collecting metrics from local node... - Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json - Metrics: extracted=0, published=0, failed=0 - Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Node is in ignore list: 192.168.96.2 - - Resumed metrics collection from node: 192.168.96.2 - ncelRecoveryTask(): Cancelled recovery task for Node: id=null, address=192.168.96.2 - - Collecting metrics from local node... - Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json - Metrics: extracted=0, published=0, failed=0 - Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Collecting data from url: http://192.168.96.2:19999/api/v1/allmetrics?format=json - Exception while collecting metrics from node: 192.168.96.2, #errors=1, exception: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://192.168.96.2:19999/api/v1/allmetrics": No route to host (Host unreachable); nested exception is java.net.NoRouteToHostException: No route to host (Host unreachable) -> java.net.NoRouteToHostException: No route to host (Host unreachable) - - Collecting metrics from local node... - Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json - Metrics: extracted=0, published=0, failed=0 - Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Collecting data from url: http://192.168.96.2:19999/api/v1/allmetrics?format=json - Exception while collecting metrics from node: 192.168.96.2, #errors=2, exception: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://192.168.96.2:19999/api/v1/allmetrics": No route to host (Host unreachable); nested exception is java.net.NoRouteToHostException: No route to host (Host unreachable) -> java.net.NoRouteToHostException: No route to host (Host unreachable) - - Collecting metrics from local node... - Collecting data from url: http://127.0.0.1:19999/api/v1/allmetrics?format=json - Metrics: extracted=0, published=0, failed=0 - Collecting metrics from remote nodes (without EMS client): [192.168.96.2] - Collecting data from url: http://192.168.96.2:19999/api/v1/allmetrics?format=json - Exception while collecting metrics from node: 192.168.96.2, #errors=3, exception: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://192.168.96.2:19999/api/v1/allmetrics": No route to host (Host unreachable); nested exception is java.net.NoRouteToHostException: No route to host (Host unreachable) -> java.net.NoRouteToHostException: No route to host (Host unreachable) - Too many consecutive errors occurred while attempting to collect metrics from node: 192.168.96.2, num-of-errors=3 - Will pause metrics collection from node for 60 seconds: 192.168.96.2 ......................... + SelfHealingPlugin: Retry #3: Recovering node: id=null, address=192.168.96.2 + VmNodeRecoveryTask: connectToNode(): Connecting to node using SSH: address=192.168.96.2, port=22, username=ubuntu + Connecting to server... + SelfHealingPlugin: EXCEPTION while recovering node: node-address=192.168.96.2 -- Exception: + java.net.NoRouteToHostException: No route to host + at sun.nio.ch.UnixAsynchronousSocketChannelImpl.checkConnect(Native Method) + at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:252) + at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finish(UnixAsynchronousSocketChannelImpl.java:198) + at sun.nio.ch.UnixAsynchronousSocketChannelImpl.onEvent(UnixAsynchronousSocketChannelImpl.java:213) + at sun.nio.ch.EPollPort$EventHandlerTask.run(EPollPort.java:293) + at java.lang.Thread.run(Thread.java:748) ``` + *

Aggregator log: Netdata agent recovery Give Up message

* ``` - ......................... BUG: No Give up message + SelfHealingPlugin: Max retries reached. No more recovery retries for node: id=null, address=192.168.96.2 + SelfHealingPlugin: cancelRecoveryTask(): Cancelled recovery task for Node: id=null, address=192.168.96.2 + Collectors::Netdata: Giving up collection from Node: 192.168.96.2 + NOTIFY-X: RECOVERY GIVE_UP null @ 192.168.96.2 ``` * ***Normal nodes (that operate)***, for NO logs indicating connection failures or recovery actions. -**B.7) Successful recovery of Netdata agent in a clustered Normal node (including Aggregator)** +**B.7) Successful recovery of local Netdata agent, in a clustered Normal node (including Aggregator)** > Test Case Quick Notes: > - Kill Netdata agent of any Normal node. @@ -1343,10 +1319,9 @@ We distinguish between monitoring topologies: ------ -## Limitations and Bugs +## Limitations * Clustering is never used for 2-level monitoring topologies. -* ***Bug:*** EMS clients do not give up after many recovery failures. -- No message is sent to EMS server for failed recoveries. * When no Normal nodes (and hence no Aggregator) exist in a cluster, no one will collect metrics from the (orphan) RL nodes. * When no Normal nodes (and hence no Aggregator) exist in a cluster, no one will recover the (orphan) RL nodes. * If EMS server fails no one will recover it. diff --git a/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/AbstractInstallationHelper.java b/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/AbstractInstallationHelper.java index 3f332ae021c9e37e971aba77605c61e1b702510c..4b87ca66085b6731153e53accbc807037e9258a3 100644 --- a/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/AbstractInstallationHelper.java +++ b/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/AbstractInstallationHelper.java @@ -271,8 +271,6 @@ public abstract class AbstractInstallationHelper implements InitializingBean, Ap protected String _prepareUrl(String urlTemplate, String baseUrl) { return urlTemplate - .replace("%{BASE_URL}%", Optional.ofNullable(baseUrl).orElse("")) - .replace("%{PUBLIC_IP}%", Optional.ofNullable(NetUtil.getPublicIpAddress()).orElse("")) - .replace("%{DEFAULT_IP}%", Optional.ofNullable(NetUtil.getDefaultIpAddress()).orElse("")); + .replace("%{BASE_URL}%", Optional.ofNullable(baseUrl).orElse("")); } } diff --git a/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/VmInstallationHelper.java b/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/VmInstallationHelper.java index d72f9ab26fa0845576a5d2f487b67e317844e894..c418fa247934682b5e79bc6c6f7e8c11ba56ba38 100644 --- a/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/VmInstallationHelper.java +++ b/event-management/baguette-client-install/src/main/java/eu/melodic/event/baguette/client/install/helper/VmInstallationHelper.java @@ -19,6 +19,7 @@ import eu.melodic.event.baguette.client.install.instruction.Instruction; import eu.melodic.event.baguette.server.BaguetteServer; import eu.melodic.event.baguette.server.NodeRegistryEntry; import eu.melodic.event.util.CredentialsMap; +import eu.melodic.event.util.NetUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringSubstitutor; @@ -133,7 +134,7 @@ public class VmInstallationHelper extends AbstractInstallationHelper { Map nodeMap = entry.getPreregistration(); BaguetteServer baguette = entry.getBaguetteServer(); - String baseUrl = nodeMap.get("BASE_URL"); + String baseUrl = StringUtils.removeEnd(nodeMap.get("BASE_URL"), "/"); String clientId = nodeMap.get("CLIENT_ID"); String ipSetting = nodeMap.get("IP_SETTING"); log.debug("VmInstallationHelper.prepareInstallationInstructionsForLinux(): Invoked: base-url={}", baseUrl); @@ -167,7 +168,7 @@ public class VmInstallationHelper extends AbstractInstallationHelper { // Load client config. template and prepare configuration nodeMap.put("BAGUETTE_CLIENT_ID", clientId); nodeMap.put("BAGUETTE_SERVER_ADDRESS", baguette.getConfiguration().getServerAddress()); - nodeMap.put("BAGUETTE_SERVER_HOSTNAME", baguette.getConfiguration().getServerHostname()); + nodeMap.put("BAGUETTE_SERVER_HOSTNAME", NetUtil.getHostname()); nodeMap.put("BAGUETTE_SERVER_PORT", ""+baguette.getConfiguration().getServerPort()); nodeMap.put("BAGUETTE_SERVER_PUBKEY", baguette.getServerPubkey()); nodeMap.put("BAGUETTE_SERVER_PUBKEY_FINGERPRINT", baguette.getServerPubkeyFingerprint()); diff --git a/event-management/baguette-client/conf/baguette-client.properties b/event-management/baguette-client/conf/baguette-client.properties index dded9204152a395d3efaf9e9a1472708d0afd321..deb4020fc2976ce0f9018c6e428fd76e180e074a 100644 --- a/event-management/baguette-client/conf/baguette-client.properties +++ b/event-management/baguette-client/conf/baguette-client.properties @@ -16,6 +16,7 @@ exit-command-allowed = false #kill-delay = 10 IP_SETTING=${IP_SETTING} +EMS_CLIENT_ADDRESS=${${IP_SETTING}} # ----------------------------------------------------------------------------- # Client Id and Baguette Server credentials diff --git a/event-management/baguette-client/conf/eu.melodic.event.brokercep.properties b/event-management/baguette-client/conf/eu.melodic.event.brokercep.properties index f6f46317cb7c151611a73b8a4ded970da62c366d..7937665c5937356decef13638e8ece746f76793d 100644 --- a/event-management/baguette-client/conf/eu.melodic.event.brokercep.properties +++ b/event-management/baguette-client/conf/eu.melodic.event.brokercep.properties @@ -27,8 +27,7 @@ brokercep.broker-url-3 = brokercep.broker-url-properties = transport.daemon=true&transport.trace=false&transport.useKeepAlive=true&transport.useInactivityMonitor=false&transport.needClientAuth=${brokercep.ssl.client-auth.required}&transport.verifyHostName=true&transport.connectionTimeout=0&transport.keepAlive=true brokercep.ssl.client-auth.required = false brokercep.broker-url-for-consumer = tcp://127.0.0.1:61616?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true -brokercep.broker-url-for-clients = ${brokercep.broker-protocol}://${IP_SETTING}:${brokercep.broker-port}?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true -#brokercep.broker-url-for-clients = tcp://127.0.0.1:61616?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true +brokercep.broker-url-for-clients = ${brokercep.broker-protocol}://${EMS_CLIENT_ADDRESS}:${brokercep.broker-port}?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true # Must be a public IP address # Key store @@ -45,12 +44,9 @@ brokercep.ssl.truststore-password = ENC(ISMbn01HVPbtRPkqm2Lslg==) brokercep.ssl.certificate-file = ${MELODIC_CONFIG_DIR}/client-broker.crt # Key-and-Cert data brokercep.ssl.key-entry-generate = IF-IP-CHANGED -brokercep.ssl.key-entry-name = ${IP_SETTING} -brokercep.ssl.key-entry-dname = CN=${IP_SETTING},OU=Information Management Unit (IMU),O=Institute of Communication and Computer Systems (ICCS),L=Athens,ST=Attika,C=GR -brokercep.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:%{DEFAULT_IP}%,ip:%{PUBLIC_IP}% -# Public and Default IP address defaults (if case NetUtil fails to detect any of them) -#control.ssl.default-ip-address = -#control.ssl.public-ip-address = +brokercep.ssl.key-entry-name = ${EMS_CLIENT_ADDRESS} +brokercep.ssl.key-entry-dname = CN=${EMS_CLIENT_ADDRESS},OU=Information Management Unit (IMU),O=Institute of Communication and Computer Systems (ICCS),L=Athens,ST=Attika,C=GR +brokercep.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:${DEFAULT_IP},ip:${PUBLIC_IP} # Authentication and Authorization settings brokercep.authentication-enabled = true diff --git a/event-management/baguette-client/src/main/assembly/baguette-client-installation-package.xml b/event-management/baguette-client/src/main/assembly/baguette-client-installation-package.xml index 9c70619122114a20086d8cffcbb9ce4cfebe7890..b63abe00368c9a7d047661a047e08ec14e6678f9 100644 --- a/event-management/baguette-client/src/main/assembly/baguette-client-installation-package.xml +++ b/event-management/baguette-client/src/main/assembly/baguette-client-installation-package.xml @@ -77,6 +77,15 @@ unix 0755 + + bin + ${project.parent.basedir}/bin + + sysmon.* + + unix + 0755 + diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClient.java b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClient.java index a121b5b089a1678e7126de9fa1e95e3b2fb2ae20..26f1171c812b56b3884ba0f75d1e0856f0c6bdf6 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClient.java +++ b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClient.java @@ -42,6 +42,7 @@ import java.util.List; "eu.melodic.event.brokerclient", "eu.melodic.event.util"}) @RequiredArgsConstructor public class BaguetteClient implements ApplicationRunner { + @Getter private final BaguetteClientProperties baguetteClientProperties; private final ClusterManagerProperties clusterManagerProperties; private final ConfigurableApplicationContext applicationContext; diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClientProperties.java b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClientProperties.java index 380f24f6ddb8129afcb76c592515ca8e946d912a..4eaccd367483674f82e867d76c07e0f33f7fae73 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClientProperties.java +++ b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/BaguetteClientProperties.java @@ -9,6 +9,7 @@ package eu.melodic.event.baguette.client; +import eu.melodic.event.common.client.SshClientProperties; import lombok.Data; import lombok.ToString; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -21,25 +22,14 @@ import java.util.List; @Configuration @ConfigurationProperties @PropertySource("file:${MELODIC_CONFIG_DIR}/baguette-client.properties") -@ToString(exclude = "serverPassword") -public class BaguetteClientProperties { - private long authTimeout = 60000; - private long execTimeout = 120000; - private long retryPeriod = 60000; - +@ToString(callSuper = true) +public class BaguetteClientProperties extends SshClientProperties { private boolean exitCommandAllowed = false; private int killDelay = 5; private List> collectorClasses; - private String clientId; private String debugFakeIpAddress; - private String serverAddress = "127.0.0.1"; - private int serverPort = 22; - private String serverPubkey; - private String serverFingerprint; - - private String serverUsername; - private String serverPassword; + private long sendStatisticsDelay = 10000L; } diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/CommandExecutor.java b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/CommandExecutor.java index dc6ffde6a5988e70c9265fbd49996545f02fd006..c07ca2fa426e78f669b40cf9381b2aac4f7b0f15 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/CommandExecutor.java +++ b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/CommandExecutor.java @@ -16,9 +16,10 @@ import eu.melodic.event.brokercep.BrokerCepService; import eu.melodic.event.brokercep.BrokerCepStatementSubscriber; import eu.melodic.event.brokercep.cep.CepService; import eu.melodic.event.brokercep.event.EventMap; -import eu.melodic.event.brokerclient.BrokerClient; import eu.melodic.event.brokerclient.event.EventGenerator; import eu.melodic.event.brokerclient.properties.BrokerClientProperties; +import eu.melodic.event.common.misc.EventConstant; +import eu.melodic.event.common.misc.SystemResourceMonitor; import eu.melodic.event.util.*; import io.atomix.cluster.ClusterMembershipEvent; import io.atomix.cluster.Member; @@ -28,6 +29,7 @@ import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Service; import java.io.*; @@ -35,6 +37,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; @@ -113,6 +116,11 @@ public class CommandExecutor { private boolean captureInputLine; @Getter private String lastInputLine; + @Autowired + private TaskScheduler taskScheduler; + private ScheduledFuture statsSendTask; + @Autowired + private SystemResourceMonitor systemResourceMonitor; public CommandExecutor() { initializeClientId(); @@ -120,6 +128,7 @@ public class CommandExecutor { public void setConfiguration(BaguetteClientProperties config) { log.trace("CommandExecutor: brokerCepService: {}", brokerCepService); + log.trace("CommandExecutor: config: {}", config); this.config = config; this.idFile = DEFAULT_ID_FILE; initializeClientId(); @@ -634,8 +643,26 @@ public class CommandExecutor { } else if ("SHOW-CONFIG".equals(cmd)) { log.info("BaguetteClient: configuration:\n{}", config); log.info("Cluster: configuration:\n{}", clusterManagerProperties); - } else if ("SHOW-STATS".equals(cmd)) { - sendStatistics(args[1]); + } else if ("GET-STATS".equals(cmd)) { + getStatistics(args[1]); + } else if ("SEND-STATS".equals(cmd)) { + if (args.length < 2) { + log.warn("Too few arguments"); + out.println("Too few arguments"); + return false; + } + String operation = args[1]; + + if ("START".equalsIgnoreCase(operation)) + sendStatisticsStart(); + else if ("STOP".equalsIgnoreCase(operation)) + sendStatisticsStop(); + else if ("CLEAR".equalsIgnoreCase(operation)) + clearStatistics(); + else { + log.error("BaguetteClient: Unknown STATS operation: {}", operation); + } + } else if ("CLEAR-STATS".equals(cmd)) { clearStatistics(); } else if ("SEND-CLIENT-PROPERTY".equals(cmd)) { @@ -727,6 +754,10 @@ public class CommandExecutor { clientConfiguration = config; } log.info("New client config.: {}", config); + HashMap payload = new HashMap<>(); + payload.put("new", clientConfiguration); + payload.put("old", oldConfig); + eventBus.send(EventConstant.EVENT_CLIENT_CONFIG_UPDATED, payload, this); } catch (Exception ex) { log.error("Exception while deserializing received Client configuration: ", ex); @@ -1223,12 +1254,38 @@ public class CommandExecutor { } @SneakyThrows - private void sendStatistics(String inputUuid) { + private void getStatistics(String inputUuid) { Map statsMap = brokerCepService.getBrokerCepStatistics(); log.debug("Statistics: {}", statsMap); if (out!=null) out.println("-INPUT:"+inputUuid+":"+serializeToString(statsMap)); } + @SneakyThrows + private void sendStatisticsStart() { + statsSendTask = taskScheduler.scheduleWithFixedDelay(() -> { + try { + Map statsMap = brokerCepService.getBrokerCepStatistics(); + log.debug("BCEP Statistics: {}", statsMap); + Map sysMap = systemResourceMonitor.getLatestMeasurements(); + log.debug("System Statistics: {}", sysMap); + + Map clientStats = new HashMap<>(); + if (statsMap!=null) clientStats.putAll(statsMap); + if (sysMap!=null) clientStats.putAll(sysMap); + if (out != null) out.println("-STATS:" + serializeToString(clientStats)); + } catch (Exception ex) { + log.error("Exception while sending Statistics to server: ", ex); + } + }, baguetteClient.getBaguetteClientProperties().getSendStatisticsDelay()); + log.info("Start sending STATS to server"); + } + + @SneakyThrows + private void sendStatisticsStop() { + statsSendTask.cancel(true); + log.info("Stop sending STATS to server"); + } + private void clearStatistics() { brokerCepService.clearBrokerCepStatistics(); log.info("Statistics cleared"); @@ -1243,6 +1300,11 @@ public class CommandExecutor { return ! isAggregator(); } + public void notifyEmsServer(String message) { + log.info("NOTIFY-X: {}", message); + out.println("-NOTIFY-X: "+message); + } + /*private static class StreamGobbler implements Runnable { private InputStream inputStream1; private InputStream inputStream2; diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/Sshc.java b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/Sshc.java index 3ed61686a4b5eeed297398f64c6182b760227124..b5820872c46f9f9a5440da2db612182daa653bfd 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/Sshc.java +++ b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/Sshc.java @@ -46,7 +46,7 @@ import java.util.Optional; */ @Slf4j @Service -public class Sshc { +public class Sshc implements eu.melodic.event.common.client.SshClient { private BaguetteClientProperties config; private SshClient client; private SimpleClient simple; @@ -62,15 +62,17 @@ public class Sshc { private InputStream in; @Getter private PrintStream out; - //@Getter - //private PrintStream err; + @Getter + private PrintStream err; @Getter private String clientId; @Getter @Setter private boolean useServerKeyVerifier = true; - public void setConfiguration(BaguetteClientProperties config) throws IOException { + @Override + public void setConfiguration(BaguetteClientProperties config) { + log.trace("Sshc: New config: {}", config); this.config = config; this.clientId = config.getClientId(); log.trace("Sshc: cmd-exec: {}", commandExecutor); @@ -102,6 +104,7 @@ public class Sshc { if (started) log.trace("Client started"); } + @Override public synchronized void start() throws IOException { if (started) return; log.info("Connecting to server..."); @@ -201,6 +204,7 @@ public class Sshc { this.started = true; } + @Override public synchronized void stop() throws IOException { if (!started) return; this.started = false; diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/collector/ClientCollectorContext.java b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/collector/ClientCollectorContext.java index 6a92a4b105d2191b30ec225e05c90acd67f20e7e..901895df7ff6ba32be96a58c34280afb39f0f7c3 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/collector/ClientCollectorContext.java +++ b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/collector/ClientCollectorContext.java @@ -9,8 +9,11 @@ package eu.melodic.event.baguette.client.collector; +import eu.melodic.event.baguette.client.BaguetteClientProperties; import eu.melodic.event.baguette.client.CommandExecutor; +import eu.melodic.event.baguette.client.Sshc; import eu.melodic.event.brokercep.event.EventMap; +import eu.melodic.event.common.client.SshClient; import eu.melodic.event.common.collector.CollectorContext; import eu.melodic.event.util.ClientConfiguration; import eu.melodic.event.util.GroupingConfiguration; @@ -27,7 +30,7 @@ import java.util.Set; @Slf4j @Component @RequiredArgsConstructor -public class ClientCollectorContext implements CollectorContext { +public class ClientCollectorContext implements CollectorContext { private final CommandExecutor commandExecutor; public Map getGroupings() { @@ -54,4 +57,14 @@ public class ClientCollectorContext implements CollectorContext { public boolean sendEvent(String connectionString, String destinationName, EventMap event, boolean createDestination) { return commandExecutor.sendEvent(connectionString, destinationName, event, createDestination); } + + @Override + public SshClient getSshClient() { + return new Sshc(); + } + + @Override + public BaguetteClientProperties getSshClientProperties() { + return new BaguetteClientProperties(); + } } diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NodeInfoHelper.java b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NodeInfoHelper.java index dd7071c8b0a231205c54148d11ce90af6ee056b9..43664966b7b170f559c3c85ab766fa3b04a0b3f5 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NodeInfoHelper.java +++ b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NodeInfoHelper.java @@ -10,23 +10,16 @@ package eu.melodic.event.baguette.client.plugin.recovery; import com.google.gson.Gson; -import eu.melodic.event.baguette.client.BaguetteClientProperties; import eu.melodic.event.baguette.client.CommandExecutor; -import eu.melodic.event.util.EventBus; -import eu.melodic.event.util.PasswordUtil; -import lombok.Data; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ScheduledFuture; /** * Node Info helper -- Retrieves node info from EMS server and caches them @@ -62,13 +55,13 @@ public class NodeInfoHelper { throw ex; } } - log.debug("NodeInfoHelper: getNodeInfo(): Node info: {}", nodeInfo); + //log.debug("NodeInfoHelper: getNodeInfo(): Node info: {}", nodeInfo); return nodeInfo; } public void remove(String nodeId, @NonNull String nodeAddress) { log.debug("NodeInfoHelper: remove(): node-id={}, node-address={}", nodeId, nodeAddress); Map nodeInfo = nodeInfoCache.remove(nodeAddress); - log.trace("NodeInfoHelper: remove(): Removed: node-id={}, node-address={}, node-info={}", nodeId, nodeAddress, nodeInfo); + log.trace("NodeInfoHelper: remove(): Removed: node-id={}, node-address={}", nodeId, nodeAddress); } } diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/SelfHealingPlugin.java b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/SelfHealingPlugin.java index 33be7c8fe12bd951e16edd4bf43d65f0aa78a7ab..8e6108920ad04b7453d9191d435099dfcc23431c 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/SelfHealingPlugin.java +++ b/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/SelfHealingPlugin.java @@ -12,17 +12,15 @@ package eu.melodic.event.baguette.client.plugin.recovery; import eu.melodic.event.baguette.client.BaguetteClientProperties; import eu.melodic.event.baguette.client.CommandExecutor; import eu.melodic.event.baguette.client.collector.netdata.NetdataCollector; +import eu.melodic.event.common.recovery.*; import eu.melodic.event.util.EventBus; import eu.melodic.event.util.PasswordUtil; import eu.melodic.event.util.Plugin; import io.atomix.cluster.ClusterMembershipEvent; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; +import lombok.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; @@ -46,31 +44,21 @@ import java.util.concurrent.atomic.AtomicInteger; public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.EventConsumer { private final ApplicationContext applicationContext; private final BaguetteClientProperties properties; + private final SelfHealingProperties selfHealingProperties; private final CommandExecutor commandExecutor; private final EventBus eventBus; private final PasswordUtil passwordUtil; private final NodeInfoHelper nodeInfoHelper; - final static String SELF_HEALING_RECOVERY_FAILED = "SELF_HEALING_RECOVERY_FAILED"; - final static String SELF_HEALING_RECOVERY_COMPLETED = "SELF_HEALING_RECOVERY_COMPLETED"; - private boolean started; - private final HashMap> waitingTasks = new HashMap<>(); + private final HashMap> waitingTasks = new HashMap<>(); private final TaskScheduler taskScheduler; - @Value("${self.healing.enabled:true}") - private boolean enabled; - @Value("${self.healing.recovery.delay:10000}") - private long clientRecoveryDelay; - @Value("${self.healing.recovery.retry.wait:60000}") - private long clientRecoveryRetryDelay; - @Value("${self.healing.recovery.max.retries:3}") - private int clientRecoveryMaxRetries; - @Override public void afterPropertiesSet() { log.debug("SelfHealingPlugin: properties: {}", properties); + log.debug("SelfHealingPlugin: selfHealingProperties: {}", selfHealingProperties); } public synchronized void start() { @@ -82,8 +70,8 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve eventBus.subscribe(CommandExecutor.EVENT_CLUSTER_NODE_ADDED, this); eventBus.subscribe(CommandExecutor.EVENT_CLUSTER_NODE_REMOVED, this); - eventBus.subscribe(NetdataCollector.NETDATA_NODE_PAUSED, this); - eventBus.subscribe(NetdataCollector.NETDATA_NODE_RESUMED, this); + eventBus.subscribe(NetdataCollector.NETDATA_NODE_OK, this); + eventBus.subscribe(NetdataCollector.NETDATA_NODE_FAILED, this); log.info("SelfHealingPlugin: Started"); } @@ -95,11 +83,11 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve eventBus.unsubscribe(CommandExecutor.EVENT_CLUSTER_NODE_ADDED, this); eventBus.unsubscribe(CommandExecutor.EVENT_CLUSTER_NODE_REMOVED, this); - eventBus.unsubscribe(NetdataCollector.NETDATA_NODE_PAUSED, this); - eventBus.unsubscribe(NetdataCollector.NETDATA_NODE_RESUMED, this); + eventBus.unsubscribe(NetdataCollector.NETDATA_NODE_OK, this); + eventBus.unsubscribe(NetdataCollector.NETDATA_NODE_FAILED, this); // Cancel all waiting recovery tasks - waitingTasks.forEach((nodeAddress,future) -> { + waitingTasks.forEach((nodeKey,future) -> { future.cancel(true); }); waitingTasks.clear(); @@ -109,7 +97,7 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve @Override public void onMessage(String topic, Object message, Object sender) { log.debug("SelfHealingPlugin: onMessage(): BEGIN: topic={}, message={}, sender={}", topic, message, sender); - if (!enabled) return; + if (!selfHealingProperties.isEnabled()) return; // Self-Healing for EMS clients if (CommandExecutor.EVENT_CLUSTER_NODE_REMOVED.equals(topic)) { @@ -122,13 +110,13 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve } else // Self-healing for Netdata agents - if (NetdataCollector.NETDATA_NODE_PAUSED.equals(topic)) { + if (NetdataCollector.NETDATA_NODE_FAILED.equals(topic)) { log.debug("SelfHealingPlugin: onMessage(): NETDATA NODE PAUSED: message={}", message); - processNetdataNodePausedEvent(message); + processNetdataNodeFailedEvent(message); } else - if (NetdataCollector.NETDATA_NODE_RESUMED.equals(topic)) { + if (NetdataCollector.NETDATA_NODE_OK.equals(topic)) { log.debug("SelfHealingPlugin: onMessage(): NETDATA NODE RESUMED: message={}", message); - processNetdataNodeResumedEvent(message); + processNetdataNodeOkEvent(message); } else // Unsupported message @@ -173,7 +161,7 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve } // Cancel any waiting recovery task - cancelRecoveryTask(nodeId, nodeAddress, false); + cancelRecoveryTask(nodeId, nodeAddress, EmsClientRecoveryTask.class, false); } else { log.warn("SelfHealingPlugin: processClusterNodeAddedEvent(): Message is not a {} object. Will ignore it.", ClusterMembershipEvent.class.getSimpleName()); } @@ -181,18 +169,18 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve // ------------------------------------------------------------------------ - private void processNetdataNodePausedEvent(Object message) { - log.debug("SelfHealingPlugin: processNetdataNodePausedEvent(): BEGIN: message={}", message); + private void processNetdataNodeFailedEvent(Object message) { + log.debug("SelfHealingPlugin: processNetdataNodeFailedEvent(): BEGIN: message={}", message); if (!(message instanceof Map)) { - log.warn("SelfHealingPlugin: processNetdataNodePausedEvent(): Message is not a {} object. Will ignore it.", Map.class.getSimpleName()); + log.warn("SelfHealingPlugin: processNetdataNodeFailedEvent(): Message is not a {} object. Will ignore it.", Map.class.getSimpleName()); return; } // Get paused node address Object addressValue = ((Map) message).getOrDefault("address", null); - log.debug("SelfHealingPlugin: processNetdataNodePausedEvent(): node-address={}", addressValue); + log.debug("SelfHealingPlugin: processNetdataNodeFailedEvent(): node-address={}", addressValue); if (addressValue==null) { - log.warn("SelfHealingPlugin: processNetdataNodePausedEvent(): Node address is missing. Cannot recover node. Initial message: {}", message); + log.warn("SelfHealingPlugin: processNetdataNodeFailedEvent(): Node address is missing. Cannot recover node. Initial message: {}", message); return; } String nodeAddress = addressValue.toString(); @@ -221,35 +209,40 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve } } - private void processNetdataNodeResumedEvent(Object message) { - log.debug("SelfHealingPlugin: processNetdataNodeResumedEvent(): BEGIN: message={}", message); + private void processNetdataNodeOkEvent(Object message) { + log.debug("SelfHealingPlugin: processNetdataNodeOkEvent(): BEGIN: message={}", message); if (!(message instanceof Map)) { - log.warn("SelfHealingPlugin: processNetdataNodeResumedEvent(): Message is not a {} object. Will ignore it.", Map.class.getSimpleName()); + log.warn("SelfHealingPlugin: processNetdataNodeOkEvent(): Message is not a {} object. Will ignore it.", Map.class.getSimpleName()); return; } // Get resumed node address String nodeAddress = ((Map) message).getOrDefault("address", "").toString(); - log.debug("SelfHealingPlugin: processNetdataNodeResumedEvent(): node-address={}", nodeAddress); + log.debug("SelfHealingPlugin: processNetdataNodeOkEvent(): node-address={}", nodeAddress); /*if (StringUtils.isBlank(nodeAddress)) { - log.warn("SelfHealingPlugin: processNetdataNodeResumedEvent(): Node address is missing. Initial message: {}", message); + log.warn("SelfHealingPlugin: processNetdataNodeOkEvent(): Node address is missing. Initial message: {}", message); return; }*/ // Cancel any waiting recovery task - cancelRecoveryTask(null, nodeAddress, false); + @NonNull Class recoverTaskClass = + StringUtils.isNotBlank(nodeAddress) + ? NetdataAgentRecoveryTask.class + : NetdataAgentLocalRecoveryTask.class; + cancelRecoveryTask(null, nodeAddress, recoverTaskClass, false); } // ------------------------------------------------------------------------ private void createRecoveryTask(String nodeId, @NonNull String nodeAddress, @NonNull Class recoveryTaskClass) { // Check if a recovery task has already been scheduled + NodeKey nodeKey = new NodeKey(nodeAddress, recoveryTaskClass); synchronized (waitingTasks) { - if (waitingTasks.containsKey(nodeAddress)) { + if (waitingTasks.containsKey(nodeKey)) { log.warn("SelfHealingPlugin: createRecoveryTask(): Recovery has already been scheduled for Node: id={}, address={}", nodeId, nodeAddress); return; } - waitingTasks.put(nodeAddress, null); + waitingTasks.put(nodeKey, null); } // Get node info and credentials from EMS server @@ -260,7 +253,7 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve log.warn("SelfHealingPlugin: createRecoveryTask(): Node info is null or empty. Cannot recover node."); return; } - log.trace("SelfHealingPlugin: createRecoveryTask(): Node info retrieved for node: id={}, address={}, node-info:\n{}", nodeId, nodeAddress, nodeInfo); + log.trace("SelfHealingPlugin: createRecoveryTask(): Node info retrieved for node: id={}, address={}", nodeId, nodeAddress); } else { log.debug("SelfHealingPlugin: createRecoveryTask(): Node address is blank. Node info will not be retrieved: id={}, address={}", nodeId, nodeAddress); } @@ -269,34 +262,46 @@ public class SelfHealingPlugin implements Plugin, InitializingBean, EventBus.Eve final RecoveryTask recoveryTask = applicationContext.getBean(recoveryTaskClass); if (nodeInfo!=null && nodeInfo.size()>0) recoveryTask.setNodeInfo(nodeInfo); - AtomicInteger retries = new AtomicInteger(0); + final AtomicInteger retries = new AtomicInteger(0); ScheduledFuture future = taskScheduler.scheduleWithFixedDelay(() -> { try { log.info("SelfHealingPlugin: Retry #{}: Recovering node: id={}, address={}", retries.get(), nodeId, nodeAddress); recoveryTask.runNodeRecovery(); //NOTE: 'recoveryTask.runNodeRecovery()' must send SELF_HEALING_RECOVERY_COMPLETED or _FAILED event - if (retries.getAndIncrement() > clientRecoveryMaxRetries) { - log.warn("SelfHealingPlugin: Max retries reached. No more recovery retries for node: id={}, address={}", nodeId, nodeAddress); - cancelRecoveryTask(nodeId, nodeAddress, true); - } } catch (Exception e) { - log.error("SelfHealingPlugin: EXCEPTION while recovering node: node-info={} -- Exception: ", recoveryTask.getNodeInfo(), e); - eventBus.send(SELF_HEALING_RECOVERY_FAILED, nodeAddress); + log.error("SelfHealingPlugin: EXCEPTION while recovering node: node-address={} -- Exception: ", nodeAddress, e); + eventBus.send(RecoveryConstant.SELF_HEALING_RECOVERY_FAILED, nodeAddress); + } + if (retries.getAndIncrement() >= selfHealingProperties.getRecovery().getMaxRetries()) { + log.warn("SelfHealingPlugin: Max retries reached. No more recovery retries for node: id={}, address={}", nodeId, nodeAddress); + cancelRecoveryTask(nodeId, nodeAddress, recoveryTaskClass, true); + eventBus.send(RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP, nodeAddress); + + // Notify EMS server about giving up recovery due to permanent failure + commandExecutor.notifyEmsServer("RECOVERY GIVE_UP "+nodeId+" @ "+nodeAddress); } - }, Instant.now().plusMillis(clientRecoveryDelay), Duration.ofMillis(clientRecoveryRetryDelay)); - waitingTasks.put(nodeAddress, future); + }, Instant.now().plusMillis(selfHealingProperties.getRecovery().getDelay()), Duration.ofMillis(selfHealingProperties.getRecovery().getRetryDelay())); + waitingTasks.put(nodeKey, future); log.info("SelfHealingPlugin: createRecoveryTask(): Created recovery task for Node: id={}, address={}", nodeId, nodeAddress); } - private void cancelRecoveryTask(String nodeId, @NonNull String nodeAddress, boolean retainAddress) { + private void cancelRecoveryTask(String nodeId, @NonNull String nodeAddress, @NonNull Class recoveryTaskClass, boolean retainNodeKey) { + NodeKey nodeKey = new NodeKey(nodeAddress, recoveryTaskClass); synchronized (waitingTasks) { - ScheduledFuture future = retainAddress ? waitingTasks.put(nodeAddress, null) : waitingTasks.remove(nodeAddress); + ScheduledFuture future = retainNodeKey ? waitingTasks.put(nodeKey, null) : waitingTasks.remove(nodeKey); if (future != null) { future.cancel(true); nodeInfoHelper.remove(nodeId, nodeAddress); log.info("SelfHealingPlugin: cancelRecoveryTask(): Cancelled recovery task for Node: id={}, address={}", nodeId, nodeAddress); } else - log.warn("SelfHealingPlugin: cancelRecoveryTask(): No recovery task is scheduled for Node: id={}, address={}", nodeId, nodeAddress); + log.debug("SelfHealingPlugin: cancelRecoveryTask(): No recovery task is scheduled for Node: id={}, address={}", nodeId, nodeAddress); } } + + @Data + @AllArgsConstructor + protected static class NodeKey { + private String address; + @NonNull private Class recoveryTaskClass; + } } diff --git a/event-management/baguette-client/src/main/resources/META-INF/spring.factories b/event-management/baguette-client/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000000000000000000000000000000000..7966109cfe09255ae63e437f39f3e26ee8170e0b --- /dev/null +++ b/event-management/baguette-client/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.env.EnvironmentPostProcessor=eu.melodic.event.util.NetUtilPostProcessor \ No newline at end of file diff --git a/event-management/baguette-server/pom.xml b/event-management/baguette-server/pom.xml index 16fc0aeff3a64741915db3e862fba77ea5c923e3..8d99b8e863b489c7dee74fe0233a5e7078772aeb 100644 --- a/event-management/baguette-server/pom.xml +++ b/event-management/baguette-server/pom.xml @@ -32,6 +32,11 @@ ${project.version} compile + + eu.melodic.event + common + ${project.version} + diff --git a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/BaguetteServer.java b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/BaguetteServer.java index 28cee7c6675ce66364c56cc7a48e296bf7627cb6..a51cb419452cb63fa8db5f75ea3ae637ca6debba 100644 --- a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/BaguetteServer.java +++ b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/BaguetteServer.java @@ -11,6 +11,7 @@ package eu.melodic.event.baguette.server; import eu.melodic.event.baguette.server.properties.BaguetteServerProperties; import eu.melodic.event.brokercep.BrokerCepService; +import eu.melodic.event.common.recovery.RecoveryConstant; import eu.melodic.event.translate.TranslationContext; import eu.melodic.event.util.*; import lombok.SneakyThrows; @@ -34,7 +35,7 @@ import java.util.stream.Collectors; */ @Slf4j @Service -public class BaguetteServer implements InitializingBean { +public class BaguetteServer implements InitializingBean, EventBus.EventConsumer { @Autowired private BaguetteServerProperties config; @Autowired @@ -148,6 +149,8 @@ public class BaguetteServer implements InitializingBean { // Server control methods public synchronized void startServer(ServerCoordinator coordinator) throws IOException { if (server == null) { + eventBus.subscribe(RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP, this); + log.info("BaguetteServer.startServer(): Starting SSH server instance..."); nodeRegistry.setCoordinator(coordinator); Sshd server = new Sshd(); @@ -162,6 +165,8 @@ public class BaguetteServer implements InitializingBean { public synchronized void stopServer() throws IOException { if (server != null) { + eventBus.unsubscribe(RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP, this); + log.info("BaguetteServer.setServerConfiguration(): stopping running instance of SSH server..."); server.stop(); this.server = null; @@ -181,6 +186,29 @@ public class BaguetteServer implements InitializingBean { return server != null; } + @Override + public void onMessage(String topic, Object message, Object sender) { + log.trace ("BaguetteServer.onMessage: BEGIN: topic={}, message={}, sender={}", topic, message, sender); + + String nodeAddress = (message!=null) ? message.toString() : null; + log.trace("BaguetteServer.onMessage: nodeAddress={}", nodeAddress); + + if (RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP.equals(topic)) { + if (StringUtils.isNotBlank(nodeAddress)) { + NodeRegistryEntry node = nodeRegistry.getNodeByAddress(nodeAddress); + if (node!=null) { + node.nodeFailed(null); + log.info("BaguetteServer.onMessage: Marked Node as Failed: {}", nodeAddress); + } else { + log.warn("BaguetteServer.onMessage: Node with Address not found: {}", nodeAddress); + log.debug("BaguetteServer.onMessage: Node addresses: {}", nodeRegistry.getNodeAddresses()); + } + } + } else { + log.warn("BaguetteServer.onMessage: Event from unexpected topic received. Ignoring it: {}", topic); + } + } + // Topology configuration methods public synchronized void setTopologyConfiguration( TranslationContext _TC, @@ -271,7 +299,7 @@ public class BaguetteServer implements InitializingBean { } if (coordinatorClass == null) - throw new IllegalArgumentException("Either coordinator class or configuration id must be specified"); + throw new IllegalArgumentException("Either coordinator class or coordinator id must be specified"); // Initialize coordinator class and parameters for backward compatibility ServerCoordinator coordinator = createServerCoordinator(null, coordinatorClass, coordinatorParams, _TC, upperwareGrouping); diff --git a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/ClientShellCommand.java b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/ClientShellCommand.java index 7d26f99b5a09d8c48d4d39850860a38ca1db301e..dc553fdd19117aaa4c93dad5cdf427a706fb8e05 100644 --- a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/ClientShellCommand.java +++ b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/ClientShellCommand.java @@ -10,6 +10,7 @@ package eu.melodic.event.baguette.server; import com.google.gson.Gson; +import eu.melodic.event.common.recovery.RecoveryConstant; import eu.melodic.event.util.ClientConfiguration; import eu.melodic.event.util.EventBus; import eu.melodic.event.baguette.server.coordinator.cluster.IClusterZone; @@ -27,6 +28,7 @@ import org.apache.sshd.server.session.ServerSession; import org.cryptacular.util.CertUtil; import org.slf4j.event.Level; +import javax.validation.constraints.NotBlank; import java.io.*; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; @@ -53,10 +55,14 @@ public class ClientShellCommand implements Command, Runnable, SessionAware { return Collections.unmodifiableSet(activeCmdMap.keySet()); } - public static ClientShellCommand getActiveByIpAddress(String address) { + public static ClientShellCommand getActiveByIpAddress(@NotBlank String address) { return activeCmdMap.get(address); } + public static ClientShellCommand getActiveById(@NotBlank String id) { + return activeCmdList.stream().filter(csc->csc.getId().equals(id)).findFirst().orElse(null); + } + private InputStream in; private PrintStream out; private PrintStream err; @@ -102,6 +108,9 @@ public class ClientShellCommand implements Command, Runnable, SessionAware { @Getter @Setter private NodeRegistryEntry nodeRegistryEntry; + @Getter + private Map clientStatistics; + public ClientShellCommand(ServerCoordinator coordinator, boolean allowClientOverrideItsAddress, EventBus eventBus, NodeRegistry registry) { synchronized (LOCK) { id = String.format("#%05d", counter.getAndIncrement()); @@ -186,6 +195,7 @@ public class ClientShellCommand implements Command, Runnable, SessionAware { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String line; + boolean helloReceived = false; while ((line = reader.readLine()) != null) { line = line.trim(); log.debug("{}--> {}", id, line); @@ -194,10 +204,13 @@ public class ClientShellCommand implements Command, Runnable, SessionAware { if (echoOn) out.printf("ECHO %s\n", line); //if (line.equalsIgnoreCase("exit")) break; - if (line.startsWith("-HELLO FROM CLIENT:")) { + if (!helloReceived && line.startsWith("-HELLO FROM CLIENT:")) { + helloReceived = true; getClientInfoFromGreeting(line.substring("-HELLO FROM CLIENT:".length())); coordinator.register(this); eventBus.send("BAGUETTE_SERVER_CLIENT_REGISTERED", this); + + sendCommand("SEND-STATS START"); } else if (line.startsWith("-INPUT:")) { String input = line.substring("-INPUT:".length()); String[] part = input.split(":",2 ); @@ -236,10 +249,54 @@ public class ClientShellCommand implements Command, Runnable, SessionAware { log.info("{}--> Client status changed: {} --> {}", getId(), clientNodeStatus, newNodeStatus); if (StringUtils.isNotBlank(newNodeStatus) && ! StringUtils.equals(clientNodeStatus, newNodeStatus)) this.clientNodeStatus = newNodeStatus; + } else if (line.startsWith("-NOTIFY-X:")) { + String message = line.substring("-NOTIFY-X:".length()).trim(); + String[] part = message.split(" ", 2); + String command = part[0].trim(); + String args = part.length>1 ? part[1] : null; + log.info("{}--> Client notification: CMD={}, ARGS={}", getId(), command, args); + + if ("DEBUG".equalsIgnoreCase(command)) { + log.debug("{}--> {}", getId(), args); + } else + if ("INFO".equalsIgnoreCase(command)) { + log.info("{}--> {}", getId(), args); + } else + if ("WARN".equalsIgnoreCase(command)) { + log.warn("{}--> {}", getId(), args); + } else + if ("ERROR".equalsIgnoreCase(command)) { + log.error("{}--> {}", getId(), args); + } else + if ("RECOVERY".equalsIgnoreCase(command)) { + args = args==null ? "" : args; + part = args.split(" ", 2); + String notificationType = part[0].trim(); + String clientData = part.length>1 ? part[1] : null; + if (StringUtils.isNotBlank(notificationType) && StringUtils.isNotBlank(clientData)) { + log.info("{}--> Client Recovery Notification: {}: {}", getId(), notificationType, clientData); + if ("GIVE_UP".equalsIgnoreCase(notificationType)) { + String[] tmp = clientData.split("@", 2); + String nodeId = tmp[0].trim(); + String nodeAddress = tmp.length>1 ? tmp[1].trim() : null; + if (StringUtils.isNotBlank(nodeAddress)) + eventBus.send(RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP, nodeAddress, "Client_" + getId()); + else + log.warn("{}--> Missing Node Address in Client Recovery Notification: {}", getId(), args); + } else + log.warn("{}--> UNKNOWN Client Recovery Notification: {}", getId(), args); + } else { + log.warn("{}--> INVALID Client Recovery Notification: {}", getId(), args); + } + } else + { + log.warn("{}--> UNKNOWN Client Notification type: {}", getId(), message); + } + } else if (line.startsWith("-CLIENT-PROPERTY-CHANGE:")) { String[] part = line.substring("-CLIENT-PROPERTY-CHANGE:".length()).trim().split(" ", 2); String propertyName = part[0]; - String propertyValue = part.length>1 ? part[1] : null; + String propertyValue = part.length > 1 ? part[1] : null; String oldValue = clientProperties.getProperty(propertyName); if (StringUtils.isNotBlank(propertyName)) { log.info("{}--> Client property changed: {} = {} --> {}", getId(), propertyName, oldValue, propertyValue); @@ -247,6 +304,19 @@ public class ClientShellCommand implements Command, Runnable, SessionAware { } else { log.warn("{}--> Invalid Client property: input line: ", line); } + } else if (line.startsWith("-STATS:")) { + String statsStr = line.substring("-STATS:".length()); + Object statsObj = deserializeFromString(statsStr); + if (statsObj instanceof Map) { + Map statsMap = (Map) statsObj; + statsMap.put("_received_at_server_timestamp", System.currentTimeMillis()); + log.debug("{}--> Client STATS received: {}", getId(), statsMap); + this.clientStatistics = statsMap; + } else if (statsObj==null) { + log.debug("{}--> Client STATS object is NULL", getId()); + } else { + log.error("{}--> Unsupported Client STATS object: class={}, object={}", getId(), statsObj.getClass().getName(), statsObj); + } } else if (line.equalsIgnoreCase("READY")) { coordinator.clientReady(this); } else { diff --git a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/NodeRegistryEntry.java b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/NodeRegistryEntry.java index b9d572d03bf9734d58345737c30d57ed88872744..fe20cc0f06e16728c032676cdb346ecf3327cd7e 100644 --- a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/NodeRegistryEntry.java +++ b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/NodeRegistryEntry.java @@ -24,7 +24,7 @@ import java.util.UUID; @AllArgsConstructor public class NodeRegistryEntry { public enum STATE { PREREGISTERED, IGNORE_NODE, INSTALLING, NOT_INSTALLED, INSTALLED, INSTALL_ERROR, - WAITING_REGISTRATION, REGISTERED, NOT_REGISTERED, REGISTRATION_ERROR, DISCONNECTED + WAITING_REGISTRATION, REGISTERED, NOT_REGISTERED, REGISTRATION_ERROR, DISCONNECTED, NODE_FAILED }; @Getter private final String ipAddress; @Getter private final String clientId; @@ -114,6 +114,13 @@ public class NodeRegistryEntry { return this; } + public NodeRegistryEntry nodeFailed(Map failInfo) { + if (failInfo!=null) + registration.putAll(processMap("", failInfo)); + setState(STATE.NODE_FAILED); + return this; + } + private Map processMap(Map inMap) { Map outMap = new LinkedHashMap<>(); for (Map.Entry entry : inMap.entrySet()) { diff --git a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/properties/BaguetteServerProperties.java b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/properties/BaguetteServerProperties.java index 36fe7b76030ebc1fc1ec77c31f014544d7c3ef3b..a9d1cae0bd1fba75abe9eabfffc0ff7d41c1217e 100644 --- a/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/properties/BaguetteServerProperties.java +++ b/event-management/baguette-server/src/main/java/eu/melodic/event/baguette/server/properties/BaguetteServerProperties.java @@ -11,11 +11,10 @@ package eu.melodic.event.baguette.server.properties; import eu.melodic.event.baguette.server.ServerCoordinator; import eu.melodic.event.util.CredentialsMap; -import eu.melodic.event.util.NetUtil; +import eu.melodic.event.util.EmsConstant; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @@ -30,10 +29,13 @@ import java.util.Map; @Data @Validated @Configuration -@ConfigurationProperties(prefix = "baguette.server") +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "baguette.server") @PropertySource("file:${MELODIC_CONFIG_DIR}/eu.melodic.event.baguette-server.properties") @Slf4j -public class BaguetteServerProperties { +public class BaguetteServerProperties implements InitializingBean { + public void afterPropertiesSet() { + log.debug("BaguetteServerProperties: {}", this); + } /*XXX: TODO: Add combinatorial properties check @Override @@ -52,68 +54,37 @@ public class BaguetteServerProperties { } }*/ - //@Size(min = 1, message = "Please provide a valid Coordinator class (use Fully-Qualified Class Name)") - @Value("${baguette.server.coordinator.class}") private Class coordinatorClass; private Map coordinatorParameters = new HashMap<>(); - @Value("${baguette.server.coordinator.id}") private List coordinatorId; private Map coordinatorConfig = new HashMap<>(); - @Value("${baguette.server.registration-window:30000}") @Min(-1) - private long registrationWindow; - @Value("${baguette.server.num-of-instances:-1}") + private long registrationWindow = 30000; @Min(-1) - private int numberOfInstances; - @Value("${baguette.server.num-of-segments:-1}") + private int numberOfInstances = -1; @Min(-1) - private int NumberOfSegments; - - //@Value("#{ '${baguette.server.address}'!='' ? '${baguette.server.address}' : T(eu.melodic.event.util.NetUtil).getPublicIpAddress() }") - @Value("${baguette.server.address:}") - private String serverAddress; - - public String getServerAddress() { - String oldVal = serverAddress; - if (StringUtils.isEmpty(serverAddress) || "%{PUBLIC_IP}%".equals(serverAddress.trim())) { - serverAddress = NetUtil.getPublicIpAddress(); - log.info("BaguetteServerProperties: Set serverAddress to PUBLIC: {} -> {}", oldVal, serverAddress); - } else if ("%{DEFAULT_IP}%".equals(serverAddress.trim())) { - serverAddress = eu.melodic.event.util.NetUtil.getDefaultIpAddress(); - log.info("BaguetteServerProperties: Set serverAddress to DEFAULT: {} -> {}", oldVal, serverAddress); - } - return serverAddress; - } + private int NumberOfSegments = -1; - public String getServerHostname() { - return NetUtil.getHostname(); - } + private String address; + public String getServerAddress() { return address; } - public String getCanonicalHostName() { - return NetUtil.getCanonicalHostName(); - } - - @Value("${baguette.server.port:2222}") @Min(value = 1, message = "Valid server ports are between 1 and 65535. Please prefer ports higher than 1023.") @Max(value = 65535, message = "Valid server ports are between 1 and 65535. Please prefer ports higher than 1023.") - private int serverPort; + private int port = 2222; + public int getServerPort() { return port; } + + private String keyFile = "hostkey.ser"; + public String getServerKeyFile() { return keyFile; } - @Value("${baguette.server.key.file:hostkey.ser}") - private String serverKeyFile; - @Value("${baguette.server.heartbeat:false}") private boolean heartbeatEnabled; - @Value("${baguette.server.heartbeat.period:60000}") @Min(-1) - private long heartbeatPeriod; + private long heartbeatPeriod = 60000; - @Value("${baguette.server.debug.client-address-override-allowed:false}") private boolean clientAddressOverrideAllowed; - @Value("${baguette.server.client-id-format}") private String clientIdFormat; - @Value("${baguette.server.client-id-format.escape:~}") - private String clientIdFormatEscape; + private String clientIdFormatEscape = "~"; private final CredentialsMap credentials = new CredentialsMap(); diff --git a/event-management/bin/sysmon.sh b/event-management/bin/sysmon.sh index 9d15d4a640c0e657f828ea13b336098e1585ebf6..c53778da2b5034c6a31a02a03dbab84c2779b832 100644 --- a/event-management/bin/sysmon.sh +++ b/event-management/bin/sysmon.sh @@ -8,6 +8,16 @@ # https://www.mozilla.org/en-US/MPL/2.0/ # +# Current Time / Start Time / Uptime +curr_dt=`date '+%Y-%m-%d %H:%M:%S'` +up_dt=`uptime -s` +curr_dt_sec=`date -d "$curr_dt" +%s` +up_dt_sec=`date -d "$up_dt" +%s` +uptime_sec=$(( curr_dt_sec - up_dt_sec )) +echo CurrDateTime: $curr_dt_sec +echo UpDateTime: $up_dt_sec +echo Uptime: $uptime_sec + # Report CPU usage (%) echo CPU: `top -b -n1 | grep "Cpu(s)" | awk '{print $2 + $4}'` diff --git a/event-management/broker-cep/pom.xml b/event-management/broker-cep/pom.xml index 7a2ba555c5c6f9d0328290d10c75a3a7b790fc9e..c41fd4839aa91b6b2752bece1a3b02a710ee41da 100644 --- a/event-management/broker-cep/pom.xml +++ b/event-management/broker-cep/pom.xml @@ -85,7 +85,6 @@ com.google.code.gson gson - 2.8.5 diff --git a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepService.java b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepService.java index ca31e62881e77b15312afc66cc021ad2adbe2c99..28786803f29c07475510ff5bfb80e0c027e07323 100644 --- a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepService.java +++ b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepService.java @@ -42,9 +42,9 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -@AllArgsConstructor(onConstructor = @__({@Autowired})) -@Service @Slf4j +@Service +@AllArgsConstructor(onConstructor = @__({@Autowired})) public class BrokerCepService { private BrokerCepProperties properties; private BrokerConfig brokerConfig; diff --git a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepStatementSubscriber.java b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepStatementSubscriber.java index 651836e5c9cec0642f16e87827b785069725fb18..22a650374ecc137a989486c7b2e9e903fc42f5b2 100644 --- a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepStatementSubscriber.java +++ b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/BrokerCepStatementSubscriber.java @@ -53,40 +53,30 @@ public class BrokerCepStatementSubscriber implements StatementSubscriber { String password = brokerCep.getBrokerPassword(); String passwordEncoded = passwordUtil.encodePassword(password); try { - // Publish new event to Local Broker topic - log.trace("- Publishing event to local broker: subscriber={}, local-broker={}, username={}, password={}, topic={}, payload={}", + // Queue new event for publishing to Local Broker topic + EventForwarder.getInstance().addLocalPublishTask(name, topic, eventMap, ()->countLocalPublish(true), ()->countLocalPublish(false)); + log.trace("- Event queued for publishing to local broker: subscriber={}, local-broker={}, username={}, password={}, topic={}, payload={}", name, localBrokerUrl, username, passwordEncoded, topic, eventMap); - brokerCep.publishEvent(localBrokerUrl, username, password, topic, eventMap); - log.debug("- Event published to local broker: subscriber={}, local-broker={}, username={}, password={}, topic={}, payload={}", - name, localBrokerUrl, username, passwordEncoded, topic, eventMap); - countLocalPublish(true); - } catch (Exception ex) { - log.error("- New event: ERROR while publishing to local broker: subscriber={}, local-broker={}, username={}, password={}, topic={}, exception=", + log.error("- New event: ERROR while queueing event for publishing to local broker: subscriber={}, local-broker={}, username={}, password={}, topic={}, exception=", name, localBrokerUrl, username, passwordEncoded, topic, ex); countLocalPublish(false); } } protected void forwardToGroupings(Map eventMap) { - // Send new event to the next grouping(s) + // Queue event for forwarding to the next grouping(s) log.trace("- Forwarding event to groupings: subscriber={}, forward-to-groupings={}, payload={}", name, forwardToGroupings, eventMap); if (forwardToGroupings==null) return; for (GroupingConfiguration.BrokerConnectionConfig fwdToGrouping : forwardToGroupings) { try { - String brokerUrl = fwdToGrouping.getUrl(); - String username = fwdToGrouping.getUsername(); - String password = fwdToGrouping.getPassword(); - log.debug("- Forwarding event to grouping: subscriber={}, forward-to-grouping={}, url={}, username={}, topic={}, payload={}", - name, fwdToGrouping, brokerUrl, username, topic, eventMap); - brokerCep.publishEvent(brokerUrl, username, password, topic, eventMap); - log.debug("- Event forwarded to grouping: subscriber={}, forwarded-to-grouping={}, url={}, username={}, topic={}, payload={}", - name, fwdToGrouping, brokerUrl, username, topic, eventMap); - countForward(true); + EventForwarder.getInstance().addEventForwardTask(name, fwdToGrouping, topic, eventMap, ()->countForward(true), ()->countForward(false)); + log.debug("- Event queued for forwarding to grouping: subscriber={}, forward-to-grouping={}, topic={}, payload={}", + name, fwdToGrouping, topic, eventMap); } catch (Exception ex) { - log.error("- Error while sending event: subscriber={}, forward-to-groupings={}, payload={}, exception: ", + log.error("- ERROR while queuing event in forward queue: subscriber={}, forward-to-groupings={}, payload={}, exception: ", name, forwardToGroupings, eventMap, ex); countForward(false); } diff --git a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/EventForwarder.java b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/EventForwarder.java new file mode 100644 index 0000000000000000000000000000000000000000..339d808b606c374da15ee23c3539db2f9e7542b1 --- /dev/null +++ b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/EventForwarder.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.brokercep; + +import eu.melodic.event.brokercep.properties.BrokerCepProperties; +import eu.melodic.event.util.GroupingConfiguration; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.task.TaskExecutor; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; + +@Slf4j +@Service +@RequiredArgsConstructor +public class EventForwarder implements InitializingBean, Runnable { + @Getter @Setter + private static EventForwarder instance; + + private final BrokerCepProperties properties; + private final BrokerCepService brokerCepService; + private final LinkedBlockingDeque eventForwardingQueue = new LinkedBlockingDeque<>(); + + public void addEventForwardTask(String senderName, GroupingConfiguration.BrokerConnectionConfig brokerConnectionConfig, String topic, Map eventMap, Runnable success, Runnable failure) { + boolean isLocalPublish = + brokerCepService.getBrokerCepProperties().getBrokerUrlForConsumer() + .equals(brokerConnectionConfig.getUrl()); + eventForwardingQueue.add(new EventForwardTask(senderName, isLocalPublish, brokerConnectionConfig, topic, eventMap, success, failure)); + log.debug("EventForwarder: {} task in the queue", eventForwardingQueue.size()); + } + + public void addEventForwardTask(String senderName, String brokerUrl, String certificate, String username, String password, String topic, Map eventMap, Runnable success, Runnable failure) { + GroupingConfiguration.BrokerConnectionConfig brokerConnectionConfig = + new GroupingConfiguration.BrokerConnectionConfig(null, brokerUrl, certificate, username, password); + addEventForwardTask(senderName, brokerConnectionConfig, topic, eventMap, success, failure); + } + + public void addLocalPublishTask(String senderName, String topic, Map eventMap, Runnable success, Runnable failure) { + String brokerUrl = brokerCepService.getBrokerCepProperties().getBrokerUrlForConsumer(); + String username = brokerCepService.getBrokerUsername(); + String password = brokerCepService.getBrokerPassword(); + GroupingConfiguration.BrokerConnectionConfig brokerConnectionConfig = + new GroupingConfiguration.BrokerConnectionConfig(null, brokerUrl, null, username, password); + eventForwardingQueue.add(new EventForwardTask(senderName, true, brokerConnectionConfig, topic, eventMap, success, failure)); + log.debug("EventForwarder: {} task in the queue", eventForwardingQueue.size()); + } + + @Override + public void afterPropertiesSet() throws Exception { + if (instance==null) instance = this; + Executors.newFixedThreadPool(1).submit(this); + log.info("EventForwarder: Starting event publish/forward worker"); + } + + @Override + public void run() { + while (true) { + try { + processEventForwardTask(eventForwardingQueue.take()); + } catch (Throwable t) { + log.warn("EventForwarder: Exception thrown in task processing loop: ", t); + } + } + } + + private void processEventForwardTask(EventForwardTask task) { + String senderName = task.getSenderName(); + String topic = task.getTopic(); + Map eventMap = task.getEventMap(); + + // Check if max task processing duration has been exceeded + long duration = System.currentTimeMillis() - task.getCreation(); + if (properties.getMaxEventForwardDuration()>0 && duration > properties.getMaxEventForwardDuration()) { + log.error("- Max event publish/forward duration exceeded. Dropping event: subscriber={}, forward-to-groupings={}, topic={}, payload={}", + senderName, task.getBrokerConnectionConfig(), topic, eventMap); + + runIfNotNull(task.getFailure()); + return; + } + + // Process event publish/forward task + try { + String brokerUrl = task.getBrokerConnectionConfig().getUrl(); + String username = task.getBrokerConnectionConfig().getUsername(); + String password = task.getBrokerConnectionConfig().getPassword(); + + if (task.isLocalPublish()) { + log.trace("- Publishing event to local broker: subscriber={}, local-broker={}, username={}, password={}, topic={}, retry={}, payload={}", + senderName, brokerUrl, username, "passwordEncoded", topic, task.getRetries(), eventMap); + } else { + log.debug("- Forwarding event to grouping: subscriber={}, forward-to-grouping={}, url={}, username={}, topic={}, retry={}, payload={}", + senderName, task.getBrokerConnectionConfig(), brokerUrl, username, topic, task.getRetries(), eventMap); + } + + task.newRetry(); + brokerCepService.publishEvent(brokerUrl, username, password, topic, eventMap); + task.completed(); + + if (task.isLocalPublish()) { + log.debug("- Event published to local broker: subscriber={}, local-broker={}, username={}, topic={}, payload={}, duration={}ms", + senderName, brokerUrl, username, topic, eventMap, task.getTotalDuration()); + } else { + log.debug("- Event forwarded to grouping: subscriber={}, forwarded-to-grouping={}, url={}, username={}, topic={}, payload={}, duration={}ms", + senderName, task.brokerConnectionConfig, brokerUrl, username, topic, eventMap, task.getTotalDuration()); + } + + runIfNotNull(task.getSuccess()); + + } catch (Exception ex) { + task.increaseRetries(); + log.error("- Error while sending event: subscriber={}, forward-to-groupings={}, topic={}, retry={}, duration={}ms, payload={}, exception: ", + senderName, task.getBrokerConnectionConfig(), topic, task.getRetries()-1, task.getTotalDuration(), eventMap, ex); + + if (properties.getMaxEventForwardRetries()>=0 && task.getRetries() > properties.getMaxEventForwardRetries()) { + log.error("- Max event publish/forward retries exceeded. Dropping event: subscriber={}, forward-to-groupings={}, topic={}, payload={}", + senderName, task.getBrokerConnectionConfig(), topic, eventMap); + + runIfNotNull(task.getFailure()); + + } else + if (properties.getMaxEventForwardDuration()>0 && task.getTotalDuration() > properties.getMaxEventForwardDuration()) { + log.error("- Max event publish/forward duration exceeded. Dropping event: subscriber={}, forward-to-groupings={}, topic={}, payload={}", + senderName, task.getBrokerConnectionConfig(), topic, eventMap); + + runIfNotNull(task.getFailure()); + + } else { + eventForwardingQueue.add(task); + log.debug("- Event placed back in queue: subscriber={}, forward-to-groupings={}, topic={}, payload={}", + senderName, task.getBrokerConnectionConfig(), topic, eventMap); + } + } + } + + protected void runIfNotNull(Runnable r) { + if (r==null) return; + r.run(); + } + + @Getter + @RequiredArgsConstructor + protected static class EventForwardTask { + private final String senderName; + private final boolean localPublish; + private final GroupingConfiguration.BrokerConnectionConfig brokerConnectionConfig; + private final String topic; + private final Map eventMap; + private final Runnable success; + private final Runnable failure; + private final long creation = System.currentTimeMillis(); + + private long lastRetryStart; + private long lastRetryEnd; + private boolean completed; + private int retries = 0; + + public void newRetry() { + if (completed) return; + lastRetryStart = System.currentTimeMillis(); + } + + public void completed() { + if (completed) return; + completed = true; + lastRetryEnd = System.currentTimeMillis(); + } + + public void increaseRetries() { + if (completed) return; + lastRetryEnd = System.currentTimeMillis(); + ++retries; + } + + public long getLastRetryDuration() { + return lastRetryEnd - lastRetryStart; + } + + public long getTotalDuration() { + return lastRetryEnd - creation; + } + } +} diff --git a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/broker/BrokerConfig.java b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/broker/BrokerConfig.java index 4b10425f12a68eaabaa2678886818284542288ed..3ca67e816ffc22d5404788fc4af2a679bf576919 100644 --- a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/broker/BrokerConfig.java +++ b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/broker/BrokerConfig.java @@ -30,7 +30,6 @@ import org.apache.activemq.usage.SystemUsage; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -80,12 +79,7 @@ public class BrokerConfig implements InitializingBean { private KeyStore truststore; - @Value("${brokercep.broker-url-2}") - private String brokerUrl2; - @Value("${brokercep.broker-url-3}") - private String brokerUrl3; - - private HashMap connectionFactoryCache = new HashMap<>(); + private final HashMap connectionFactoryCache = new HashMap<>(); @Override public void afterPropertiesSet() throws Exception { @@ -167,11 +161,11 @@ public class BrokerConfig implements InitializingBean { this.brokerCert = KeystoreUtil .getKeystore(properties.getSsl().getKeystoreFile(), properties.getSsl().getKeystoreType(), properties.getSsl().getKeystorePassword()) .passwordUtil(passwordUtil) - .getEntryCertificateAsPEM(properties.getSsl().getKeyEntryNameValue()); + .getEntryCertificateAsPEM(properties.getSsl().getKeyEntryName()); log.trace("BrokerConfig.initializeKeyAndCert(): Retrieving certificate for Broker-SSL: file={}, type={}, password={}, alias={}, cert=\n{}", properties.getSsl().getKeystoreFile(), properties.getSsl().getKeystoreType(), passwordUtil.encodePassword(properties.getSsl().getKeystorePassword()), - properties.getSsl().getKeyEntryNameValue(), this.brokerCert); + properties.getSsl().getKeyEntryName(), this.brokerCert); log.info("BrokerConfig.initializeKeyAndCert(): Initializing keystore, truststore and certificate for Broker-SSL... done"); } @@ -238,31 +232,41 @@ public class BrokerConfig implements InitializingBean { /** * Creates an embedded JMS server - * - * @return - * @throws Exception */ - @Bean//(initMethod = "start", destroyMethod = "stop") + @Bean public BrokerService createBrokerService() throws Exception { // Create new broker service instance String brokerUrl = getBrokerUrl(); log.info("BrokerConfig: Creating new Broker Service instance: url={}", brokerUrl); - BrokerService brokerService; - if (brokerUrl.startsWith("ssl")) { - brokerService = _createSslBrokerService(); - } else { - brokerService = new BrokerService(); - brokerService.addConnector(brokerUrl); - } + SslBrokerService brokerService = new SslBrokerService();; brokerService.setBrokerName(getBrokerName()); - // Start additional connectors (non-SSL) - log.debug("BrokerConfig: 2nd connector: {}", brokerUrl2); - log.debug("BrokerConfig: 3rd connector: {}", brokerUrl3); - if (StringUtils.isNotEmpty(brokerUrl2)) brokerService.addConnector(brokerUrl2); - if (StringUtils.isNotEmpty(brokerUrl3)) brokerService.addConnector(brokerUrl3); + // Initialize keystore and truststore for broker SSL connectors + KeyManager[] keystore = null; + TrustManager[] truststore = null; + if (secureConnectorsExist()) { + keystore = readKeystore(); + truststore = readTruststore(); + } + + // Start broker connectors + if (properties.getBrokerUrlList()!=null) { + int i = 1; + for (String url : properties.getBrokerUrlList()) { + if (StringUtils.isNotBlank(url)) { + String num = (i==1 ? "st" : (i==2 ? "nd" : "rd")); + log.info("BrokerConfig: {}{} connector: {}", i++, num, url); + if (isSecureUrl(url)) + // Add an SSL broker connector + brokerService.addSslConnector(url, keystore, truststore, null); + else + // Add a non-SSL broker connector + brokerService.addConnector(url); + } + } + } // Set authentication and authorization plugins List plugins = new ArrayList<>(); @@ -280,14 +284,14 @@ public class BrokerConfig implements InitializingBean { brokerService.setUseShutdownHook(properties.isBrokerUsingShutdownHook()); brokerService.setAdvisorySupport(properties.isBrokerAdvisorySupportEnabled()); - brokerService.setPopulateJMSXUserID(properties.isPopulateJmsxUserId()); - brokerService.setEnableStatistics(properties.isEnableStatistics()); + brokerService.setPopulateJMSXUserID(properties.isBrokerPopulateJmsxUserId()); + brokerService.setEnableStatistics(properties.isBrokerEnableStatistics()); // Change the JMX connector port - if (properties != null && properties.getConnectorPort() > 0) { + if (properties.getManagementConnectorPort() > 0) { if (brokerService.getManagementContext() != null) { - log.info("BrokerConfig.createBrokerService(): Setting connector port to: {}", properties.getConnectorPort()); - brokerService.getManagementContext().setConnectorPort(properties.getConnectorPort()); + log.info("BrokerConfig.createBrokerService(): Setting connector port to: {}", properties.getManagementConnectorPort()); + brokerService.getManagementContext().setConnectorPort(properties.getManagementConnectorPort()); } } @@ -317,8 +321,8 @@ public class BrokerConfig implements InitializingBean { } // Set memory limit in order not to use too much memory - int memHeapPercent = properties.getMemoryJvmHeapPercentage(); - long memSize = properties.getMemorySize(); + int memHeapPercent = properties.getUsage().getMemory().getJvmHeapPercentage(); + long memSize = properties.getUsage().getMemory().getSize(); if (memHeapPercent > 0 || memSize > 0) { final MemoryUsage memoryUsage = new MemoryUsage(); if (memHeapPercent > 0) { @@ -372,18 +376,19 @@ public class BrokerConfig implements InitializingBean { log.info("BrokerConfig: Registering message interceptors... done"); } - private BrokerService _createSslBrokerService() throws Exception { - // Create new SSL broker service instance - SslBrokerService brokerService = new SslBrokerService(); - - // Add ActiveMQ SSL connector using configured keystore and truststore - final KeyManager[] keystore = readKeystore(); - final TrustManager[] truststore = readTruststore(); - String props = Optional.ofNullable(properties.getBrokerUrlProperties()).orElse("").trim(); - if (!props.isEmpty() && !props.startsWith("?")) props = "?" + props; - brokerService.addSslConnector(properties.getBrokerUrl() + props, keystore, truststore, null); + private boolean isSecureUrl(String url) { + int p = url.indexOf(":"); + if (p<=0) return false; + String scheme = url.substring(0, p); + return scheme.startsWith("ssl") || scheme.contains("+ssl") || scheme.startsWith("https:"); + } - return brokerService; + private boolean secureConnectorsExist() { + if (properties.getBrokerUrlList()!=null) { + for (String url : properties.getBrokerUrlList()) + if (isSecureUrl(url.trim())) return true; + } + return false; } private KeyManager[] readKeystore() throws Exception { diff --git a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/cep/CepEvalFunction.java b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/cep/CepEvalFunction.java index b648a39b41e5926e34faedb6ec68f7aba4b5f95b..9e198c5f0c8906fd723b013958802aad412df82c 100644 --- a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/cep/CepEvalFunction.java +++ b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/cep/CepEvalFunction.java @@ -53,7 +53,7 @@ public class CepEvalFunction { if (entryValue instanceof String) entryValue = Double.parseDouble((String)entryValue); args.put(entryName, (Double) entryValue); } - log.debug(">> eval(map): mp-args: {}", args); + log.debug(">> eval(map): map-args: {}", args); double result = MathUtil.eval(formula, args); log.debug(">> eval(map): result: {}", result); @@ -73,7 +73,7 @@ public class CepEvalFunction { throw new IllegalArgumentException("The num. of stream names provided is not equal to the num. of values provided"); Map args = new HashMap<>(); for (int i = 0; i < names.length; i++) args.put(names[i].trim(), v[i]); - log.debug(">> eval(double): mp-args: {}", args); + log.debug(">> eval(double): map-args: {}", args); double result = MathUtil.eval(formula, args); log.debug(">> eval(double): result: {}", result); diff --git a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/properties/BrokerCepProperties.java b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/properties/BrokerCepProperties.java index 667fe90c13ce404418927da18029d5429c8e1bcd..03d14bcecdb2641d35305b83653d20c6dca914bb 100644 --- a/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/properties/BrokerCepProperties.java +++ b/event-management/broker-cep/src/main/java/eu/melodic/event/brokercep/properties/BrokerCepProperties.java @@ -9,92 +9,82 @@ package eu.melodic.event.brokercep.properties; +import eu.melodic.event.util.EmsConstant; import eu.melodic.event.util.KeystoreAndCertificateProperties; import lombok.Data; import lombok.ToString; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +@Slf4j @Data @Configuration -@ConfigurationProperties(prefix = "brokercep") +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "brokercep") @PropertySource("file:${MELODIC_CONFIG_DIR}/eu.melodic.event.brokercep.properties") -@Slf4j -public class BrokerCepProperties { - - @Value("${broker-name:broker}") - private String brokerName; - @Value("${broker-url:ssl://0.0.0.0:61616}") - private String brokerUrl; - @Value("${broker-url-for-consumer:ssl://127.0.0.1:61616}") - private String brokerUrlForConsumer; - @Value("#{ '${brokercep.broker-url-for-clients}'!='' ? '${brokercep.broker-url-for-clients}' : 'ssl://'+T(eu.melodic.event.util.NetUtil).getPublicIpAddress()+':61616' }") - private String brokerUrlForClients; - - public String getBrokerUrl() { return KeystoreAndCertificateProperties.prepareUrl(brokerUrl); } - public String getBrokerUrlForConsumer() { return KeystoreAndCertificateProperties.prepareUrl(brokerUrlForConsumer); } - public String getBrokerUrlForClients() { return KeystoreAndCertificateProperties.prepareUrl(brokerUrlForClients); } - - @Value("${default-ip-address:}") - private String defaultIpAddress; - @Value("${public-ip-address:}") - private String publicIpAddress; - - @Value("${broker-url-properties:}") - private String brokerUrlProperties; - @Value("${brokercep.ssl.client-auth.required:false}") - private boolean clientAuthRequired; - @Value("${connector-port:-1}") - private int connectorPort; - @Value("${bypass-local-broker:false}") +public class BrokerCepProperties implements InitializingBean { + public void afterPropertiesSet() { + log.debug("BrokerCepProperties: {}", this); + } + + private String brokerName = "broker"; + + // Broker connector URLs + private List brokerUrl = Collections.singletonList("ssl://0.0.0.0:61616"); + public String getBrokerUrl() { return brokerUrl.get(0); } + public List getBrokerUrlList() { return brokerUrl; } + + private String brokerUrlForConsumer = "ssl://127.0.0.1:61616"; + private String brokerUrlForClients = "ssl://"+eu.melodic.event.util.NetUtil.getPublicIpAddress()+":61616"; + + private int managementConnectorPort = -1; private boolean bypassLocalBroker; // brokercep.ssl.** settings private KeystoreAndCertificateProperties ssl; - @Value("${authentication-enabled:false}") private boolean authenticationEnabled; @ToString.Exclude - @Value("${additional-broker-credentials:}") private String additionalBrokerCredentials; - @Value("${authorization-enabled:false}") private boolean authorizationEnabled; - @Value("${broker-persistence-enabled:false}") private boolean brokerPersistenceEnabled; - @Value("${broker-using-jmx:false}") private boolean brokerUsingJmx; - @Value("${broker-advisory-support-enabled:false}") private boolean brokerAdvisorySupportEnabled; - @Value("${broker-using-shutdown-hook:false}") private boolean brokerUsingShutdownHook; - @Value("${broker-enable-statistics:false}") - private boolean enableStatistics; - @Value("${broker-populate-jmsx-user-id:false}") - private boolean populateJmsxUserId; + private boolean brokerEnableStatistics; + private boolean brokerPopulateJmsxUserId; + + private boolean enableAdvisoryWatcher = true; private List messageInterceptors; private Map messageInterceptorsSpecs = new HashMap<>(); - @Value("${message-forward-destinations:}#{T(java.util.Collections).emptyList()}") - private List messageForwardDestinations; + private List messageForwardDestinations = Collections.emptyList(); - @Value("${enable-advisory-watcher:true}") - private boolean enableAdvisoryWatcher; + private int maxEventForwardRetries = -1; + private long maxEventForwardDuration = -1; - @Value("${brokercep.usage.memory.jvm-heap-percentage:-1}") - private int memoryJvmHeapPercentage; - @Value("${brokercep.usage.memory.size:-1}") - private long memorySize; + private Usage usage = new Usage(); + @Data + public static class Usage { + private Memory memory = new Memory(); + + @Data + public static class Memory { + private int jvmHeapPercentage = -1; + private long size = -1; + } + } @Data public static class MessageInterceptorSpec { private String className; diff --git a/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/BrokerClient.java b/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/BrokerClient.java index 28a1f408d1778bdf4dbdee9d76a7670882c1ac10..ff818362ebdcb25915b688dee90e1d0f0128cd5a 100644 --- a/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/BrokerClient.java +++ b/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/BrokerClient.java @@ -390,12 +390,12 @@ public class BrokerClient { log.debug("BrokerClient.createConnectionFactory(): Creating new SSL connection factory instance: url={}", brokerUrl); final ActiveMQSslConnectionFactory sslConnectionFactory = new ActiveMQSslConnectionFactory(brokerUrl); try { - sslConnectionFactory.setTrustStore(properties.getTruststoreFile()); - sslConnectionFactory.setTrustStoreType(properties.getTruststoreType()); - sslConnectionFactory.setTrustStorePassword(properties.getTruststorePassword()); - sslConnectionFactory.setKeyStore(properties.getKeystoreFile()); - sslConnectionFactory.setKeyStoreType(properties.getKeystoreType()); - sslConnectionFactory.setKeyStorePassword(properties.getKeystorePassword()); + sslConnectionFactory.setTrustStore(properties.getSsl().getTruststoreFile()); + sslConnectionFactory.setTrustStoreType(properties.getSsl().getTruststoreType()); + sslConnectionFactory.setTrustStorePassword(properties.getSsl().getTruststorePassword()); + sslConnectionFactory.setKeyStore(properties.getSsl().getKeystoreFile()); + sslConnectionFactory.setKeyStoreType(properties.getSsl().getKeystoreType()); + sslConnectionFactory.setKeyStorePassword(properties.getSsl().getKeystorePassword()); //sslConnectionFactory.setKeyStoreKeyPassword( properties........ ); connectionFactory = sslConnectionFactory; diff --git a/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/properties/BrokerClientProperties.java b/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/properties/BrokerClientProperties.java index 6c9de856e6e8ae16945043efc479715dd581cfde..f34bdd1ff141a1109ba48d80dfcb68d42aa09273 100644 --- a/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/properties/BrokerClientProperties.java +++ b/event-management/broker-client/src/main/java/eu/melodic/event/brokerclient/properties/BrokerClientProperties.java @@ -12,63 +12,48 @@ package eu.melodic.event.brokerclient.properties; import lombok.Data; import lombok.ToString; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; @Data -@ToString(exclude = {"truststorePassword", "keystorePassword", "brokerPassword"}) @Configuration @ConfigurationProperties(prefix = "brokerclient") //@PropertySource("file:${MELODIC_CONFIG_DIR}/eu.melodic.event.brokerclient.properties") @Slf4j public class BrokerClientProperties { - @Value("${broker-name:broker}") - private String brokerName; - @Value("${broker-url:tcp://localhost:61616}") - private String brokerUrl; - @Value("${broker-url-properties:}") + private String brokerName = "broker"; + private String brokerUrl = "tcp://localhost:61616"; private String brokerUrlProperties; - @Value("${ssl.client-auth.required:false}") - private boolean clientAuthRequired; - @Value("${connector-port:-1}") - private int connectorPort; - @Value("${preserve-connection:false}") + private int managementConnectorPort = -1; private boolean preserveConnection; - @Value("${ssl.truststore.file:}") - private String truststoreFile; - @Value("${ssl.truststore.type:}") - private String truststoreType; - @Value("${ssl.truststore.password:}") - private String truststorePassword; - @Value("${ssl.keystore.file:}") - private String keystoreFile; - @Value("${ssl.keystore.type:}") - private String keystoreType; - @Value("${ssl.keystore.password:}") - private String keystorePassword; + private Ssl ssl = new Ssl(); - @Value("${broker-username:}") private String brokerUsername; - @Value("${broker-password:}") + @ToString.Exclude private String brokerPassword; + @Data + public static class Ssl { + private boolean clientAuthRequired; + private String truststoreFile; + private String truststoreType; + @ToString.Exclude + private String truststorePassword; + private String keystoreFile; + private String keystoreType; + @ToString.Exclude + private String keystorePassword; + } + public BrokerClientProperties() { brokerName = "broker"; brokerUrl = "tcp://localhost:61616"; brokerUrlProperties = ""; - connectorPort = -1; + managementConnectorPort = -1; preserveConnection = false; - truststoreFile = ""; - truststoreType = ""; - truststorePassword = ""; - keystoreFile = ""; - keystoreType = ""; - keystorePassword = ""; - clientAuthRequired = false; + ssl = new Ssl(); brokerUsername = ""; brokerPassword = ""; @@ -78,20 +63,21 @@ public class BrokerClientProperties { brokerName = p.getProperty("brokerclient.broker-name", "broker"); brokerUrl = p.getProperty("brokerclient.broker-url", "tcp://localhost:61616"); brokerUrlProperties = p.getProperty("brokerclient.broker-url-properties", ""); - connectorPort = Integer.parseInt(p.getProperty("brokerclient.connector-port", "-1")); + managementConnectorPort = Integer.parseInt(p.getProperty("brokerclient.connector-port", "-1")); preserveConnection = Boolean.parseBoolean(p.getProperty("brokerclient.preserve-connection", "false")); - truststoreFile = p.getProperty("brokerclient.ssl.truststore.file", ""); - truststoreType = p.getProperty("brokerclient.ssl.truststore.type", ""); - truststorePassword = p.getProperty("brokerclient.ssl.truststore.password", ""); - keystoreFile = p.getProperty("brokerclient.ssl.keystore.file", ""); - keystoreType = p.getProperty("brokerclient.ssl.keystore.type", ""); - keystorePassword = p.getProperty("brokerclient.ssl.keystore.password", ""); - clientAuthRequired = Boolean.parseBoolean(p.getProperty("brokerclient.ssl.client-auth.required", "false")); + ssl = new Ssl(); + ssl.truststoreFile = p.getProperty("brokerclient.ssl.truststore.file", ""); + ssl.truststoreType = p.getProperty("brokerclient.ssl.truststore.type", ""); + ssl.truststorePassword = p.getProperty("brokerclient.ssl.truststore.password", ""); + ssl.keystoreFile = p.getProperty("brokerclient.ssl.keystore.file", ""); + ssl.keystoreType = p.getProperty("brokerclient.ssl.keystore.type", ""); + ssl.keystorePassword = p.getProperty("brokerclient.ssl.keystore.password", ""); + ssl.clientAuthRequired = Boolean.parseBoolean(p.getProperty("brokerclient.ssl.client-auth.required", "false")); brokerUsername = p.getProperty("brokerclient.broker-username", ""); brokerPassword = p.getProperty("brokerclient.broker-password", ""); - brokerUrlProperties = brokerUrlProperties.replace("${brokerclient.ssl.client-auth.required}", Boolean.toString(clientAuthRequired)); + brokerUrlProperties = brokerUrlProperties.replace("${brokerclient.ssl.client-auth.required}", Boolean.toString(ssl.clientAuthRequired)); } } diff --git a/event-management/common/src/main/java/eu/melodic/event/common/client/SshClient.java b/event-management/common/src/main/java/eu/melodic/event/common/client/SshClient.java new file mode 100644 index 0000000000000000000000000000000000000000..7e06e5e75fb72878c1a3e69776d7634a5f9a7978 --- /dev/null +++ b/event-management/common/src/main/java/eu/melodic/event/common/client/SshClient.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.common.client; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; + +public interface SshClient { + void setConfiguration(C config); + void setUseServerKeyVerifier(boolean useServerKeyVerifier); + void start() throws IOException; + void stop() throws IOException; + InputStream getIn(); + PrintStream getOut(); + PrintStream getErr(); +} diff --git a/event-management/common/src/main/java/eu/melodic/event/common/client/SshClientProperties.java b/event-management/common/src/main/java/eu/melodic/event/common/client/SshClientProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..d5881dedd0288706490b544e47424abc510cf4c7 --- /dev/null +++ b/event-management/common/src/main/java/eu/melodic/event/common/client/SshClientProperties.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.common.client; + +import lombok.Data; +import lombok.ToString; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +@ConfigurationProperties +@ToString(exclude = "serverPassword") +public class SshClientProperties { + private long authTimeout = 60000; + private long execTimeout = 120000; + private long retryPeriod = 60000; + + private String clientId; + + private String serverAddress; + private int serverPort = 22; + private String serverPubkey; + private String serverFingerprint; + + private String serverUsername; + private String serverPassword; +} diff --git a/event-management/common/src/main/java/eu/melodic/event/common/collector/CollectorContext.java b/event-management/common/src/main/java/eu/melodic/event/common/collector/CollectorContext.java index a2498ddc751f6bad694ab7b96a082c2dcebbdda8..333e67128dec9a90bf205868941e59b02ef86705 100644 --- a/event-management/common/src/main/java/eu/melodic/event/common/collector/CollectorContext.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/collector/CollectorContext.java @@ -10,15 +10,19 @@ package eu.melodic.event.common.collector; import eu.melodic.event.brokercep.event.EventMap; +import eu.melodic.event.common.client.SshClient; +import eu.melodic.event.common.client.SshClientProperties; import eu.melodic.event.util.ClientConfiguration; import java.io.Serializable; import java.util.List; import java.util.Set; -public interface CollectorContext { +public interface CollectorContext

{ List getNodeConfigurations(); Set getNodesWithoutClient(); boolean isAggregator(); boolean sendEvent(String connectionString, String destinationName, EventMap event, boolean createDestination); + default SshClient

getSshClient() { return null; } + default P getSshClientProperties() { return null; } } diff --git a/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollector.java b/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollector.java index e14238c95eccae1957a91146a54664eda2326f30..dfd5fbee770454a5da02b36dbf145a695ca05f19 100644 --- a/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollector.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollector.java @@ -11,6 +11,8 @@ package eu.melodic.event.common.collector.netdata; import eu.melodic.event.brokercep.event.EventMap; import eu.melodic.event.common.collector.CollectorContext; +import eu.melodic.event.common.misc.EventConstant; +import eu.melodic.event.common.recovery.RecoveryConstant; import eu.melodic.event.util.EmsConstant; import eu.melodic.event.util.EventBus; import lombok.NonNull; @@ -24,13 +26,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.scheduling.TaskScheduler; import org.springframework.web.client.RestTemplate; -import java.io.Serializable; import java.time.Duration; -import java.time.Instant; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.ScheduledFuture; import java.util.stream.Collectors; @@ -39,13 +36,13 @@ import java.util.stream.Collectors; */ @Slf4j @RequiredArgsConstructor -public class NetdataCollector implements InitializingBean, Runnable { +public class NetdataCollector implements InitializingBean, Runnable, EventBus.EventConsumer { public final static String NETDATA_COLLECTION_START = "NETDATA_COLLECTION_START"; public final static String NETDATA_COLLECTION_END = "NETDATA_COLLECTION_END"; public final static String NETDATA_CONN_OK = "NETDATA_CONN_OK"; public final static String NETDATA_CONN_ERROR = "NETDATA_CONN_ERROR"; - public final static String NETDATA_NODE_PAUSED = "NETDATA_NODE_PAUSED"; - public final static String NETDATA_NODE_RESUMED = "NETDATA_NODE_RESUMED"; + public final static String NETDATA_NODE_OK = "NETDATA_NODE_OK"; + public final static String NETDATA_NODE_FAILED = "NETDATA_NODE_FAILED"; protected final NetdataCollectorProperties properties; protected final CollectorContext collectorContext; @@ -104,6 +101,11 @@ public class NetdataCollector implements InitializingBean, Runnable { log.info("Collectors::Netdata: configuration: {}", properties); + // Subscribe for SELF-HEALING plugin GIVE_UP events + eventBus.subscribe(RecoveryConstant.SELF_HEALING_RECOVERY_COMPLETED, this); + eventBus.subscribe(RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP, this); + eventBus.subscribe(EventConstant.EVENT_CLIENT_CONFIG_UPDATED, this); + // Schedule collection execution errorsMap.clear(); ignoredNodes.clear(); @@ -119,14 +121,45 @@ public class NetdataCollector implements InitializingBean, Runnable { return; } + // Unsubscribe from SELF-HEALING plugin GIVE_UP events + eventBus.unsubscribe(EventConstant.EVENT_CLIENT_CONFIG_UPDATED, this); + eventBus.unsubscribe(RecoveryConstant.SELF_HEALING_RECOVERY_COMPLETED, this); + eventBus.unsubscribe(RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP, this); + // Cancel collection execution started = false; runner.cancel(true); runner = null; - ignoredNodes.values().forEach(task -> task.cancel(true)); + ignoredNodes.values().stream().filter(Objects::nonNull).forEach(task -> task.cancel(true)); log.info("Collectors::Netdata: Stopped"); } + @Override + public void onMessage(String topic, Object message, Object sender) { + log.trace("Collectors::Netdata: onMessage: BEGIN: topic={}, message={}, sender={}", topic, message, sender); + + String nodeAddress = (message!=null) ? message.toString() : null; + log.trace("Collectors::Netdata: nodeAddress={}", nodeAddress); + + if (RecoveryConstant.SELF_HEALING_RECOVERY_COMPLETED.equals(topic)) { + log.info("Collectors::Netdata: Resuming collection from Node: {}", nodeAddress); + ignoredNodes.remove(nodeAddress); + } else + if (RecoveryConstant.SELF_HEALING_RECOVERY_GIVE_UP.equals(topic)) { + log.info("Collectors::Netdata: Giving up collection from Node: {}", nodeAddress); + ignoredNodes.put(nodeAddress, null); + } else + if (EventConstant.EVENT_CLIENT_CONFIG_UPDATED.equals(topic)) { + log.info("Collectors::Netdata: Client configuration updated. Purging nodes without recovery task from ignore list: Old ignore list nodes: {}", ignoredNodes.keySet()); + List nodesToPurge = ignoredNodes.entrySet().stream().filter(e -> e.getValue() == null).map(Map.Entry::getKey).collect(Collectors.toList()); + nodesToPurge.forEach(node -> { + ignoredNodes.remove(node); + log.info("Collectors::Netdata: Client configuration updated. Node purged from ignore list: {}", node); + }); + } else + log.warn("Collectors::Netdata: onMessage: Event from unexpected topic received. Ignoring it: {}", topic); + } + public void run() { if (!started) return; @@ -151,7 +184,7 @@ public class NetdataCollector implements InitializingBean, Runnable { if (collectorContext.getNodesWithoutClient().size()>0) { log.info("Collectors::Netdata: Collecting metrics from remote nodes (without EMS client): {}", collectorContext.getNodesWithoutClient()); - for (Serializable nodeAddress : collectorContext.getNodesWithoutClient()) { + for (Object nodeAddress : collectorContext.getNodesWithoutClient()) { // collect data from remote node collectAndPublishData(nodeAddress.toString()); } @@ -174,32 +207,24 @@ public class NetdataCollector implements InitializingBean, Runnable { //if (Optional.ofNullable(errorsMap.put(nodeAddress, 0)).orElse(0)>0) sendEvent(NETDATA_CONN_OK, nodeAddress); sendEvent(NETDATA_CONN_OK, nodeAddress); + sendEvent(NETDATA_NODE_OK, nodeAddress); + errorsMap.put(nodeAddress, 0); return COLLECTION_RESULT.OK; } catch (Throwable t) { int errors = errorsMap.compute(nodeAddress, (k, v) -> Optional.ofNullable(v).orElse(0) + 1); int errorLimit = properties.getErrorLimit(); - int pausePeriod = properties.getPausePeriod(); log.warn("Collectors::Netdata: Exception while collecting metrics from node: {}, #errors={}, exception: {}", nodeAddress, errors, getExceptionMessages(t)); log.debug("Collectors::Netdata: Exception while collecting metrics from node: {}, #errors={}\n", nodeAddress, errors, t); sendEvent(NETDATA_CONN_ERROR, nodeAddress, "errors="+errors); - if (errorLimit>0 && pausePeriod>0) { - if (errors >= errorLimit) { - log.warn("Collectors::Netdata: Too many consecutive errors occurred while attempting to collect metrics from node: {}, num-of-errors={}", nodeAddress, errors); - log.warn("Collectors::Netdata: Will pause metrics collection from node for {} seconds: {}", pausePeriod, nodeAddress); - ignoredNodes.put(nodeAddress, taskScheduler.schedule(() -> { - errorsMap.put(nodeAddress, 0); - ignoredNodes.remove(nodeAddress); - log.info("Collectors::Netdata: Resumed metrics collection from node: {}", nodeAddress); - sendEvent(NETDATA_NODE_RESUMED, nodeAddress); - }, Instant.now().plusSeconds(pausePeriod))); - - sendEvent(NETDATA_NODE_PAUSED, nodeAddress); - } - } else - log.debug("Collectors::Netdata: Metrics collection pausing is disabled"); + if (errorLimit<=0 || errors >= errorLimit) { + log.warn("Collectors::Netdata: Too many consecutive errors occurred while attempting to collect metrics from node: {}, num-of-errors={}", nodeAddress, errors); + log.warn("Collectors::Netdata: Pausing collection from Node: {}", nodeAddress); + ignoredNodes.put(nodeAddress, null); + sendEvent(NETDATA_NODE_FAILED, nodeAddress); + } return COLLECTION_RESULT.ERROR; } } diff --git a/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollectorProperties.java b/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollectorProperties.java index b73c6cf5356bb74f9ae409da63df4aad014bce05..2f1013218cbc33351ad3637a505ad74b3b3de81e 100644 --- a/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollectorProperties.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/collector/netdata/NetdataCollectorProperties.java @@ -29,6 +29,5 @@ public class NetdataCollectorProperties { private boolean createTopic; private List allowedTopics; - private int errorLimit; // num of consecutive errors. Zero or negative value disables collection pausing - private int pausePeriod; // in seconds. Zero or negative value disables collection pausing + private int errorLimit; // num of consecutive errors. Zero or negative value will immediately trigger self-healing } diff --git a/event-management/common/src/main/java/eu/melodic/event/common/misc/EventConstant.java b/event-management/common/src/main/java/eu/melodic/event/common/misc/EventConstant.java new file mode 100644 index 0000000000000000000000000000000000000000..1695dd161abdec2ea1073dec3931a6d27e4a913c --- /dev/null +++ b/event-management/common/src/main/java/eu/melodic/event/common/misc/EventConstant.java @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.common.misc; + +/** + * Common Event Constants + */ +public class EventConstant { + public final static String EVENT_CLIENT_CONFIG_UPDATED = "EVENT_CLIENT_CONFIG_UPDATED"; +} \ No newline at end of file diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/info/SystemResourceMonitor.java b/event-management/common/src/main/java/eu/melodic/event/common/misc/SystemResourceMonitor.java similarity index 94% rename from event-management/control-service/src/main/java/eu/melodic/event/control/info/SystemResourceMonitor.java rename to event-management/common/src/main/java/eu/melodic/event/common/misc/SystemResourceMonitor.java index dc1c24b0ac37c7ccb046b8286158f80edab4937e..1f9fe8a83dba881d3c31c67eda5b8d6c92e398f3 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/info/SystemResourceMonitor.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/misc/SystemResourceMonitor.java @@ -7,7 +7,7 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.control.info; +package eu.melodic.event.common.misc; import eu.melodic.event.brokercep.BrokerCepService; import eu.melodic.event.brokercep.event.EventMap; @@ -21,8 +21,6 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Service; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -37,12 +35,12 @@ public class SystemResourceMonitor implements Runnable, InitializingBean { @Getter @Setter private boolean enabled = Boolean.parseBoolean( System.getenv().getOrDefault("EMS_SYSMON_ENABLED", "true")); - @Getter @Setter @Min(1000) + @Getter @Setter private long period = Math.max(1000L,Long.parseLong( System.getenv().getOrDefault("EMS_SYSMON_PERIOD", "30000"))); - @Getter @Setter @NotBlank - private String commandStr = System.getenv("EMS_SYSMON_COMMAND"); - @Getter @Setter @NotBlank + @Getter @Setter + private String commandStr = System.getenv().getOrDefault("EMS_SYSMON_COMMAND", "./bin/sysmon.sh"); + @Getter @Setter private String systemResourceMetricsTopic = System.getenv("EMS_SYSMON_TOPIC"); private final BrokerCepService brokerCepService; diff --git a/event-management/common/src/main/java/eu/melodic/event/common/recovery/AbstractRecoveryTask.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/AbstractRecoveryTask.java new file mode 100644 index 0000000000000000000000000000000000000000..3157dfe0a732fb5d68da3a82c285841d793a6a0a --- /dev/null +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/AbstractRecoveryTask.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.common.recovery; + +import eu.melodic.event.util.EventBus; +import eu.melodic.event.util.PasswordUtil; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.stereotype.Component; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.time.Instant; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +@Slf4j +@Component +@RequiredArgsConstructor +public abstract class AbstractRecoveryTask implements RecoveryTask { + @NonNull protected final EventBus eventBus; + @NonNull protected final PasswordUtil passwordUtil; + @NonNull protected final TaskScheduler taskScheduler; + @NonNull protected final SelfHealingProperties selfHealingProperties; + + @NonNull + @Getter @Setter + protected Map nodeInfo = Collections.emptyMap(); + + public abstract List getRecoveryCommands(); + public abstract void runNodeRecovery() throws Exception; + public abstract void runNodeRecovery(List recoveryCommands) throws Exception; + + protected void waitFor(long millis, String description) { + if (millis>0) { + log.warn("############## Waiting for {}ms after {}...", millis, description); + try { Thread.sleep(millis); } catch (InterruptedException e) { } + } + } + + protected void redirectOutput(InputStream in, String id, AtomicBoolean closed, String connectionClosedMessageFormatter, String exceptionMessageFormatter) { + taskScheduler.schedule(() -> { + try { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { + while (reader.ready()) { + log.info(" {}> {}", id, reader.readLine()); + } + } + } catch (IOException e) { + if (closed.get()) { + log.info(connectionClosedMessageFormatter, id); + } else { + log.error(exceptionMessageFormatter, id, e); + } + } + }, + Instant.now() + ); + } +} diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/EmsClientRecoveryTask.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/EmsClientRecoveryTask.java similarity index 71% rename from event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/EmsClientRecoveryTask.java rename to event-management/common/src/main/java/eu/melodic/event/common/recovery/EmsClientRecoveryTask.java index 8a7cacbe763b260a5301968a937f014db05473c7..53fab5d03f49c3353a0e38d63a487915868e205a 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/EmsClientRecoveryTask.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/EmsClientRecoveryTask.java @@ -7,15 +7,16 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.baguette.client.plugin.recovery; +package eu.melodic.event.common.recovery; +import eu.melodic.event.common.client.SshClientProperties; +import eu.melodic.event.common.collector.CollectorContext; import eu.melodic.event.util.EventBus; import eu.melodic.event.util.PasswordUtil; import lombok.Getter; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; @@ -24,11 +25,11 @@ import java.util.Collections; import java.util.List; /** - * EMS client (client-side) Self-Healing + * EMS client Self-Healing */ @Slf4j @Component -public class EmsClientRecoveryTask extends VmNodeRecoveryTask { +public class EmsClientRecoveryTask

extends VmNodeRecoveryTask

{ @Getter private final List recoveryCommands = Collections.unmodifiableList(Arrays.asList( new RECOVERY_COMMAND("Initial wait...", @@ -39,14 +40,13 @@ public class EmsClientRecoveryTask extends VmNodeRecoveryTask { "/opt/baguette-client/bin/run.sh",0, 10000) )); - @Value("${self.healing.recovery.file.baguette:}") - private String emsRecoveryFile; - - public EmsClientRecoveryTask(@NonNull EventBus eventBus, @NonNull PasswordUtil passwordUtil, @NonNull TaskScheduler taskScheduler) { - super(eventBus, passwordUtil, taskScheduler); + public EmsClientRecoveryTask(@NonNull EventBus eventBus, @NonNull PasswordUtil passwordUtil, @NonNull TaskScheduler taskScheduler, @NonNull CollectorContext

collectorContext, @NonNull SelfHealingProperties selfHealingProperties) { + super(eventBus, passwordUtil, taskScheduler, selfHealingProperties, collectorContext); } public void runNodeRecovery() throws Exception { + String emsRecoveryFile = selfHealingProperties.getRecovery().getFile().get("baguette"); + log.debug("runNodeRecovery: file={}", emsRecoveryFile); if (StringUtils.isNotBlank(emsRecoveryFile)) runNodeRecovery(emsRecoveryFile); else diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NetdataAgentLocalRecoveryTask.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/NetdataAgentLocalRecoveryTask.java similarity index 80% rename from event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NetdataAgentLocalRecoveryTask.java rename to event-management/common/src/main/java/eu/melodic/event/common/recovery/NetdataAgentLocalRecoveryTask.java index 5ef1e707df689fc0dd917544baaae211c494ff2d..4680dd2db61c62d5b793d081fc838be135cf0781 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NetdataAgentLocalRecoveryTask.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/NetdataAgentLocalRecoveryTask.java @@ -7,7 +7,7 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.baguette.client.plugin.recovery; +package eu.melodic.event.common.recovery; import eu.melodic.event.util.EventBus; import eu.melodic.event.util.PasswordUtil; @@ -15,7 +15,6 @@ import lombok.Getter; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; @@ -24,7 +23,7 @@ import java.util.Collections; import java.util.List; /** - * Netdata agent (client-side) Self-Healing + * Local Netdata agent Self-Healing */ @Slf4j @Component @@ -39,14 +38,13 @@ public class NetdataAgentLocalRecoveryTask extends ShellRecoveryTask { "sudo netdata",0, 10000) )); - @Value("${self.healing.recovery.file.netdata:}") - private String netdataRecoveryFile; - - public NetdataAgentLocalRecoveryTask(@NonNull EventBus eventBus, @NonNull PasswordUtil passwordUtil, @NonNull TaskScheduler taskScheduler) { - super(eventBus, taskScheduler); + public NetdataAgentLocalRecoveryTask(@NonNull EventBus eventBus, @NonNull PasswordUtil passwordUtil, @NonNull TaskScheduler taskScheduler, @NonNull SelfHealingProperties selfHealingProperties) { + super(eventBus, passwordUtil, taskScheduler, selfHealingProperties); } public void runNodeRecovery() throws Exception { + String netdataRecoveryFile = selfHealingProperties.getRecovery().getFile().get("netdata"); + log.debug("runNodeRecovery: file={}", netdataRecoveryFile); if (StringUtils.isNotBlank(netdataRecoveryFile)) runNodeRecovery(netdataRecoveryFile); else diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NetdataAgentRecoveryTask.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/NetdataAgentRecoveryTask.java similarity index 70% rename from event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NetdataAgentRecoveryTask.java rename to event-management/common/src/main/java/eu/melodic/event/common/recovery/NetdataAgentRecoveryTask.java index 1b986d6c56c99687e132d50b4fc163476753de11..7ecc449181fe1c17b915650d24c31718c25d51f3 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/NetdataAgentRecoveryTask.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/NetdataAgentRecoveryTask.java @@ -7,15 +7,16 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.baguette.client.plugin.recovery; +package eu.melodic.event.common.recovery; +import eu.melodic.event.common.client.SshClientProperties; +import eu.melodic.event.common.collector.CollectorContext; import eu.melodic.event.util.EventBus; import eu.melodic.event.util.PasswordUtil; import lombok.Getter; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; @@ -24,11 +25,11 @@ import java.util.Collections; import java.util.List; /** - * Netdata agent (client-side) Self-Healing + * Remote Netdata agent Self-Healing using an SSH connection */ @Slf4j @Component -public class NetdataAgentRecoveryTask extends VmNodeRecoveryTask { +public class NetdataAgentRecoveryTask

extends VmNodeRecoveryTask

{ @Getter private final List recoveryCommands = Collections.unmodifiableList(Arrays.asList( new RECOVERY_COMMAND("Initial wait...", @@ -39,14 +40,13 @@ public class NetdataAgentRecoveryTask extends VmNodeRecoveryTask { "sudo netdata",0, 10000) )); - @Value("${self.healing.recovery.file.netdata:}") - private String netdataRecoveryFile; - - public NetdataAgentRecoveryTask(@NonNull EventBus eventBus, @NonNull PasswordUtil passwordUtil, @NonNull TaskScheduler taskScheduler) { - super(eventBus, passwordUtil, taskScheduler); + public NetdataAgentRecoveryTask(@NonNull EventBus eventBus, @NonNull PasswordUtil passwordUtil, @NonNull TaskScheduler taskScheduler, @NonNull CollectorContext

collectorContext, @NonNull SelfHealingProperties selfHealingProperties) { + super(eventBus, passwordUtil, taskScheduler, selfHealingProperties, collectorContext); } public void runNodeRecovery() throws Exception { + String netdataRecoveryFile = selfHealingProperties.getRecovery().getFile().get("netdata"); + log.debug("runNodeRecovery: file={}", netdataRecoveryFile); if (StringUtils.isNotBlank(netdataRecoveryFile)) runNodeRecovery(netdataRecoveryFile); else diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/RECOVERY_COMMAND.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/RECOVERY_COMMAND.java similarity index 87% rename from event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/RECOVERY_COMMAND.java rename to event-management/common/src/main/java/eu/melodic/event/common/recovery/RECOVERY_COMMAND.java index 727499505c8968e29b2a7b0d3f42cb4b84fd739f..a16e017e01684fb64d5c8ab9f8a457e9c5188627 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/RECOVERY_COMMAND.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/RECOVERY_COMMAND.java @@ -7,12 +7,12 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.baguette.client.plugin.recovery; +package eu.melodic.event.common.recovery; import lombok.Data; @Data -class RECOVERY_COMMAND { +public class RECOVERY_COMMAND { private final String name; private final String command; private final long waitBefore; diff --git a/event-management/common/src/main/java/eu/melodic/event/common/recovery/RecoveryConstant.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/RecoveryConstant.java new file mode 100644 index 0000000000000000000000000000000000000000..1b573e7e1e4fb9df8ae9ea13944d4fce67d16f79 --- /dev/null +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/RecoveryConstant.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.common.recovery; + +/** + * Recovery Constant + */ +public class RecoveryConstant { + public final static String SELF_HEALING_RECOVERY_FAILED = "SELF_HEALING_RECOVERY_FAILED"; + public final static String SELF_HEALING_RECOVERY_GIVE_UP = "SELF_HEALING_RECOVERY_GIVE_UP"; + public final static String SELF_HEALING_RECOVERY_COMPLETED = "SELF_HEALING_RECOVERY_COMPLETED"; +} \ No newline at end of file diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/RecoveryTask.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/RecoveryTask.java similarity index 93% rename from event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/RecoveryTask.java rename to event-management/common/src/main/java/eu/melodic/event/common/recovery/RecoveryTask.java index 87e5dc1cb0da1235262f0a20efbf09869a5ecbbb..ee302a98e0f6cb98d97901ed4371a52271b43704 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/RecoveryTask.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/RecoveryTask.java @@ -7,7 +7,7 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.baguette.client.plugin.recovery; +package eu.melodic.event.common.recovery; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -19,7 +19,7 @@ import java.util.List; import java.util.Map; /** - * Client-side Self-Healing task + * Self-Healing task */ public interface RecoveryTask { Map getNodeInfo(); diff --git a/event-management/common/src/main/java/eu/melodic/event/common/recovery/SelfHealingProperties.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/SelfHealingProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..3b5dbdcd49991977097c2045e3839553920d03c2 --- /dev/null +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/SelfHealingProperties.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.common.recovery; + +import eu.melodic.event.util.EmsConstant; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +@Data +@Configuration +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "self.healing") +public class SelfHealingProperties { + private boolean enabled = true; + private Recovery recovery = new Recovery(); + + @Data + public static class Recovery { + private long delay = 10000; + private long retryDelay = 60000; + private int maxRetries = 3; + + private Map file = new HashMap<>(); + } +} diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/ShellRecoveryTask.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/ShellRecoveryTask.java similarity index 58% rename from event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/ShellRecoveryTask.java rename to event-management/common/src/main/java/eu/melodic/event/common/recovery/ShellRecoveryTask.java index 05cae3af2b992d3bc6dc53fc9eb3e15685649ad6..2ac45b61017398bdb8fa72ff46b3996fcdf0320c 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/ShellRecoveryTask.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/ShellRecoveryTask.java @@ -7,41 +7,30 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.baguette.client.plugin.recovery; +package eu.melodic.event.common.recovery; import eu.melodic.event.util.EventBus; -import lombok.*; +import eu.melodic.event.util.PasswordUtil; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; -import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.time.Instant; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; -import static eu.melodic.event.baguette.client.plugin.recovery.SelfHealingPlugin.SELF_HEALING_RECOVERY_COMPLETED; +import static eu.melodic.event.common.recovery.RecoveryConstant.SELF_HEALING_RECOVERY_COMPLETED; /** - * Client-side, Local-node Self-Healing + * Local-node Self-Healing using Shell */ @Slf4j @Component -@RequiredArgsConstructor -public class ShellRecoveryTask implements RecoveryTask { - @NonNull private final EventBus eventBus; - @NonNull private final TaskScheduler taskScheduler; - - @Getter @Setter - private Map nodeInfo; - - public void setNodeInfo(@NonNull Map nodeInfo) { - this.nodeInfo = nodeInfo; +public class ShellRecoveryTask extends AbstractRecoveryTask { + public ShellRecoveryTask(EventBus eventBus, PasswordUtil passwordUtil, TaskScheduler taskScheduler, SelfHealingProperties selfHealingProperties) { + super(eventBus, passwordUtil, taskScheduler, selfHealingProperties); } @SneakyThrows @@ -83,31 +72,10 @@ public class ShellRecoveryTask implements RecoveryTask { eventBus.send(SELF_HEALING_RECOVERY_COMPLETED, ""); } - private void waitFor(long millis, String description) { - if (millis>0) { - log.warn("############## Waiting for {}ms after {}...", millis, description); - try { Thread.sleep(millis); } catch (InterruptedException e) { } - } - } - private void redirectShellOutput(InputStream in, String id, AtomicBoolean closed) { - taskScheduler.schedule(() -> { - try { - //IoUtils.copy(in, System.out); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { - while (reader.ready()) { - log.info(" {}> {}", id, reader.readLine()); - } - } - } catch (IOException e) { - if (closed.get()) { - log.info("ShellRecoveryTask: redirectShellOutput(): Connection closed: id={}", id); - } else { - log.error("ShellRecoveryTask: redirectShellOutput(): Exception while copying Process IN stream: id={}\n", id, e); - } - } - }, - Instant.now() - ); + redirectOutput(in, id, closed, + "ShellRecoveryTask: redirectShellOutput(): Connection closed: id={}", + "ShellRecoveryTask: redirectShellOutput(): Exception while copying Process IN stream: id={}\n"); + //IoUtils.copy(in, System.out); } } diff --git a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/VmNodeRecoveryTask.java b/event-management/common/src/main/java/eu/melodic/event/common/recovery/VmNodeRecoveryTask.java similarity index 53% rename from event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/VmNodeRecoveryTask.java rename to event-management/common/src/main/java/eu/melodic/event/common/recovery/VmNodeRecoveryTask.java index 4ab05b5ca3dd5632881e087cec679995c51049d9..78c61ede8786858be72c01528a163f9164de304f 100644 --- a/event-management/baguette-client/src/main/java/eu/melodic/event/baguette/client/plugin/recovery/VmNodeRecoveryTask.java +++ b/event-management/common/src/main/java/eu/melodic/event/common/recovery/VmNodeRecoveryTask.java @@ -7,48 +7,46 @@ * https://www.mozilla.org/en-US/MPL/2.0/ */ -package eu.melodic.event.baguette.client.plugin.recovery; +package eu.melodic.event.common.recovery; -import eu.melodic.event.baguette.client.BaguetteClientProperties; -import eu.melodic.event.baguette.client.Sshc; +import eu.melodic.event.common.client.SshClient; +import eu.melodic.event.common.client.SshClientProperties; +import eu.melodic.event.common.collector.CollectorContext; import eu.melodic.event.util.EventBus; import eu.melodic.event.util.PasswordUtil; -import lombok.*; +import lombok.NonNull; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.time.Instant; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; -import static eu.melodic.event.baguette.client.plugin.recovery.SelfHealingPlugin.SELF_HEALING_RECOVERY_COMPLETED; +import static eu.melodic.event.common.recovery.RecoveryConstant.SELF_HEALING_RECOVERY_COMPLETED; /** - * Client-side, VM-node Self-Healing + * VM-node Self-Healing using an SSH connection */ @Slf4j @Component -@RequiredArgsConstructor -public class VmNodeRecoveryTask implements RecoveryTask { - @NonNull private final EventBus eventBus; - @NonNull private final PasswordUtil passwordUtil; - @NonNull private final TaskScheduler taskScheduler; +public class VmNodeRecoveryTask

extends AbstractRecoveryTask { + @NonNull private final CollectorContext

collectorContext; - @Getter @Setter - private Map nodeInfo; + private P sshClientProperties; - private BaguetteClientProperties baguetteClientProperties; + public VmNodeRecoveryTask(EventBus eventBus, PasswordUtil passwordUtil, TaskScheduler taskScheduler, SelfHealingProperties selfHealingProperties, CollectorContext

collectorContext) { + super(eventBus, passwordUtil, taskScheduler, selfHealingProperties); + this.collectorContext = collectorContext; + } public void setNodeInfo(@NonNull Map nodeInfo) { - this.nodeInfo = nodeInfo; - this.baguetteClientProperties = createBaguetteClientProperties(); + super.setNodeInfo(nodeInfo); + this.sshClientProperties = createSshClientProperties(); } @SneakyThrows @@ -61,10 +59,10 @@ public class VmNodeRecoveryTask implements RecoveryTask { } public void runNodeRecovery(List recoveryCommands) throws Exception { - log.debug("VmNodeRecoveryTask: runNodeRecovery(): node-info={}", nodeInfo); + log.debug("VmNodeRecoveryTask: runNodeRecovery(): BEGIN: recovery-command: {}", recoveryCommands); // Connect to Node (VM) - Sshc sshc = connectToNode(); + SshClient sshc = connectToNode(); // Redirect SSH output to standard output final AtomicBoolean closed = new AtomicBoolean(false); @@ -86,7 +84,7 @@ public class VmNodeRecoveryTask implements RecoveryTask { disconnectFromNode(sshc, closed); // Send recovery complete event - eventBus.send(SELF_HEALING_RECOVERY_COMPLETED, baguetteClientProperties.getServerAddress()); + eventBus.send(SELF_HEALING_RECOVERY_COMPLETED, sshClientProperties.getServerAddress()); } private String str(Object o) { @@ -94,15 +92,8 @@ public class VmNodeRecoveryTask implements RecoveryTask { return o.toString(); } - private void waitFor(long millis, String description) { - if (millis>0) { - log.warn("############## Waiting for {}ms after {}...", millis, description); - try { Thread.sleep(millis); } catch (InterruptedException e) { } - } - } - - private BaguetteClientProperties createBaguetteClientProperties() { - log.debug("VmNodeRecoveryTask: createBaguetteClientProperties(): node-info={}", nodeInfo); + private P createSshClientProperties() { + log.debug("VmNodeRecoveryTask: createSshClientProperties(): BEGIN:"); // Extract connection info and credentials String os = str(nodeInfo.get("operatingSystem")); @@ -121,12 +112,12 @@ public class VmNodeRecoveryTask implements RecoveryTask { port = 22; } catch (Exception e) {} - log.debug("VmNodeRecoveryTask: createBaguetteClientProperties(): os={}, address={}, type={}", os, address, type); - log.debug("VmNodeRecoveryTask: createBaguetteClientProperties(): username={}, password={}", username, passwordUtil.encodePassword(password)); - log.debug("VmNodeRecoveryTask: createBaguetteClientProperties(): fingerprint={}, key={}", fingerprint, passwordUtil.encodePassword(key)); + log.debug("VmNodeRecoveryTask: createSshClientProperties(): os={}, address={}, type={}", os, address, type); + log.debug("VmNodeRecoveryTask: createSshClientProperties(): username={}, password={}", username, passwordUtil.encodePassword(password)); + log.debug("VmNodeRecoveryTask: createSshClientProperties(): fingerprint={}, key={}", fingerprint, passwordUtil.encodePassword(key)); - // Connect to node and restart Baguette Client - BaguetteClientProperties config = new BaguetteClientProperties(); + // Connect to node and restart EMS client + P config = collectorContext.getSshClientProperties(); config.setServerAddress(address); config.setServerPort(port); config.setServerUsername(username); @@ -144,46 +135,32 @@ public class VmNodeRecoveryTask implements RecoveryTask { return config; } - private Sshc connectToNode() throws IOException { - Sshc sshc = new Sshc(); - sshc.setConfiguration(baguetteClientProperties); + private SshClient

connectToNode() throws IOException { + SshClient

sshc = collectorContext.getSshClient(); + sshc.setConfiguration(sshClientProperties); //XXX:TODO: Try enabling server key verification sshc.setUseServerKeyVerifier(false); log.info("VmNodeRecoveryTask: connectToNode(): Connecting to node using SSH: address={}, port={}, username={}", - baguetteClientProperties.getServerAddress(), baguetteClientProperties.getServerPort(), baguetteClientProperties.getServerUsername()); + sshClientProperties.getServerAddress(), sshClientProperties.getServerPort(), sshClientProperties.getServerUsername()); sshc.start(); log.debug("VmNodeRecoveryTask: connectToNode(): Connected to node: address={}, port={}, username={}", - baguetteClientProperties.getServerAddress(), baguetteClientProperties.getServerPort(), baguetteClientProperties.getServerUsername()); + sshClientProperties.getServerAddress(), sshClientProperties.getServerPort(), sshClientProperties.getServerUsername()); return sshc; } - private void disconnectFromNode(Sshc sshc, AtomicBoolean closed) throws IOException { + private void disconnectFromNode(SshClient sshc, AtomicBoolean closed) throws IOException { log.info("VmNodeRecoveryTask: disconnectFromNode(): Disconnecting from node: address={}, port={}, username={}", - baguetteClientProperties.getServerAddress(), baguetteClientProperties.getServerPort(), baguetteClientProperties.getServerUsername()); + sshClientProperties.getServerAddress(), sshClientProperties.getServerPort(), sshClientProperties.getServerUsername()); closed.set(true); sshc.stop(); log.debug("VmNodeRecoveryTask: disconnectFromNode(): Disconnected from node: address={}, port={}, username={}", - baguetteClientProperties.getServerAddress(), baguetteClientProperties.getServerPort(), baguetteClientProperties.getServerUsername()); + sshClientProperties.getServerAddress(), sshClientProperties.getServerPort(), sshClientProperties.getServerUsername()); } private void redirectSshOutput(InputStream in, String id, AtomicBoolean closed) { - taskScheduler.schedule(() -> { - try { - //IoUtils.copy(sshc.getIn(), System.out); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { - while (reader.ready()) { - log.info(" {}> {}", id, reader.readLine()); - } - } - } catch (IOException e) { - if (closed.get()) { - log.info("VmNodeRecoveryTask: redirectSshOutput(): Connection closed: id={}", id); - } else { - log.error("VmNodeRecoveryTask: redirectSshOutput(): Exception while copying SSH IN stream: id={}\n", id, e); - } - } - }, - Instant.now() - ); + redirectOutput(in, id, closed, + "VmNodeRecoveryTask: redirectSshOutput(): Connection closed: id={}", + "VmNodeRecoveryTask: redirectSshOutput(): Exception while copying SSH IN stream: id={}\n"); + //IoUtils.copy(sshc.getIn(), System.out); } } diff --git a/event-management/config-files/baguette-client-install/linux/jre8.json b/event-management/config-files/baguette-client-install/linux/jre8.json index 3a909408864f57e7c5a72b0182959673637da21e..220b2f0d73c40e900f1b811d21317031ffb41332 100644 --- a/event-management/config-files/baguette-client-install/linux/jre8.json +++ b/event-management/config-files/baguette-client-install/linux/jre8.json @@ -29,7 +29,7 @@ { "description": "Download JRE package", "taskType": "CMD", - "command": "curl https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jre8.0.282-linux_x64.tar.gz --output /tmp/jre8.282.tar.gz", + "command": "curl -v -k ${DOWNLOAD_URL}/resources/zulu8.52.0.23-ca-jre8.0.282-linux_x64.tar.gz --output /tmp/jre8.282.tar.gz", "executable": false, "exitCode": 0, "match": false diff --git a/event-management/config-files/baguette-client/conf/baguette-client.properties b/event-management/config-files/baguette-client/conf/baguette-client.properties index dded9204152a395d3efaf9e9a1472708d0afd321..deb4020fc2976ce0f9018c6e428fd76e180e074a 100644 --- a/event-management/config-files/baguette-client/conf/baguette-client.properties +++ b/event-management/config-files/baguette-client/conf/baguette-client.properties @@ -16,6 +16,7 @@ exit-command-allowed = false #kill-delay = 10 IP_SETTING=${IP_SETTING} +EMS_CLIENT_ADDRESS=${${IP_SETTING}} # ----------------------------------------------------------------------------- # Client Id and Baguette Server credentials diff --git a/event-management/config-files/baguette-client/conf/eu.melodic.event.brokercep.properties b/event-management/config-files/baguette-client/conf/eu.melodic.event.brokercep.properties index 9480923825b872d51bc672738584b622605f0a91..8743cf7dad7244ae4447ee2f19f5632ac7fd43fe 100644 --- a/event-management/config-files/baguette-client/conf/eu.melodic.event.brokercep.properties +++ b/event-management/config-files/baguette-client/conf/eu.melodic.event.brokercep.properties @@ -14,20 +14,21 @@ # Broker ports and protocol brokercep.broker-name = broker brokercep.broker-port = 61617 -#brokercep.connector-port = 1088 +#brokercep.management-connector-port = 1088 brokercep.broker-protocol = ssl # Don't use in Upperware #brokercep.bypass-local-broker = true # Common Broker settings -#brokercep.ssl.enable = false -brokercep.broker-url = ${brokercep.broker-protocol}://0.0.0.0:${brokercep.broker-port} -brokercep.broker-url-2 = tcp://127.0.0.1:61616?${brokercep.broker-url-properties} -brokercep.broker-url-3 = -brokercep.broker-url-properties = transport.daemon=true&transport.trace=false&transport.useKeepAlive=true&transport.useInactivityMonitor=false&transport.needClientAuth=${brokercep.ssl.client-auth.required}&transport.verifyHostName=true&transport.connectionTimeout=0&transport.keepAlive=true -brokercep.ssl.client-auth.required = false -brokercep.broker-url-for-consumer = tcp://127.0.0.1:61616?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true -brokercep.broker-url-for-clients = ${brokercep.broker-protocol}://${IP_SETTING}:${brokercep.broker-port}?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true +BROKER_URL_PROPERTIES = transport.daemon=true&transport.trace=false&transport.useKeepAlive=true&transport.useInactivityMonitor=false&transport.needClientAuth=${CLIENT_AUTH_REQUIRED}&transport.verifyHostName=true&transport.connectionTimeout=0&transport.keepAlive=true +CLIENT_AUTH_REQUIRED = false +brokercep.broker-url[0] = ${brokercep.broker-protocol}://0.0.0.0:${brokercep.broker-port}?${BROKER_URL_PROPERTIES} +brokercep.broker-url[1] = tcp://127.0.0.1:61616?${BROKER_URL_PROPERTIES} +brokercep.broker-url[2] = + +CLIENT_URL_PROPERTIES=daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true +brokercep.broker-url-for-consumer = tcp://127.0.0.1:61616?${CLIENT_URL_PROPERTIES} +brokercep.broker-url-for-clients = ${brokercep.broker-protocol}://${EMS_CLIENT_ADDRESS}:${brokercep.broker-port}?${CLIENT_URL_PROPERTIES} # Must be a public IP address # Key store @@ -44,12 +45,9 @@ brokercep.ssl.truststore-password = ENC(ISMbn01HVPbtRPkqm2Lslg==) brokercep.ssl.certificate-file = ${MELODIC_CONFIG_DIR}/client-broker.crt # Key-and-Cert data brokercep.ssl.key-entry-generate = IF-IP-CHANGED -brokercep.ssl.key-entry-name = ${IP_SETTING} -brokercep.ssl.key-entry-dname = CN=${IP_SETTING},OU=Information Management Unit (IMU),O=Institute of Communication and Computer Systems (ICCS),L=Athens,ST=Attika,C=GR -brokercep.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:%{DEFAULT_IP}%,ip:%{PUBLIC_IP}% -# Public and Default IP address defaults (if case NetUtil fails to detect any of them) -#control.ssl.default-ip-address = -#control.ssl.public-ip-address = +brokercep.ssl.key-entry-name = ${EMS_CLIENT_ADDRESS} +brokercep.ssl.key-entry-dname = CN=${EMS_CLIENT_ADDRESS},OU=Information Management Unit (IMU),O=Institute of Communication and Computer Systems (ICCS),L=Athens,ST=Attika,C=GR +brokercep.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:${DEFAULT_IP},ip:${PUBLIC_IP} # Authentication and Authorization settings brokercep.authentication-enabled = true diff --git a/event-management/config-files/eu.melodic.event.baguette-client-install.properties b/event-management/config-files/eu.melodic.event.baguette-client-install.properties index e7cac2b81222cb66ce6aaefb431f8b723b4cff94..01a85766760e559581e3867c94268fde0207af10 100644 --- a/event-management/config-files/eu.melodic.event.baguette-client-install.properties +++ b/event-management/config-files/eu.melodic.event.baguette-client-install.properties @@ -21,7 +21,7 @@ baguette.client.install.touchFiles=${baguette.client.install.baseDir}/logs/outpu baguette.client.install.checkInstalledFile=${baguette.client.install.baseDir}/conf/ok.txt baguette.client.install.downloadUrl=%{BASE_URL}% -#baguette.client.install.downloadUrl=http://${IP_SETTING}:8111/resources +#baguette.client.install.downloadUrl=http://${EMS_SERVER_ADDRESS}:8111/resources baguette.client.install.apiKey=1234567890 baguette.client.install.installScriptUrl=${baguette.client.install.downloadUrl}/install.sh baguette.client.install.installScriptFile=${baguette.client.install.baseDir}/bin/install.sh @@ -68,9 +68,9 @@ baguette.client.install.sessionRecordingDir = ${LOGS_DIR:${MELODIC_CONFIG_DIR}/. #baguette.client.install.parameters.SKIP_JRE_INSTALLATION=true #baguette.client.install.parameters.SKIP_START=true -baguette.client.install.parameters.BAGUETTE_INSTALLATION_MIN_PROCESSORS=2 -baguette.client.install.parameters.BAGUETTE_INSTALLATION_MIN_RAM=2*1024*1024 -baguette.client.install.parameters.BAGUETTE_INSTALLATION_MIN_DISK_FREE=1024*1024 +#baguette.client.install.parameters.BAGUETTE_INSTALLATION_MIN_PROCESSORS=2 +#baguette.client.install.parameters.BAGUETTE_INSTALLATION_MIN_RAM=2*1024*1024 +#baguette.client.install.parameters.BAGUETTE_INSTALLATION_MIN_DISK_FREE=1024*1024 # Settings for resolving Node state after baguette client installation #baguette.client.install.clientInstallVarName=__EMS_CLIENT_INSTALL__ diff --git a/event-management/config-files/eu.melodic.event.baguette-server.properties b/event-management/config-files/eu.melodic.event.baguette-server.properties index d8b999dae78d4ebece49927679cb3788c6ef777d..fd884d58c15ce332afbe117ad863e01fc0bddbf3 100644 --- a/event-management/config-files/eu.melodic.event.baguette-server.properties +++ b/event-management/config-files/eu.melodic.event.baguette-server.properties @@ -10,9 +10,9 @@ # Baguette Server configuration # Coordinator and Registration settings -baguette.server.coordinator.class = eu.melodic.event.baguette.server.coordinator.cluster.ClusteringCoordinator -#baguette.server.coordinator.class = eu.melodic.event.baguette.server.coordinator.TestCoordinator -#coordinator.class = eu.melodic.event.baguette.server.coordinator.ServerCoordinatorPerCloud +baguette.server.coordinator-class = eu.melodic.event.baguette.server.coordinator.cluster.ClusteringCoordinator +#baguette.server.coordinator-class = eu.melodic.event.baguette.server.coordinator.TestCoordinator +#baguette.server.coordinator-class = eu.melodic.event.baguette.server.coordinator.ServerCoordinatorPerCloud # Available Coordinators (in 'eu.melodic.event.baguette.server.coordinator' package) : # ServerCoordinatorWaitAll, ServerCoordinatorTimeWin, ServerCoordinatorClientsOnly, @@ -21,7 +21,7 @@ baguette.server.coordinator.class = eu.melodic.event.baguette.server.coordinator #baguette.server.coordinatorParameters.param1 = p1 #baguette.server.coordinatorParameters.param2 = p2 -baguette.server.coordinator.id = clustering, 2level, noop +baguette.server.coordinator-id = clustering, 2level, noop baguette.server.coordinatorConfig.clustering.coordinatorClass = eu.melodic.event.baguette.server.coordinator.cluster.ClusteringCoordinator baguette.server.coordinatorConfig.clustering.parameters.zone-management-strategy-class = eu.melodic.event.baguette.server.coordinator.cluster.DefaultZoneManagementStrategy baguette.server.coordinatorConfig.clustering.parameters.zone-port-start = 2000 @@ -36,20 +36,20 @@ baguette.server.coordinatorConfig.clustering.parameters.zone-keystore-file-name- baguette.server.coordinatorConfig.2level.coordinatorClass = eu.melodic.event.baguette.server.coordinator.TwoLevelCoordinator baguette.server.coordinatorConfig.noop.coordinatorClass = eu.melodic.event.baguette.server.coordinator.NoopCoordinator -#baguette.server.num-of-instances = 1 +#baguette.server.number-of-instances = 1 baguette.server.registration-window = 30000 # SSH Server settings -baguette.server.address = ${IP_SETTING} +baguette.server.address = ${EMS_SERVER_ADDRESS} baguette.server.port = 2222 -baguette.server.key.file = ${MELODIC_CONFIG_DIR}/hostkey.ser -baguette.server.heartbeat = on -baguette.server.heartbeat.period = 60000 +baguette.server.key-file = ${MELODIC_CONFIG_DIR}/hostkey.ser +baguette.server.heartbeat-enabled = on +baguette.server.heartbeat-period = 60000 baguette.server.credentials.aa=xx baguette.server.credentials.bb=yy -#baguette.server.debug.client-address-override-allowed=true -baguette.server.client-id-format.escape = ~ +#baguette.server.client-address-override-allowed=true +baguette.server.client-id-format-escape = ~ #baguette.server.client-id-format = ~{type}-~{operatingSystem}-~{id}-~{name}-~{providerId}-~{ip}-~{random} baguette.server.client-id-format = ~{type:-_}-~{operatingSystem:-_}-~{id:-_}-~{name:-_}-~{provider:-_}-~{address:-_}-~{random:-_} diff --git a/event-management/config-files/eu.melodic.event.brokercep.properties b/event-management/config-files/eu.melodic.event.brokercep.properties index 7a768f9564669e2ede74c3959c50a8f5efa348c0..2740d11761fe525488a74a48eea00310fda6779f 100644 --- a/event-management/config-files/eu.melodic.event.brokercep.properties +++ b/event-management/config-files/eu.melodic.event.brokercep.properties @@ -10,42 +10,40 @@ # Broker ports and protocol #brokercep.broker-name = broker brokercep.broker-port = 61617 -#brokercep.connector-port = 1099 +#brokercep.management-connector-port = 1099 brokercep.broker-protocol = ssl # Don't use in Upperware #brokercep.bypass-local-broker = true # Common Broker settings -#brokercep.ssl.enable = false -brokercep.broker-url = ${brokercep.broker-protocol}://0.0.0.0:${brokercep.broker-port} -brokercep.broker-url-2 = tcp://0.0.0.0:61616?${brokercep.broker-url-properties} -brokercep.broker-url-3 = stomp://0.0.0.0:61610 -brokercep.broker-url-properties = transport.daemon=true&transport.trace=false&transport.useKeepAlive=true&transport.useInactivityMonitor=false&transport.needClientAuth=${brokercep.ssl.client-auth.required}&transport.verifyHostName=true&transport.connectionTimeout=0&transport.keepAlive=true -brokercep.ssl.client-auth.required = false -brokercep.broker-url-for-consumer = tcp://${IP_SETTING}:61616?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true -brokercep.broker-url-for-clients = ${brokercep.broker-protocol}://${IP_SETTING}:${brokercep.broker-port}?daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true +BROKER_URL_PROPERTIES = transport.daemon=true&transport.trace=false&transport.useKeepAlive=true&transport.useInactivityMonitor=false&transport.needClientAuth=${CLIENT_AUTH_REQUIRED}&transport.verifyHostName=true&transport.connectionTimeout=0&transport.keepAlive=true +CLIENT_AUTH_REQUIRED = false +brokercep.broker-url[0] = ${brokercep.broker-protocol}://0.0.0.0:${brokercep.broker-port}?${BROKER_URL_PROPERTIES} +brokercep.broker-url[1] = tcp://0.0.0.0:61616?${BROKER_URL_PROPERTIES} +brokercep.broker-url[2] = stomp://0.0.0.0:61610 + +CLIENT_URL_PROPERTIES=daemon=true&trace=false&useInactivityMonitor=false&connectionTimeout=0&keepAlive=true +brokercep.broker-url-for-consumer = tcp://${EMS_SERVER_ADDRESS}:61616?${CLIENT_URL_PROPERTIES} +brokercep.broker-url-for-clients = ${brokercep.broker-protocol}://${EMS_SERVER_ADDRESS}:${brokercep.broker-port}?${CLIENT_URL_PROPERTIES} # Must be a public IP address # Key store -brokercep.ssl.keystore-file = ${MELODIC_CONFIG_DIR}/broker-keystore.p12 +brokercep.ssl.keystore-file = ${MELODIC_CONFIG_DIR}/ems-keystore.p12 brokercep.ssl.keystore-type = PKCS12 #brokercep.ssl.keystore-password = melodic brokercep.ssl.keystore-password = ENC(ISMbn01HVPbtRPkqm2Lslg==) # Trust store -brokercep.ssl.truststore-file = ${MELODIC_CONFIG_DIR}/broker-truststore.p12 +brokercep.ssl.truststore-file = ${MELODIC_CONFIG_DIR}/ems-truststore.p12 brokercep.ssl.truststore-type = PKCS12 #brokercep.ssl.truststore-password = melodic brokercep.ssl.truststore-password = ENC(ISMbn01HVPbtRPkqm2Lslg==) # Certificate -brokercep.ssl.certificate-file = ${MELODIC_CONFIG_DIR}/broker.crt +brokercep.ssl.certificate-file = ${MELODIC_CONFIG_DIR}/ems.crt # Key-and-Cert data brokercep.ssl.key-entry-generate = ALWAYS brokercep.ssl.key-entry-name = ems brokercep.ssl.key-entry-dname = CN=ems,OU=Information Management Unit (IMU),O=Institute of Communication and Computer Systems (ICCS),L=Athens,ST=Attika,C=GR -brokercep.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:%{DEFAULT_IP}%,ip:%{PUBLIC_IP}% -# Public and Default IP address defaults (if case NetUtil fails to detect any of them) -#control.ssl.default-ip-address = -#control.ssl.public-ip-address = +brokercep.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:${DEFAULT_IP},ip:${PUBLIC_IP} # Authentication and Authorization settings brokercep.authentication-enabled = true diff --git a/event-management/config-files/eu.melodic.event.control.properties b/event-management/config-files/eu.melodic.event.control.properties index f69d2abd60c55fa284e611176fbfcdb48b7a0c70..0c0c446fb50bfe17ec17097830d27c1b9475abbb 100644 --- a/event-management/config-files/eu.melodic.event.control.properties +++ b/event-management/config-files/eu.melodic.event.control.properties @@ -12,10 +12,11 @@ #control.metasolver-configuration-url = ${METASOLVER_URL:http://metasolver:8092/updateConfiguration} ### Don't touch the next lines!! -#IP_SETTING=%{DEFAULT_IP}% -IP_SETTING=${EMS_IP_SETTING:%{PUBLIC_IP}%} -#EXECUTIONWARE=CLOUDIATOR -EXECUTIONWARE=PROACTIVE +#control.IP_SETTING=DEFAULT_IP +control.IP_SETTING=${EMS_IP_SETTING:PUBLIC_IP} +EMS_SERVER_ADDRESS=${${control.IP_SETTING}} +#control.EXECUTIONWARE=CLOUDIATOR +control.EXECUTIONWARE=PROACTIVE ################################################################################ ### Log settings @@ -43,6 +44,9 @@ control.tc-save-file = ${EMS_TC_FILE:${LOGS_DIR:${MELODIC_CONFIG_DIR}/../logs}/_ ### Debug settings - Enable event debugging control.event-debug-enabled = ${EVENT_DEBUG_ENABLED:true} +#control.event-debug-resource-path=classpath:/public/ +control.event-debug-resource-path=file:${PUBLIC_DIR}/ +control.event-debug-resource-context=/event-debug/** ################################################################################ ### Process CAMEL model on start-up @@ -103,39 +107,51 @@ control.ssl.key-entry-generate = NEVER control.ssl.key-entry-name = ems #control.ssl.key-entry-password = control.ssl.key-entry-dname = CN=ems,OU=Information Management Unit (IMU),O=Institute of Communication and Computer Systems (ICCS),L=Athens,ST=Attika,C=GR -control.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:%{DEFAULT_IP}%,ip:%{PUBLIC_IP}% -# Public and Default IP address defaults (if case NetUtil fails to detect any of them) -#control.ssl.default-ip-address = -#control.ssl.public-ip-address = +control.ssl.key-entry-ext-san = dns:localhost,ip:127.0.0.1,ip:${DEFAULT_IP},ip:${PUBLIC_IP} -### Enable JWT Web security ### +### Web configuration - JWT security ### #melodic.security.enabled=false -#web.jwt-token-authentication.enabled=false +#web.jwt-authentication.enabled=false +#web.jwt-authentication.request-parameter=jwt +#web.jwt-authentication.print-sample-token=false + +### Web configuration - API key security ### +#web.api-key-authentication.enabled=false +#web.api-key-authentication.value=${random.uuid} +#web.api-key-authentication.value=1234567890 +#web.api-key-authentication.request-header=EMS-API-KEY +#web.api-key-authentication.request-parameter=ems-api-key + +### Web configuration - OTP security ### +#web.otp-authentication.enabled=false +#web.otp-authentication.duration=3600000 +#web.otp-authentication.request-header=EMS-OTP +#web.otp-authentication.request-parameter=ems-otp + +### Web configuration - User Form security ### +#web.form-authentication.enabled=false +#web.form-authentication.username=admin +#web.form-authentication.password=ems + +### Web configuration - Resources and redirects +spring.mvc.favicon.enabled=false +static.favicon-path=file:${PUBLIC_DIR}/favicon.ico -### Web configuration - API key -#web.api-key.value=${random.uuid} -#web.api-key.value=1234567890 -#web.api-key.header=EMS-API-KEY -#web.api-key.parameter=ems-api-key +#static.resource-path=file:${PUBLIC_DIR}/ +#static.resource-context=/resources/** +static.resource-path=file:${PUBLIC_DIR}/ +static.resource-context=/** -### Web configuration - Resources -spring.mvc.favicon.enabled=false -static.favicon.path=file:${PUBLIC_DIR}/favicon.ico -#static.resource.path=file:${PUBLIC_DIR}/ -#static.resource.context=/resources/** -#static.resource.redirect=/resources/index.html -static.resource.path=file:${PUBLIC_DIR}/ -static.resource.context=/** -static.resource.redirects={ '/': '/admin/index.html', '/index.html': '/admin/index.html', '/admin': '/admin/index.html', '/admin/': '/admin/index.html', '/resources': '/resources/index.html', '/resources/': '/resources/index.html' } - -static.logs.path=file:${LOGS_DIR}/ -static.logs.context=/logs/** - -# Effective only if 'control.event-debug-enabled' is 'true' -#event-debug.resource.path=classpath:/public/ -event-debug.resource.path=file:${PUBLIC_DIR}/ -event-debug.resource.context=/event-debug/** -#static.resource.redirect=/event-debug/index.html +#static.resource-redirect=/resources/index.html +static.resource-redirects.[/]=/admin/index.html +static.resource-redirects.[/index.html]=/admin/index.html +static.resource-redirects.[/admin]=/admin/index.html +static.resource-redirects.[/admin/]=/admin/index.html +static.resource-redirects.[/resources]=/resources/index.html +static.resource-redirects.[/resources/]=/resources/index.html + +static.logs-path=file:${LOGS_DIR}/ +static.logs-context=/logs/** ### Web configuration - Authorization check authorization.enabled = false @@ -149,16 +165,16 @@ control.exit-grace-period = 10 control.exit-code = 0 ### Topic Beacon settings -beacon.enable = true +beacon.enabled = true beacon.initial-delay = 60000 beacon.delay = 60000 #beacon.rate = 60000 -beacon.topics.heartbeat = -beacon.topics.threshold = _ui_threshold_info -beacon.topics.instance = _ui_instance_info -beacon.topics.prediction = metrics_to_predict -beacon.topics.prediction.rate = 60000 -beacon.topics.slo-violation-detector = metric.metric_list +beacon.heartbeat-topics = +beacon.threshold-topics = _ui_threshold_info +beacon.instance-topics = _ui_instance_info +beacon.prediction-topics = metrics_to_predict +beacon.prediction-rate = 60000 +beacon.slo-violation-detector-topics = metric.metric_list ################################################################################ ### Management and Endpoint settings diff --git a/event-management/config-files/eu.melodic.event.translator.properties b/event-management/config-files/eu.melodic.event.translator.properties index 8282fa1680a85ff4d1155e9b57c4f3ddb03666ff..e6f43b89d6fe74aecdd64fff811618499e003c77 100644 --- a/event-management/config-files/eu.melodic.event.translator.properties +++ b/event-management/config-files/eu.melodic.event.translator.properties @@ -15,27 +15,26 @@ translator.add-top-level-metrics=true translator.full-name-pattern={TYPE}__{CAMEL}__{MODEL}__{ELEM}__{COUNT} translator.formula-check-enabled=true -#XXX:TODO: put the correct MMS annotation (Ask Marcin and Kyriakos) -translator.sensor-config-annotation=ApplicationPlacementModel.iaas.processing +translator.sensor-configuration-annotation= translator.sensor-min-interval=1 translator.sensor-default-interval=60 # Print results and export switches #translator.print-results=true -dag.export-to-dot.enabled=false -dag.export-to-file.enabled=false +translator.dag.export-to-dot-enabled=false +translator.dag.export-to-file-enabled=false # Graph rendering parameters -dag.export.path=${LOGS_DIR:${MELODIC_CONFIG_DIR}/../logs}/exports -#dag.export.formats=png,svg,xdot -dag.export.formats=png,svg -#dag.export.formats=png,svg,xdot,ps,json,plain,plain_ext -dag.export.image-width=600 +translator.dag.export-path=${LOGS_DIR:${MELODIC_CONFIG_DIR}/../logs}/exports +#translator.dag.export-formats=png,svg,xdot +translator.dag.export-formats=png,svg +#translator.dag.export-formats=png,svg,xdot,ps,json,plain,plain_ext +translator.dag.export-image-width=600 ## Active sinks (list) -#active-sinks=JMS +#translator.active-sinks=JMS # ## Sink configurations -#sink-config.JMS.jms.broker=failover:(tcp://localhost:61616)?initialReconnectDelay=1000&warnAfterReconnectAttempts=10 -#sink-config.JMS.jms.topic.selector=de.uniulm.omi.cloudiator.visor.reporting.jms.MetricNameTopicSelector -#sink-config.JMS.jms.message.format=de.uniulm.omi.cloudiator.visor.reporting.jms.MelodicJsonEncoding +#translator.sink-config.JMS.jms.broker=failover:(tcp://localhost:61616)?initialReconnectDelay=1000&warnAfterReconnectAttempts=10 +#translator.sink-config.JMS.jms.topic.selector=de.uniulm.omi.cloudiator.visor.reporting.jms.MetricNameTopicSelector +#translator.sink-config.JMS.jms.message.format=de.uniulm.omi.cloudiator.visor.reporting.jms.MelodicJsonEncoding diff --git a/event-management/control-service/pom.xml b/event-management/control-service/pom.xml index 4bd5c4b21ddf8bc533c59f0a1a5eae01730bb114..a26d2ba084ae571bf69a490cb99789256c78af5e 100644 --- a/event-management/control-service/pom.xml +++ b/event-management/control-service/pom.xml @@ -27,7 +27,11 @@ ${maven.build.timestamp} yyyy-MM-dd HH:mm:ss - + + ${project.build.finalName}.jar + esper-${esper-version}.jar + + ems-server - esper-${esper-version}.jar + + + 0.39.1 + ems-server + + - - - - com.google.code.findbugs - jsr305 - 3.0.2 - compile - - eu.melodic @@ -127,6 +127,7 @@ spring-boot-starter-webflux + org.springframework.boot spring-boot-starter-actuator @@ -138,11 +139,12 @@ ${micrometer.registry.prometheus.version} - + + com.github.ulisesbocchio @@ -171,6 +173,7 @@ + io.hawt hawtio-springboot @@ -186,6 +189,7 @@ true *.txt + META-INF/spring.factories @@ -415,56 +419,93 @@ + + + maven-resources-plugin + 3.2.0 + + + copy-resources-to-docker-context + package + + copy-resources + + + ${project.build.directory}/docker + + + ${project.basedir}/src/main/docker + + + + /jars + ${project.build.directory} + ${docker.controlServiceJar} + ${docker.esperJar} + false + + + /bin + ${project.basedir}/../bin/ + run.sh + sysmon.sh + detect.sh + false + + + /config + ${project.basedir}/../config-files + + false + + + + + /public_resources + ${project.basedir}/../public_resources + false + + + + + /jars + ${project.basedir}/../broker-client/target + broker-client-jar-with-dependencies.jar + false + + + + + /bin + ${project.basedir}/../bin/ + client.sh + false + + + + + + + com.spotify docker-maven-plugin - - /jars - ${project.build.directory} - ${docker.jarToInclude} - ${docker.esperJarToInclude} - + /bin ${project.basedir}/../bin/ run.sh - sysmon.sh - detect.sh - - - /config - ${project.basedir}/../config-files - - - - - - /public_resources - ${project.basedir}/../public_resources - - - - - /jars - ${project.basedir}/../broker-client/target - broker-client-jar-with-dependencies.jar - - - - - /bin - ${project.basedir}/../bin/ - client.sh @@ -492,6 +533,140 @@ + + + dev-local-docker-image-build + + + ../.dev-local-docker-image-build + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.1.0 + + + validate + + read-project-properties + + + + + + + ../.dev-local-docker-image-build + + + + + + + + com.spotify + docker-maven-plugin + + + execution + none + + + + + + + maven-clean-plugin + + true + + + ${project.build.directory}/docker-context + false + + + + + + remove-old-docker-context + install + + clean + + + + + + com.coderplus.maven.plugins + copy-rename-maven-plugin + 1.0.1 + + + rename-docker-context-dir + install + + rename + + + ${project.build.directory}/docker + ${project.build.directory}/docker-context + + + + + + + + io.fabric8 + docker-maven-plugin + ${docker-maven-plugin.version} + + + true + true + + + ${docker-maven-plugin.imageName}:${docker-image-tag} + + ${project.build.directory}/docker-context + + + + + + + docker-image-build + install + + build + + + + + + + diff --git a/event-management/control-service/src/main/docker/Dockerfile b/event-management/control-service/src/main/docker/Dockerfile index c601ff096cb746b2be30fd36ed7848ff778e64f7..380a43b95b37568afba596fbe0dca124b52ace27 100644 --- a/event-management/control-service/src/main/docker/Dockerfile +++ b/event-management/control-service/src/main/docker/Dockerfile @@ -27,7 +27,8 @@ RUN apt-get update && apt-get install -y \ iputils-ping \ && rm -rf /var/lib/apt/lists/* -# XXX: TODO: Remove after tests and update url at 'config-files/baguette-client-install/jre8.json' +# Download a JRE8 suitable for running EMS clients, and +# offer it for download during EMS client installations RUN mkdir -p ${PUBLIC_DIR}/resources RUN curl https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jre8.0.282-linux_x64.tar.gz --output ${PUBLIC_DIR}/resources/zulu8.52.0.23-ca-jre8.0.282-linux_x64.tar.gz diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceApplication.java b/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceApplication.java index c993f9db0345bcd8b3b60595acb590d79908e820..f0c8804c52b1786523484a0478ded27e2ad37d66 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceApplication.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceApplication.java @@ -32,15 +32,15 @@ import org.springframework.scheduling.annotation.EnableAsync; import java.util.Timer; import java.util.TimerTask; +@Slf4j +@EnableAsync +@Configuration @SpringBootApplication( scanBasePackages = {"eu.melodic.event.baguette.server", "eu.melodic.event.baguette.client.install", "eu.melodic.event.baguette.client.selfhealing", "eu.melodic.event.brokercep", "eu.melodic.event.control", "eu.melodic.event.translate", "eu.melodic.event.common", "eu.melodic.event.util"}, exclude = { SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class } ) -@EnableAsync -@Configuration -@Slf4j -public class ControlServiceApplication /*implements ApplicationContextAware*/ { +public class ControlServiceApplication { private static ConfigurableApplicationContext applicationContext; private static Timer exitTimer; diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceController.java b/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceController.java index 9c340e717109d829bbbe2db95ef2518f2b9e8506..4cd1f445b5b860d5d000f9a05f0e00de5016ec64 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceController.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceController.java @@ -18,10 +18,11 @@ import eu.melodic.event.baguette.server.BaguetteServer; import eu.melodic.event.baguette.server.NodeRegistryEntry; import eu.melodic.event.baguette.server.properties.BaguetteServerProperties; import eu.melodic.event.control.properties.ControlServiceProperties; +import eu.melodic.event.control.properties.StaticResourceProperties; import eu.melodic.event.control.webconf.WebSecurityConfig; import eu.melodic.event.translate.TranslationContext; import eu.melodic.event.util.CredentialsMap; -import eu.melodic.event.util.NetUtil; +import eu.melodic.event.util.PasswordUtil; import eu.melodic.models.commons.Watermark; import eu.melodic.models.interfaces.ems.*; import lombok.AllArgsConstructor; @@ -36,6 +37,7 @@ import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.BadRequestException; @@ -60,7 +62,13 @@ public class ControlServiceController { @Autowired private ControlServiceProperties properties; @Autowired + private StaticResourceProperties staticResourceProperties; + @Autowired private ControlServiceCoordinator coordinator; + @Autowired + private WebSecurityConfig webSecurityConfig; + @Autowired + private PasswordUtil passwordUtil; @Autowired private RequestMappingHandlerMapping mvcHandlerMapping; @@ -416,14 +424,16 @@ public class ControlServiceController { private void updateRegistrationInfo(HttpServletRequest request, NodeRegistryEntry entry) { // Get web server base URL - String staticResourceContext = coordinator.getControlServiceProperties().getStaticResourceContext(); + String staticResourceContext = staticResourceProperties.getResourceContext(); staticResourceContext = StringUtils.substringBeforeLast(staticResourceContext,"/**"); staticResourceContext = StringUtils.substringBeforeLast(staticResourceContext,"/*"); if (!staticResourceContext.startsWith("/")) staticResourceContext = "/"+staticResourceContext; - String baseUrl = - (ControlServiceProperties.IpSetting.DEFAULT_IP == coordinator.getControlServiceProperties().getIpSetting()) - ? request.getScheme()+"://"+ NetUtil.getDefaultIpAddress() +":"+request.getServerPort()+staticResourceContext - : request.getScheme()+"://"+ NetUtil.getPublicIpAddress() +":"+request.getServerPort()+staticResourceContext; + /*String baseUrl = + request.getScheme()+"://"+ coordinator.getServerIpAddress() +":"+request.getServerPort()+staticResourceContext;*/ + String baseUrl = ServletUriComponentsBuilder.fromRequestUri(request) + .host(coordinator.getServerIpAddress()) + .replacePath(staticResourceContext) + .build().toUriString(); log.debug("ControlServiceController.baguetteRegisterNode(): baseUrl={}", baseUrl); // Get IP Setting and Client ID @@ -545,6 +555,26 @@ public class ControlServiceController { return coordinator.clusterCommandSend(clusterId, command); } + // ------------------------------------------------------------------------------------------------------------ + // EMS One-Time-Password (OTP) endpoints + // ------------------------------------------------------------------------------------------------------------ + + @RequestMapping(value = "/ems/otp/new", method = {GET, POST}) + public String newOtp() { + log.info("ControlServiceController.newOtp(): BEGIN"); + String newOtp = webSecurityConfig.otpCreate(); + log.debug("ControlServiceController.newOtp(): New OTP: {}", passwordUtil.encodePassword(newOtp)); + return newOtp; + } + + @RequestMapping(value = "/ems/otp/remove", method = {GET, POST}) + public String removeOtp(@PathVariable String otp) { + log.info("ControlServiceController.removeOtp(): BEGIN"); + webSecurityConfig.otpRemove(otp); + log.debug("ControlServiceController.removeOtp(): Removed OTP: {}", passwordUtil.encodePassword(otp)); + return "OK"; + } + // ------------------------------------------------------------------------------------------------------------ // EMS status and information query methods // ------------------------------------------------------------------------------------------------------------ diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceCoordinator.java b/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceCoordinator.java index fe3bd0e947207a5fe2d1c4d37e9ce4111aca3af0..7c2a250454033ae6472e710f94af5fa073b74f89 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceCoordinator.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/ControlServiceCoordinator.java @@ -26,6 +26,7 @@ import eu.melodic.event.translate.CamelToEplTranslator; import eu.melodic.event.translate.TranslationContext; import eu.melodic.event.translate.analyze.DAGNode; import eu.melodic.event.util.KeystoreUtil; +import eu.melodic.event.util.NetUtil; import eu.melodic.event.util.PasswordUtil; import eu.melodic.models.commons.NotificationResult; import eu.melodic.models.commons.NotificationResultImpl; @@ -126,6 +127,12 @@ public class ControlServiceCoordinator implements InitializingBean { } } + public String getServerIpAddress() { + return (properties.getIpSetting() == ControlServiceProperties.IpSetting.DEFAULT_IP) + ? NetUtil.getDefaultIpAddress() + : NetUtil.getPublicIpAddress(); + } + // ------------------------------------------------------------------------------------------------------------ public ControlServiceProperties getControlServiceProperties() { diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceBuildInfoEndpoint.java b/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceBuildInfoEndpoint.java index 2559ce366ceda9a977a1de5b70bbc8cd82b3f40e..5d5bed7767d210a26b4fe5acf868a5ce975de7ac 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceBuildInfoEndpoint.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceBuildInfoEndpoint.java @@ -9,7 +9,6 @@ package eu.melodic.event.control.info; -import io.micrometer.core.lang.NonNullApi; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; @@ -21,7 +20,6 @@ import java.util.Map; @Slf4j @Component -@NonNullApi @Endpoint(id = "emsBuildInfo") public class ControlServiceBuildInfoEndpoint { @Autowired diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceMetrics.java b/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceMetrics.java index 973f4c4d6b765be3d743e0e38609e80d0782e5e6..ea3abdd06d2d64f55ba7952faf039b6d4aef30dd 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceMetrics.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/info/ControlServiceMetrics.java @@ -12,7 +12,6 @@ package eu.melodic.event.control.info; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.lang.NonNullApi; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; @@ -22,7 +21,6 @@ import org.springframework.stereotype.Component; @Slf4j @Component -@NonNullApi @RequiredArgsConstructor public class ControlServiceMetrics implements ApplicationContextAware { diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/info/EmsInfoServiceImpl.java b/event-management/control-service/src/main/java/eu/melodic/event/control/info/EmsInfoServiceImpl.java index 4199a670d27bc538fea8e06549c832ef621f70f4..030db52f791a05bcf7d129fb166ba21c078dbc08 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/info/EmsInfoServiceImpl.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/info/EmsInfoServiceImpl.java @@ -9,10 +9,14 @@ package eu.melodic.event.control.info; -import eu.melodic.event.baguette.server.BaguetteServer; +import eu.melodic.event.baguette.server.ClientShellCommand; import eu.melodic.event.brokercep.BrokerCepService; +import eu.melodic.event.common.misc.SystemResourceMonitor; import eu.melodic.event.control.ControlServiceCoordinator; import eu.melodic.event.control.properties.ControlServiceProperties; +import eu.melodic.event.control.properties.InfoServiceProperties; +import eu.melodic.event.control.properties.StaticResourceProperties; +import eu.melodic.event.control.properties.WebSecurityProperties; import eu.melodic.event.translate.TranslationContext; import eu.melodic.event.util.FunctionDefinition; import eu.melodic.event.util.GROUPING; @@ -21,7 +25,6 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.slf4j.event.Level; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; @@ -40,9 +43,11 @@ public class EmsInfoServiceImpl implements IEmsInfoService { private Map currentClientMetrics; private final ApplicationContext applicationContext; - private final ControlServiceProperties properties; + private final ControlServiceProperties controlServiceProperties; + private final InfoServiceProperties infoServiceProperties; private final ControlServiceCoordinator controlServiceCoordinator; - private final BaguetteServer baguetteServer; + private final StaticResourceProperties staticResourceProperties; + private final WebSecurityProperties webSecurityProperties; private final BuildInfoProvider buildInfoProvider; private final SystemInfoProvider systemInfoProvider; @@ -106,9 +111,9 @@ public class EmsInfoServiceImpl implements IEmsInfoService { if (currentServerMetrics!=null) { long timestamp = (long) currentServerMetrics.get(".timestamp"); log.trace("updateServerMetricValues(): stored-timestamp: {}", timestamp); - if (System.currentTimeMillis() - timestamp < properties.getMetricsUpdateInterval()) { + if (System.currentTimeMillis() - timestamp < infoServiceProperties.getMetricsUpdateInterval()) { log.debug("updateServerMetricValues(): STOP: Retry in {}ms", - timestamp+properties.getMetricsUpdateInterval()-System.currentTimeMillis()); + timestamp + infoServiceProperties.getMetricsUpdateInterval() - System.currentTimeMillis()); return; } } @@ -118,10 +123,7 @@ public class EmsInfoServiceImpl implements IEmsInfoService { Map metrics = new LinkedHashMap<>(); - metrics.put("ip-address", - controlServiceCoordinator.getControlServiceProperties().getIpSetting()==ControlServiceProperties.IpSetting.PUBLIC_IP - ? NetUtil.getPublicIpAddress() - : NetUtil.getDefaultIpAddress()); + metrics.put("ip-address", controlServiceCoordinator.getServerIpAddress()); metrics.put("public-ip-address", NetUtil.getPublicIpAddress()); metrics.put("default-ip-address", NetUtil.getDefaultIpAddress()); metrics.put("reference", controlServiceCoordinator.getReference()); @@ -143,34 +145,67 @@ public class EmsInfoServiceImpl implements IEmsInfoService { controlServiceInfo.put("current-ems-state-change-timestamp", controlServiceCoordinator.getCurrentEmsStateChangeTimestamp()); controlServiceInfo.put("current-camel-model-id", controlServiceCoordinator.getCurrentCamelModelId()); controlServiceInfo.put("current-cp-model-id", controlServiceCoordinator.getCurrentCpModelId()); - if (controlServiceCoordinator.getControlServiceProperties()!=null) { - controlServiceInfo.put("prop-ip-setting", controlServiceCoordinator.getControlServiceProperties().getIpSetting()); - controlServiceInfo.put("prop-esb-url", controlServiceCoordinator.getControlServiceProperties().getEsbUrl()); - controlServiceInfo.put("prop-metasolver-config-url", controlServiceCoordinator.getControlServiceProperties().getMetasolverConfigurationUrl()); - controlServiceInfo.put("prop-metrics-update-interval", controlServiceCoordinator.getControlServiceProperties().getMetricsUpdateInterval()); - controlServiceInfo.put("prop-metrics-client-update-interval", controlServiceCoordinator.getControlServiceProperties().getMetricsClientUpdateInterval()); - controlServiceInfo.put("prop-metrics-stream-event-name", controlServiceCoordinator.getControlServiceProperties().getMetricsStreamEventName()); - controlServiceInfo.put("prop-metrics-stream-update-interval", controlServiceCoordinator.getControlServiceProperties().getMetricsStreamUpdateInterval()); - controlServiceInfo.put("prop-executionware", controlServiceCoordinator.getControlServiceProperties().getExecutionware().toString()); - controlServiceInfo.put("prop-preload-camel-model", controlServiceCoordinator.getControlServiceProperties().getPreloadCamelModel()); - controlServiceInfo.put("prop-preload-cp-model", controlServiceCoordinator.getControlServiceProperties().getPreloadCpModel()); - controlServiceInfo.put("prop-static-resource-context", controlServiceCoordinator.getControlServiceProperties().getStaticResourceContext()); - controlServiceInfo.put("prop-upperware-grouping", controlServiceCoordinator.getControlServiceProperties().getUpperwareGrouping()); - controlServiceInfo.put("prop-tc-load-file", controlServiceCoordinator.getControlServiceProperties().getTcLoadFile()); - controlServiceInfo.put("prop-tc-save-file", controlServiceCoordinator.getControlServiceProperties().getTcSaveFile()); + if (controlServiceProperties!=null && infoServiceProperties!=null) { + controlServiceInfo.put("prop-ip-setting", controlServiceProperties.getIpSetting()); + controlServiceInfo.put("prop-executionware", controlServiceProperties.getExecutionware().toString()); + controlServiceInfo.put("prop-esb-url", controlServiceProperties.getEsbUrl()); + controlServiceInfo.put("prop-metasolver-config-url", controlServiceProperties.getMetasolverConfigurationUrl()); + controlServiceInfo.put("prop-metrics-update-interval", infoServiceProperties.getMetricsUpdateInterval()); + controlServiceInfo.put("prop-metrics-client-update-interval", infoServiceProperties.getMetricsClientUpdateInterval()); + controlServiceInfo.put("prop-metrics-stream-event-name", infoServiceProperties.getMetricsStreamEventName()); + controlServiceInfo.put("prop-metrics-stream-update-interval", infoServiceProperties.getMetricsStreamUpdateInterval()); + controlServiceInfo.put("prop-preload-camel-model", controlServiceProperties.getPreloadCamelModel()); + controlServiceInfo.put("prop-preload-cp-model", controlServiceProperties.getPreloadCpModel()); + controlServiceInfo.put("prop-upperware-grouping", controlServiceProperties.getUpperwareGrouping()); + controlServiceInfo.put("prop-tc-load-file", controlServiceProperties.getTcLoadFile()); + controlServiceInfo.put("prop-tc-save-file", controlServiceProperties.getTcSaveFile()); Map debugFlags = new LinkedHashMap<>(); - debugFlags.put("event-debug-enabled", controlServiceCoordinator.getControlServiceProperties().isEventDebugEnabled()); - debugFlags.put("exit-allowed", controlServiceCoordinator.getControlServiceProperties().isExitAllowed()); - debugFlags.put("print-build-info", controlServiceCoordinator.getControlServiceProperties().isPrintBuildInfo()); - debugFlags.put("skip-translation", controlServiceCoordinator.getControlServiceProperties().isSkipTranslation()); - debugFlags.put("skip-broker-cep-init", controlServiceCoordinator.getControlServiceProperties().isSkipBrokerCep()); - debugFlags.put("skip-baguette-server-init", controlServiceCoordinator.getControlServiceProperties().isSkipBaguette()); - debugFlags.put("skip-mvv-retrieve", controlServiceCoordinator.getControlServiceProperties().isSkipMvvRetrieve()); - debugFlags.put("skip-metasolver-configuration", controlServiceCoordinator.getControlServiceProperties().isSkipMetasolver()); - debugFlags.put("skip-esb-notification", controlServiceCoordinator.getControlServiceProperties().isSkipEsbNotification()); + debugFlags.put("event-debug-enabled", controlServiceProperties.isEventDebugEnabled()); + debugFlags.put("exit-allowed", controlServiceProperties.isExitAllowed()); + debugFlags.put("print-build-info", controlServiceProperties.isPrintBuildInfo()); + debugFlags.put("skip-translation", controlServiceProperties.isSkipTranslation()); + debugFlags.put("skip-broker-cep-init", controlServiceProperties.isSkipBrokerCep()); + debugFlags.put("skip-baguette-server-init", controlServiceProperties.isSkipBaguette()); + debugFlags.put("skip-mvv-retrieve", controlServiceProperties.isSkipMvvRetrieve()); + debugFlags.put("skip-metasolver-configuration", controlServiceProperties.isSkipMetasolver()); + debugFlags.put("skip-esb-notification", controlServiceProperties.isSkipEsbNotification()); controlServiceInfo.put("prop-debug-flags",debugFlags); } + if (staticResourceProperties!=null) { + Map staticResourceCfg = new LinkedHashMap<>(); + staticResourceCfg.put("favicon-context", staticResourceProperties.getFaviconContext()); + staticResourceCfg.put("favicon-path", staticResourceProperties.getFaviconPath()); + staticResourceCfg.put("resource-context", staticResourceProperties.getResourceContext()); + staticResourceCfg.put("resource-path", staticResourceProperties.getResourcePath()); + staticResourceCfg.put("resource-redirect", staticResourceProperties.getResourceRedirect()); + staticResourceCfg.put("resource-redirects", staticResourceProperties.getResourceRedirects()); + staticResourceCfg.put("logs-context", staticResourceProperties.getLogsContext()); + staticResourceCfg.put("logs-path", staticResourceProperties.getLogsPath()); + controlServiceInfo.put("prop-static-resource", staticResourceCfg); + } + if (controlServiceProperties!=null && controlServiceProperties.getTaskScheduler()!=null) { + ControlServiceProperties.TaskSchedulerProperties taskSchedulerProperties = controlServiceProperties.getTaskScheduler(); + Map taskSchedulerMap = new LinkedHashMap<>(); + taskSchedulerMap.put("thread-pool-size", taskSchedulerProperties.getThreadPoolSize()); + controlServiceInfo.put("prop-task-scheduler", taskSchedulerMap); + } + if (controlServiceProperties!=null && controlServiceProperties.getAuthorization()!=null) { + ControlServiceProperties.AuthorizationProperties authorizationProperties = controlServiceProperties.getAuthorization(); + Map authMap = new LinkedHashMap<>(); + authMap.put("enabled", authorizationProperties.isEnabled()); + authMap.put("paths-protected", authorizationProperties.getPathsProtected()); + authMap.put("paths-excluded", authorizationProperties.getPathsExcluded()); + controlServiceInfo.put("prop-authorization", authMap); + } + if (webSecurityProperties!=null) { + Map authMap = new LinkedHashMap<>(); + authMap.put("jwt-authentication-enabled", webSecurityProperties.getJwtAuthentication().isEnabled()); + authMap.put("api-key-authentication-enabled", webSecurityProperties.getApiKeyAuthentication().isEnabled()); + authMap.put("otp-authentication-enabled", webSecurityProperties.getOtpAuthentication().isEnabled()); + authMap.put("form-authentication-enabled", webSecurityProperties.getFormAuthentication().isEnabled()); + controlServiceInfo.put("prop-authentication-methods", authMap); + } metrics.put(CONTROL_INFO_PROVIDER, controlServiceInfo); // Collect Broker-CEP metrics @@ -230,12 +265,13 @@ public class EmsInfoServiceImpl implements IEmsInfoService { protected void updateClientMetricValues() { log.debug("updateClientMetricValues(): BEGIN"); + // Not really needed check, since clients PUSH their statistics to server if (currentClientMetrics!=null) { long timestamp = (long) currentClientMetrics.get(".timestamp"); log.trace("updateClientMetricValues(): stored-timestamp: {}", timestamp); - if (System.currentTimeMillis() - timestamp < properties.getMetricsClientUpdateInterval()) { + if (System.currentTimeMillis() - timestamp < infoServiceProperties.getMetricsClientUpdateInterval()) { log.debug("updateClientMetricValues(): STOP: Retry in {}ms", - timestamp+properties.getMetricsClientUpdateInterval()-System.currentTimeMillis()); + timestamp + infoServiceProperties.getMetricsClientUpdateInterval() - System.currentTimeMillis()); return; } } @@ -249,12 +285,26 @@ public class EmsInfoServiceImpl implements IEmsInfoService { List clientIds = controlServiceCoordinator.clientList(); log.trace("updateClientMetricValues(): active-baguette-clients: {}", clientIds); for (String clientId : clientIds.stream().map(s->s.split(" ")[0]).collect(Collectors.toList())) { - log.trace("updateClientMetricValues(): Requesting metrics from client: {}", clientId); - Object o = baguetteServer.readFromClient(clientId, "SHOW-STATS", Level.DEBUG); + /*log.trace("updateClientMetricValues(): Requesting metrics from client: {}", clientId); + Object o = baguetteServer.readFromClient(clientId, "GET-STATS", org.slf4j.event.Level.DEBUG); log.trace("updateClientMetricValues(): Metrics from client: {}, metrics: {}", clientId, o); if (o instanceof Map) { clientMetrics.put(clientId, o); log.trace("updateClientMetricValues(): client-metrics: id={}, Client metrics ADDED in results map", clientId); + }*/ + + log.trace("updateClientMetricValues(): Retrieving cached statistics of client: id={}", clientId); + ClientShellCommand csc = ClientShellCommand.getActiveById(clientId); + log.trace("updateClientMetricValues(): CSC of client: id={}, CSC={}", clientId, csc); + if (csc!=null) { + if (csc.getClientStatistics()!=null) { + clientMetrics.put(clientId, csc.getClientStatistics()); + log.trace("updateClientMetricValues(): client-metrics: id={}, Client metrics ADDED in results map", clientId); + } else { + log.debug("updateClientMetricValues(): No client statistics available: client-id={}", clientId); + } + } else { + log.warn("updateClientMetricValues(): CSC NOT FOUND: client-id={}", clientId); } } log.debug("updateClientMetricValues(): Collected client metrics: {}", clientMetrics); diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/info/InfoServiceController.java b/event-management/control-service/src/main/java/eu/melodic/event/control/info/InfoServiceController.java index 954b436a00fbf5896cba64d666aed91c3d3da77f..860f08a19d685b76860b7b898f5d8a4fb541c270 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/info/InfoServiceController.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/info/InfoServiceController.java @@ -10,7 +10,7 @@ package eu.melodic.event.control.info; import eu.melodic.event.control.ControlServiceCoordinator; -import eu.melodic.event.control.properties.ControlServiceProperties; +import eu.melodic.event.control.properties.InfoServiceProperties; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -33,7 +33,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class InfoServiceController { - private final ControlServiceProperties properties; + private final InfoServiceProperties properties; private final ControlServiceCoordinator coordinator; private final IEmsInfoService emsInfoService; @@ -183,12 +183,9 @@ public class InfoServiceController { public Map createServerMetricsResult(String sid, long sequence) { log.trace("createServerMetricsResult: BEGIN: sid={}, seq={}", sid, sequence); Map metrics = new LinkedHashMap<>(emsInfoService.getServerMetricValues()); - metrics.put("WEBSSH-BASE-URL", System.getenv("WEBSSH_BASE_URL")); - System.getenv().forEach((property,value) -> { - if (property.startsWith("WEB_ADMIN_")) { - metrics.put(property.substring("WEB_ADMIN_".length()), value); - } - }); + + addMetricsFromEnvVars(metrics); + metrics.put(".stream-id", sid); metrics.put(".sequence", sequence); log.trace("createMetricsResult: {}", metrics); @@ -229,4 +226,52 @@ public class InfoServiceController { log.trace("createClientMetricsResult: END: sid={}, seq={} ==> {}", sid, sequence, clientMetrics); return clientMetrics; } + + protected void addMetricsFromEnvVars(Map metrics) { + // Process configured env. var. prefixes + for (String prefix : properties.getEnvVarPrefixes()) { + prefix = prefix.trim(); + if (StringUtils.isNotBlank(prefix)) { + // Check for processing switches (at the end of the prefix) + boolean trimPrefix = false; + boolean underscoreToDash = false; + boolean uppercase = false; + boolean lowercase = false; + int len = prefix.length(); + while (len>0) { + char ch = prefix.charAt(len-1); + if (ch=='/') { trimPrefix = true; len--; } + else if (ch=='-') { underscoreToDash = true; len--; } + else if (ch=='^') { uppercase = true; len--; } + else if (ch=='~') { lowercase = true; len--; } + else break; + } + + // Check env. vars against the prefix (and its switches) + if (len>0) { + if (prefix.length()!=len) prefix = prefix.substring(0, len); + + final String _prefix = prefix; + final boolean _trimPrefix = trimPrefix; + final boolean _underscoreToDash = underscoreToDash; + final boolean _uppercase = uppercase; + final boolean _lowercase = lowercase; + System.getenv().forEach((varName,varValue) -> { + if (StringUtils.startsWithIgnoreCase(varName, _prefix)) { + // Process switches + String varNameOriginal = varName; + if (_trimPrefix) varName = varName.substring(_prefix.length()); + if (_underscoreToDash) varName = varName.replace("_", "-"); + if (_uppercase) varName = varName.toUpperCase(); + if (_lowercase) varName = varName.toLowerCase(); + + // Add env. var. in the metrics map + log.debug("addMetricsFromEnvVars: Adding env. var. {} in metrics map as: {} = {}", varNameOriginal, varName, varValue); + metrics.put(varName, varValue); + } + }); + } + } + } + } } diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/properties/ControlServiceProperties.java b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/ControlServiceProperties.java index 52b96acc5dd817cc1cc6d1e937225b8561a8e132..8d9fbecdd72de930505f7bcd2c0bff9e465ed202 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/properties/ControlServiceProperties.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/ControlServiceProperties.java @@ -9,6 +9,7 @@ package eu.melodic.event.control.properties; +import eu.melodic.event.control.webconf.WebMvcConfig; import eu.melodic.event.util.KeystoreAndCertificateProperties; import lombok.Data; import lombok.extern.slf4j.Slf4j; @@ -19,97 +20,75 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; +import java.util.Arrays; +import java.util.List; +import static eu.melodic.event.util.EmsConstant.EMS_PROPERTIES_PREFIX; + +@Slf4j @Data @Validated @Configuration -@ConfigurationProperties(prefix = "control") +@ConfigurationProperties(prefix = EMS_PROPERTIES_PREFIX + "control") @PropertySource("file:${MELODIC_CONFIG_DIR}/eu.melodic.event.control.properties") -@Slf4j public class ControlServiceProperties { public enum IpSetting { - DEFAULT_IP("%{DEFAULT_IP}%"), - PUBLIC_IP("%{PUBLIC_IP}%"); - - private final String placeholder; - - IpSetting(String placeholder) { - this.placeholder = placeholder; - } - - public String toString() { - return placeholder; - } + DEFAULT_IP, + PUBLIC_IP } public enum ExecutionWare { CLOUDIATOR, PROACTIVE } - @Value("${control.printBuildInfo:false}") private boolean printBuildInfo; - @Value("${IP_SETTING:}") - private IpSetting ipSetting; - @Value("${EXECUTIONWARE:PROACTIVE}") - private ExecutionWare executionware; - @Value("${control.upperware-grouping}") + private IpSetting ipSetting = IpSetting.PUBLIC_IP; + private ExecutionWare executionware = ExecutionWare.PROACTIVE; + private String upperwareGrouping; - @Value("${control.metasolver-configuration-url:}") private String metasolverConfigurationUrl; - @Value("${control.esb-url:}") private String esbUrl; - @Value("${control.preload.camel-model:}") private String preloadCamelModel; - @Value("${control.preload.cp-model:}") private String preloadCpModel; - @Value("${control.skip-translation:false}") private boolean skipTranslation; - @Value("${control.skip-mvv-retrieve:false}") private boolean skipMvvRetrieve; - @Value("${control.skip-broker-cep:false}") private boolean skipBrokerCep; - @Value("${control.skip-baguette:false}") private boolean skipBaguette; - @Value("${control.skip-collectors:false}") private boolean skipCollectors; - @Value("${control.skip-metasolver:false}") private boolean skipMetasolver; - @Value("${control.skip-esb-notification:false}") private boolean skipEsbNotification; - @Value("${control.tc-load-file:}") private String tcLoadFile; - @Value("${control.tc-save-file:}") private String tcSaveFile; - @Value("${control.event-debug-enabled:false}") + private boolean eventDebugEnabled; + private String eventDebugResourceContext; + private String[] eventDebugResourcePath; - @Value("${control.exit-allowed:false}") private boolean exitAllowed; - @Value("${control.exit-grace-period:10}") @Min(1) - private long exitGracePeriod; - @Value("${control.exit-code:0}") - private int exitCode; - - @Value("${static.resource.context:/**}") - private String staticResourceContext; - - @Value("${password-encoder-class:}") - private String passwordEncoderClass; - - @Value("${info.metrics.update.interval:1000}") @Min(1) - private long metricsUpdateInterval; - @Value("${info.client.metrics.update.interval:10000}") @Min(1) - private long metricsClientUpdateInterval; - @Value("${info.metrics.stream.update.interval:10}") @Min(1) - private int metricsStreamUpdateInterval; // in seconds - @Value("${info.metrics.stream.event.name:ems-metrics-event}") @NotBlank - private String metricsStreamEventName; + @Min(1) + private long exitGracePeriod = 10; + private int exitCode = 0; // control.ssl.** settings private KeystoreAndCertificateProperties ssl; + + private TaskSchedulerProperties taskScheduler = new TaskSchedulerProperties(); + private AuthorizationProperties authorization = new AuthorizationProperties(); + + @Data + public static class TaskSchedulerProperties { + @Min(1) + private int threadPoolSize = 2; + } + + @Data + public static class AuthorizationProperties { + private boolean enabled = true; + private List pathsProtected = Arrays.asList(WebMvcConfig.DEFAULT_PATHS_PROTECTED); + private List pathsExcluded = Arrays.asList(WebMvcConfig.DEFAULT_PATHS_EXCLUDED); + } } diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/properties/InfoServiceProperties.java b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/InfoServiceProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..96e26f1e524b97485343e32a73cab5f2197a955d --- /dev/null +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/InfoServiceProperties.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.control.properties; + +import eu.melodic.event.util.EmsConstant; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import java.util.Arrays; +import java.util.List; + +@Slf4j +@Data +@Validated +@Configuration +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "info") +public class InfoServiceProperties { + @Min(1) + private long metricsUpdateInterval = 1000; + @Min(1) + private long metricsClientUpdateInterval = 500; // Not really needed since clients PUSH their statistics to server + @Min(1) + private int metricsStreamUpdateInterval = 10; // in seconds + @NotBlank + private String metricsStreamEventName = "ems-metrics-event"; + private List envVarPrefixes = Arrays.asList("WEBSSH_SERVICE_-^", "WEB_ADMIN_!^"); + // ! at the end means to trim off the prefix; - at the end means to convert '_' to '-'; + // ^ at the end means convert to upper case; ~ at the end means convert to lower case; +} diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/properties/StaticResourceProperties.java b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/StaticResourceProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..f67c3f6cb0f2849dd4075d31b53c129d32e9fb79 --- /dev/null +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/StaticResourceProperties.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.control.properties; + +import eu.melodic.event.util.EmsConstant; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +@Data +@Validated +@Configuration +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "static") +public class StaticResourceProperties { + private String faviconContext = "/favicon.ico"; + private String faviconPath; + + private String resourceContext = "/resources/**"; + private List resourcePath; + + private String resourceRedirect; + private Map resourceRedirects = new LinkedHashMap<>(); + + private String logsContext = "/logs/**"; + private List logsPath; +} diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/properties/TopicBeaconProperties.java b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/TopicBeaconProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..e17baa6df5c561668db9aa22f2a97c98c9decc4b --- /dev/null +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/TopicBeaconProperties.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.control.properties; + +import eu.melodic.event.util.EmsConstant; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.Min; +import java.util.HashSet; +import java.util.Set; + +@Slf4j +@Data +@Validated +@Configuration +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "beacon") +public class TopicBeaconProperties { + private boolean enabled = true; + @Min(0) private long initialDelay = 60000; + @Min(1) private long delay = 60000; + @Min(1) private long rate = 60000; + + private Set heartbeatTopics = new HashSet<>(); + private Set thresholdTopics = new HashSet<>(); + private Set instanceTopics = new HashSet<>(); + private Set predictionTopics = new HashSet<>(); + @Min(1) private long predictionRate = 60000; + private Set sloViolationDetectorTopics = new HashSet<>(); +} diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/properties/WebSecurityProperties.java b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/WebSecurityProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..7f6fce643c607128de6fc3da77398a74605ccffa --- /dev/null +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/properties/WebSecurityProperties.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.control.properties; + +import eu.melodic.event.util.EmsConstant; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +@Slf4j +@Data +@Validated +@Configuration +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "web") +public class WebSecurityProperties { + // JWT Token authentication + @Valid + @NotNull + private JwtAuthentication jwtAuthentication = new JwtAuthentication(); + + @Data + public static class JwtAuthentication { + private boolean enabled = true; + private String requestParameter; + private boolean printSampleToken; + } + + // API-Key authentication + @Valid + @NotNull + private ApiKeyAuthentication apiKeyAuthentication = new ApiKeyAuthentication(); + + @Data + public static class ApiKeyAuthentication { + private boolean enabled = true; + private String requestHeader = "EMS-API-KEY"; + private String requestParameter = "ems-api-key"; + private String value; + } + + // OTP authentication + @Valid + @NotNull + private OtpAuthentication otpAuthentication = new OtpAuthentication(); + + @Data + public static class OtpAuthentication { + private boolean enabled = true; + @Min(1) + private long duration = 3600000; + private String requestHeader = "EMS-OTP"; + private String requestParam = "ems-otp"; + } + + // User form authentication + @Valid + @NotNull + private FormAuthentication formAuthentication = new FormAuthentication(); + + @Data + public static class FormAuthentication { + private boolean enabled = true; + private String username = "admin"; + private String password; + + private String loginPage = "/admin/login.html"; + private String loginUrl = "/login"; + private String loginSuccessUrl = "/"; + private String loginFailureUrl = "/admin/login.html?error=Invalid+username+or+password"; + private String logoutUrl = "/logout"; + private String logoutSuccessUrl = "/admin/login.html?message=Signed+out"; + } + + // Permitted URLs + private List permittedUrls = Arrays.asList( + "/login*", "/logout*", "/favicon.ico", "/admin/login.html", "/admin/favicon.ico", "/admin/assets/**", "/resources/*"); +} diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/util/TaskSchedulerConfig.java b/event-management/control-service/src/main/java/eu/melodic/event/control/util/TaskSchedulerConfig.java index 66623682584c737a2af428da73e4e030c9b48218..578acfec80a881cbfdfafe181bdce74b33a9dedb 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/util/TaskSchedulerConfig.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/util/TaskSchedulerConfig.java @@ -9,25 +9,24 @@ package eu.melodic.event.control.util; +import eu.melodic.event.control.properties.ControlServiceProperties; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import javax.validation.constraints.Min; - @Slf4j @Configuration @EnableScheduling +@RequiredArgsConstructor public class TaskSchedulerConfig { - @Value("${control.task-scheduler.thread-pool-size:2}") - @Min(1) - private int threadPoolSize; + private final ControlServiceProperties properties; @Bean public ThreadPoolTaskScheduler threadPoolTaskScheduler() { + int threadPoolSize = properties.getTaskScheduler().getThreadPoolSize(); log.info("TaskSchedulerConfig: TaskScheduler thread pool size: {}", threadPoolSize); ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); threadPoolTaskScheduler.setPoolSize(threadPoolSize); diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/util/TopicBeacon.java b/event-management/control-service/src/main/java/eu/melodic/event/control/util/TopicBeacon.java index 6030df0b7d3b7b9f5d215a6ab7052d7a3a17d38f..eaff6d3eaa262e5bd315f442cceadd36aedb16cb 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/util/TopicBeacon.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/util/TopicBeacon.java @@ -15,13 +15,13 @@ import eu.melodic.event.baguette.server.NodeRegistryEntry; import eu.melodic.event.brokercep.BrokerCepService; import eu.melodic.event.brokercep.event.EventMap; import eu.melodic.event.control.ControlServiceCoordinator; +import eu.melodic.event.control.properties.TopicBeaconProperties; import eu.melodic.event.translate.TranslationContext; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.SetUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Service; @@ -36,27 +36,8 @@ import java.util.stream.Collectors; @Service @EnableScheduling public class TopicBeacon implements InitializingBean { - // Topic Beacon settings - @Value("${beacon.enable:true}") - private boolean beaconEnable; - @Value("${beacon.initial-delay:60000}") - private long beaconInitialDelay; - @Value("${beacon.delay:60000}") - private long beaconDelay; - @Value("${beacon.rate:60000}") - private long beaconRate; - @Value("${beacon.topics.heartbeat:}") - private Set beaconHeartbeatTopics; - @Value("${beacon.topics.threshold:}") - private Set beaconThresholdTopics; - @Value("${beacon.topics.instance:}") - private Set beaconInstanceTopics; - @Value("${beacon.topics.prediction:}") - private Set beaconPredictionTopics; - @Value("${beacon.topics.prediction.rate:60000}") - private long beaconPredictionRate; - @Value("${beacon.topics.slo-violation-detector:}") - private Set beaconSloViolationDetectorTopics; + @Autowired + private TopicBeaconProperties properties; @Autowired private ControlServiceCoordinator coordinator; @@ -71,7 +52,7 @@ public class TopicBeacon implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { - if (!beaconEnable) { + if (!properties.isEnabled()) { log.warn("Topic Beacon is disabled"); return; } @@ -80,17 +61,18 @@ public class TopicBeacon implements InitializingBean { gson = new GsonBuilder().disableHtmlEscaping().create(); // configure and start scheduler - Date startTime = new Date(System.currentTimeMillis()+beaconInitialDelay); + Date startTime = new Date(System.currentTimeMillis() + properties.getInitialDelay()); log.debug("Topic Beacon settings: init-delay={}, delay={}, heartbeat-topics={}, threshold-topics={}, instance-topics={}", - beaconInitialDelay, beaconDelay, beaconHeartbeatTopics, beaconThresholdTopics, beaconInstanceTopics); + properties.getInitialDelay(), properties.getDelay(), properties.getHeartbeatTopics(), properties.getThresholdTopics(), + properties.getInstanceTopics()); scheduler.scheduleWithFixedDelay(() -> { try { transmitInfo(); } catch (Exception e) { log.error("Topic Beacon: Exception while sending info: ", e); } - }, startTime, beaconDelay); - log.info("Topic Beacon started: init-delay={}ms", beaconInitialDelay); + }, startTime, properties.getDelay()); + log.info("Topic Beacon started: init-delay={}ms", properties.getInitialDelay()); } public void transmitInfo() throws JMSException { @@ -105,15 +87,15 @@ public class TopicBeacon implements InitializingBean { } public void transmitHeartbeat() throws JMSException { - if (SetUtils.emptyIfNull(beaconHeartbeatTopics).isEmpty()) return; + if (SetUtils.emptyIfNull(properties.getHeartbeatTopics()).isEmpty()) return; String message = "TOPIC BEACON HEARTBEAT "+new Date(); - log.debug("Topic Beacon: Transmitting Heartbeat info: message={}, topics={}", message, beaconHeartbeatTopics); - sendMessageToTopics(message, beaconHeartbeatTopics); + log.debug("Topic Beacon: Transmitting Heartbeat info: message={}, topics={}", message, properties.getHeartbeatTopics()); + sendMessageToTopics(message, properties.getHeartbeatTopics()); } public void transmitThresholdInfo() { - if (SetUtils.emptyIfNull(beaconThresholdTopics).isEmpty()) return; + if (SetUtils.emptyIfNull(properties.getThresholdTopics()).isEmpty()) return; if (coordinator.getTranslationContextOfCamelModel(coordinator.getCurrentCamelModelId())==null) return; @@ -121,35 +103,35 @@ public class TopicBeacon implements InitializingBean { .getMetricConstraints() .forEach(c -> { String message = gson.toJson(c); - log.debug("Topic Beacon: Transmitting Metric Constraint threshold info: message={}, topics={}",message, beaconThresholdTopics); + log.debug("Topic Beacon: Transmitting Metric Constraint threshold info: message={}, topics={}",message, properties.getThresholdTopics()); try { - sendEventToTopics(message, beaconThresholdTopics); + sendEventToTopics(message, properties.getThresholdTopics()); } catch (JMSException e) { log.error("Topic Beacon: EXCEPTION while transmitting Metric Constraint threshold info: message={}, topics={}, exception: ", - message, beaconThresholdTopics, e); + message, properties.getThresholdTopics(), e); } }); } public void transmitInstanceInfo() throws JMSException { - if (SetUtils.emptyIfNull(beaconInstanceTopics).isEmpty()) return; + if (SetUtils.emptyIfNull(properties.getInstanceTopics()).isEmpty()) return; if (coordinator.getBaguetteServer().isServerRunning()) { - log.debug("Topic Beacon: Transmitting Instance info: topics={}", beaconInstanceTopics); + log.debug("Topic Beacon: Transmitting Instance info: topics={}", properties.getInstanceTopics()); for (NodeRegistryEntry node : coordinator.getBaguetteServer().getNodeRegistry().getNodes()) { String nodeName = node.getPreregistration().getOrDefault("name", ""); String nodeIp = node.getIpAddress(); //String nodeIp = node.getPreregistration().getOrDefault("ip",""); String message = gson.toJson(node); log.debug("Topic Beacon: Transmitting Instance info for: instance={}, ip-address={}, message={}, topics={}", - nodeName, nodeIp, message, beaconInstanceTopics); - sendEventToTopics(message, beaconInstanceTopics); + nodeName, nodeIp, message, properties.getInstanceTopics()); + sendEventToTopics(message, properties.getInstanceTopics()); } } } public void transmitPredictionInfo() { - if (SetUtils.emptyIfNull(beaconPredictionTopics).isEmpty()) return; + if (SetUtils.emptyIfNull(properties.getPredictionTopics()).isEmpty()) return; String modelId = coordinator.getCurrentCamelModelId(); log.trace("Topic Beacon: transmitPredictionInfo: current-camel-model-id: {}", modelId); @@ -167,7 +149,7 @@ public class TopicBeacon implements InitializingBean { map.put("version", currVersion); map.put("publish_rate", s.getSchedule()!=null ? s.getSchedule().getIntervalInMillis() : - beaconPredictionRate); + properties.getPredictionRate()); return map; }).collect(Collectors.toList()); log.debug("Topic Beacon: Transmitting Prediction info: Metric Contexts in event format: {}", payload); @@ -180,17 +162,17 @@ public class TopicBeacon implements InitializingBean { String eventPayload = gson.toJson(payload); - log.debug("Topic Beacon: Transmitting Prediction info: event={}, topics={}", eventPayload, beaconPredictionTopics); + log.debug("Topic Beacon: Transmitting Prediction info: event={}, topics={}", eventPayload, properties.getPredictionTopics()); try { - sendMessageToTopics(eventPayload, beaconPredictionTopics); + sendMessageToTopics(eventPayload, properties.getPredictionTopics()); } catch (JMSException e) { log.error("Topic Beacon: EXCEPTION while transmitting Prediction info: event={}, topics={}, exception: ", - eventPayload, beaconPredictionTopics, e); + eventPayload, properties.getPredictionTopics(), e); } } public void transmitSloViolatorInfo() { - if (SetUtils.emptyIfNull(beaconSloViolationDetectorTopics).isEmpty()) return; + if (SetUtils.emptyIfNull(properties.getSloViolationDetectorTopics()).isEmpty()) return; String modelId = coordinator.getCurrentCamelModelId(); log.trace("Topic Beacon: transmitSloViolatorInfo: current-camel-model-id: {}", modelId); @@ -207,12 +189,12 @@ public class TopicBeacon implements InitializingBean { sloMetricDecompositions.put("version", modelVersion.get()); String eventPayload = gson.toJson(sloMetricDecompositions); - log.debug("Topic Beacon: Transmitting SLO Violator info: event={}, topics={}", eventPayload, beaconSloViolationDetectorTopics); + log.debug("Topic Beacon: Transmitting SLO Violator info: event={}, topics={}", eventPayload, properties.getSloViolationDetectorTopics()); try { - sendMessageToTopics(eventPayload, beaconSloViolationDetectorTopics); + sendMessageToTopics(eventPayload, properties.getSloViolationDetectorTopics()); } catch (JMSException e) { log.error("Topic Beacon: EXCEPTION while transmitting SLO Violator info: event={}, topics={}, exception: ", - eventPayload, beaconPredictionTopics, e); + eventPayload, properties.getSloViolationDetectorTopics(), e); } } diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/StaticResourceConfiguration.java b/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/StaticResourceConfiguration.java index 58c596232e034e9e4b2a39fe9475acf73e10fe0c..9444ae11d401ae3201b7da1ac76edfc43b32d014 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/StaticResourceConfiguration.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/StaticResourceConfiguration.java @@ -9,9 +9,12 @@ package eu.melodic.event.control.webconf; +import eu.melodic.event.control.properties.ControlServiceProperties; +import eu.melodic.event.control.properties.StaticResourceProperties; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -20,64 +23,56 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.util.List; import java.util.Map; @Slf4j @Configuration -public class StaticResourceConfiguration implements WebMvcConfigurer { - @Value("${static.favicon.context:/favicon.ico}") - private String faviconContext; - @Value("${static.favicon.path:#{null}}") - private String faviconPath; - - @Value("${static.resource.context:/resources/**}") - private String staticResourceContext; - @Value("${static.resource.path:#{null}}") - private String[] staticResourcePath; - - @Value("${static.resource.redirect:#{null}}") - private String staticResourceRedirect; - @Value("#{${static.resource.redirects:{}}}") - private Map staticResourceRedirects; - - @Value("${static.logs.context:/logs/**}") - private String staticLogsContext; - @Value("${static.logs.path:#{null}}") - private String[] staticLogsPath; - - @Value("${event-debug.resource.context:/event-debug/**}") - private String eventDebugResourceContext; - @Value("${event-debug.resource.path:#{null}}") - private String[] eventDebugResourcePath; - @Value("${control.event-debug-enabled:false}") - private boolean eventDebugEnabled; +public class StaticResourceConfiguration implements WebMvcConfigurer, InitializingBean { + @Autowired + private StaticResourceProperties properties; + @Autowired + private ControlServiceProperties controlServiceProperties; + + public void afterPropertiesSet() { + log.debug("StaticResourceConfiguration: afterPropertiesSet: {}", properties); + } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { + String faviconContext = properties.getFaviconContext(); + String faviconPath = properties.getFaviconPath(); if(StringUtils.isNotBlank(faviconPath)) { log.info("Serving favicon.ico from: {} --> {}", faviconContext, faviconPath); registry .addResourceHandler(faviconContext) .addResourceLocations(faviconPath); } - if(staticResourcePath != null && staticResourcePath.length > 0) { - log.info("Serving static content from: {} --> {}", staticResourceContext, staticResourcePath); + String resourceContext = properties.getResourceContext(); + List resourcePath = properties.getResourcePath(); + if (resourcePath != null && resourcePath.size() > 0) { + log.info("Serving static content from: {} --> {}", resourceContext, resourcePath); registry - .addResourceHandler(staticResourceContext) - .addResourceLocations(staticResourcePath); + .addResourceHandler(resourceContext) + .addResourceLocations(resourcePath.toArray(new String[0])); } - if(staticLogsPath != null && staticLogsPath.length > 0) { - log.info("Serving logs from: {} --> {}", staticLogsContext, staticLogsPath); + String logsContext = properties.getLogsContext(); + List logsPath = properties.getLogsPath(); + if (logsPath != null && logsPath.size() > 0) { + log.info("Serving logs from: {} --> {}", logsContext, logsPath); registry - .addResourceHandler(staticLogsContext) - .addResourceLocations(staticLogsPath); + .addResourceHandler(logsContext) + .addResourceLocations(logsPath.toArray(new String[0])); } - if(eventDebugEnabled && eventDebugResourcePath != null && eventDebugResourcePath.length > 0) { - log.info("Serving event-debug content from: {} --> {}", eventDebugResourceContext, eventDebugResourcePath); + if (controlServiceProperties.isEventDebugEnabled() + && controlServiceProperties.getEventDebugResourcePath()!=null + && controlServiceProperties.getEventDebugResourcePath().length > 0) + { + log.info("Serving event-debug content from: {} --> {}", controlServiceProperties.getEventDebugResourceContext(), controlServiceProperties.getEventDebugResourcePath()); registry - .addResourceHandler(eventDebugResourceContext) - .addResourceLocations(eventDebugResourcePath) + .addResourceHandler(controlServiceProperties.getEventDebugResourceContext()) + .addResourceLocations(controlServiceProperties.getEventDebugResourcePath()) //.setCachePeriod(0) ; } @@ -88,16 +83,18 @@ public class StaticResourceConfiguration implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // Remains for backward compatibility (of properties file) - if (StringUtils.isNotBlank(staticResourceRedirect)) { - log.info("Redirecting / to: {}", staticResourceRedirect); + String resourceRedirect = properties.getResourceRedirect(); + if (StringUtils.isNotBlank(resourceRedirect)) { + log.info("Redirecting / to: {}", resourceRedirect); registry .addViewController("/") - .setViewName("redirect:" + staticResourceRedirect); + .setViewName("redirect:" + resourceRedirect); } - log.debug("Configured resource redirects: {}", staticResourceRedirects); - if (staticResourceRedirects!=null) { - staticResourceRedirects.forEach((context, redirect) -> { + Map resourceRedirects = properties.getResourceRedirects(); + log.debug("Configured resource redirects: {}", resourceRedirects); + if (resourceRedirects!=null) { + resourceRedirects.forEach((context, redirect) -> { if (StringUtils.isNotBlank(context) && StringUtils.isNotBlank(redirect)) { context = context.trim(); redirect = redirect.trim(); diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebMvcConfig.java b/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebMvcConfig.java index 82e80eb462a4c2fc8237d8aea199e3d83c2dd0b3..2dfe887aa4ab0de1935cbfc478f2972d315837dc 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebMvcConfig.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebMvcConfig.java @@ -9,12 +9,12 @@ package eu.melodic.event.control.webconf; +import eu.melodic.event.control.properties.ControlServiceProperties; import eu.melodic.security.authorization.client.AuthorizationServiceTomcatInterceptor; import eu.melodic.security.authorization.util.properties.AuthorizationServiceClientProperties; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -33,24 +33,22 @@ import java.util.concurrent.TimeUnit; @Component @ComponentScan(basePackages={"eu.melodic.security.authorization.util.properties"}) public class WebMvcConfig implements WebMvcConfigurer { - private final static String[] DEFAULT_PATHS_PROTECTED = { "/**" }; - private final static String[] DEFAULT_PATHS_EXCLUDED = { }; + public final static String[] DEFAULT_PATHS_PROTECTED = { "/**" }; + public final static String[] DEFAULT_PATHS_EXCLUDED = { }; @Autowired private AuthorizationServiceClientProperties authProperties; @Autowired + private ControlServiceProperties controlServiceProperties; + @Autowired private ApplicationContext applicationContext; - @Value("${authorization.enabled:true}") - private boolean authEnabled; - @Value("${authorization.paths-protected:}") - private String[] authPathsProtected; - @Value("${authorization.paths-excluded:}") - private String[] authPathsExcluded; - @Override public void addInterceptors(InterceptorRegistry registry) { // Add authorization interceptor (if configured) + boolean authEnabled = controlServiceProperties.getAuthorization().isEnabled(); + String[] authPathsProtected = controlServiceProperties.getAuthorization().getPathsProtected().toArray(new String[0]); + String[] authPathsExcluded = controlServiceProperties.getAuthorization().getPathsExcluded().toArray(new String[0]); if (!authEnabled || authProperties.getPdp().isDisabled()) { log.warn("WebMvcConfig.addInterceptors(): Authorization check is disabled"); } else { diff --git a/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebSecurityConfig.java b/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebSecurityConfig.java index f39b0e323a295bd9980e0889688b7b602527c8be..526c0156bd88e813b8021566904682eb543304a1 100644 --- a/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebSecurityConfig.java +++ b/event-management/control-service/src/main/java/eu/melodic/event/control/webconf/WebSecurityConfig.java @@ -9,6 +9,8 @@ package eu.melodic.event.control.webconf; +import eu.melodic.event.control.properties.StaticResourceProperties; +import eu.melodic.event.control.properties.WebSecurityProperties; import eu.melodic.event.util.PasswordUtil; import eu.paasage.upperware.security.authapi.SecurityConstants; import eu.paasage.upperware.security.authapi.properties.MelodicSecurityProperties; @@ -18,6 +20,8 @@ import io.jsonwebtoken.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; @@ -26,6 +30,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @@ -45,6 +50,8 @@ import javax.servlet.http.HttpServletResponse; import java.security.InvalidParameterException; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; @Slf4j @Order(1) @@ -53,91 +60,154 @@ import java.util.Collections; @EnableGlobalMethodSecurity(prePostEnabled = true) @EnableConfigurationProperties(MelodicSecurityProperties.class) @RequiredArgsConstructor -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { +public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements InitializingBean { public final static String ROLE_USER_FORM = "ROLE_USER_FORM"; public static final String ROLE_JWT_TOKEN = "ROLE_JWT_TOKEN"; public static final String ROLE_API_KEY = "ROLE_API_KEY"; + public static final String ROLE_OTP = "ROLE_OTP"; private final MelodicSecurityProperties melodicSecurityProperties; + private final StaticResourceProperties staticResourceProperties; + private final WebSecurityProperties properties; + private final PasswordUtil passwordUtil; + + private final Map otpCache = new HashMap<>(); @Value("${melodic.security.enabled:true}") private boolean securityEnabled; + private boolean propertiesCopied; // JWT Token authentication fields - @Value("${web.jwt-token-authentication.enabled:true}") - private boolean jwtTokenAuthEnabled; - @Value("${web.jwt-print-sample-token:false}") + private boolean jwtAuthEnabled; + private String jwtRequestParam; private boolean printSampleJwt; // API-Key authentication fields - @Value("${web.api-key-authentication.enabled:true}") private boolean apiKeyAuthEnabled; - @Value("${web.api-key.header:EMS-API-KEY}") private String apiKeyRequestHeader; - @Value("${web.api-key.parameter:ems-api-key}") private String apiKeyRequestParam; - @Value("${web.api-key.value:#{null}}") private String apiKeyValue; - @Autowired - private PasswordUtil passwordUtil; + // OTP authentication fields + private boolean otpAuthEnabled; + private long otpDuration; + private String otpRequestHeader; + private String otpRequestParam; // User form authentication fields - @Value("${web.form-authentication.enabled:true}") private boolean userFormAuthEnabled; - @Value("${web.form-authentication.username:admin}") private String username; - @Value("${web.form-authentication.password:}") private String password; - @Value("${web.permitted.urls:/login*,/logout*,/admin/login.html,/admin/favicon.ico,/admin/assets/**,/resources/*}") - private String[] permittedUrls; - @Value("${web.login.page:/admin/login.html}") private String loginPage; - @Value("${web.login.url:/login}") private String loginUrl; - @Value("${web.login.success.url:/}") private String loginSuccessUrl; - @Value("${web.login.failure.url:/admin/login.html?error=Invalid+username+or+password}") private String loginFailureUrl; - @Value("${web.logout.url:/logout}") private String logoutUrl; - @Value("${web.logout.success.url:/admin/login.html?message=Signed+out}") private String logoutSuccessUrl; + // Permitted URLs + private String[] permittedUrls; + private final static String divider = "--------------------------------------------------------------------------------"; + @Override + public void afterPropertiesSet() { + copyPropertiesToLocalFields(); + } + + private void copyPropertiesToLocalFields() { + if (properties==null) return; + if (propertiesCopied) return; + + // JWT Token authentication fields + jwtAuthEnabled = properties.getJwtAuthentication().isEnabled(); + jwtRequestParam = properties.getJwtAuthentication().getRequestParameter(); + printSampleJwt = properties.getJwtAuthentication().isPrintSampleToken(); + + // API-Key authentication fields + apiKeyAuthEnabled = properties.getApiKeyAuthentication().isEnabled(); + apiKeyRequestHeader = properties.getApiKeyAuthentication().getRequestHeader(); + apiKeyRequestParam = properties.getApiKeyAuthentication().getRequestParameter(); + apiKeyValue = properties.getApiKeyAuthentication().getValue(); + + // OTP authentication fields + otpAuthEnabled = properties.getOtpAuthentication().isEnabled(); + otpDuration = properties.getOtpAuthentication().getDuration(); + otpRequestHeader = properties.getOtpAuthentication().getRequestHeader(); + otpRequestParam = properties.getOtpAuthentication().getRequestParam(); + + // User form authentication fields + userFormAuthEnabled = properties.getFormAuthentication().isEnabled(); + username = properties.getFormAuthentication().getUsername(); + password = properties.getFormAuthentication().getPassword(); + + loginPage = properties.getFormAuthentication().getLoginPage(); + loginUrl = properties.getFormAuthentication().getLoginUrl(); + loginSuccessUrl = properties.getFormAuthentication().getLoginSuccessUrl(); + loginFailureUrl = properties.getFormAuthentication().getLoginFailureUrl(); + logoutUrl = properties.getFormAuthentication().getLogoutUrl(); + logoutSuccessUrl = properties.getFormAuthentication().getLogoutSuccessUrl(); + + // Permitted URLs + permittedUrls = properties.getPermittedUrls()!=null + ? properties.getPermittedUrls().toArray(new String[0]) + : new String[0]; + + propertiesCopied = true; + } + @EventListener(ApplicationReadyEvent.class) public void applicationReady() { - if (userFormAuthEnabled && (StringUtils.isBlank(username) || password.isEmpty())) + if (securityEnabled && userFormAuthEnabled && (StringUtils.isBlank(username) || password.isEmpty())) throw new InvalidParameterException("User form authentication is enabled but username or password are blank"); - if (apiKeyAuthEnabled && StringUtils.isBlank(apiKeyValue)) + if (securityEnabled && apiKeyAuthEnabled && StringUtils.isBlank(apiKeyValue)) throw new InvalidParameterException("API Key authentication is enabled but no API Key provided or it is blank"); if (permittedUrls==null) permittedUrls = new String[0]; - log.info("afterPropertiesSet: Admin Username: {}", username); - log.info("afterPropertiesSet: Admin Password: {}", passwordUtil.encodePassword(password)); - log.info("afterPropertiesSet: API Key: {}", passwordUtil.encodePassword(apiKeyValue)); + if (securityEnabled && userFormAuthEnabled) { + log.info("afterPropertiesSet: Admin Username: {}", username); + log.info("afterPropertiesSet: Admin Password: {}", passwordUtil.encodePassword(password)); + } + if (securityEnabled && apiKeyAuthEnabled) { + log.info("afterPropertiesSet: API Key: {}", passwordUtil.encodePassword(apiKeyValue)); + } if (printSampleJwt) log.info("afterPropertiesSet:\n{}\nSample JWT Token: \nBearer {}\n{}", divider, jwtService(melodicSecurityProperties).create("USER"), divider); - log.debug("afterPropertiesSet: securityEnabled: {}", securityEnabled); - log.debug("afterPropertiesSet: jwtTokenAuthEnabled: {}", jwtTokenAuthEnabled); - log.debug("afterPropertiesSet: apiKeyRequestHeader: {}", apiKeyRequestHeader); - log.debug("afterPropertiesSet: apiKeyRequestParam: {}", apiKeyRequestParam); - log.debug("afterPropertiesSet: permittedUrls: {}", Arrays.asList(permittedUrls)); + log.debug("afterPropertiesSet: ---------------------"); + log.debug("afterPropertiesSet: securityEnabled: {}", securityEnabled); + log.debug("afterPropertiesSet: ---------------------"); + log.debug("afterPropertiesSet: jwtTokenAuthEnabled: {}", jwtAuthEnabled); + log.debug("afterPropertiesSet: jwtTokenRequestParam: {}", jwtRequestParam); + log.debug("afterPropertiesSet: ---------------------"); + log.debug("afterPropertiesSet: apiKeyAuthEnabled: {}", apiKeyAuthEnabled); + log.debug("afterPropertiesSet: apiKeyRequestHeader: {}", apiKeyRequestHeader); + log.debug("afterPropertiesSet: apiKeyRequestParam: {}", apiKeyRequestParam); + log.debug("afterPropertiesSet: ---------------------"); + log.debug("afterPropertiesSet: otpAuthEnabled: {}", otpAuthEnabled); + log.debug("afterPropertiesSet: otpDuration: {}", otpDuration); + log.debug("afterPropertiesSet: otpRequestHeader: {}", otpRequestHeader); + log.debug("afterPropertiesSet: otpRequestParam: {}", otpRequestParam); + log.debug("afterPropertiesSet: ---------------------"); + log.debug("afterPropertiesSet: userFormAuthEnabled: {}", userFormAuthEnabled); + log.debug("afterPropertiesSet: username: {}", username); log.debug("afterPropertiesSet: loginPage: {}", loginPage); log.debug("afterPropertiesSet: loginUrl: {}", loginUrl); log.debug("afterPropertiesSet: loginSuccessUrl: {}", loginSuccessUrl); log.debug("afterPropertiesSet: loginFailUrl: {}", loginFailureUrl); log.debug("afterPropertiesSet: logoutUrl: {}", logoutUrl); log.debug("afterPropertiesSet: logoutSuccessUrl: {}", logoutSuccessUrl); + log.debug("afterPropertiesSet: ---------------------"); + log.debug("afterPropertiesSet: permittedUrls: {}", Arrays.asList(permittedUrls)); + log.debug("afterPropertiesSet: ---------------------"); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + copyPropertiesToLocalFields(); if (this.userFormAuthEnabled && StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) { auth.inMemoryAuthentication() .withUser(username).password(passwordEncoder().encode(password)).authorities(ROLE_USER_FORM); @@ -154,7 +224,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public void configure(WebSecurity web) throws Exception { web.ignoring() // Spring Security should completely ignore the following URLs - .antMatchers("/favicon.ico", "/health"); + .antMatchers(staticResourceProperties.getFaviconContext(), "/health"); } @Override @@ -164,9 +234,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { checkSettings(); // Check if authentication is disabled - log.debug("WebSecurityConfig: security-enabled={}, user-form-auth-enabled={}, jwt-token-auth-enabled={}, api-key-auth-enabled={}", - securityEnabled, userFormAuthEnabled, jwtTokenAuthEnabled, apiKeyAuthEnabled); - if (!securityEnabled || !userFormAuthEnabled && !jwtTokenAuthEnabled && !apiKeyAuthEnabled) { + log.debug("WebSecurityConfig: security-enabled={}, user-form-auth-enabled={}, jwt-token-auth-enabled={}, api-key-auth-enabled={}, otp-auth-enabled={}", + securityEnabled, userFormAuthEnabled, jwtAuthEnabled, apiKeyAuthEnabled, otpAuthEnabled); + if (!securityEnabled || !userFormAuthEnabled && !jwtAuthEnabled && !apiKeyAuthEnabled && !otpAuthEnabled) { log.warn("WebSecurityConfig: Authentication is disabled"); // Authorize all requests httpSecurity @@ -217,7 +287,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { .anyRequest().authenticated(); log.debug("WebSecurityConfig: API-Key Authentication filter added"); } - if (jwtTokenAuthEnabled) { + if (jwtAuthEnabled) { log.info("WebSecurityConfig: JWT-Token Authentication is enabled"); httpSecurity .addFilterAfter(jwtAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class) @@ -225,6 +295,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { .anyRequest().authenticated(); log.debug("WebSecurityConfig: JWT-Token Authentication filter added"); } + if (otpAuthEnabled) { + log.info("WebSecurityConfig: OTP Authentication is enabled"); + httpSecurity + .addFilterAfter(otpAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) + .authorizeRequests() + .anyRequest().authenticated(); + log.debug("WebSecurityConfig: OTP Authentication filter added"); + } } private void checkSettings() { @@ -247,7 +325,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { if (StringUtils.isBlank(apiKeyValue)) log.warn("WebSecurityConfig: API Key authentication is enabled but -no- API Key has been provided. It will not be possible to authenticate using API Key"); else - log.warn("WebSecurityConfig: API Key authentication is enabled but -no- API Key request header or parameter have been set. It will not be possible to authenticate using API Key"); + log.warn("WebSecurityConfig: API Key authentication is enabled but -no- API Key request header or parameter has been set. It will not be possible to authenticate using API Key"); + } + + // Check OTP authentication settings + boolean otpAuthEnabled = this.otpAuthEnabled + && (StringUtils.isNotBlank(otpRequestHeader) || StringUtils.isNotBlank(otpRequestParam)); + if (this.otpAuthEnabled && !otpAuthEnabled) { + log.warn("WebSecurityConfig: OTP authentication is enabled but -no- OTP request header or parameter has been set. It will not be possible to authenticate using OTP"); } } @@ -260,12 +345,28 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { if (servletRequest instanceof HttpServletRequest) { HttpServletRequest req = (HttpServletRequest) servletRequest; - String header = req.getHeader(SecurityConstants.HEADER_STRING); - log.debug("jwtAuthorizationFilter: Authorization Header: {}", header); - if (header!=null && header.startsWith(SecurityConstants.TOKEN_PREFIX)) { + // Get JWT token from Authorization header + String jwtValue = req.getHeader(SecurityConstants.HEADER_STRING); + log.debug("jwtAuthorizationFilter: Authorization Header: {}", passwordUtil.encodePassword(jwtValue)); + + // ...else get JWT token from 'jwt' query parameter + if (StringUtils.isBlank(jwtValue)) { + if (StringUtils.isNotBlank(jwtRequestParam)) { + log.debug("jwtAuthorizationFilter: Authorization Header is missing. Checking for '{}' parameter", jwtRequestParam); + jwtValue = req.getParameter(jwtRequestParam); + log.debug("jwtAuthorizationFilter: '{}' parameter value: {}", jwtRequestParam, passwordUtil.encodePassword(jwtValue)); + if (StringUtils.isNotBlank(jwtValue)) + jwtValue = SecurityConstants.TOKEN_PREFIX + jwtValue; + } else { + log.debug("jwtAuthorizationFilter: JWT token not found in headers and no JWT token parameter has been set"); + } + } + + // Check JWT token validity + if (jwtValue!=null && jwtValue.startsWith(SecurityConstants.TOKEN_PREFIX)) { try { log.debug("jwtAuthorizationFilter: Parsing Authorization header..."); - Claims claims = jwtService(melodicSecurityProperties).parse(header); + Claims claims = jwtService(melodicSecurityProperties).parse(jwtValue); String user = claims.getSubject(); String audience = claims.getAudience(); log.debug("jwtAuthorizationFilter: Authorization header --> user: {}", user); @@ -294,7 +395,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { log.warn("jwtAuthorizationFilter: Not an HttpServletRequest"); } - // continue down the chain + // continue filter chain processing filterChain.doFilter(servletRequest, servletResponse); }; } @@ -332,18 +433,99 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { log.debug("apiKeyAuthenticationFilter: API Key is incorrect"); } } else { - log.debug("apiKeyAuthenticationFilter: No API Key found in request header or parameters"); + log.debug("apiKeyAuthenticationFilter: No API Key found in request headers or parameters"); } } else { throw new IllegalArgumentException("API Key Authentication filter does not support non-HTTP requests and responses. Req-class: " +servletRequest.getClass().getName()+" Resp-class: "+servletResponse.getClass().getName()); } } else { - log.warn("apiKeyAuthenticationFilter: No API-Key specified. Access is granted"); + log.warn("apiKeyAuthenticationFilter: No API-Key specified"); + } + + // continue down the chain + filterChain.doFilter(servletRequest, servletResponse); + }; + } + + public Filter otpAuthenticationFilter() { + return (servletRequest, servletResponse, filterChain) -> { + log.trace("OTPAuthenticationFilter: BEGIN: request={}", servletRequest); + if (otpAuthEnabled) { + if (servletRequest instanceof HttpServletRequest && servletResponse instanceof HttpServletResponse) { + HttpServletRequest request = (HttpServletRequest) servletRequest; + log.trace("OTPAuthenticationFilter: http-request={}", request); + String otp = request.getHeader(otpRequestHeader); + log.debug("OTPAuthenticationFilter: Request Header OTP: {}={}", otpRequestHeader, passwordUtil.encodePassword(otp)); + if (StringUtils.isBlank(otp)) { + otp = request.getParameter(otpRequestParam); + log.debug("OTPAuthenticationFilter: Request Parameter OTP: {}={}", otpRequestParam, passwordUtil.encodePassword(otp)); + } + if (StringUtils.isNotBlank(otp)) { + log.debug("OTPAuthenticationFilter: OTP provided"); + + if (otpCache.containsKey(otp)) { + long issueTimestamp = otpCache.remove(otp); + boolean expired = (System.currentTimeMillis() - issueTimestamp) > otpDuration; + + if (!expired) { + log.debug("OTPAuthenticationFilter: OTP found in cache"); + try { + // construct one of Spring's auth tokens + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(otpRequestHeader, otp, + Collections.singletonList(new SimpleGrantedAuthority(ROLE_OTP))); + // store completed authentication in security context + SecurityContextHolder.getContext().setAuthentication(authentication); + log.debug("OTPAuthenticationFilter: Security context has been updated"); + } catch (Exception e) { + log.error("OTPAuthenticationFilter: EXCEPTION: ", e); + } + } else { + log.debug("OTPAuthenticationFilter: OTP found in cache but has expired"); + } + } else { + log.debug("OTPAuthenticationFilter: OTP not found in cache"); + } + } else { + log.debug("OTPAuthenticationFilter: No OTP provided in request headers or parameters"); + } + } else { + throw new IllegalArgumentException("OTP Authentication filter does not support non-HTTP requests and responses. Req-class: " + +servletRequest.getClass().getName()+" Resp-class: "+servletResponse.getClass().getName()); + } + } else { + log.warn("OTPAuthenticationFilter: OTP is disabled"); } // continue down the chain filterChain.doFilter(servletRequest, servletResponse); }; } + + public String otpCreate() { + String newOtp = RandomStringUtils.randomAlphanumeric(32, 64); + otpCache.put(newOtp, System.currentTimeMillis()); + return newOtp; + } + + public long otpIssueTimestamp(String otp) { + return otpCache.get(otp); + } + + public long otpExpirationTimestamp(String otp) { + return otpCache.get(otp) + otpDuration; + } + + public long otpDuration(String otp) { + return otpDuration; + } + + public void otpRemove(String otp) { + otpCache.remove(otp); + } + + public void otpClearCache() { + otpCache.clear(); + } } \ No newline at end of file diff --git a/event-management/control-service/src/main/resources/META-INF/spring.factories b/event-management/control-service/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000000000000000000000000000000000..7966109cfe09255ae63e437f39f3e26ee8170e0b --- /dev/null +++ b/event-management/control-service/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.env.EnvironmentPostProcessor=eu.melodic.event.util.NetUtilPostProcessor \ No newline at end of file diff --git a/event-management/control-service/src/main/resources/banner.txt b/event-management/control-service/src/main/resources/banner.txt index 2f4beccffd2bf6b94726a75f9e713320e829407f..bd157e77a1adacd31cee8e814f0da549d4cd793e 100644 --- a/event-management/control-service/src/main/resources/banner.txt +++ b/event-management/control-service/src/main/resources/banner.txt @@ -10,4 +10,5 @@ :: Spring Boot :: ${spring-boot.formatted-version} :: Build Num. :: @buildNumber@ :: Build Date :: @timestamp@ - :: SCM Branch :: @scmBranch@ \ No newline at end of file + :: SCM Branch :: @scmBranch@ + :: Description :: @build-description@ \ No newline at end of file diff --git a/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorInstallationHelper.java b/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorInstallationHelper.java index 76dee2865b0b94184516c63d4a378cb627ec64e6..6aba9070ba6a2ae6b5f9f721db52dc6c21d86858 100644 --- a/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorInstallationHelper.java +++ b/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorInstallationHelper.java @@ -17,6 +17,7 @@ import eu.melodic.event.baguette.client.install.instruction.InstructionsSet; import eu.melodic.event.baguette.server.BaguetteServer; import eu.melodic.event.baguette.server.NodeRegistryEntry; import eu.melodic.event.util.CredentialsMap; +import eu.melodic.event.util.NetUtil; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -91,7 +92,7 @@ public class CloudiatorInstallationHelper extends AbstractInstallationHelper { Map valueMap = new HashMap<>(); valueMap.put("BAGUETTE_CLIENT_ID", clientId); valueMap.put("BAGUETTE_SERVER_ADDRESS", baguette.getConfiguration().getServerAddress()); - valueMap.put("BAGUETTE_SERVER_HOSTNAME", baguette.getConfiguration().getServerHostname()); + valueMap.put("BAGUETTE_SERVER_HOSTNAME", NetUtil.getHostname()); valueMap.put("BAGUETTE_SERVER_PORT", ""+baguette.getConfiguration().getServerPort()); valueMap.put("BAGUETTE_SERVER_PUBKEY", baguette.getServerPubkey()); valueMap.put("BAGUETTE_SERVER_PUBKEY_FINGERPRINT", baguette.getServerPubkeyFingerprint()); diff --git a/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtil.java b/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtil.java index 971101874ebf9bebc959734dba85c20f0e0cb863..a60fa3f5b563d4621371012e7d9a9a9dd791f3da 100644 --- a/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtil.java +++ b/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtil.java @@ -55,8 +55,8 @@ public class CloudiatorUtil implements InitializingBean { log.warn("CloudiatorUtil.afterPropertiesSet(): configuration: {}", properties); this.client = ClientBuilder.getNew() - .url(properties.getColosseumEndpoint()) - .credentials(properties.getColosseumAuthEmail(), properties.getColosseumAuthTenant(), properties.getColosseumAuthPassword()) + .url(properties.getColosseum().getEndpoint()) + .credentials(properties.getColosseum().getAuthEmail(), properties.getColosseum().getAuthTenant(), properties.getColosseum().getAuthPassword()) .build(); preparePatterns(); diff --git a/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtilProperties.java b/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtilProperties.java index d28b58dbb6b7857e725c1aec7ee2afb4e5b3cbfe..7a7b9411512a0d9bf7566038c47360aaca86bf3f 100644 --- a/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtilProperties.java +++ b/event-management/extra/src/main/java/eu/melodic/event/extra/cloudiator/CloudiatorUtilProperties.java @@ -9,11 +9,10 @@ package eu.melodic.event.extra.cloudiator; -import lombok.Getter; -import lombok.Setter; +import eu.melodic.event.util.EmsConstant; +import lombok.Data; import lombok.ToString; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @@ -23,52 +22,45 @@ import javax.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; -@Getter -@Setter -@ToString +@Slf4j +@Data @Validated @Configuration -@ConfigurationProperties +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "colosseum") @PropertySource("file:${MELODIC_CONFIG_DIR}/cloudiator.properties") -@Slf4j public class CloudiatorUtilProperties { @NotNull - @Value("${colosseum.endpoint}") - private String colosseumEndpoint; - @NotNull - @Value("${colosseum.auth.email}") - private String colosseumAuthEmail; - @NotNull - @Value("${colosseum.auth.tenant}") - private String colosseumAuthTenant; - @NotNull - @Value("${colosseum.auth.password}") - private String colosseumAuthPassword; + private Colosseum colosseum = new Colosseum(); + + @Data + public static class Colosseum { + @NotNull + private String endpoint; + @NotNull + private String authEmail; + @NotNull + private String authTenant; + @NotNull + @ToString.Exclude + private String authPassword; - @Value("${colosseum.db.enabled:false}") - private boolean colosseumDbEnabled; - @Value("${colosseum.db.driver:}") - private String colosseumDbDriver; - @Value("${colosseum.db.url:}") - private String colosseumDbUrl; - @Value("${colosseum.db.username:}") - private String colosseumDbUsername; - @Value("${colosseum.db.password:}") - private String colosseumDbPassword; - @Value("${colosseum.db.database:}") - private String colosseumDbDatabase; + private boolean dbEnabled; + private String dbDriver; + private String dbUrl; + private String dbUsername; + @ToString.Exclude + private String dbPassword; + private String dbDatabase; - @Value("${colosseum.owner-id:-1}") - private int colosseumOwnerId; + private int ownerId = -1; + } @NotNull private final List providerEndpointPatterns = new ArrayList<>(); @NotNull private final List providerLocationPatterns = new ArrayList<>(); - @Getter - @Setter - @ToString + @Data public static class ProviderPatternPair { private String pattern; private String provider; diff --git a/event-management/pom.xml b/event-management/pom.xml index 460bcebfcf5db64ba720b02cdf1bce7a9dab8fc9..d582bd868951ef2b220a7edb25d2ec0fa833ad79 100644 --- a/event-management/pom.xml +++ b/event-management/pom.xml @@ -33,7 +33,7 @@ 4.5.0-SNAPSHOT--> 4.5.0-SNAPSHOT - 2.8.5 + 2.8.9 3.8.1 @@ -81,10 +81,14 @@ extra + build-web-admin - true + false + + .dev-skip-build-web-admin + web-admin diff --git a/event-management/translator/pom.xml b/event-management/translator/pom.xml index 73328b3dccd7373106d6e3f401c4a36cf22a6f1f..57ec4c0ee6debc637f184720c6084909ac3f84cf 100644 --- a/event-management/translator/pom.xml +++ b/event-management/translator/pom.xml @@ -128,7 +128,6 @@ com.google.code.gson gson - 2.8.5 diff --git a/event-management/translator/src/main/java/eu/melodic/event/translate/CamelToEplTranslator.java b/event-management/translator/src/main/java/eu/melodic/event/translate/CamelToEplTranslator.java index b2b000f2c3522bef190561950b096b005fd738a1..95bd470c2ba75e26d2f4c2c62ea5e90cce930b31 100644 --- a/event-management/translator/src/main/java/eu/melodic/event/translate/CamelToEplTranslator.java +++ b/event-management/translator/src/main/java/eu/melodic/event/translate/CamelToEplTranslator.java @@ -30,7 +30,7 @@ import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import java.util.*; @@ -41,13 +41,13 @@ import java.util.stream.Collectors; @NoArgsConstructor public class CamelToEplTranslator implements Translator { + @Autowired + private ApplicationContext applicationContext; @Autowired private CamelToEplTranslatorProperties properties; @Autowired private RuleTemplateProperties ruleTemplatesRegistry; - @Value("${translator.leaf-node-grouping}") - private String leafGrouping; - + private CDOClientX cdoClient; public CamelToEplTranslator(CDOClientX client) { @@ -106,19 +106,19 @@ public class CamelToEplTranslator implements Translator { // analyze scalability rules and metric expressions log.debug("CamelToEplTranslator.translate(): Analyzing models..."); - ModelAnalyzer modelAnalyzer = new ModelAnalyzer(); - modelAnalyzer.analyzeModel(_TC, leafGrouping, camelModel, properties); + ModelAnalyzer modelAnalyzer = applicationContext.getBean(ModelAnalyzer.class); + modelAnalyzer.analyzeModel(_TC, camelModel); log.debug("CamelToEplTranslator.translate(): Analyzing models... done"); // transform graph log.debug("CamelToEplTranslator.translate(): Transforming DAG..."); - GraphTransformer transformer = new GraphTransformer(); - transformer.transformGraph(_TC.DAG, properties); + GraphTransformer transformer = applicationContext.getBean(GraphTransformer.class); + transformer.transformGraph(_TC.DAG); log.debug("CamelToEplTranslator.translate(): Transforming DAG... done"); // generate EPL rules log.debug("CamelToEplTranslator.translate(): Generating EPL rules..."); - RuleGenerator generator = new RuleGenerator(ruleTemplatesRegistry); + RuleGenerator generator = applicationContext.getBean(RuleGenerator.class); generator.generateRules(_TC); log.debug("CamelToEplTranslator.translate(): Generating EPL rules... done"); @@ -146,7 +146,7 @@ public class CamelToEplTranslator implements Translator { // Print DAG String dot = null; - if (properties.isExportToDotEnabled()) { + if (properties.getDag().isExportToDotEnabled()) { log.info("Decomposition Graph:\n{}", _TC.DAG); log.info("*********************************************************"); try { @@ -157,14 +157,14 @@ public class CamelToEplTranslator implements Translator { } } // Export DAG to files - if (properties.isExportToFileEnabled()) { + if (properties.getDag().isExportToFileEnabled()) { log.info("*********************************************************"); log.info("Decomposition Graph export to file(s)"); try { // Get graph export configuration - String exportPath = properties.getExportPath(); - String[] exportFormats = properties.getExportFormats(); - int imageWidth = properties.getExportImageWidth(); + String exportPath = properties.getDag().getExportPath(); + String[] exportFormats = properties.getDag().getExportFormats(); + int imageWidth = properties.getDag().getExportImageWidth(); // Get base name and path of export files if (exportPath == null) exportPath = ""; diff --git a/event-management/translator/src/main/java/eu/melodic/event/translate/analyze/ModelAnalyzer.java b/event-management/translator/src/main/java/eu/melodic/event/translate/analyze/ModelAnalyzer.java index ca6fbddf744985bd5359ca791310d603454cfcae..7b4978df9e5e8758c47328b9c6278d35c52b576c 100644 --- a/event-management/translator/src/main/java/eu/melodic/event/translate/analyze/ModelAnalyzer.java +++ b/event-management/translator/src/main/java/eu/melodic/event/translate/analyze/ModelAnalyzer.java @@ -28,11 +28,14 @@ import eu.melodic.event.translate.properties.CamelToEplTranslatorProperties; import eu.melodic.models.interfaces.ems.*; import eu.melodic.event.translate.model.tools.metadata.CamelMetadata; import eu.melodic.event.translate.model.tools.metadata.CamelMetadataTool; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.emf.common.util.EList; +import org.springframework.stereotype.Service; import java.util.*; import java.util.List; @@ -40,18 +43,20 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Slf4j +@Service +@RequiredArgsConstructor public class ModelAnalyzer { - private CamelToEplTranslatorProperties properties; + private final CamelToEplTranslatorProperties properties; private List EMS_SINKS; // ================================================================================================================ // Model analysis methods - public void analyzeModel(TranslationContext _TC, String leafGrouping, CamelModel camelModel, CamelToEplTranslatorProperties properties) { + public void analyzeModel(TranslationContext _TC, CamelModel camelModel) { log.debug("ModelAnalyzer.analyzeModel(): Analyzing models..."); - this.properties = properties; + String leafGrouping = properties.getLeafNodeGrouping(); // set full-name pattern in _TC, for full-name generation _TC.setFullNamePattern(properties.getFullNamePattern()); @@ -943,7 +948,7 @@ public class ModelAnalyzer { log.debug(" _initializeSinks(): Sink type configurations: {}", properties.getSinkConfig()); List sinks = new ArrayList<>(); - for (String sinkType : properties.getSinks()) { + for (String sinkType : CollectionUtils.emptyIfNull(properties.getSinks())) { log.trace(" _initializeSinks(): Processing sink type: {}", sinkType); Sink.TypeType sinkTypeType = Sink.TypeType.valueOf(sinkType); Map configMap = properties.getSinkConfig().get(sinkType); diff --git a/event-management/translator/src/main/java/eu/melodic/event/translate/generate/RuleGenerator.java b/event-management/translator/src/main/java/eu/melodic/event/translate/generate/RuleGenerator.java index 316a501b59b45b9810e911f6973e0e084975c543..9dcc231ad3815ae42c606a9c774ab9ca772b6015 100644 --- a/event-management/translator/src/main/java/eu/melodic/event/translate/generate/RuleGenerator.java +++ b/event-management/translator/src/main/java/eu/melodic/event/translate/generate/RuleGenerator.java @@ -25,6 +25,7 @@ import camel.scalability.NonFunctionalEvent; import camel.scalability.UnaryEventPattern; import eu.melodic.event.brokercep.cep.MathUtil; import eu.melodic.event.translate.TranslationContext; +import eu.melodic.event.translate.properties.CamelToEplTranslatorProperties; import eu.melodic.event.translate.properties.RuleTemplateProperties; import eu.melodic.event.translate.model.tools.metadata.CamelMetadataTool; import lombok.extern.slf4j.Slf4j; @@ -47,12 +48,15 @@ import java.util.stream.Collectors; @Service public class RuleGenerator { + @Autowired + private CamelToEplTranslatorProperties properties; @Autowired private RuleTemplateProperties ruleTemplatesRegistry; private SpringTemplateEngine templateEngine; - public RuleGenerator(RuleTemplateProperties ruleTemplatesRegistry) { + public RuleGenerator(CamelToEplTranslatorProperties properties, RuleTemplateProperties ruleTemplatesRegistry) { + this.properties = properties; this.ruleTemplatesRegistry = ruleTemplatesRegistry; initTemplateEngine(); } diff --git a/event-management/translator/src/main/java/eu/melodic/event/translate/properties/CamelToEplTranslatorProperties.java b/event-management/translator/src/main/java/eu/melodic/event/translate/properties/CamelToEplTranslatorProperties.java index a53d6a65d290d38a80de50e4cef9039ca990cc5e..2d7d9be27c6fd15efeb7f6f90803c9f0900bf838 100644 --- a/event-management/translator/src/main/java/eu/melodic/event/translate/properties/CamelToEplTranslatorProperties.java +++ b/event-management/translator/src/main/java/eu/melodic/event/translate/properties/CamelToEplTranslatorProperties.java @@ -9,9 +9,10 @@ package eu.melodic.event.translate.properties; +import eu.melodic.event.util.EmsConstant; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @@ -21,48 +22,46 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +@Slf4j @Data @Validated @Configuration -@ConfigurationProperties -@Slf4j +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "translator") @PropertySource("file:${MELODIC_CONFIG_DIR}/eu.melodic.event.translator.properties") -public class CamelToEplTranslatorProperties { +public class CamelToEplTranslatorProperties implements InitializingBean { + @Override + public void afterPropertiesSet() { + log.debug("CamelToEplTranslatorProperties: {}", this); + } + // Translator parameters - @Value("${translator.sensor-config-annotation}") private String sensorConfigurationAnnotation; - @Value("${translator.sensor-min-interval}") private long sensorMinInterval; - @Value("${translator.sensor-default-interval}") private long sensorDefaultInterval; - @Value("${translator.prune-mvv:true}") - private boolean pruneMvv; - @Value("${translator.add-top-level-metrics:true}") - private boolean addTopLevelMetric; - @Value("${translator.full-name-pattern}") + private String leafNodeGrouping; + private boolean pruneMvv = true; + private boolean addTopLevelMetrics = true; private String fullNamePattern; - @Value("${translator.formula-check-enabled:true}") - private boolean formulaCheckEnabled; + private boolean formulaCheckEnabled = true; // Translation Results & Graph print/export Switches - @Value("${translator.print-results:true}") - private boolean printResults; - @Value("${dag.export-to-dot.enabled:true}") - private boolean exportToDotEnabled; - @Value("${dag.export-to-file.enabled:true}") - private boolean exportToFileEnabled; + private boolean printResults = true; + private Dag dag = new Dag(); + + @Data + public static class Dag { + // Graph rendering/export + private boolean exportToDotEnabled = true; + private boolean exportToFileEnabled = true; - // Graph rendering parameters - @Value("${dag.export.path:}") - private String exportPath; - @Value("${dag.export.formats:}") - private String[] exportFormats; - @Value("${dag.export.image-width:-1}") - private int exportImageWidth; + // Graph rendering parameters + private String exportPath; + private String[] exportFormats; + private int exportImageWidth = -1; + } // Active sink types - @Value("${active-sinks:}") private List sinks; // Sink type configurations diff --git a/event-management/translator/src/main/java/eu/melodic/event/translate/properties/RuleTemplateProperties.java b/event-management/translator/src/main/java/eu/melodic/event/translate/properties/RuleTemplateProperties.java index 175459e5fb41dfc9e6ad4737cc65e2cbdd3cdb3d..b044b6101f23ad0565ffabfff8943288c7785eae 100644 --- a/event-management/translator/src/main/java/eu/melodic/event/translate/properties/RuleTemplateProperties.java +++ b/event-management/translator/src/main/java/eu/melodic/event/translate/properties/RuleTemplateProperties.java @@ -9,9 +9,10 @@ package eu.melodic.event.translate.properties; +import eu.melodic.event.util.EmsConstant; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -22,14 +23,18 @@ import java.util.List; import java.util.Map; import java.util.Optional; +@Slf4j @Data @Validated @Configuration @EnableConfigurationProperties -@ConfigurationProperties(prefix = "generator") -@Slf4j -public class RuleTemplateProperties { - @Value("${generator.language:}") +@ConfigurationProperties(prefix = EmsConstant.EMS_PROPERTIES_PREFIX + "generator") +public class RuleTemplateProperties implements InitializingBean { + @Override + public void afterPropertiesSet() { + log.debug("RuleTemplateProperties: {}", this); + } + private String language; private Map>> ruleTemplates; diff --git a/event-management/translator/src/main/java/eu/melodic/event/translate/transform/GraphTransformer.java b/event-management/translator/src/main/java/eu/melodic/event/translate/transform/GraphTransformer.java index e927e43803e95e03c6ca29d3ac5e295d068a54fc..2da785639a5c9f88ed082dae591d7b78f5a6d9ab 100644 --- a/event-management/translator/src/main/java/eu/melodic/event/translate/transform/GraphTransformer.java +++ b/event-management/translator/src/main/java/eu/melodic/event/translate/transform/GraphTransformer.java @@ -17,16 +17,20 @@ import eu.melodic.event.translate.analyze.DAG; import eu.melodic.event.translate.analyze.DAGNode; import eu.melodic.event.translate.analyze.Grouping; import eu.melodic.event.translate.properties.CamelToEplTranslatorProperties; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; import java.util.Set; @Slf4j +@Service +@RequiredArgsConstructor public class GraphTransformer { - private CamelToEplTranslatorProperties properties; + private final CamelToEplTranslatorProperties properties; - public void transformGraph(DAG dag, CamelToEplTranslatorProperties properties) { + public void transformGraph(DAG dag) { log.debug("GraphTransformer.transformGraph(): Transforming DAG..."); if (properties.isPruneMvv()) { removeMVV(dag, dag.getRootNode()); @@ -34,7 +38,7 @@ public class GraphTransformer { log.debug("GraphTransformer.transformGraph(): MVV pruning from DAG is disabled"); } - if (properties.isAddTopLevelMetric()) { + if (properties.isAddTopLevelMetrics()) { addTopLevelMetrics(dag); } else { log.debug("GraphTransformer.transformGraph(): Adding Metric for Top-Level Metric Contexts in DAG is disabled"); diff --git a/event-management/util/src/main/java/eu/melodic/event/util/EmsConstant.java b/event-management/util/src/main/java/eu/melodic/event/util/EmsConstant.java index 7a5b0f98505ea9f605b8159e911b9a31fa8c7897..5a0b17b47d420eda48603551f5f1681754e1aa7f 100644 --- a/event-management/util/src/main/java/eu/melodic/event/util/EmsConstant.java +++ b/event-management/util/src/main/java/eu/melodic/event/util/EmsConstant.java @@ -13,5 +13,6 @@ package eu.melodic.event.util; * EMS constant */ public class EmsConstant { + public final static String EMS_PROPERTIES_PREFIX = ""; //""ems."; public final static String EVENT_PROPERTY_SOURCE_ADDRESS = "producer-host"; } \ No newline at end of file diff --git a/event-management/util/src/main/java/eu/melodic/event/util/IKeystoreAndCertificateProperties.java b/event-management/util/src/main/java/eu/melodic/event/util/IKeystoreAndCertificateProperties.java index 17b686d8bc0a222027ce13150429301b0ec1efb7..803c77c46cf51d0450f50450684cbc2ee711722b 100644 --- a/event-management/util/src/main/java/eu/melodic/event/util/IKeystoreAndCertificateProperties.java +++ b/event-management/util/src/main/java/eu/melodic/event/util/IKeystoreAndCertificateProperties.java @@ -11,10 +11,7 @@ package eu.melodic.event.util; public interface IKeystoreAndCertificateProperties { - public enum KEY_ENTRY_GENERATE { YES, ALWAYS, NO, NEVER, IF_MISSING, IF_IP_CHANGED }; - - String getDefaultIpAddress(); - String getPublicIpAddress(); + enum KEY_ENTRY_GENERATE { YES, ALWAYS, NO, NEVER, IF_MISSING, IF_IP_CHANGED }; String getKeystoreFile(); String getKeystoreType(); @@ -28,8 +25,4 @@ public interface IKeystoreAndCertificateProperties { String getKeyEntryName(); String getKeyEntryDName(); String getKeyEntryExtSAN(); - - public String getKeyEntryNameValue(); - public String getKeyEntryDNameValue(); - public String getKeyEntryExtSANValue(); } diff --git a/event-management/util/src/main/java/eu/melodic/event/util/KeystoreAndCertificateProperties.java b/event-management/util/src/main/java/eu/melodic/event/util/KeystoreAndCertificateProperties.java index 01dbb855645d3b073895e52adacb4005dae9e0a5..7a2e23ec9dc31b65a4bb6663ff3eb233336c618a 100644 --- a/event-management/util/src/main/java/eu/melodic/event/util/KeystoreAndCertificateProperties.java +++ b/event-management/util/src/main/java/eu/melodic/event/util/KeystoreAndCertificateProperties.java @@ -19,9 +19,6 @@ import org.apache.commons.lang3.StringUtils; @ToString(exclude = {"truststorePassword", "keystorePassword"}) public class KeystoreAndCertificateProperties implements IKeystoreAndCertificateProperties { - private String defaultIpAddress; - private String publicIpAddress; - private String keystoreFile; private String keystoreType; private String keystorePassword; @@ -36,39 +33,4 @@ public class KeystoreAndCertificateProperties implements IKeystoreAndCertificate private String keyEntryName; private String keyEntryDName; private String keyEntryExtSAN; - - public String getKeyEntryNameValue() { return prepareValue(keyEntryName, this.publicIpAddress, this.defaultIpAddress, "127.0.0.1"); } - public String getKeyEntryDNameValue() { return prepareValue(keyEntryDName, this.publicIpAddress, this.defaultIpAddress, "127.0.0.1"); } - public String getKeyEntryExtSANValue() { return prepareValue(keyEntryExtSAN, this.publicIpAddress, this.defaultIpAddress, "127.0.0.1"); } - - // ------------------------------------------------------------------------ - // Helper methods - // ------------------------------------------------------------------------ - - public static String prepareUrl(String url) { - return prepareValue(url, ""); - } - - public static String prepareValue(String value, String defaultValue) { return prepareValue(value, null, null, ""); } - - public static String prepareValue(String value, String publicIpAddress, String defaultIpAddress, String defaultValue) { - if (value==null) return null; - String pubIpAddr = ""; - if (value.contains("%{PUBLIC_IP}%")) { - pubIpAddr = NetUtil.getPublicIpAddress(); - pubIpAddr = StringUtils.isNotBlank(pubIpAddr) - ? pubIpAddr - : StringUtils.isNotBlank(publicIpAddress) ? publicIpAddress : defaultValue; - } - String defIpAddr = ""; - if (value.contains("%{DEFAULT_IP}%")) { - defIpAddr = NetUtil.getDefaultIpAddress(); - defIpAddr = StringUtils.isNotBlank(defIpAddr) - ? defIpAddr - : StringUtils.isNotBlank(defaultIpAddress) ? defaultIpAddress : defaultValue; - } - return value - .replace("%{PUBLIC_IP}%", pubIpAddr) - .replace("%{DEFAULT_IP}%", defIpAddr); - } } diff --git a/event-management/util/src/main/java/eu/melodic/event/util/KeystoreUtil.java b/event-management/util/src/main/java/eu/melodic/event/util/KeystoreUtil.java index 9d2eaedbf71145f9c35f9d1ff920eae01c141f1c..0efcf3bba729f289a2f3f3fce2d1610e617bb67d 100644 --- a/event-management/util/src/main/java/eu/melodic/event/util/KeystoreUtil.java +++ b/event-management/util/src/main/java/eu/melodic/event/util/KeystoreUtil.java @@ -50,9 +50,9 @@ public class KeystoreUtil { private static boolean bcProviderInitialized = false; - private String keystoreFile; - private String keystoreType; - private String keystorePassword; + private final String keystoreFile; + private final String keystoreType; + private final String keystorePassword; private PasswordUtil passwordUtil; // KeystoreUtil instance methods @@ -110,9 +110,6 @@ public class KeystoreUtil { } public KeystoreUtil createKeyAndCert(String entryName, String keyGenAlg, int keySize, String sigAlg, int startDateOffset, int endDateOffset, String dn, String extSAN) throws Exception { - // Replace PUBLIC_IP and DEFAULT_IP placeholders with actual values - dn = _processPlaceholders(dn, "127.0.0.1"); - extSAN = _processPlaceholders(extSAN, "127.0.0.1"); boolean hasExt = StringUtils.isNotBlank(extSAN); // Read keystore from file or create it @@ -209,22 +206,6 @@ public class KeystoreUtil { return this; } - // Replace PUBLIC_IP and DEFAULT_IP placeholders with actual values - private String _processPlaceholders(String s, String defaultValue) { - if (s==null) return null; - if (s.contains("%{PUBLIC_IP}%")) { - String publicIp = NetUtil.getPublicIpAddress(); - if (StringUtils.isBlank(publicIp)) publicIp = defaultValue; - s = s.replace("%{PUBLIC_IP}%", publicIp); - } - if (s.contains("%{DEFAULT_IP}%")) { - String defaultIp = NetUtil.getDefaultIpAddress(); - if (StringUtils.isBlank(defaultIp)) defaultIp=defaultValue; - s = s.replace("%{DEFAULT_IP}%", defaultIp); - } - return s; - } - public KeystoreUtil createOrReplaceKeyAndCert(String entryName, String keyGenAlg, int keySize, String sigAlg, int startDateOffset, int endDateOffset, String dn, String ext) throws Exception { return this .deleteEntry(entryName) @@ -232,7 +213,8 @@ public class KeystoreUtil { } public KeystoreUtil createKeyAndCertWithSAN(String entryName, String dn) throws Exception { - String sanExt = "dns:localhost,ip:127.0.0.1,ip:%{DEFAULT_IP}%,ip:%{PUBLIC_IP}%"; + String sanExt = String.format("dns:localhost,ip:127.0.0.1,ip:%s,ip:%s", + NetUtil.getDefaultIpAddress(), NetUtil.getPublicIpAddress()); return createKeyAndCert(entryName, dn, sanExt); } @@ -435,9 +417,9 @@ public class KeystoreUtil { log.debug(" Trust store type: {}", properties.getTruststoreType()); log.debug(" Trust store password: {}", truststorePassword); log.debug(" Certificate file: {}", properties.getCertificateFile()); - log.debug(" Entry name: {}", properties.getKeyEntryNameValue()); - log.debug(" Entry DName: {}", properties.getKeyEntryDNameValue()); - log.debug(" Entry SAN: {}", properties.getKeyEntryExtSANValue()); + log.debug(" Entry name: {}", properties.getKeyEntryName()); + log.debug(" Entry DName: {}", properties.getKeyEntryDName()); + log.debug(" Entry SAN: {}", properties.getKeyEntryExtSAN()); log.debug(" Entry Gen.: {}", properties.getKeyEntryGenerate()); IKeystoreAndCertificateProperties.KEY_ENTRY_GENERATE keyGen = properties.getKeyEntryGenerate(); @@ -459,11 +441,11 @@ public class KeystoreUtil { boolean containsEntry = KeystoreUtil .getKeystore(properties.getKeystoreFile(), properties.getKeystoreType(), properties.getKeystorePassword()) .passwordUtil(passwordUtil) - .containsEntry(properties.getKeyEntryNameValue()); + .containsEntry(properties.getKeyEntryName()); if (containsEntry) { - log.debug(" Keystore already contains entry: {}", properties.getKeyEntryNameValue()); + log.debug(" Keystore already contains entry: {}", properties.getKeyEntryName()); } else { - log.debug(" Keystore does not contain entry: {}", properties.getKeyEntryNameValue()); + log.debug(" Keystore does not contain entry: {}", properties.getKeyEntryName()); gen = true; } } @@ -484,7 +466,7 @@ public class KeystoreUtil { List addrList = KeystoreUtil .getKeystore(properties.getKeystoreFile(), properties.getKeystoreType(), properties.getKeystorePassword()) .passwordUtil(passwordUtil) - .getEntryNames(properties.getKeyEntryNameValue(), true); + .getEntryNames(properties.getKeyEntryName(), true); log.debug(" Entry addresses: {}", addrList); // get current Default and Public IP addresses @@ -501,30 +483,30 @@ public class KeystoreUtil { // Generate new key pair and certificate, and update keystore and trust store if (gen) { - log.debug(" Generating new Key pair and Certificate for: {}", properties.getKeyEntryNameValue()); + log.debug(" Generating new Key pair and Certificate for: {}", properties.getKeyEntryName()); KeystoreUtil ksUtil = KeystoreUtil .getKeystore(properties.getKeystoreFile(), properties.getKeystoreType(), properties.getKeystorePassword()) .passwordUtil(passwordUtil) .createIfNotExist(); - if (StringUtils.isBlank(properties.getKeyEntryExtSANValue())) { - log.debug(" Create/Replace entry (with SAN auto-generate): {}", properties.getKeyEntryNameValue()); - ksUtil.createOrReplaceKeyAndCertWithSAN(properties.getKeyEntryNameValue(), properties.getKeyEntryDNameValue()); + if (StringUtils.isBlank(properties.getKeyEntryExtSAN())) { + log.debug(" Create/Replace entry (with SAN auto-generate): {}", properties.getKeyEntryName()); + ksUtil.createOrReplaceKeyAndCertWithSAN(properties.getKeyEntryName(), properties.getKeyEntryDName()); } else { log.debug(" Create/Replace entry and SAN: entry={}, san={}", - properties.getKeyEntryNameValue(), properties.getKeyEntryExtSANValue()); - String extSAN = properties.getKeyEntryExtSANValue().trim(); - ksUtil.createOrReplaceKeyAndCert(properties.getKeyEntryNameValue(), properties.getKeyEntryDNameValue(), extSAN); + properties.getKeyEntryName(), properties.getKeyEntryExtSAN()); + String extSAN = properties.getKeyEntryExtSAN().trim(); + ksUtil.createOrReplaceKeyAndCert(properties.getKeyEntryName(), properties.getKeyEntryDName(), extSAN); } log.debug(" Exporting certificate to: {}", properties.getCertificateFile()); - ksUtil.exportCertToFile(properties.getKeyEntryNameValue(), properties.getCertificateFile()); + ksUtil.exportCertToFile(properties.getKeyEntryName(), properties.getCertificateFile()); KeystoreUtil tsUtil = KeystoreUtil .getKeystore(properties.getTruststoreFile(), properties.getTruststoreType(), properties.getTruststorePassword()) .passwordUtil(passwordUtil) .createIfNotExist(); log.debug(" Importing certificate to trust store: {}", properties.getTruststoreFile()); - tsUtil.importAndReplaceCertFromFile(properties.getKeyEntryNameValue(), properties.getCertificateFile()); + tsUtil.importAndReplaceCertFromFile(properties.getKeyEntryName(), properties.getCertificateFile()); log.debug(" Key pair and Certificate generation completed"); } else { @@ -536,7 +518,7 @@ public class KeystoreUtil { String certPemStr = KeystoreUtil .getKeystore(properties.getKeystoreFile(), properties.getKeystoreType(), properties.getKeystorePassword()) .passwordUtil(passwordUtil) - .getEntryCertificateAsPEM(properties.getKeyEntryNameValue()); + .getEntryCertificateAsPEM(properties.getKeyEntryName()); log.debug(" Certificate (PEM):\n{}", certPemStr); } } diff --git a/event-management/util/src/main/java/eu/melodic/event/util/NetUtil.java b/event-management/util/src/main/java/eu/melodic/event/util/NetUtil.java index 7ebe1a0194cce60d6f36b5cc524f7d3208e257ac..295bb6490bc2a1d59cd1befa82d3080b3287be8e 100644 --- a/event-management/util/src/main/java/eu/melodic/event/util/NetUtil.java +++ b/event-management/util/src/main/java/eu/melodic/event/util/NetUtil.java @@ -15,6 +15,7 @@ import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.net.*; import java.util.*; +import java.util.stream.Collectors; /** * Network Utility @@ -22,19 +23,52 @@ import java.util.*; @Slf4j public class NetUtil { - private final static String[] addressFilter = { - "127.", - /*"192.168.", "10.", "172.16.", "172.31.", "169.254.",*/ - "224.", "239.", "255.255.255.255" - }; + private final static String[] ADDRESS_FILTERS; - private final static String DATAGRAM_ADDRESS = "8.8.8.8"; + private final static String DATAGRAM_ADDRESS; - private final static String[][] SERVICES = { - { "AWS", "http://checkip.amazonaws.com" }, - { "Ipify", "https://api.ipify.org/?format=text" }, - { "WhatIsMyIpAddress", "http://bot.whatismyipaddress.com/" } - }; + private final static String[][] PUBLIC_ADDRESS_DISCOVERY_SERVICES; + + static { + // Configure Address Filters + String filtersStr = System.getenv("NET_UTIL_ADDRESS_FILTERS"); + List filtersList = new ArrayList<>(); + if (StringUtils.isNotBlank(filtersStr)) { + filtersList = Arrays.stream(filtersStr.split("[;, \t]+")).map(String::trim).filter(s->!s.isEmpty()).collect(Collectors.toList()); + } else { + filtersList = Arrays.asList( + "127.", + /*"192.168.", "10.", "172.16.", "172.31.", "169.254.",*/ + "224.", "239.", "255.255.255.255" + ); + } + ADDRESS_FILTERS = filtersList.toArray(new String[0]); + + // Configure Datagram address + String datagramAddress = System.getenv("NET_UTIL_DATAGRAM_ADDRESS"); + DATAGRAM_ADDRESS = StringUtils.isNotBlank(datagramAddress) ? datagramAddress.trim() : "8.8.8.8"; + + // Configure Address discovery services + String servicesStr = System.getenv("NET_UTIL_ADDRESS_DISCOVERY_SERVICES"); + List servicesList = new ArrayList<>(); + if (StringUtils.isNotBlank(servicesStr)) { + if (!"-".equals(servicesStr)) { + Arrays.stream(servicesStr.split("[;, \t]+")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .map(s -> s.split("[:=]", 2)) + .filter(a -> a.length == 2) + .peek(a->{ a[0]=a[0].trim(); a[1]=a[1].trim(); }) + .filter(a->!a[0].isEmpty() && !a[1].isEmpty()) + .forEach(servicesList::add); + } + } else { + servicesList.add(Arrays.asList("AWS", "http://checkip.amazonaws.com").toArray(new String[0])); + servicesList.add(Arrays.asList("Ipify", "https://api.ipify.org/?format=text").toArray(new String[0])); + servicesList.add(Arrays.asList("WhatIsMyIpAddress", "http://bot.whatismyipaddress.com/").toArray(new String[0])); + } + PUBLIC_ADDRESS_DISCOVERY_SERVICES = servicesList.toArray(new String[0][]); + } // ------------------------------------------------------------------------ @@ -58,7 +92,7 @@ public class NetUtil { } } else { - for (String[] service : SERVICES) { + for (String[] service : PUBLIC_ADDRESS_DISCOVERY_SERVICES) { if (service[0].equalsIgnoreCase(arg)) { printAddress(queryService(service[1])); } @@ -114,7 +148,7 @@ public class NetUtil { if (inet instanceof java.net.Inet4Address) { String addr = inet.getHostAddress(); if (!inet.isLoopbackAddress() && !inet.isMulticastAddress() && inet.isSiteLocalAddress()) { - boolean ok = Arrays.stream(addressFilter) + boolean ok = Arrays.stream(ADDRESS_FILTERS) .noneMatch(addr::startsWith); if (ok) { log_debug("{}", addr); @@ -164,7 +198,7 @@ public class NetUtil { return publicIpAddress; } - for (String[] service : SERVICES) { + for (String[] service : PUBLIC_ADDRESS_DISCOVERY_SERVICES) { log_debug("NetUtil.getPublicIpAddress(): Contacting service {}", service[0]); String ip = getIpAddressUsingService(service[1]); if (StringUtils.isNotBlank(ip)) { diff --git a/event-management/util/src/main/java/eu/melodic/event/util/NetUtilPostProcessor.java b/event-management/util/src/main/java/eu/melodic/event/util/NetUtilPostProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..175c577843c6aca5560e8c4627d85e00f7c7e433 --- /dev/null +++ b/event-management/util/src/main/java/eu/melodic/event/util/NetUtilPostProcessor.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017-2022 Institute of Communication and Computer Systems (imu.iccs.gr) + * + * This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless + * Esper library is used, in which case it is subject to the terms of General Public License v2.0. + * If a copy of the MPL was not distributed with this file, you can obtain one at + * https://www.mozilla.org/en-US/MPL/2.0/ + */ + +package eu.melodic.event.util; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.boot.logging.DeferredLog; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.PropertySource; +import org.springframework.stereotype.Component; + +@Component +public class NetUtilPostProcessor implements EnvironmentPostProcessor { + private static final DeferredLog log = new DeferredLog(); + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + PropertySource ps = new NetUtilPropertySource(); + environment.getPropertySources().addFirst(ps); + log.info("NetUtilPostProcessor: NetUtilPropertySource registered (deferred log)"); + + application.addInitializers(ctx -> log.replayTo(NetUtilPostProcessor.class)); + } + + @Getter @Setter + public static class NetUtilPropertySource extends PropertySource { + private String defaultDefaultIp = "127.0.0.1"; + private String defaultPublicIp = "127.0.0.1"; + + public NetUtilPropertySource() { + super("ems-net-util-property-source"); + } + + public NetUtilPropertySource(String name) { + super(name); + } + + @Override + public String getProperty(String s) { + String address = null; + if ("DEFAULT_IP".equals(s)) { + address = NetUtil.getDefaultIpAddress(); + if (address==null) address = defaultDefaultIp; + } + if ("PUBLIC_IP".equals(s)) { + address = NetUtil.getPublicIpAddress(); + if (address==null) address = defaultPublicIp; + } + return address; + } + } +} diff --git a/event-management/util/src/main/java/eu/melodic/event/util/PasswordUtil.java b/event-management/util/src/main/java/eu/melodic/event/util/PasswordUtil.java index b7a7e0c1b6b477d93a145a85a5f647b3f4b96ab6..794ac71dcb33bb94b129436a453b4fd8b6273e96 100644 --- a/event-management/util/src/main/java/eu/melodic/event/util/PasswordUtil.java +++ b/event-management/util/src/main/java/eu/melodic/event/util/PasswordUtil.java @@ -27,7 +27,7 @@ public class PasswordUtil implements InitializingBean { private final static Supplier passwordEncoderSupplier = AsterisksPasswordEncoder::new; private final static AtomicReference defaultPasswordEncoder = new AtomicReference<>(); - @Value("${password-encoder-class:}") + @Value("${" + EmsConstant.EMS_PROPERTIES_PREFIX + "password-encoder-class:}") private String passwordEncoderClassName; private PasswordEncoder passwordEncoder; diff --git a/event-management/web-admin/README.md b/event-management/web-admin/README.md index c47fbd8c83d7b21c75022593f19b686ecd805372..6fb53dccb4ee9f3cb89e6a6b666915663aadb5c6 100644 --- a/event-management/web-admin/README.md +++ b/event-management/web-admin/README.md @@ -1,3 +1,12 @@ + + # ems-web-admin ## Project setup diff --git a/event-management/web-admin/package-lock.json b/event-management/web-admin/package-lock.json index 736dc08c17fa9a76a7f81276ba1129457955598d..bdfaef7fd6742efc1030358b1102512dcf9aa973 100644 --- a/event-management/web-admin/package-lock.json +++ b/event-management/web-admin/package-lock.json @@ -4,6 +4,26 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@achrinza/node-ipc": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@achrinza/node-ipc/-/node-ipc-9.2.2.tgz", + "integrity": "sha512-b90U39dx0cU6emsOvy5hxU4ApNXnE3+Tuo8XQZfiKTGelDwpMwBVgBP7QX6dGTcJgu/miyJuNJ/2naFBliNWEw==", + "dev": true, + "requires": { + "@node-ipc/js-queue": "2.0.3", + "event-pubsub": "4.3.0", + "js-message": "1.0.7" + } + }, + "@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.0" + } + }, "@babel/code-frame": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", @@ -14,32 +34,144 @@ } }, "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", + "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", "dev": true }, "@babel/core": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", - "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.0", - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.15.0", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz", + "integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.9", + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.9", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.9", + "@babel/types": "^7.17.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/generator": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", + "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", + "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.9", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.9", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/generator": { @@ -54,64 +186,175 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", - "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", - "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-compilation-targets": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", - "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", + "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", "dev": true, "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", + "@babel/compat-data": "^7.17.7", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.17.5", "semver": "^6.3.0" } }, "@babel/helper-create-class-features-plugin": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", - "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", + "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-split-export-declaration": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", - "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "regexpu-core": "^4.7.1" + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" } }, "@babel/helper-define-polyfill-provider": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", - "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.13.0", @@ -124,13 +367,58 @@ "semver": "^6.1.2" } }, + "@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } + } + }, "@babel/helper-explode-assignable-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", - "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-function-name": { @@ -163,93 +451,426 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", - "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", + "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", "dev": true, "requires": { - "@babel/types": "^7.15.0" + "@babel/types": "^7.17.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-module-imports": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", - "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/generator": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", + "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", + "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.9", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.9", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-optimise-call-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", - "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", "dev": true }, "@babel/helper-remap-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", - "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-wrap-function": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-replace-supers": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", - "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/generator": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", + "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", + "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.9", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.9", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-simple-access": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", - "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", "dev": true, "requires": { - "@babel/types": "^7.14.8" + "@babel/types": "^7.17.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", - "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-split-export-declaration": { @@ -264,35 +885,260 @@ "@babel/helper-validator-identifier": { "version": "7.14.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==" + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "dev": true }, "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", "dev": true }, "@babel/helper-wrap-function": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", - "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/generator": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", + "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", + "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.9", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.9", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helpers": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.8.tgz", - "integrity": "sha512-ZRDmI56pnV+p1dH6d+UN6GINGz7Krps3+270qqI9UJ4wxYThfAIcI5i7j5vXC4FJ3Wap+S9qcebxeYiqn87DZw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", "dev": true, "requires": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.9", + "@babel/types": "^7.17.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/generator": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", + "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", + "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.9", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.9", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/highlight": { @@ -309,186 +1155,226 @@ "@babel/parser": { "version": "7.15.2", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.2.tgz", - "integrity": "sha512-bMJXql1Ss8lFnvr11TZDH4ArtwlAS5NG9qBmdiFW2UHHm6MVoR+GDc5XE2b9K938cyjc9O6/+vjjcffLDtfuDg==" + "integrity": "sha512-bMJXql1Ss8lFnvr11TZDH4ArtwlAS5NG9qBmdiFW2UHHm6MVoR+GDc5XE2b9K938cyjc9O6/+vjjcffLDtfuDg==", + "dev": true + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", - "@babel/plugin-proposal-optional-chaining": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", - "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", - "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-proposal-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz", - "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==", + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", + "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-proposal-decorators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.14.5.tgz", - "integrity": "sha512-LYz5nvQcvYeRVjui1Ykn28i+3aUiXwQ/3MGoEy0InTaz1pJo/lAzmIDXX+BQny/oufgHzJ6vnEEiXQ8KZjEVFg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.9.tgz", + "integrity": "sha512-EfH2LZ/vPa2wuPwJ26j+kYRkaubf89UlwxKXtxqEm57HrgSEYDB8t4swFP+p8LcI9yiP9ZRJJjo/58hS6BnaDA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-decorators": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.17.9", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/plugin-syntax-decorators": "^7.17.0", + "charcodes": "^0.2.0" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", - "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-export-namespace-from": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", - "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", - "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", - "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", - "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", - "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", - "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.7", - "@babel/helper-compilation-targets": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.14.5" + "@babel/plugin-transform-parameters": "^7.16.7" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", - "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-private-methods": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", - "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-proposal-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", - "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-syntax-async-generators": { @@ -519,12 +1405,12 @@ } }, "@babel/plugin-syntax-decorators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz", - "integrity": "sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", + "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-syntax-dynamic-import": { @@ -555,12 +1441,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", - "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", + "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -636,357 +1522,526 @@ } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", - "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", - "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5" + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", - "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", - "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-classes": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", - "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-computed-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", - "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-destructuring": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", - "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", + "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", - "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", - "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", - "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-for-of": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", - "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", - "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", - "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", - "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", - "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", - "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz", + "integrity": "sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.14.8", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", - "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz", + "integrity": "sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-modules-umd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", - "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", - "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", + "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.16.7" } }, "@babel/plugin-transform-new-target": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", - "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-object-super": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", - "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" } }, "@babel/plugin-transform-parameters": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", - "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-property-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", - "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-regenerator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", - "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz", + "integrity": "sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==", "dev": true, "requires": { - "regenerator-transform": "^0.14.2" + "regenerator-transform": "^0.15.0" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", - "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-runtime": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz", - "integrity": "sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz", + "integrity": "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.2", - "babel-plugin-polyfill-regenerator": "^0.2.2", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", "semver": "^6.3.0" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", - "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-spread": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", - "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", - "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-template-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", - "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", - "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", - "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", - "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/preset-env": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz", - "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-async-generator-functions": "^7.14.9", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-class-static-block": "^7.14.5", - "@babel/plugin-proposal-dynamic-import": "^7.14.5", - "@babel/plugin-proposal-export-namespace-from": "^7.14.5", - "@babel/plugin-proposal-json-strings": "^7.14.5", - "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", - "@babel/plugin-proposal-numeric-separator": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.14.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", - "@babel/plugin-proposal-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-private-methods": "^7.14.5", - "@babel/plugin-proposal-private-property-in-object": "^7.14.5", - "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", + "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.16.8", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.16.7", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", @@ -1001,51 +2056,69 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.14.5", - "@babel/plugin-transform-async-to-generator": "^7.14.5", - "@babel/plugin-transform-block-scoped-functions": "^7.14.5", - "@babel/plugin-transform-block-scoping": "^7.14.5", - "@babel/plugin-transform-classes": "^7.14.9", - "@babel/plugin-transform-computed-properties": "^7.14.5", - "@babel/plugin-transform-destructuring": "^7.14.7", - "@babel/plugin-transform-dotall-regex": "^7.14.5", - "@babel/plugin-transform-duplicate-keys": "^7.14.5", - "@babel/plugin-transform-exponentiation-operator": "^7.14.5", - "@babel/plugin-transform-for-of": "^7.14.5", - "@babel/plugin-transform-function-name": "^7.14.5", - "@babel/plugin-transform-literals": "^7.14.5", - "@babel/plugin-transform-member-expression-literals": "^7.14.5", - "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.15.0", - "@babel/plugin-transform-modules-systemjs": "^7.14.5", - "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", - "@babel/plugin-transform-new-target": "^7.14.5", - "@babel/plugin-transform-object-super": "^7.14.5", - "@babel/plugin-transform-parameters": "^7.14.5", - "@babel/plugin-transform-property-literals": "^7.14.5", - "@babel/plugin-transform-regenerator": "^7.14.5", - "@babel/plugin-transform-reserved-words": "^7.14.5", - "@babel/plugin-transform-shorthand-properties": "^7.14.5", - "@babel/plugin-transform-spread": "^7.14.6", - "@babel/plugin-transform-sticky-regex": "^7.14.5", - "@babel/plugin-transform-template-literals": "^7.14.5", - "@babel/plugin-transform-typeof-symbol": "^7.14.5", - "@babel/plugin-transform-unicode-escapes": "^7.14.5", - "@babel/plugin-transform-unicode-regex": "^7.14.5", - "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.15.0", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.2", - "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.16.0", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.16.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.16.8", + "@babel/plugin-transform-modules-systemjs": "^7.16.7", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.16.7", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.16.8", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.20.2", "semver": "^6.3.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1056,9 +2129,9 @@ } }, "@babel/runtime": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", - "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -1096,6 +2169,7 @@ "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" @@ -1140,15 +2214,37 @@ "@hapi/hoek": "^8.3.0" } }, - "@intervolga/optimize-cssnano-plugin": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz", - "integrity": "sha512-zN69TnSr0viRSU6cEDIcuPcP67QcpQ6uHACg58FiN9PDrU6SLyGW3MR4tiISbYxy1kDWAVPwD+XwQTWE5cigAA==", + "@intervolga/optimize-cssnano-plugin": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz", + "integrity": "sha512-zN69TnSr0viRSU6cEDIcuPcP67QcpQ6uHACg58FiN9PDrU6SLyGW3MR4tiISbYxy1kDWAVPwD+XwQTWE5cigAA==", + "dev": true, + "requires": { + "cssnano": "^4.0.0", + "cssnano-preset-default": "^4.0.0", + "postcss": "^7.0.0" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", "dev": true, "requires": { - "cssnano": "^4.0.0", - "cssnano-preset-default": "^4.0.0", - "postcss": "^7.0.0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, "@mrmlnc/readdir-enhanced": { @@ -1161,6 +2257,15 @@ "glob-to-regexp": "^0.3.0" } }, + "@node-ipc/js-queue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", + "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", + "dev": true, + "requires": { + "easy-stack": "1.0.1" + } + }, "@nodelib/fs.stat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", @@ -1168,65 +2273,90 @@ "dev": true }, "@soda/friendly-errors-webpack-plugin": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.0.tgz", - "integrity": "sha512-RLotfx6k1+nfLacwNCenj7VnTMPxVwYKoGOcffMFoJDKM8tXzBiCN0hMHFJNnoAojduYAsxuiMm0EOMixgiRow==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", + "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", "dev": true, "requires": { - "chalk": "^2.4.2", - "error-stack-parser": "^2.0.2", - "string-width": "^2.0.0", - "strip-ansi": "^5" + "chalk": "^3.0.0", + "error-stack-parser": "^2.0.6", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "dependencies": { "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } @@ -1253,9 +2383,9 @@ } }, "@types/body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, "requires": { "@types/connect": "*", @@ -1281,12 +2411,6 @@ "@types/node": "*" } }, - "@types/estree": { - "version": "0.0.48", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz", - "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==", - "dev": true - }, "@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -1300,9 +2424,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.24", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", - "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", "dev": true, "requires": { "@types/node": "*", @@ -1311,9 +2435,9 @@ } }, "@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, "requires": { "@types/minimatch": "*", @@ -1321,18 +2445,18 @@ } }, "@types/http-proxy": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz", - "integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==", + "version": "1.17.8", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", + "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", "dev": true, "requires": { "@types/node": "*" } }, "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, "@types/mime": { @@ -1354,9 +2478,9 @@ "dev": true }, "@types/node": { - "version": "16.4.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz", - "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg==", + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", "dev": true }, "@types/normalize-package-data": { @@ -1423,9 +2547,9 @@ } }, "@types/webpack": { - "version": "4.41.30", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.30.tgz", - "integrity": "sha512-GUHyY+pfuQ6haAfzu4S14F+R5iGRwN6b2FRNJY7U0NilmFAqbsOfK6j1HwuLBAqwRIT+pVdNDJGJ6e8rpp0KHA==", + "version": "4.41.32", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", + "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", "dev": true, "requires": { "@types/node": "*", @@ -1445,9 +2569,9 @@ } }, "@types/webpack-dev-server": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.11.5.tgz", - "integrity": "sha512-vjsbQBW3fE5FDICkF3w3ZWFRXNwQdKt7JRPLmRy5W0KXlcuew4wgpKWXhgHS71iLNv7Z2PlY9dSSIaYg+bk+9w==", + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.11.6.tgz", + "integrity": "sha512-XCph0RiiqFGetukCTC3KVnY1jwLcZ84illFRMbyFzCcWl90B/76ew0tSqF46oBhnLC4obNDG7dMO0JfTN0MgMQ==", "dev": true, "requires": { "@types/connect-history-api-fallback": "*", @@ -1489,9 +2613,9 @@ "dev": true }, "@vue/babel-plugin-jsx": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.6.tgz", - "integrity": "sha512-RzYsvBhzKUmY2YG6LoV+W5PnlnkInq0thh1AzCmewwctAgGN6e9UFon6ZrQQV1CO5G5PeME7MqpB+/vvGg0h4g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", + "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -1528,9 +2652,9 @@ } }, "@vue/babel-preset-app": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.13.tgz", - "integrity": "sha512-pM7CR3yXB6L8Gfn6EmX7FLNE3+V/15I3o33GkSNsWvgsMp6HVGXKkXgojrcfUUauyL1LZOdvTmu4enU2RePGHw==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.17.tgz", + "integrity": "sha512-iFv9J3F5VKUPcbx+TqW5qhGmAVyXQxPRpKpPOuTLFIVTzg+iwJnrqVbL4kJU5ECGDxPESW2oCVgxv9bTlDPu7w==", "dev": true, "requires": { "@babel/core": "^7.11.0", @@ -1651,20 +2775,20 @@ } }, "@vue/cli-overlay": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-4.5.13.tgz", - "integrity": "sha512-jhUIg3klgi5Cxhs8dnat5hi/W2tQJvsqCxR0u6hgfSob0ORODgUBlN+F/uwq7cKIe/pzedVUk1y07F13GQvPqg==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-4.5.17.tgz", + "integrity": "sha512-QKKp66VbMg+X8Qh0wgXSwgxLfxY7EIkZkV6bZ6nFqBx8xtaJQVDbTL+4zcUPPA6nygbIcQ6gvTinNEqIqX6FUQ==", "dev": true }, "@vue/cli-plugin-babel": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-4.5.13.tgz", - "integrity": "sha512-ykvEAfD8PgGs+dGMGqr7l/nRmIS39NRzWLhMluPLTvDV1L+IxcoB73HNLGA/aENDpl8CuWrTE+1VgydcOhp+wg==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-4.5.17.tgz", + "integrity": "sha512-6kZuc3PdoUvGAnndUq6+GqjIXn3bqdTR8lOcAb1BH2b4N7IKGlmzcipALGS23HLVMAvDgNuUS7vf0unin9j2cg==", "dev": true, "requires": { "@babel/core": "^7.11.0", - "@vue/babel-preset-app": "^4.5.13", - "@vue/cli-shared-utils": "^4.5.13", + "@vue/babel-preset-app": "^4.5.17", + "@vue/cli-shared-utils": "^4.5.17", "babel-loader": "^8.1.0", "cache-loader": "^4.1.0", "thread-loader": "^2.1.3", @@ -1672,12 +2796,12 @@ } }, "@vue/cli-plugin-eslint": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-4.5.13.tgz", - "integrity": "sha512-yc2uXX6aBiy3vEf5TwaueaDqQbdIXIhk0x0KzEtpPo23jBdLkpOSoU5NCgE06g/ZiGAcettpmBSv73Hfp4wHEw==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-4.5.17.tgz", + "integrity": "sha512-bVNDP+SuWcuJrBMc+JLaKvlxx25XKIlZBa+zzFnxhHZlwPZ7CeBD3e2wnsygJyPoKgDZcZwDgmEz1BZzMEjsNw==", "dev": true, "requires": { - "@vue/cli-shared-utils": "^4.5.13", + "@vue/cli-shared-utils": "^4.5.17", "eslint-loader": "^2.2.1", "globby": "^9.2.0", "inquirer": "^7.1.0", @@ -1686,24 +2810,24 @@ } }, "@vue/cli-plugin-router": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-4.5.13.tgz", - "integrity": "sha512-tgtMDjchB/M1z8BcfV4jSOY9fZSMDTPgF9lsJIiqBWMxvBIsk9uIZHxp62DibYME4CCKb/nNK61XHaikFp+83w==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-4.5.17.tgz", + "integrity": "sha512-9r9CSwqv2+39XHQPDZJ0uaTtTP7oe0Gx17m7kBhHG3FA7R7AOSk2aVzhHZmDRhzlOxjx9kQSvrOSMfUG0kV4dQ==", "dev": true, "requires": { - "@vue/cli-shared-utils": "^4.5.13" + "@vue/cli-shared-utils": "^4.5.17" } }, "@vue/cli-plugin-vuex": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.13.tgz", - "integrity": "sha512-I1S9wZC7iI0Wn8kw8Zh+A2Qkf6s1M6vTGBkx8boXjuzfwEEyEHRxadsVCecZc8Mkpydo0nykj+MyYF96TKFuVA==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.17.tgz", + "integrity": "sha512-ck/ju2T2dmPKLWK/5QctNJs9SCb+eSZbbmr8neFkMc7GlbXw6qLWw5v3Vpd4KevdQA8QuQOA1pjUmzpCiU/mYQ==", "dev": true }, "@vue/cli-service": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-4.5.13.tgz", - "integrity": "sha512-CKAZN4iokMMsaUyJRU22oUAz3oS/X9sVBSKAF2/shFBV5xh3jqAlKl8OXZYz4cXGFLA6djNuYrniuLAo7Ku97A==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-4.5.17.tgz", + "integrity": "sha512-MqfkRYIcIUACe3nYlzNrYstJTWRXHlIqh6JCkbWbdnXWN+IfaVdlG8zw5Q0DVcSdGvkevUW7zB4UhtZB4uyAcA==", "dev": true, "requires": { "@intervolga/optimize-cssnano-plugin": "^1.0.5", @@ -1712,10 +2836,10 @@ "@types/minimist": "^1.2.0", "@types/webpack": "^4.0.0", "@types/webpack-dev-server": "^3.11.0", - "@vue/cli-overlay": "^4.5.13", - "@vue/cli-plugin-router": "^4.5.13", - "@vue/cli-plugin-vuex": "^4.5.13", - "@vue/cli-shared-utils": "^4.5.13", + "@vue/cli-overlay": "^4.5.17", + "@vue/cli-plugin-router": "^4.5.17", + "@vue/cli-plugin-vuex": "^4.5.17", + "@vue/cli-shared-utils": "^4.5.17", "@vue/component-compiler-utils": "^3.1.2", "@vue/preload-webpack-plugin": "^1.1.0", "@vue/web-component-wrapper": "^1.2.0", @@ -1770,63 +2894,6 @@ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "optional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true - }, - "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "optional": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, "ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", @@ -1835,43 +2902,21 @@ "requires": { "minipass": "^3.1.1" } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.8.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", - "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", - "dev": true, - "optional": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - } } } }, "@vue/cli-shared-utils": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-4.5.13.tgz", - "integrity": "sha512-HpnOrkLg42RFUsQGMJv26oTG3J3FmKtO2WSRhKIIL+1ok3w9OjGCtA3nMMXN27f9eX14TqO64M36DaiSZ1fSiw==", + "version": "4.5.17", + "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-4.5.17.tgz", + "integrity": "sha512-VoFNdxvTW4vZu3ne+j1Mf7mU99J2SAoRVn9XPrsouTUUJablglM8DASk7Ixhsh6ymyL/W9EADQFR6Pgj8Ujjuw==", "dev": true, "requires": { + "@achrinza/node-ipc": "9.2.2", "@hapi/joi": "^15.0.1", "chalk": "^2.4.2", "execa": "^1.0.0", "launch-editor": "^2.2.1", "lru-cache": "^5.1.1", - "node-ipc": "^9.1.1", "open": "^6.3.0", "ora": "^3.4.0", "read-pkg": "^5.1.1", @@ -1881,17 +2926,21 @@ } }, "@vue/compiler-core": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.5.tgz", - "integrity": "sha512-TXBhFinoBaXKDykJzY26UEuQU1K07FOp/0Ie+OXySqqk0bS0ZO7Xvl7UmiTUPYcLrWbxWBR7Bs/y55AI0MNc2Q==", - "requires": { - "@babel/parser": "^7.12.0", - "@babel/types": "^7.12.0", - "@vue/shared": "3.1.5", - "estree-walker": "^2.0.1", + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.31.tgz", + "integrity": "sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", "source-map": "^0.6.1" }, "dependencies": { + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==" + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1900,81 +2949,66 @@ } }, "@vue/compiler-dom": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.1.5.tgz", - "integrity": "sha512-ZsL3jqJ52OjGU/YiT/9XiuZAmWClKInZM2aFJh9gnsAPqOrj2JIELMbkIFpVKR/CrVO/f2VxfPiiQdQTr65jcQ==", + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz", + "integrity": "sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==", "requires": { - "@vue/compiler-core": "3.1.5", - "@vue/shared": "3.1.5" + "@vue/compiler-core": "3.2.31", + "@vue/shared": "3.2.31" } }, "@vue/compiler-sfc": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.1.5.tgz", - "integrity": "sha512-mtMY6xMvZeSRx9MTa1+NgJWndrkzVTdJ1pQAmAKQuxyb5LsHVvrgP7kcQFvxPHVpLVTORbTJWHaiqoKrJvi1iA==", - "dev": true, - "requires": { - "@babel/parser": "^7.13.9", - "@babel/types": "^7.13.0", - "@types/estree": "^0.0.48", - "@vue/compiler-core": "3.1.5", - "@vue/compiler-dom": "3.1.5", - "@vue/compiler-ssr": "3.1.5", - "@vue/shared": "3.1.5", - "consolidate": "^0.16.0", - "estree-walker": "^2.0.1", - "hash-sum": "^2.0.0", - "lru-cache": "^5.1.1", + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz", + "integrity": "sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.31", + "@vue/compiler-dom": "3.2.31", + "@vue/compiler-ssr": "3.2.31", + "@vue/reactivity-transform": "3.2.31", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", "magic-string": "^0.25.7", - "merge-source-map": "^1.1.0", "postcss": "^8.1.10", - "postcss-modules": "^4.0.0", - "postcss-selector-parser": "^6.0.4", "source-map": "^0.6.1" }, "dependencies": { - "consolidate": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz", - "integrity": "sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==", - "dev": true, - "requires": { - "bluebird": "^3.7.2" - } + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==" }, "postcss": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.6.tgz", - "integrity": "sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==", - "dev": true, + "version": "8.4.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", + "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", "requires": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map-js": "^0.6.2" + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" } }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, "@vue/compiler-ssr": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.1.5.tgz", - "integrity": "sha512-CU5N7Di/a4lyJ18LGJxJYZS2a8PlLdWpWHX9p/XcsjT2TngMpj3QvHVRkuik2u8QrIDZ8OpYmTyj1WDNsOV+Dg==", - "dev": true, + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz", + "integrity": "sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==", "requires": { - "@vue/compiler-dom": "3.1.5", - "@vue/shared": "3.1.5" + "@vue/compiler-dom": "3.2.31", + "@vue/shared": "3.2.31" } }, "@vue/component-compiler-utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.2.tgz", - "integrity": "sha512-rAYMLmgMuqJFWAOb3Awjqqv5X3Q3hVr4jH/kgrFJpiU0j3a90tnNBplqbj+snzrgZhC9W128z+dtgMifOiMfJg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", + "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", "dev": true, "requires": { "consolidate": "^0.15.1", @@ -1983,7 +3017,7 @@ "merge-source-map": "^1.1.0", "postcss": "^7.0.36", "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2", + "prettier": "^1.18.2 || ^2.0.0", "source-map": "~0.6.1", "vue-template-es2015-compiler": "^1.9.0" }, @@ -2019,9 +3053,9 @@ } }, "@vue/devtools-api": { - "version": "6.0.0-beta.15", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.15.tgz", - "integrity": "sha512-quBx4Jjpexo6KDiNUGFr/zF/2A4srKM9S9v2uHgMXSU//hjgq1eGzqkIFql8T9gfX5ZaVOUzYBP3jIdIR3PKIA==" + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", + "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" }, "@vue/preload-webpack-plugin": { "version": "1.1.2", @@ -2030,36 +3064,64 @@ "dev": true }, "@vue/reactivity": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", - "integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==", + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.31.tgz", + "integrity": "sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==", + "requires": { + "@vue/shared": "3.2.31" + } + }, + "@vue/reactivity-transform": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz", + "integrity": "sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==", "requires": { - "@vue/shared": "3.1.5" + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.31", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + }, + "dependencies": { + "@babel/parser": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==" + } } }, "@vue/runtime-core": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.1.5.tgz", - "integrity": "sha512-YQbG5cBktN1RowQDKA22itmvQ+b40f0WgQ6CXK4VYoYICAiAfu6Cc14777ve8zp1rJRGtk5oIeS149TOculrTg==", + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.31.tgz", + "integrity": "sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==", "requires": { - "@vue/reactivity": "3.1.5", - "@vue/shared": "3.1.5" + "@vue/reactivity": "3.2.31", + "@vue/shared": "3.2.31" } }, "@vue/runtime-dom": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.1.5.tgz", - "integrity": "sha512-tNcf3JhVR0RfW0kw1p8xZgv30nvX8Y9rsz7eiQ0dHe273sfoCngAG0y4GvMaY4Xd8FsjUwFedd4suQ8Lu8meXg==", + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.31.tgz", + "integrity": "sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==", "requires": { - "@vue/runtime-core": "3.1.5", - "@vue/shared": "3.1.5", + "@vue/runtime-core": "3.2.31", + "@vue/shared": "3.2.31", "csstype": "^2.6.8" } }, + "@vue/server-renderer": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.31.tgz", + "integrity": "sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==", + "requires": { + "@vue/compiler-ssr": "3.2.31", + "@vue/shared": "3.2.31" + } + }, "@vue/shared": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz", - "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==" + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.31.tgz", + "integrity": "sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==" }, "@vue/web-component-wrapper": { "version": "1.3.0", @@ -2255,13 +3317,13 @@ "dev": true }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, "acorn": { @@ -2341,10 +3403,10 @@ } } }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", "dev": true }, "ansi-regex": { @@ -2445,9 +3507,9 @@ "dev": true }, "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "requires": { "safer-buffer": "~2.1.0" @@ -2552,18 +3614,26 @@ "dev": true }, "autoprefixer": { - "version": "9.8.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", - "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", "dev": true, "requires": { "browserslist": "^4.12.0", "caniuse-lite": "^1.0.30001109", - "colorette": "^1.2.1", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", "postcss": "^7.0.32", "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + } } }, "aws-sign2": { @@ -2593,13 +3663,13 @@ } }, "babel-loader": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", - "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.4.tgz", + "integrity": "sha512-8dytA3gcvPPPv4Grjhnt8b5IIiTcq/zeXOPk4iTYI0SVXcsmuGg7JtBRDp8S9X+gJfhQ8ektjXZlDu1Bb33U8A==", "dev": true, "requires": { "find-cache-dir": "^3.3.1", - "loader-utils": "^1.4.0", + "loader-utils": "^2.0.0", "make-dir": "^3.1.0", "schema-utils": "^2.6.5" } @@ -2614,39 +3684,40 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", - "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", "dev": true, "requires": { "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.2", + "@babel/helper-define-polyfill-provider": "^0.3.1", "semver": "^6.1.1" } }, "babel-plugin-polyfill-corejs3": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz", - "integrity": "sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.2", - "core-js-compat": "^3.14.0" + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", - "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.2" + "@babel/helper-define-polyfill-provider": "^0.3.1" } }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "base": { "version": "0.11.2", @@ -2762,21 +3833,21 @@ "dev": true }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", "dev": true, "requires": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "1.7.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" }, "dependencies": { "debug": { @@ -2795,9 +3866,9 @@ "dev": true }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", "dev": true } } @@ -2834,6 +3905,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2967,16 +4039,16 @@ } }, "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", + "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001317", + "electron-to-chromium": "^1.4.84", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" } }, "buffer": { @@ -3021,9 +4093,9 @@ "dev": true }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true }, "cacache": { @@ -3078,6 +4150,28 @@ "mkdirp": "^0.5.1", "neo-async": "^2.6.1", "schema-utils": "^2.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "call-bind": { @@ -3131,9 +4225,9 @@ } }, "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, "caniuse-api": { @@ -3149,9 +4243,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001300", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001300.tgz", - "integrity": "sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==", + "version": "1.0.30001327", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz", + "integrity": "sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==", "dev": true }, "case-sensitive-paths-webpack-plugin": { @@ -3177,6 +4271,12 @@ "supports-color": "^5.3.0" } }, + "charcodes": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", + "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", + "dev": true + }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -3184,9 +4284,9 @@ "dev": true }, "chart.js": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.0.tgz", - "integrity": "sha512-J1a4EAb1Gi/KbhwDRmoovHTRuqT8qdF0kZ4XgwxpGethJHUdDrkqyPYwke0a+BuvSeUxPf8Cos6AX2AB8H8GLA==" + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz", + "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==" }, "check-types": { "version": "8.0.3", @@ -3195,9 +4295,9 @@ "dev": true }, "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "optional": true, "requires": { @@ -3307,9 +4407,9 @@ } }, "clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", "dev": true, "requires": { "source-map": "~0.6.0" @@ -3323,15 +4423,6 @@ } } }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" - } - }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -3407,9 +4498,9 @@ } }, "cli-spinners": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", - "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", "dev": true }, "cli-width": { @@ -3541,21 +4632,15 @@ "dev": true }, "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", + "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", "dev": true, "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3633,7 +4718,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -3675,12 +4761,20 @@ "dev": true }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } } }, "content-type": { @@ -3699,9 +4793,9 @@ } }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "dev": true }, "cookie-signature": { @@ -3819,6 +4913,26 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -3889,17 +5003,17 @@ } }, "core-js": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.1.tgz", - "integrity": "sha512-AAkP8i35EbefU+JddyWi12AWE9f2N/qr/pwnDtWz4nyUIBGMJPX99ANFFRSw6FefM374lDujdtLDyhN2A/btHw==" + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", + "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==" }, "core-js-compat": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.16.1.tgz", - "integrity": "sha512-NHXQXvRbd4nxp9TEmooTJLUf94ySUG6+DSsscBpTftN1lQLQ4LjnWvc7AoIo4UjDsFF3hB8Uh5LLCRRdaiT5MQ==", + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", + "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", "dev": true, "requires": { - "browserslist": "^4.16.7", + "browserslist": "^4.19.1", "semver": "7.0.0" }, "dependencies": { @@ -3914,7 +5028,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cosmiconfig": { "version": "5.2.1", @@ -4067,6 +5182,26 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } } } }, @@ -4229,9 +5364,9 @@ } }, "csstype": { - "version": "2.6.17", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz", - "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==" + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" }, "cyclist": { "version": "1.0.1", @@ -4248,11 +5383,6 @@ "assert-plus": "^1.0.0" } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" - }, "debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -4621,15 +5751,17 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, "requires": { "domelementtype": "^2.0.1", "entities": "^2.0.0" }, "dependencies": { "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true } } }, @@ -4642,21 +5774,22 @@ "domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true }, "domhandler": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", - "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, "requires": { "domelementtype": "^2.2.0" }, "dependencies": { "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true } } @@ -4739,9 +5872,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.799", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.799.tgz", - "integrity": "sha512-V2rbYWdGvSqrg+95KjkVuSi41bGfrhrOzjl1tSi2VLnm0mRe3FsSvhiqidSiSll9WiMhrQAhpDcW/wcqK3c+Yw==", + "version": "1.4.106", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.106.tgz", + "integrity": "sha512-ZYfpVLULm67K7CaaGP7DmjyeMY4naxsbTy+syVVxT6QHI1Ww8XbJjmr9fDckrhq44WzCrcC5kH3zGpdusxwwqg==", "dev": true }, "elliptic": { @@ -4820,7 +5953,8 @@ "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true }, "errno": { "version": "0.1.8", @@ -4841,32 +5975,35 @@ } }, "error-stack-parser": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", - "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.7.tgz", + "integrity": "sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA==", "dev": true, "requires": { "stackframe": "^1.1.1" } }, "es-abstract": { - "version": "1.18.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", - "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.2.tgz", + "integrity": "sha512-gfSBJoZdlL2xRiOCy0g8gLMryhoe1TlimjzU99L/31Z8QEGIhVQI+EWwt5lT+AuU9SnorVupXFqqOGqGfsyO6w==", "dev": true, "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.2", + "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", - "object-inspect": "^1.11.0", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -5011,12 +6148,34 @@ "object-assign": "^4.0.1", "object-hash": "^1.1.4", "rimraf": "^2.6.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "eslint-plugin-vue": { - "version": "7.15.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-7.15.1.tgz", - "integrity": "sha512-4/r+n/i+ovyeW2gVRRH92kpy4lkpFbyPR4BMxGBTLtGnwqOKKzjSo6EMSaT0RhWPvEjK9uifcY8e7z5n8BIEgw==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-7.20.0.tgz", + "integrity": "sha512-oVNDqzBC9h3GO+NTgWeLMhhGigy6/bQaQbHS+0z7C4YEu/qK/yxHvca/2PTZtGNPsCrHwOTgKMrwu02A9iPBmw==", "dev": true, "requires": { "eslint-utils": "^2.1.0", @@ -5195,11 +6354,6 @@ "strip-eof": "^1.0.0" } }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5251,17 +6405,17 @@ } }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", "dev": true, "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -5275,13 +6429,13 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", @@ -5304,9 +6458,15 @@ "dev": true }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true } } @@ -5516,6 +6676,28 @@ "requires": { "loader-utils": "^1.2.3", "schema-utils": "^2.5.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "filesize": { @@ -5580,9 +6762,9 @@ } }, "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -5639,9 +6821,9 @@ } }, "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", "dev": true }, "for-in": { @@ -5724,7 +6906,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "2.3.2", @@ -5745,15 +6928,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "generic-names": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-2.0.1.tgz", - "integrity": "sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0" - } - }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -5786,6 +6960,16 @@ "pump": "^3.0.0" } }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -5805,6 +6989,7 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5852,9 +7037,9 @@ } }, "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "gzip-size": { @@ -5911,9 +7096,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true }, "has-tostringtag": { @@ -6098,9 +7283,9 @@ } }, "html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", "dev": true }, "html-webpack-plugin": { @@ -6184,15 +7369,15 @@ } }, "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true }, "domutils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", - "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, "requires": { "dom-serializer": "^1.0.1", @@ -6209,30 +7394,22 @@ "dev": true }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } + "toidentifier": "1.0.1" } }, "http-parser-js": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", + "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", "dev": true }, "http-proxy": { @@ -6284,13 +7461,13 @@ "dev": true }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "to-regex-range": { @@ -6336,12 +7513,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, "icss-utils": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", @@ -6474,6 +7645,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -6482,7 +7654,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "inquirer": { "version": "7.3.3", @@ -6684,10 +7857,13 @@ "dev": true }, "is-bigint": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.3.tgz", - "integrity": "sha512-ZU538ajmYJmzysE5yU4Y7uIrPQ2j704u+hXFiIPQExpqzzUbpe5jCPdTfmz7jXRxZdvjY3KZ3ZNenoXQovX+Dg==", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } }, "is-binary-path": { "version": "2.1.0", @@ -6841,9 +8017,9 @@ } }, "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, "is-number": { @@ -6867,9 +8043,9 @@ } }, "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "requires": { "has-tostringtag": "^1.0.0" @@ -6936,6 +8112,15 @@ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -6966,6 +8151,15 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -7024,9 +8218,12 @@ "integrity": "sha1-G+i3twTdOFcVJwiu+x1KSzpp+zM=" }, "jquery-ui": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz", - "integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE=" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.1.tgz", + "integrity": "sha512-2VlU59N5P4HaumDK1Z3XEVjSvegFbEOQRgpHUBaB2Ak98Axl3hFhJ6RFcNQNuk9SfL6WxIbuLst8dW/U56NSiA==", + "requires": { + "jquery": ">=1.8.0 <4.0.0" + } }, "js-message": { "version": "1.0.7", @@ -7034,15 +8231,6 @@ "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", "dev": true }, - "js-queue": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz", - "integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==", - "dev": true, - "requires": { - "easy-stack": "^1.0.1" - } - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7071,91 +8259,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jshint": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.1.tgz", - "integrity": "sha512-vymzfR3OysF5P774x6zYv0bD4EpH6NWRxpq54wO9mA9RuY49yb1teKSICkLx2Ryx+mfzlVVNNbTBtsRtg78t7g==", - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.21", - "minimatch": "~3.0.2", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x" - }, - "dependencies": { - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "requires": { - "date-now": "^0.1.4" - } - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=" - } - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -7169,9 +8272,9 @@ "dev": true }, "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, "json-schema-traverse": { @@ -7192,20 +8295,11 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", - "dev": true - }, "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true }, "jsonfile": { "version": "4.0.0", @@ -7217,14 +8311,14 @@ } }, "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" } }, @@ -7254,22 +8348,22 @@ "dev": true }, "launch-editor": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz", - "integrity": "sha512-On+V7K2uZK6wK7x691ycSUbLD/FyKKelArkbaAMSSJU8JmqmhwN2+mnJDNINuJWSrh2L0kDk+ZQtbC/gOWUwLw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.3.0.tgz", + "integrity": "sha512-3QrsCXejlWYHjBPFXTyGNhPj4rrQdB+5+r5r3wArpLH201aR+nWUgw/zKKkTmilCfY/sv6u8qo98pNvtg8LUTA==", "dev": true, "requires": { - "chalk": "^2.3.0", + "picocolors": "^1.0.0", "shell-quote": "^1.6.1" } }, "launch-editor-middleware": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz", - "integrity": "sha512-s0UO2/gEGiCgei3/2UN3SMuUj1phjQN8lcpnvgLSz26fAzNWPQ6Nf/kF5IFClnfU2ehp6LrmKdMU/beveO+2jg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.3.0.tgz", + "integrity": "sha512-GJR64trLdFFwCoL9DMn/d1SZX0OzTDPixu4mcfWTShQ4tIqCHCGvlg9fOEYQXyBlrSMQwylsJfUWncheShfV2w==", "dev": true, "requires": { - "launch-editor": "^2.2.1" + "launch-editor": "^2.3.0" } }, "leaflet": { @@ -7278,18 +8372,14 @@ "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==" }, "leaflet-providers": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/leaflet-providers/-/leaflet-providers-1.12.0.tgz", - "integrity": "sha512-pU/mR4B+NbayBGCg5/88dmRq7t1EGiNPhsVGV3yqHuDn594vIwus4CiPVW0RtiKJNKg8Vf1pILAbFl0i+yk+lQ==" + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/leaflet-providers/-/leaflet-providers-1.13.0.tgz", + "integrity": "sha512-f/sN5wdgBbVA2jcCYzScIfYNxKdn2wBJP9bu+5cRX9Xj6g8Bt1G9Sr8WgJAt/ckIFIc3LVVxCBNFpSCfTuUElg==" }, "leaflet.markercluster": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.1.tgz", - "integrity": "sha512-dRGndfMZibkWMBD7g8h+lJW0R0keTx1GGMErre7uhqnKiYBoMxR2VPX6Sy8oGNzg+FA7FKtTuO1hGh5HtV9s2g==", - "requires": { - "jshint": "^2.13.1", - "npm-ci": "0.0.2" - } + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==" }, "levn": { "version": "0.3.0", @@ -7302,9 +8392,9 @@ } }, "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, "loader-fs-cache": { @@ -7365,25 +8455,14 @@ "dev": true }, "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", "dev": true, "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } + "json5": "^2.1.2" } }, "locate-path": { @@ -7398,12 +8477,7 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.debounce": { @@ -7458,9 +8532,9 @@ } }, "loglevel": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", - "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", "dev": true }, "lower-case": { @@ -7479,12 +8553,11 @@ } }, "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "requires": { - "sourcemap-codec": "^1.4.4" + "sourcemap-codec": "^1.4.8" } }, "make-dir": { @@ -7625,24 +8698,24 @@ } }, "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true }, "mime-db": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true }, "mime-types": { - "version": "2.1.32", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", - "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "requires": { - "mime-db": "1.49.0" + "mime-db": "1.52.0" } }, "mimic-fn": { @@ -7663,6 +8736,26 @@ "webpack-sources": "^1.1.0" }, "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, "normalize-url": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", @@ -7704,20 +8797,21 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -7838,10 +8932,9 @@ } }, "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", - "dev": true + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.2.tgz", + "integrity": "sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==" }, "nanomatch": { "version": "1.2.13", @@ -7869,9 +8962,9 @@ "dev": true }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true }, "neo-async": { @@ -7901,17 +8994,6 @@ "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", "dev": true }, - "node-ipc": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz", - "integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==", - "dev": true, - "requires": { - "event-pubsub": "4.3.0", - "js-message": "1.0.7", - "js-queue": "2.0.2" - } - }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -7952,9 +9034,9 @@ } }, "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", "dev": true }, "normalize-package-data": { @@ -7995,11 +9077,6 @@ "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", "dev": true }, - "npm-ci": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/npm-ci/-/npm-ci-0.0.2.tgz", - "integrity": "sha1-n2t2IMKFeAL7baJoEGnkCinjEHI=" - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -8074,9 +9151,9 @@ "dev": true }, "object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", "dev": true }, "object-is": { @@ -8117,14 +9194,14 @@ } }, "object.getownpropertydescriptors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", - "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", + "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" + "es-abstract": "^1.19.1" } }, "object.pick": { @@ -8137,14 +9214,14 @@ } }, "object.values": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", - "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.2" + "es-abstract": "^1.19.1" } }, "obuf": { @@ -8172,6 +9249,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -8438,7 +9516,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-is-inside": { "version": "1.0.2", @@ -8500,10 +9579,15 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pify": { @@ -8574,30 +9658,26 @@ "dev": true }, "postcss": { - "version": "7.0.36", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", - "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "dev": true, "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, @@ -8709,6 +9789,26 @@ "schema-utils": "^1.0.0" }, "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -8854,65 +9954,6 @@ } } }, - "postcss-modules": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.2.2.tgz", - "integrity": "sha512-/H08MGEmaalv/OU8j6bUKi/kZr2kqGF6huAW8m9UAgOLWtpFdhA14+gPBoymtqyv+D4MLsmqaF2zvIegdCxJXg==", - "dev": true, - "requires": { - "generic-names": "^2.0.1", - "icss-replace-symbols": "^1.1.0", - "lodash.camelcase": "^4.3.0", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "string-hash": "^1.1.1" - }, - "dependencies": { - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true - }, - "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - } - } - }, "postcss-modules-extract-imports": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", @@ -9169,9 +10210,9 @@ } }, "postcss-selector-parser": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", - "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -9209,9 +10250,9 @@ } }, "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, "prelude-ls": { @@ -9227,9 +10268,9 @@ "dev": true }, "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", "dev": true, "optional": true }, @@ -9363,9 +10404,9 @@ "dev": true }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true }, "query-string": { @@ -9422,13 +10463,13 @@ "dev": true }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", "dev": true, "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -9477,12 +10518,12 @@ "dev": true }, "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", "dev": true, "requires": { - "regenerate": "^1.4.0" + "regenerate": "^1.4.2" } }, "regenerator-runtime": { @@ -9492,9 +10533,9 @@ "dev": true }, "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", "dev": true, "requires": { "@babel/runtime": "^7.8.4" @@ -9511,9 +10552,9 @@ } }, "regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", + "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -9527,29 +10568,29 @@ "dev": true }, "regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", "dev": true, "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" } }, "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", "dev": true }, "regjsparser": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", - "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -9595,22 +10636,22 @@ "dev": true }, "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "dev": true, "requires": { "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" } }, "css-what": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", - "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true }, "dom-serializer": { @@ -9625,15 +10666,15 @@ } }, "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true }, "domutils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", - "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, "requires": { "dom-serializer": "^1.0.1", @@ -9872,9 +10913,9 @@ "dev": true }, "selfsigned": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", - "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", "dev": true, "requires": { "node-forge": "^0.10.0" @@ -9887,9 +10928,9 @@ "dev": true }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", "dev": true, "requires": { "debug": "2.6.9", @@ -9899,9 +10940,9 @@ "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "1.8.1", "mime": "1.6.0", - "ms": "2.1.1", + "ms": "2.1.3", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" @@ -9931,9 +10972,9 @@ "dev": true }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -10004,15 +11045,15 @@ } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.17.2" } }, "set-blocking": { @@ -10051,9 +11092,9 @@ "dev": true }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, "sha.js": { @@ -10082,16 +11123,11 @@ "dev": true }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" - }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -10274,28 +11310,35 @@ } }, "sockjs": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", - "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, "requires": { "faye-websocket": "^0.11.3", - "uuid": "^3.4.0", + "uuid": "^8.3.2", "websocket-driver": "^0.7.4" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } } }, "sockjs-client": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz", - "integrity": "sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.6.0.tgz", + "integrity": "sha512-qVHJlyfdHFht3eBFZdKEXKTlb7I4IV41xnVNo8yUKA1UHcPJwgW2SvTq9LhnjjCywSkSK7c/e4nghU0GOoMCRQ==", "dev": true, "requires": { - "debug": "^3.2.6", - "eventsource": "^1.0.7", - "faye-websocket": "^0.11.3", + "debug": "^3.2.7", + "eventsource": "^1.1.0", + "faye-websocket": "^0.11.4", "inherits": "^2.0.4", - "json3": "^3.3.3", - "url-parse": "^1.5.1" + "url-parse": "^1.5.10" }, "dependencies": { "debug": { @@ -10339,10 +11382,9 @@ "dev": true }, "source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, "source-map-resolve": { "version": "0.5.3", @@ -10358,9 +11400,9 @@ } }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -10384,8 +11426,7 @@ "sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" }, "spdx-correct": { "version": "3.1.1", @@ -10414,9 +11455,9 @@ } }, "spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "dev": true }, "spdy": { @@ -10475,9 +11516,9 @@ "dev": true }, "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -10507,9 +11548,9 @@ "dev": true }, "stackframe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", - "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz", + "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==", "dev": true }, "static-extend": { @@ -10584,12 +11625,6 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, - "string-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=", - "dev": true - }, "string-width": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", @@ -10941,6 +11976,28 @@ "loader-runner": "^2.3.1", "loader-utils": "^1.1.0", "neo-async": "^2.6.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "through": { @@ -10998,7 +12055,8 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true }, "to-object-path": { "version": "0.3.0", @@ -11043,9 +12101,9 @@ } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, "toposort": { @@ -11171,31 +12229,31 @@ } }, "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true }, "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" } }, "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", "dev": true }, "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", "dev": true }, "union-value": { @@ -11352,12 +12410,34 @@ "loader-utils": "^1.2.3", "mime": "^2.4.4", "schema-utils": "^2.5.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, "requires": { "querystringify": "^2.1.1", @@ -11469,19 +12549,21 @@ "dev": true }, "vue": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.1.5.tgz", - "integrity": "sha512-Ho7HNb1nfDoO+HVb6qYZgeaobt1XbY6KXFe4HGs1b9X6RhkWG/113n4/SrtM1LUclM6OrP/Se5aPHHvAPG1iVQ==", + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.31.tgz", + "integrity": "sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==", "requires": { - "@vue/compiler-dom": "3.1.5", - "@vue/runtime-dom": "3.1.5", - "@vue/shared": "3.1.5" + "@vue/compiler-dom": "3.2.31", + "@vue/compiler-sfc": "3.2.31", + "@vue/runtime-dom": "3.2.31", + "@vue/server-renderer": "3.2.31", + "@vue/shared": "3.2.31" } }, "vue-eslint-parser": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.10.0.tgz", - "integrity": "sha512-7tc/ewS9Vq9Bn741pvpg8op2fWJPH3k32aL+jcIcWGCTzh/zXSdh7pZ5FV3W2aJancP9+ftPAv292zY5T5IPCg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz", + "integrity": "sha512-qh3VhDLeh773wjgNTl7ss0VejY9bMMa0GoDG2fQVyDzRFdiU3L7fw74tWZDHNQXdZqxO3EveQroa9ct39D2nqg==", "dev": true, "requires": { "debug": "^4.1.1", @@ -11517,9 +12599,9 @@ "dev": true }, "vue-json-pretty": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-2.0.4.tgz", - "integrity": "sha512-17opXQveJOkxWu6NzjXqtIelm3DeQfeQUevbfRAw91eZXix2hNzGAwGrkqEDWhLMDVpENm2NhVpYqzB8eQzytg==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-2.0.6.tgz", + "integrity": "sha512-aVdxw8ZRGR/Uj8GEaJ1/W2Ks/MdCfv5t2HRbbd+ICp3nL7msKRLN+1qOkSzaMvDygbDPxGhwUHBxZz8nxP+r3A==" }, "vue-loader": { "version": "15.9.8", @@ -11539,15 +12621,104 @@ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.8.3", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", + "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "dev": true, + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "optional": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "vue-router": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.11.tgz", - "integrity": "sha512-sha6I8fx9HWtvTrFZfxZkiQQBpqSeT+UCwauYjkdOQYRvwsGwimlQQE2ayqUwuuXGzquFpCPoXzYKWlzL4OuXg==", + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.14.tgz", + "integrity": "sha512-wAO6zF9zxA3u+7AkMPqw9LjoUCjSxfFvINQj3E/DceTt6uEz1XZLraDhdg2EYmvVwTBSGlLYsUw8bDmx0754Mw==", "requires": { - "@vue/devtools-api": "^6.0.0-beta.14" + "@vue/devtools-api": "^6.0.0" } }, "vue-style-loader": { @@ -11565,6 +12736,26 @@ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } } } }, @@ -11771,6 +12962,26 @@ "webpack-sources": "^1.4.1" }, "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -11837,12 +13048,12 @@ } }, "webpack-dev-server": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", - "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz", + "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==", "dev": true, "requires": { - "ansi-html": "0.0.7", + "ansi-html-community": "0.0.8", "bonjour": "^3.5.0", "chokidar": "^2.1.8", "compression": "^1.7.4", @@ -11948,9 +13159,9 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "strip-ansi": { @@ -12099,9 +13310,9 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "strip-ansi": { @@ -12145,9 +13356,9 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "strip-ansi": { @@ -12328,7 +13539,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "write": { "version": "1.0.3", diff --git a/event-management/web-admin/package.json b/event-management/web-admin/package.json index 053649b6cf188d42671b5f3e4aaaa259632fa57f..68c99c3de789e38774c0170d67924e5d44c6be1d 100644 --- a/event-management/web-admin/package.json +++ b/event-management/web-admin/package.json @@ -9,33 +9,33 @@ }, "dependencies": { "@tip2tail/jqvmap": "^1.6.0", - "chart.js": "^3.5.0", - "core-js": "^3.6.5", + "chart.js": "^3.7.1", + "core-js": "^3.21.1", "jquery": "^3.6.0", "jquery-knob": "^1.2.11", "jquery-sparkline": "^2.4.0", - "jquery-ui": "^1.12.1", + "jquery-ui": "^1.13.1", "jvectormap-content": "^0.1.0", "jvectormap-next": "^3.1.1", "leaflet": "^1.7.1", - "leaflet-providers": "^1.12.0", - "leaflet.markercluster": "^1.5.1", + "leaflet-providers": "^1.13.0", + "leaflet.markercluster": "^1.5.3", "mitt": "^3.0.0", - "vue": "^3.0.0", + "vue": "^3.2.31", "vue-gauge": "^1.0.3", - "vue-json-pretty": "^2.0.4", - "vue-router": "^4.0.11", + "vue-json-pretty": "^2.0.6", + "vue-router": "^4.0.14", "vue-world-map": "^0.1.1", "vue3-blocks-tree": "^0.5.2" }, "devDependencies": { - "@vue/cli-plugin-babel": "~4.5.0", - "@vue/cli-plugin-eslint": "~4.5.0", - "@vue/cli-service": "~4.5.0", - "@vue/compiler-sfc": "^3.0.0", + "@vue/cli-plugin-babel": "^4.5.17", + "@vue/cli-plugin-eslint": "^4.5.17", + "@vue/cli-service": "^4.5.17", + "@vue/compiler-sfc": "^3.2.31", "babel-eslint": "^10.1.0", "eslint": "^6.7.2", - "eslint-plugin-vue": "^7.0.0" + "eslint-plugin-vue": "^7.20.0" }, "eslintConfig": { "root": true, diff --git a/event-management/web-admin/src/App.vue b/event-management/web-admin/src/App.vue index b8a41ceac54a7863dd8c71c1545e6e0ad34b3205..22d1dabf38810322eba2325f913e0aaa3b176074 100644 --- a/event-management/web-admin/src/App.vue +++ b/event-management/web-admin/src/App.vue @@ -1,3 +1,11 @@ +